- 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>
1540 lines
53 KiB
C++
1540 lines
53 KiB
C++
// BDE - (C) Copyright 1995 by Borland International
|
|
|
|
#include "snipit.h"
|
|
#include <ctype.h>
|
|
#include <ctl3d.h>
|
|
#include <commdlg.h>
|
|
|
|
#define FILEHANDLESNEEDED 40
|
|
|
|
// Prototypes for static functions.
|
|
static void CreateResources(HINSTANCE hInstance, HWND hWnd);
|
|
static void InitMainWnd(HWND hWnd);
|
|
static BOOL InitApp(int nCmdShow, HINSTANCE hInst);
|
|
static void get_search_text(void);
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
|
|
//
|
|
// Input: hInstance - The handle that represents the
|
|
// application's unique instance ID
|
|
// hPrevInstance - Indicates if this is the first instance
|
|
// of the application
|
|
// lpCmdLine - Command line parameters (it is the
|
|
// application's responsibility to parse them)
|
|
// nCmdShow - TRUE = Show as non-icon application
|
|
//
|
|
// Return: int - Success?
|
|
//
|
|
// Description:
|
|
// Application entry point. Init the app, main window, and
|
|
// global variables.
|
|
//===================================================================
|
|
int PASCAL
|
|
WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
MSG msg;
|
|
HACCEL hAccel;
|
|
|
|
// Avoid warning: Parameter not used
|
|
lpCmdLine = lpCmdLine;
|
|
|
|
// Make this a single instance program
|
|
if (hPrevInstance)
|
|
{
|
|
MessageBox(GetFocus(), "This application is already running!",
|
|
"Windows Driver", MB_OK);
|
|
return FALSE;
|
|
}
|
|
|
|
// Register CTL3D
|
|
Ctl3dRegister(hInstance);
|
|
Ctl3dAutoSubclass(hInstance);
|
|
Ctl3dColorChange();
|
|
|
|
// Start the application
|
|
if (InitApp(nCmdShow, hInstance) == FALSE)
|
|
return FALSE;
|
|
|
|
// Load the keyboard accelerators
|
|
hAccel = LoadAccelerators(hInstance, "MenuAccel");
|
|
|
|
// Process all event driven messages...
|
|
while (GetMessage(&msg, NULL, NULL, NULL))
|
|
{
|
|
if ((! TranslateAccelerator(hMainWnd, hAccel, &msg)) &&
|
|
(! IsDialogMessage(hMainWnd, &msg)))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
// Clean up and return
|
|
if (GlobBuf)
|
|
{
|
|
free(GlobBuf);
|
|
}
|
|
if (Search.pText)
|
|
{
|
|
free(Search.pText);
|
|
}
|
|
if (Search.pSearchStr)
|
|
{
|
|
free(Search.pSearchStr);
|
|
}
|
|
|
|
DestroyWindow(hMainWnd);
|
|
|
|
// Unregister CTL3D
|
|
Ctl3dUnregister(hInstance);
|
|
return msg.wParam;
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// get_array_offset(void);
|
|
//
|
|
// Input: None.
|
|
//
|
|
// Return: The array element -OR-
|
|
// -1 if the element is not found
|
|
//
|
|
// Description:
|
|
// Return the array element for InputData[]. The element
|
|
// returned is determined by scanning the array for the
|
|
// currently selected code sample.
|
|
//===================================================================
|
|
INT16
|
|
get_array_offset (void)
|
|
{
|
|
INT32 Index;
|
|
INT16 i;
|
|
INT16 ret = -1;
|
|
|
|
// Get the currently selected code sample
|
|
Index = SendMsg(IDL_SELECT_CODE, LB_GETCURSEL, 0, 0);
|
|
SendMsg(IDL_SELECT_CODE, LB_GETTEXT, (WORD) Index,
|
|
(LONG)(LPSTR)GlobBuf);
|
|
|
|
// Search for the text in the input array
|
|
if (GlobBuf[0])
|
|
{
|
|
for (i = 0; i < MAX_VIEW_CODE_MODULES; i++)
|
|
{
|
|
// Scan for a match
|
|
if (lstrcmp(InputData[i].pCodeName, GlobBuf) ==
|
|
GOOD_STR_COMPARE)
|
|
{
|
|
ret = i;
|
|
i = MAX_VIEW_CODE_MODULES; // End the loop...
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// yield_control(void);
|
|
//
|
|
// Input: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Description:
|
|
// This routine will give Windows a chance to yield control
|
|
// of the CPU to other applications.
|
|
//===================================================================
|
|
void
|
|
yield_control (void)
|
|
{
|
|
MSG msg;
|
|
|
|
// Process all messages for the suite "dialog"
|
|
while (PeekMessage(&msg, hMainWnd, 0, 0, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// clear_multi_line_edit_box(hWnd, EditId);
|
|
//
|
|
// Input: hWnd - The dialog handle
|
|
// EditId - The edit box to clear
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Description:
|
|
// Clear the specified multi-line edit box selected code. If
|
|
// no description is available, then the text box will be left
|
|
// blank.
|
|
//===================================================================
|
|
void
|
|
clear_multi_line_edit_box (HWND hWnd, INT16 EditId)
|
|
{
|
|
// Select all text in the edit box, then replace it with ""
|
|
SendDlgItemMessage(hWnd, EditId, EM_SETSEL, (WPARAM)(UINT) 1,
|
|
MAKELPARAM(0, -1));
|
|
SendDlgItemMessage(hWnd, EditId, EM_REPLACESEL, 0,
|
|
(LPARAM)(LPCSTR)"");
|
|
|
|
// Allow Windows to process above messages
|
|
yield_control();
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// fill_in_description(void);
|
|
//
|
|
// Input: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Description:
|
|
// Fill in the brief description for the currently selected
|
|
// code. If no description is available, then the text box
|
|
// will be left blank.
|
|
//===================================================================
|
|
void
|
|
fill_in_description (void)
|
|
{
|
|
INT16 Offset;
|
|
|
|
// First clear the text
|
|
SendMsg(IDE_DESCRIBE_CODE, WM_SETTEXT, (WPARAM) 0,
|
|
(LPARAM)(LPCSTR)"");
|
|
|
|
// Get the array offset of the code selected
|
|
Offset = get_array_offset();
|
|
if ((Offset != -1) && (InputData[Offset].CodeDescId > 0))
|
|
{
|
|
// Display the text if it loads
|
|
if (LoadString(hInst, InputData[Offset].CodeDescId,
|
|
(LPSTR) GlobBuf, 256) > 0)
|
|
{
|
|
SendMsg(IDE_DESCRIBE_CODE, WM_SETTEXT, (WPARAM) 0,
|
|
(LPARAM)(LPCSTR) GlobBuf);
|
|
}
|
|
|
|
// Display the sample code file
|
|
SendMsg(IDT_FILE_NAME, WM_SETTEXT, (WPARAM) 0,
|
|
(LPARAM)(LPCSTR) InputData[Offset].pSourceFile);
|
|
}
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// get_search_text(void);
|
|
//
|
|
// Input: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Description:
|
|
// Retrieve the text from the main edit box. The text will
|
|
// be used during the "Search First" and "Search Next" calls.
|
|
//===================================================================
|
|
static void
|
|
get_search_text (void)
|
|
{
|
|
UINT16 TextLen;
|
|
|
|
// Allocate buffer for edit box text (add extra space just
|
|
// in case)
|
|
if (Search.pText)
|
|
{
|
|
free(Search.pText);
|
|
}
|
|
TextLen = (UINT16) SendMsg(IDE_VIEWER_OUTPUT, WM_GETTEXTLENGTH, 0, 0);
|
|
Search.pText = (char *)malloc(TextLen + 10);
|
|
|
|
// Retrieve the edit box text (used for searching)
|
|
SendMsg(IDE_VIEWER_OUTPUT, WM_GETTEXT, (WPARAM)(TextLen + 1),
|
|
(LPARAM)(LPCSTR) Search.pText);
|
|
|
|
// Reset the "last search" pointer
|
|
Search.pLastSearch = Search.pText;
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// run_sample_code(void);
|
|
//
|
|
// Input: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Description:
|
|
// Fill in the brief description for the currently selected
|
|
// code. If no description is available, then the text box
|
|
// will be left blank.
|
|
//===================================================================
|
|
void
|
|
run_sample_code (void)
|
|
{
|
|
INT16 Offset;
|
|
|
|
Offset = get_array_offset();
|
|
if ((Offset != -1) && InputData[Offset].pFunc)
|
|
{
|
|
// Set the header
|
|
SendMsg(IDT_OUTPUT_HEADER, WM_SETTEXT, (WPARAM) 0,
|
|
(LPARAM)(LPCSTR) "Sample Code Output");
|
|
|
|
// Run the sample code
|
|
(*InputData[Offset].pFunc)();
|
|
|
|
// Cache the program output (for searching)
|
|
get_search_text();
|
|
}
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// view_sample_code(void);
|
|
//
|
|
// Input: None.
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Description:
|
|
// Put a copy of the sample code into the edit box.
|
|
//===================================================================
|
|
void
|
|
view_sample_code (void)
|
|
{
|
|
pCHAR pBuf;
|
|
HFILE hFile;
|
|
INT16 Offset;
|
|
UINT16 BytesRead;
|
|
|
|
Offset = get_array_offset();
|
|
if ((Offset != -1) && InputData[Offset].pSourceFile)
|
|
{
|
|
// Open the file in question
|
|
hFile = _lopen(InputData[Offset].pSourceFile, OF_READ);
|
|
if (hFile >= 0)
|
|
{
|
|
SendMsg(IDT_OUTPUT_HEADER, WM_SETTEXT, 0,
|
|
(LPARAM)(LPCSTR) "Sample Code Viewer");
|
|
|
|
// Allocate a 64k buffer
|
|
pBuf = (pCHAR) malloc(64000U);
|
|
|
|
// Read in a chunk of file data and get rid of EOF
|
|
BytesRead = _lread(hFile, pBuf, (UINT) 64000U);
|
|
pBuf[BytesRead] = '\0';
|
|
|
|
// Echo the code to the screen
|
|
SendMsg(IDE_VIEWER_OUTPUT, WM_SETTEXT, 0,
|
|
(LPARAM)(LPCSTR) pBuf);
|
|
|
|
// Trap for any possible errors
|
|
if (BytesRead == 64000U)
|
|
{
|
|
WinMsg("Sample code has been trimmed (too large to fit).",
|
|
MSG_INFO, BTN_OK);
|
|
}
|
|
|
|
// Clean up and return
|
|
free(pBuf);
|
|
_lclose(hFile);
|
|
|
|
// Cache the program output (for searching)
|
|
get_search_text();
|
|
}
|
|
else
|
|
{
|
|
WinMsg("Could not open sample code file.", MSG_STOP, BTN_OK);
|
|
}
|
|
}
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// resize_resources(MainWidth, MainHeight);
|
|
//
|
|
// Input: MainWidth - Height of the main window
|
|
// MainHeight - Width of the main window
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Description:
|
|
// The size of the main window has changed. Go ahead and
|
|
// resize the child windows.
|
|
//===================================================================
|
|
void
|
|
resize_resources (int MainWidth, int MainHeight)
|
|
{
|
|
BOOL ResizeMe;
|
|
INT16 i, Offset, X1, Y1, X2, Y2;
|
|
|
|
// Scan through the resources and resize specific ones. Note that the
|
|
// starting X and Y positions will never change. Resizing will only
|
|
// occur on the right and bottom borders.
|
|
for (i = 0; i < NUM_RESOURCES; i++)
|
|
{
|
|
ResizeMe = FALSE;
|
|
switch (MainRes[i].Id)
|
|
{
|
|
case IDT_HEADER_1:
|
|
case IDT_FILE_NAME:
|
|
case IDE_DESCRIBE_CODE:
|
|
Offset = 9;
|
|
ResizeMe = TRUE;
|
|
X1 = (MainRes[i].X1 * DialogWidthUnits);
|
|
X2 = ((MainWidth - (Offset * DialogWidthUnits)) - X1);
|
|
Y1 = (MainRes[i].Y1 * DialogHeightUnits);
|
|
Y2 = (MainRes[i].Y2 * DialogHeightUnits);
|
|
break;
|
|
case IDS_SHADE:
|
|
case IDT_HEADER_2:
|
|
case IDT_OUTPUT_HEADER:
|
|
Offset = 3;
|
|
ResizeMe = TRUE;
|
|
X1 = (MainRes[i].X1 * DialogWidthUnits);
|
|
X2 = ((MainWidth - (Offset * DialogWidthUnits)) - X1);
|
|
Y1 = (MainRes[i].Y1 * DialogHeightUnits);
|
|
Y2 = (MainRes[i].Y2 * DialogHeightUnits);
|
|
break;
|
|
case IDE_VIEWER_OUTPUT:
|
|
Offset = 6;
|
|
ResizeMe = TRUE;
|
|
X1 = (MainRes[i].X1 * DialogWidthUnits);
|
|
X2 = (MainWidth - (Offset * DialogWidthUnits));
|
|
Y1 = (MainRes[i].Y1 * DialogHeightUnits);
|
|
Y2 = ((MainHeight - (4 * DialogHeightUnits)) - Y1);
|
|
break;
|
|
}
|
|
|
|
if (ResizeMe)
|
|
{
|
|
MoveWindow(GetDlgItem(hMainWnd, MainRes[i].Id),
|
|
X1, Y1, X2, Y2, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// search_text(hWnd, bSearchFirst);
|
|
//
|
|
// Input: hWnd - A dialog handle
|
|
// bSearchFirst - TRUE means "define the search" before you
|
|
// start the search
|
|
//
|
|
// Return: None.
|
|
//
|
|
// Description:
|
|
// Search the edit box for the first instance of a specific
|
|
// string.
|
|
//===================================================================
|
|
void
|
|
search_text (HWND hWnd, BOOL bSearchFirst)
|
|
{
|
|
FARPROC lpTempProc;
|
|
LONG iStart, iEnd;
|
|
|
|
// Make sure the search text is available
|
|
if (Search.pText == NULL)
|
|
{
|
|
WinMsg("You must VIEW or RUN sample code before you can search.",
|
|
MSG_INFO, BTN_OK);
|
|
return;
|
|
}
|
|
|
|
// Define the search criteria
|
|
if (bSearchFirst || (Search.pSearchStr == NULL))
|
|
{
|
|
// Define the search criteria
|
|
lpTempProc = MakeProcInstance((FARPROC) SearchDlgProc, hInst);
|
|
DialogBox(hInst, "SearchDlg", hWnd, (DLGPROC) lpTempProc);
|
|
FreeProcInstance((FARPROC) lpTempProc);
|
|
|
|
// Return if the "Cancel" button was pressed
|
|
if (Search.bCancelPressed)
|
|
return;
|
|
}
|
|
|
|
// Only search if the search string is defined
|
|
if (Search.pSearchStr)
|
|
{
|
|
if (!Search.pLastSearch)
|
|
{
|
|
WinMsg("Search string not found!", MSG_INFO, BTN_OK);
|
|
return;
|
|
}
|
|
|
|
if (!bSearchFirst)
|
|
Search.pLastSearch += strlen(Search.pSearchStr);
|
|
Search.pLastSearch = StrStr(Search.pLastSearch, Search.pSearchStr);
|
|
|
|
if (!Search.pLastSearch)
|
|
{
|
|
WinMsg("Search string not found!", MSG_INFO, BTN_OK);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
iStart = (Search.pLastSearch - Search.pText);
|
|
iEnd = (iStart + strlen(Search.pSearchStr));
|
|
SendDlgItemMessage(hWnd, IDE_VIEWER_OUTPUT, EM_SETSEL, 0,
|
|
MAKELPARAM((UINT16) iStart, (UINT16) iEnd));
|
|
}
|
|
}
|
|
else
|
|
WinMsg("Search string not defined!", MSG_INFO, BTN_OK);
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// StrStr(pSourceString, pSearchString);
|
|
//
|
|
// Input: pSourceString - A pointer to the source string
|
|
// pSearchString - A pointer to the search string
|
|
//
|
|
// Return: A pointer to the string found in the source string.
|
|
//
|
|
// Description:
|
|
// Find the search string in the source string.
|
|
//===================================================================
|
|
char *
|
|
StrStr (pCHAR pSourceString, pCHAR pSearchString)
|
|
{
|
|
pCHAR ptrSource = NULL, ptrSearch = NULL;
|
|
|
|
// bCaseSens is TRUE
|
|
if (Search.bCaseSens)
|
|
{
|
|
return strstr(pSourceString, pSearchString);
|
|
}
|
|
|
|
// bCaseSens is not TRUE
|
|
for( ; *pSourceString ; pSourceString++ )
|
|
{
|
|
if (CaseInsensitiveCompare(*pSourceString, *pSearchString))
|
|
{
|
|
ptrSource = pSourceString + 1;
|
|
ptrSearch = pSearchString + 1;
|
|
for ( ; *ptrSearch ; ptrSearch ++, ptrSource++ )
|
|
{
|
|
if (!CaseInsensitiveCompare(*ptrSource, *ptrSearch))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (!(*ptrSearch))
|
|
{
|
|
return pSourceString;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// CaseInsensitiveCompare(Char1, Char2);
|
|
//
|
|
// Input: Char1 - A character
|
|
// Char2 - A character
|
|
//
|
|
// Return: Boolean TRUE/FALSE.
|
|
//
|
|
// Description:
|
|
// Compare these two characters case insensitively.
|
|
//===================================================================
|
|
BOOL
|
|
CaseInsensitiveCompare (CHAR Char1, CHAR Char2)
|
|
{
|
|
if (isalpha(Char1))
|
|
{
|
|
if (isupper(Char1))
|
|
{
|
|
return(((Char1 == Char2) || (Char1 == Char2 - 32)) ? TRUE : FALSE);
|
|
}
|
|
else
|
|
{
|
|
return(((Char1 == Char2) || (Char1 == Char2 + 32)) ? TRUE : FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ((Char1 == Char2) ? TRUE : FALSE);
|
|
}
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// setup_tab_edit_box(hDlg, EditId);
|
|
//
|
|
// Input: hWnd - A dialog handle
|
|
// EditId - The edit box that is to be customized
|
|
//
|
|
// Return: The newly assigned procedure pointer
|
|
//
|
|
// Description:
|
|
// Set up an edit box so that tab keys change focus to
|
|
// another resource.
|
|
//===================================================================
|
|
FARPROC
|
|
setup_tab_edit_box (HWND hWnd, int EditId)
|
|
{
|
|
HWND hTempWnd; // Handle of the Edit control
|
|
FARPROC EditProc; // The TabEditBox Windows procedure
|
|
|
|
// If the standard edit box function has not yet been saved, save it.
|
|
hTempWnd = GetDlgItem(hWnd, EditId);
|
|
if (fpStdEditBoxProc == NULL)
|
|
fpStdEditBoxProc = (WNDPROC) GetWindowLong(hTempWnd, GWL_WNDPROC);
|
|
|
|
// Force the edit box processing to the sub-class function
|
|
EditProc = (FARPROC) MakeProcInstance((FARPROC) TabEditBox, hInst);
|
|
SetWindowLong(hTempWnd, GWL_WNDPROC, (LONG) EditProc);
|
|
|
|
// Return the variable created by MakeProcInstance()
|
|
return EditProc;
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// TabEditBox(hDlg, msg, wParam, lParam);
|
|
//
|
|
// Input: hWnd - The Window handle
|
|
// msg - Message to process
|
|
// wParam - Word Parameter
|
|
// lParam - Long Parameter
|
|
//
|
|
// Return: Long - Value returned from Message - depends on
|
|
// message.
|
|
//
|
|
// Description:
|
|
// This routine will change focus away from the edit box when
|
|
// a TAB, or BACKTAB, is hit.
|
|
//===================================================================
|
|
long FAR PASCAL _export
|
|
TabEditBox (HWND hWnd, UINT msg, WORD wParam, LONG lParam)
|
|
{
|
|
int Id; // ID of currently selected control
|
|
long ret = FALSE; // Return value
|
|
|
|
// Check for special cases
|
|
switch (msg)
|
|
{
|
|
case WM_GETDLGCODE:
|
|
return DLGC_WANTMESSAGE;
|
|
|
|
case WM_CHAR:
|
|
if (wParam == VK_TAB)
|
|
{
|
|
ret = TRUE;
|
|
Id = GetDlgCtrlID(hWnd);
|
|
if (GetKeyState(VK_SHIFT) < 0)
|
|
{
|
|
if (Id == IDE_DESCRIBE_CODE)
|
|
Id = IDL_SELECT_CODE;
|
|
else
|
|
Id = IDE_DESCRIBE_CODE;
|
|
}
|
|
else // Standard TAB
|
|
{
|
|
if (Id == IDE_DESCRIBE_CODE)
|
|
Id = IDE_VIEWER_OUTPUT;
|
|
else
|
|
Id = IDB_VIEW_CODE;
|
|
}
|
|
|
|
// Change resource focus
|
|
SetFocus(GetDlgItem(hMainWnd, Id));
|
|
}
|
|
|
|
// Don't want to exit the app on escape.
|
|
if (wParam == VK_ESCAPE)
|
|
{
|
|
MessageBeep(1);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Send unprocessed messages to standard edit box processor
|
|
if (ret == FALSE)
|
|
ret = CallWindowProc(fpStdEditBoxProc, hWnd, msg, wParam, lParam);
|
|
return ret;
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// SendMsg(Id, Msg, wParam, lParam);
|
|
//
|
|
// Input: Id - Child ID to send the message to
|
|
// Msg - Windows message (i.e. EM_SETSEL)
|
|
// wParam - Message Parameter
|
|
// lParam - Message parameter
|
|
//
|
|
// Return: None
|
|
//
|
|
// Description:
|
|
// Send a message to a child of the main window.
|
|
//===================================================================
|
|
LRESULT
|
|
SendMsg (int Id, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
return SendMessage(GetDlgItem(hMainWnd, Id), Msg, wParam, lParam);
|
|
}
|
|
|
|
//===================================================================
|
|
// Name: CreateResources(hInstance, hWnd);
|
|
//
|
|
// Input: hInstance - Application instance handle
|
|
// hWnd - Handle for the main window
|
|
//
|
|
// Return: None
|
|
//
|
|
// Description:
|
|
// Create child resources on main window.
|
|
//===================================================================
|
|
static void
|
|
CreateResources (HINSTANCE hInstance, HWND hWnd)
|
|
{
|
|
HWND hResWnd; // Window Handle to the resource
|
|
char TypeRes[20]; // Type of the resource
|
|
int i; // Loop counter - iterate throught the
|
|
// number of resources
|
|
int X1; // Horizontal position of top left
|
|
int X2; // Horizontal position of bottom right
|
|
int Y1; // Vertical position of top left
|
|
int Y2; // Vertical position of bottom right
|
|
HINSTANCE hTempPtr; // Pointer used in creating an edit control
|
|
// which dynamically allocates memory
|
|
HGLOBAL TextAlloc; // Global handle to memory - used in
|
|
// creating a 64K edit control
|
|
void* TextPtr; // Pointer used in allocating space for the
|
|
// large (64K) edit control
|
|
UINT16 uTextBufferSize;// The number of bytes in the 64K edit
|
|
// control.
|
|
|
|
hTempPtr = hInstance; // Use the application instance in all cases
|
|
// except when creating an edit control to not
|
|
// use the heap.
|
|
// Create all resources
|
|
for (i = 0; i < NUM_RESOURCES; i++)
|
|
{
|
|
switch (MainRes[i].Res)
|
|
{
|
|
case resBUTTON:
|
|
strcpy(TypeRes, "BUTTON");
|
|
break;
|
|
case resCOMBOBOX:
|
|
strcpy(TypeRes, "COMBOBOX");
|
|
break;
|
|
case resEDIT:
|
|
strcpy(TypeRes, "EDIT");
|
|
break;
|
|
case resEDIT64:
|
|
strcpy(TypeRes, "EDIT");
|
|
|
|
// Allow the edit control to contain up to 64000 bytes of
|
|
// information.
|
|
uTextBufferSize = 64000U; // Set the size of the buffer
|
|
|
|
// Allocate the memory for the edit control.
|
|
// Edit control takes ownership of this memory, so
|
|
// this memory is not released explicitly by this
|
|
// application.
|
|
// WARNING! A GPF will occur if the application is
|
|
// terminated after the memory is freed.
|
|
TextAlloc = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE,
|
|
uTextBufferSize);
|
|
TextPtr = GlobalLock(TextAlloc);
|
|
LocalInit(HIWORD((LONG) TextPtr), 0,
|
|
(WORD) GlobalSize(TextAlloc) - 16);
|
|
UnlockSegment(HIWORD((LONG) TextPtr));
|
|
|
|
hTempPtr = (HINSTANCE) HIWORD(TextPtr); // Set the hInstance
|
|
// for the edit control.
|
|
break;
|
|
case resGROUP:
|
|
strcpy(TypeRes, "BUTTON");
|
|
break;
|
|
case resLISTBOX:
|
|
strcpy(TypeRes, "LISTBOX");
|
|
break;
|
|
case resSTATIC:
|
|
strcpy(TypeRes, "STATIC");
|
|
break;
|
|
case resSHADE:
|
|
strcpy(TypeRes, "BorShade");
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
// Adjust resource size with standard dialog units
|
|
X1 = (MainRes[i].X1 * DialogWidthUnits);
|
|
X2 = (MainRes[i].X2 * DialogWidthUnits);
|
|
Y1 = (MainRes[i].Y1 * DialogHeightUnits);
|
|
Y2 = (MainRes[i].Y2 * DialogHeightUnits);
|
|
|
|
// Create the child window
|
|
hResWnd = CreateWindow(TypeRes, MainRes[i].Text, MainRes[i].Attrib,
|
|
X1, Y1, X2, Y2, hWnd, (HMENU)MainRes[i].Id,
|
|
hTempPtr, NULL);
|
|
if (hResWnd)
|
|
{
|
|
ShowWindow(hResWnd, SW_SHOW);
|
|
|
|
// Sub-class the edit boxes
|
|
if (MainRes[i].Id == IDE_VIEWER_OUTPUT)
|
|
{
|
|
hViewEdit = hResWnd;
|
|
fnTabEditBox[0] =
|
|
(WNDPROC)setup_tab_edit_box(hWnd,
|
|
IDE_VIEWER_OUTPUT);
|
|
}
|
|
else if (MainRes[i].Id == IDE_DESCRIBE_CODE)
|
|
{
|
|
hDescEdit = hResWnd;
|
|
fnTabEditBox[1] =
|
|
(WNDPROC)setup_tab_edit_box(hWnd,
|
|
IDE_DESCRIBE_CODE);
|
|
}
|
|
}
|
|
else
|
|
i = NUM_RESOURCES; // End the loop...
|
|
}
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// InitMainWnd(hWnd);
|
|
//
|
|
// Input: hWnd - Handle for main window
|
|
//
|
|
// Return: None
|
|
//
|
|
// Description:
|
|
// Init the main window. Fill list boxes, set the focus of
|
|
// the default window.
|
|
//===================================================================
|
|
static void
|
|
InitMainWnd (HWND hWnd)
|
|
{
|
|
INT16 i; // Loop counter - iterate through the number of
|
|
// resources
|
|
HFONT hFont; // Handle to the font
|
|
|
|
// Fill the list box with the code available
|
|
for (i = 0; i < MAX_VIEW_CODE_MODULES; i++)
|
|
{
|
|
if (InputData[i].pCodeName[0])
|
|
{
|
|
SendDlgItemMessage(hWnd, IDL_SELECT_CODE, LB_ADDSTRING, 0,
|
|
(LPARAM)(LPCSTR) InputData[i].pCodeName);
|
|
}
|
|
else
|
|
i = MAX_VIEW_CODE_MODULES; // No more code mods;
|
|
// end the loop...
|
|
}
|
|
|
|
// Select the first item of the list box
|
|
SendDlgItemMessage(hWnd, IDL_SELECT_CODE, LB_SETCURSEL, 0, 0);
|
|
|
|
// Use a non-proportional font in the main edit box
|
|
hFont = (HFONT) GetStockObject(ANSI_FIXED_FONT);
|
|
SendDlgItemMessage(hWnd, IDE_VIEWER_OUTPUT, WM_SETFONT,
|
|
(WPARAM) hFont, FALSE);
|
|
|
|
// Set the focus to the dialog to the "select code" list box
|
|
SetFocus(GetDlgItem(hWnd, IDL_SELECT_CODE));
|
|
|
|
// Set the description for the first item
|
|
fill_in_description();
|
|
}
|
|
|
|
//=================================================================
|
|
// Function:
|
|
// InitApp(nCmdShow, hInst);
|
|
//
|
|
// Input: nCmdShow - Whether to show the window after it is created
|
|
// hInst - The current instance for the application
|
|
//
|
|
// Return: TRUE - Init worked
|
|
// FALSE - Init failed
|
|
//
|
|
// Description:
|
|
// Create the application window (in this case a dialog).
|
|
//================================================================
|
|
static BOOL
|
|
InitApp (int nCmdShow, HINSTANCE hInstance)
|
|
{
|
|
WNDCLASS wc; // Window class
|
|
HWND hWnd; // Handle to the main window
|
|
BOOL ret = TRUE; // Return value
|
|
unsigned uCount; // Number of available file handles
|
|
char szMessage[DBIMAXMSGLEN * 2 + 1]; // Allocate enough space for
|
|
// the message.
|
|
// The directory relative to the SNIPIT directory which contains the
|
|
// tables.
|
|
CHAR szRelativeTblDirectory[DBIMAXPATHLEN+1];
|
|
|
|
// Init the application and create the needed windows
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
wc.lpfnWndProc = MainWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = hInstance;
|
|
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(1100));
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
|
|
wc.lpszMenuName = "MainMenu";
|
|
wc.lpszClassName = "SnipIt";
|
|
|
|
if (! RegisterClass(&wc))
|
|
{
|
|
MessageBox(NULL, "RegisterClass failed!", "System Error",
|
|
MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
// Get the base horizontal and vertical dialog units
|
|
DialogWidthUnits = (LOWORD(GetDialogBaseUnits()) / 4);
|
|
DialogHeightUnits = (HIWORD(GetDialogBaseUnits()) / 8);
|
|
|
|
// Create windows used for I/O
|
|
GetWindowRect(GetDesktopWindow(), &DeskRect);
|
|
MinWidth = (BASE_MIN_WIDTH * DialogWidthUnits);
|
|
MinHeight = (BASE_MIN_HEIGHT * DialogHeightUnits);
|
|
hWnd = CreateWindow("SnipIt", "SnipIt Code Viewer",
|
|
WS_OVERLAPPEDWINDOW,
|
|
DeskRect.left, DeskRect.top,
|
|
DeskRect.right, DeskRect.bottom,
|
|
NULL, NULL, hInstance, NULL);
|
|
if (hWnd)
|
|
{
|
|
hMainWnd = hWnd;
|
|
hInst = hInstance;
|
|
GlobBuf = (pCHAR) malloc(1024);
|
|
ShowWindow(hMainWnd, nCmdShow);
|
|
UpdateWindow(hMainWnd);
|
|
InitMainWnd(hMainWnd);
|
|
}
|
|
else
|
|
{
|
|
MessageBox(NULL, "CreateWindow failed!", "System Error",
|
|
MB_OK | MB_ICONHAND);
|
|
ret = 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. 'Set files=40' in"
|
|
" CONFIG.SYS.", "System Error", MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
// Get the directory which contains the tables.
|
|
GetPrivateProfileString("SNIPIT", "TblDir",
|
|
"..\\TABLES",
|
|
(LPSTR)szRelativeTblDirectory,
|
|
sizeof(szRelativeTblDirectory),
|
|
"bde.ini");
|
|
|
|
// Create a fully qualified path for the table directory.
|
|
if (MakeFullPath(szTblDirectory, szRelativeTblDirectory))
|
|
{
|
|
sprintf(szMessage, "Working Directory does not exist: %s",
|
|
szTblDirectory);
|
|
MessageBox(NULL, szMessage, "System Error", MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
// Get the Private directory.
|
|
GetPrivateProfileString("SNIPIT", "PrivateDir",
|
|
".",
|
|
(LPSTR)szRelativeTblDirectory,
|
|
sizeof(szRelativeTblDirectory),
|
|
"bde.ini");
|
|
|
|
// Create a fully qualified path for the private directory.
|
|
if (MakeFullPath(szPrivDirectory, szRelativeTblDirectory))
|
|
{
|
|
sprintf(szMessage, "Private Directory does not exist: %s",
|
|
szPrivDirectory);
|
|
MessageBox(NULL, szMessage, "System Error", MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// MainWndProc(hWnd, msg, wParam, lParam);
|
|
//
|
|
// Input: hWnd - The Window handle
|
|
// msg - Message to handle
|
|
// wParam - Word Parameter
|
|
// lParam - Long Parameter
|
|
//
|
|
// Return: BOOL - Was message handled?
|
|
//
|
|
// Description:
|
|
// This routine will process all messages for
|
|
// the primary application window. Included in this are all
|
|
// menu commands.
|
|
//===================================================================
|
|
long FAR PASCAL _export
|
|
MainWndProc (HWND hWnd, UINT msg, UINT wParam,
|
|
LONG lParam)
|
|
{
|
|
HWND hFocus; // Child window which currently has
|
|
// focus.
|
|
HWND hwnd; // Variable used to iterate through
|
|
// list of child windows
|
|
MINMAXINFO* pMinMax; // Used to determine the minimum and
|
|
// maximum size of the window
|
|
FARPROC lpTempProc; // Temporary windows procedure used
|
|
// for child dialogs and windows
|
|
INT32 ret = FALSE; // Return Value
|
|
HBRUSH hBrush; // Handle to the brush
|
|
|
|
long lMinMax; // Contains both starting and ending
|
|
// selected positions in edit
|
|
// control
|
|
unsigned int iStart; // Starting position of selected text
|
|
unsigned int iEnd; // Ending position of selected text
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_CREATE:
|
|
CreateResources(((LPCREATESTRUCT) lParam)->hInstance, hWnd);
|
|
hwnd = GetWindow(hWnd, GW_CHILD);
|
|
while (hwnd != NULL)
|
|
{
|
|
Ctl3dSubclassCtl(hwnd);
|
|
hwnd = GetWindow(hwnd, GW_HWNDNEXT);
|
|
}
|
|
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:
|
|
SetFocus(GetDlgItem(hWnd, IDL_SELECT_CODE));
|
|
break;
|
|
case WM_GETMINMAXINFO:
|
|
pMinMax = (MINMAXINFO *) lParam;
|
|
pMinMax->ptMinTrackSize.x = MinWidth;
|
|
pMinMax->ptMinTrackSize.y = MinHeight;
|
|
ret = DefWindowProc(hWnd, msg, wParam, lParam);
|
|
break;
|
|
case WM_SIZE:
|
|
resize_resources(LOWORD(lParam), HIWORD(lParam));
|
|
break;
|
|
case WM_COMMAND:
|
|
// Process the menu commands
|
|
hFocus = GetFocus();
|
|
switch(wParam)
|
|
{
|
|
case IDL_SELECT_CODE:
|
|
if (HIWORD(lParam) == LBN_SELCHANGE)
|
|
fill_in_description();
|
|
else if (HIWORD(lParam) == LBN_DBLCLK)
|
|
view_sample_code();
|
|
break;
|
|
case IDB_RUN_CODE:
|
|
case IDM_RUN_CODE:
|
|
clear_multi_line_edit_box(hWnd, IDE_VIEWER_OUTPUT);
|
|
run_sample_code();
|
|
break;
|
|
case IDB_VIEW_CODE:
|
|
case IDM_VIEW_CODE:
|
|
clear_multi_line_edit_box(hWnd, IDE_VIEWER_OUTPUT);
|
|
view_sample_code();
|
|
break;
|
|
case IDB_COPY:
|
|
case IDM_COPY:
|
|
// Determine which characters are selected
|
|
lMinMax = SendDlgItemMessage(hWnd, IDE_VIEWER_OUTPUT,
|
|
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, IDE_VIEWER_OUTPUT,
|
|
EM_SETSEL, 0, 0xfffeL);
|
|
}
|
|
|
|
SendDlgItemMessage(hWnd, IDE_VIEWER_OUTPUT, WM_COPY,
|
|
0, 0L);
|
|
break;
|
|
case IDM_SEARCH_FIRST:
|
|
case IDB_SEARCH_TEXT:
|
|
hFocus = GetDlgItem(hWnd, IDE_VIEWER_OUTPUT);
|
|
search_text(hWnd, TRUE);
|
|
break;
|
|
case IDM_SEARCH_NEXT:
|
|
hFocus = GetDlgItem(hWnd, IDE_VIEWER_OUTPUT);
|
|
search_text(hWnd, FALSE);
|
|
break;
|
|
case IDM_ABOUT:
|
|
lpTempProc =
|
|
MakeProcInstance((FARPROC) AboutDlgProc, hInst);
|
|
DialogBox(hInst, "AboutDlg", hMainWnd,
|
|
(DLGPROC)lpTempProc);
|
|
FreeProcInstance((FARPROC) lpTempProc);
|
|
break;
|
|
case IDM_EXIT:
|
|
PostQuitMessage(0);
|
|
break;
|
|
default:
|
|
ret = DefWindowProc(hWnd, msg, wParam, lParam);
|
|
break;
|
|
}
|
|
SetFocus(hFocus);
|
|
break;
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
break;
|
|
default:
|
|
ret = DefWindowProc(hWnd, msg, wParam, lParam);
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//===============================================================
|
|
// Function:
|
|
// About(hDlg, msg, wParam, lParam);
|
|
//
|
|
// Input: hDlg - The dialog handle
|
|
// msg - Message to handle
|
|
// wParam - Word Parameter
|
|
// lParam - Long Parameter
|
|
//
|
|
// Return: BOOL - Was message handled?
|
|
//
|
|
// Description: This routine will process all I/O for the
|
|
// ABOUT dialog.
|
|
//================================================================
|
|
BOOL FAR PASCAL _export
|
|
AboutDlgProc (HWND hDlg, WORD msg, WORD wParam,
|
|
LONG lParam)
|
|
{
|
|
int ret = FALSE;
|
|
|
|
lParam = lParam; // Avoid warning - Parameter not used
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
ret = TRUE;
|
|
break;
|
|
case WM_COMMAND:
|
|
switch (wParam)
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, TRUE);
|
|
ret = TRUE;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//===================================================================
|
|
// Fuction:
|
|
// reset_connect_dialog(hWnd, bResetAll);
|
|
//
|
|
// Input: hWnd - The dialog handle
|
|
// bResetAll - TRUE means to repaint the entire dialog
|
|
// FALSE means to repaint alias information
|
|
//
|
|
// Return: None
|
|
//
|
|
// Description: Reset the "connect to the database" dialog based
|
|
// on the current driver selected.
|
|
//===================================================================
|
|
void
|
|
reset_connect_dialog (HWND hWnd, BOOL bResetAll)
|
|
{
|
|
hDBICur hList;
|
|
DBDesc DbData;
|
|
pFLDDesc pCfgInfo;
|
|
WORD ListIndex;
|
|
pCHAR pCfgRecBuf;
|
|
pCHAR Driver;
|
|
pCHAR Alias;
|
|
pCHAR CfgPath;
|
|
|
|
// Allocate resources
|
|
Alias = (pCHAR) malloc((DBIMAXSCFLDLEN + 1) * sizeof(CHAR));
|
|
Driver = (pCHAR) malloc((DBIMAXSCFLDLEN + 1) * sizeof(CHAR));
|
|
CfgPath = (pCHAR) malloc((DBIMAXPATHLEN + 1) * sizeof(CHAR));
|
|
pCfgRecBuf = (pCHAR) malloc((DBIMAXSCRECSIZE + 1) * sizeof(CHAR));
|
|
pCfgInfo = (pFLDDesc) malloc(sizeof(FLDDesc) * DBIMAXSCFIELDS);
|
|
|
|
// Get the driver currently selected
|
|
ListIndex = (WORD) SendDlgItemMessage(hWnd, IDL_DRIVERS, LB_GETCURSEL,
|
|
0,0);
|
|
SendDlgItemMessage(hWnd, IDL_DRIVERS, LB_GETTEXT, (WPARAM) ListIndex,
|
|
(LPARAM) Driver);
|
|
|
|
// Reset the driver to "STANDARD" if Paradox or dBASE
|
|
if ((strncmp(Driver, szDBASE, DBIMAXSCFLDLEN) == GOOD_STR_COMPARE) ||
|
|
(strncmp(Driver, szPARADOX, DBIMAXSCFLDLEN) == GOOD_STR_COMPARE))
|
|
{
|
|
strcpy(Driver, "STANDARD");
|
|
}
|
|
|
|
// Leave the alias list alone if not resetting entire listbox
|
|
if (bResetAll)
|
|
{
|
|
// Reset info displayed (based on the driver type)
|
|
if (strncmp(Driver, "STANDARD", DBIMAXSCFLDLEN) == GOOD_STR_COMPARE)
|
|
{
|
|
// Remove the user name and password if alias is STANDARD
|
|
ShowWindow(GetDlgItem(hWnd, IDE_PASSWORD), SW_HIDE);
|
|
ShowWindow(GetDlgItem(hWnd, IDT_PASSWORD_HDR), SW_HIDE);
|
|
}
|
|
else
|
|
{
|
|
// Make sure all is displayed
|
|
ShowWindow(GetDlgItem(hWnd, IDE_PASSWORD), SW_SHOW);
|
|
ShowWindow(GetDlgItem(hWnd, IDT_PASSWORD_HDR), SW_SHOW);
|
|
}
|
|
|
|
// Clear and fill the alias listbox
|
|
SendDlgItemMessage(hWnd, IDL_ALIASES, LB_RESETCONTENT, 0, 0);
|
|
if (DbiOpenDatabaseList(&hList) == DBIERR_NONE)
|
|
{
|
|
// Scan the list of aliases for matching drivers
|
|
while (DbiGetNextRecord(hList, dbiNOLOCK, (pBYTE) &DbData,
|
|
NULL) == DBIERR_NONE)
|
|
{
|
|
if (strncmp(DbData.szDbType, Driver, DBIMAXSCFLDLEN) == GOOD_STR_COMPARE)
|
|
{
|
|
SendDlgItemMessage(hWnd, IDL_ALIASES, LB_INSERTSTRING,
|
|
0, (LPARAM) DbData.szName);
|
|
}
|
|
}
|
|
DbiCloseCursor(&hList);
|
|
SendDlgItemMessage(hWnd, IDL_ALIASES, LB_SETCURSEL, 0, 0);
|
|
}
|
|
}
|
|
|
|
// Free resources used
|
|
free(Alias);
|
|
free(Driver);
|
|
free(CfgPath);
|
|
free(pCfgRecBuf);
|
|
free((pCHAR) pCfgInfo);
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// ConnectDlgProc(hDlg, msg, wParam, lParam);
|
|
//
|
|
// Input: hDlg - The dialog handle
|
|
// msg - Message to handle
|
|
// wParam - Word Parameter
|
|
// lParam - Long Parameter
|
|
//
|
|
// Return: BOOL - Was message handled?
|
|
//
|
|
// Description: This routine will make a connection
|
|
// to a database (setting a global handle).
|
|
//===================================================================
|
|
BOOL FAR PASCAL _export
|
|
ConnectDlgProc (HWND hDlg, WORD msg, WORD wParam,
|
|
LONG lParam)
|
|
{
|
|
DBIResult rslt;
|
|
hDBICur hList;
|
|
WORD ListIndex;
|
|
int ret = FALSE;
|
|
pCHAR Driver;
|
|
pCHAR Alias;
|
|
pCHAR Password;
|
|
pCHAR Message;
|
|
DBIMSG dbi_status;
|
|
DBIErrInfo ErrInfo;
|
|
|
|
// Process dialog
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
// This code assumes that IDAPI is already initialized.
|
|
// Fill the listbox with the drivers available
|
|
ret = TRUE;
|
|
Driver = (pCHAR) malloc(DBIMAXSCFLDLEN + 1);
|
|
if (Driver)
|
|
{
|
|
if (DbiOpenDriverList(&hList) == DBIERR_NONE)
|
|
{
|
|
while (DbiGetNextRecord(hList, dbiNOLOCK, (pBYTE)Driver,
|
|
NULL) == DBIERR_NONE)
|
|
{
|
|
// Make certain driver name is terminated -
|
|
// max driver length is DBIMAXNAMELEN (32)
|
|
Driver[DBIMAXNAMELEN] = 0;
|
|
SendDlgItemMessage(hDlg, IDL_DRIVERS,
|
|
LB_INSERTSTRING, 0,
|
|
(LPARAM) Driver);
|
|
}
|
|
DbiCloseCursor(&hList);
|
|
}
|
|
free(Driver);
|
|
}
|
|
|
|
// Select the first items of the list boxes
|
|
SendDlgItemMessage(hDlg, IDL_DRIVERS, LB_SETCURSEL, 0, 0);
|
|
|
|
// Fill the listbox with the aliases
|
|
reset_connect_dialog(hDlg, TRUE);
|
|
break;
|
|
case WM_COMMAND:
|
|
switch (wParam)
|
|
{
|
|
case IDL_DRIVERS:
|
|
if (HIWORD(lParam) == LBN_SELCHANGE)
|
|
reset_connect_dialog(hDlg, TRUE);
|
|
break;
|
|
case IDL_ALIASES:
|
|
if (HIWORD(lParam) == LBN_SELCHANGE)
|
|
reset_connect_dialog(hDlg, FALSE);
|
|
break;
|
|
case IDOK:
|
|
// Init the strings
|
|
Alias = (pCHAR) malloc(DBIMAXSCFLDLEN * sizeof(BYTE));
|
|
Driver = (pCHAR) malloc(DBIMAXSCFLDLEN * sizeof(BYTE));
|
|
Password = (pCHAR) malloc(DBIMAXSCFLDLEN * sizeof(BYTE));
|
|
Alias[0] = '\0';
|
|
Driver[0] = '\0';
|
|
Password[0] = '\0';
|
|
|
|
// Get the selected driver
|
|
ListIndex =
|
|
(WORD) SendDlgItemMessage(hDlg, IDL_DRIVERS,
|
|
LB_GETCURSEL, 0, 0);
|
|
SendDlgItemMessage(hDlg, IDL_DRIVERS, LB_GETTEXT,
|
|
(WPARAM) ListIndex, (LPARAM) Driver);
|
|
|
|
if ((strncmp(Driver, szDBASE, DBIMAXSCFLDLEN) == GOOD_STR_COMPARE) ||
|
|
(strncmp(Driver, szPARADOX, DBIMAXSCFLDLEN) == GOOD_STR_COMPARE))
|
|
{
|
|
Driver[0] = '\0';
|
|
ListIndex =
|
|
(WORD) SendDlgItemMessage(hDlg, IDL_ALIASES,
|
|
LB_GETCURSEL, 0, 0);
|
|
SendDlgItemMessage(hDlg, IDL_ALIASES, LB_GETTEXT,
|
|
(WPARAM) ListIndex,
|
|
(LPARAM)Alias);
|
|
}
|
|
else // SQL database...
|
|
{
|
|
// SQL database needs the alias & password
|
|
ListIndex =
|
|
(WORD) SendDlgItemMessage(hDlg, IDL_ALIASES,
|
|
LB_GETCURSEL, 0, 0);
|
|
SendDlgItemMessage(hDlg, IDL_ALIASES, LB_GETTEXT,
|
|
(WPARAM) ListIndex,
|
|
(LPARAM)Alias);
|
|
SendDlgItemMessage(hDlg, IDE_PASSWORD, WM_GETTEXT,
|
|
80, (LPARAM) Password);
|
|
}
|
|
|
|
// Try to open the database
|
|
SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
SnipItDb = NULL;
|
|
rslt = DbiOpenDatabase(Alias, Driver, dbiREADWRITE,
|
|
dbiOPENSHARED, Password, 0,
|
|
NULL, NULL, &SnipItDb);
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
if (rslt == DBIERR_NONE)
|
|
{
|
|
ret = TRUE;
|
|
EndDialog(hDlg, TRUE);
|
|
}
|
|
else
|
|
{
|
|
// Make certain to allocate enough space for all the
|
|
// Error contexts
|
|
Message = (pCHAR)malloc(8 * DBIMAXMSGLEN *
|
|
sizeof(BYTE));
|
|
if (!Message)
|
|
{
|
|
MessageBox(hDlg, "Out of memory!", "Initialization"
|
|
" Error", MB_OK | MB_ICONSTOP);
|
|
}
|
|
else
|
|
{
|
|
// Get as much error information as possible
|
|
DbiGetErrorInfo(TRUE, &ErrInfo);
|
|
|
|
// Make certain information is returned on the
|
|
// correct error
|
|
if (ErrInfo.iError == rslt)
|
|
{
|
|
wsprintf(Message, "Cat:Code = [%xh:%xh]\r\n%s",
|
|
ErrCat(ErrInfo.iError),
|
|
ErrCode(ErrInfo.iError),
|
|
ErrInfo.szErrCode);
|
|
|
|
if (strncmp(ErrInfo.szContext1, "", DBIMAXMSGLEN))
|
|
{
|
|
strcat(Message, ErrInfo.szContext1);
|
|
}
|
|
if (strncmp(ErrInfo.szContext2, "", DBIMAXMSGLEN))
|
|
{
|
|
strcat(Message, ErrInfo.szContext2);
|
|
}
|
|
if (strncmp(ErrInfo.szContext3, "", DBIMAXMSGLEN))
|
|
{
|
|
strcat(Message, ErrInfo.szContext3);
|
|
}
|
|
if (strncmp(ErrInfo.szContext4, "", DBIMAXMSGLEN))
|
|
{
|
|
strcat(Message, ErrInfo.szContext4);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbiGetErrorString(rslt, dbi_status);
|
|
wsprintf(Message, "%s\r\nCat:Code = [%xh:%xh]"
|
|
"\r\n\r\n %s", "Failed to connect!",
|
|
ErrCat(rslt), ErrCode(rslt),
|
|
dbi_status);
|
|
}
|
|
MessageBox(hDlg, (LPSTR) Message, "Initialization"
|
|
" Error", MB_OK | MB_ICONSTOP);
|
|
free(Message);
|
|
}
|
|
}
|
|
// Free up resources
|
|
free(Alias);
|
|
free(Driver);
|
|
free(Password);
|
|
break;
|
|
case IDCANCEL:
|
|
ret = TRUE;
|
|
SnipItDb = NULL;
|
|
EndDialog(hDlg, TRUE);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//===================================================================
|
|
// Function:
|
|
// SearchDlgProc(hDlg, msg, wParam, lParam);
|
|
//
|
|
// Input: hDlg - The dialog handle
|
|
// msg - Message to handle
|
|
// wParam - Word Parameter
|
|
// lParam - Long Parameter
|
|
//
|
|
// Return: BOOL - Was message handled?
|
|
//
|
|
// Description: This routine will process all messages for the
|
|
// dialog used to define search criteria.
|
|
//===================================================================
|
|
BOOL FAR PASCAL _export
|
|
SearchDlgProc (HWND hDlg, WORD msg, WORD wParam, LONG lParam)
|
|
{
|
|
INT16 len;
|
|
BOOL ret = FALSE;
|
|
|
|
// Avoid warning: Parameter not used
|
|
lParam = lParam;
|
|
|
|
// Process dialog
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
// Set search value to what it was previously
|
|
if (Search.pSearchStr)
|
|
{
|
|
SendDlgItemMessage(hDlg, IDE_SEARCH_TEXT, WM_SETTEXT, 0,
|
|
(LPARAM)(LPCSTR) Search.pSearchStr);
|
|
}
|
|
else
|
|
{
|
|
SendDlgItemMessage(hDlg, IDE_SEARCH_TEXT, WM_SETTEXT, 0,
|
|
(LPARAM)(LPCSTR) "Dbi");
|
|
}
|
|
|
|
// Set check boxes to previous values
|
|
SendDlgItemMessage(hDlg, IDCHK_CASE_SENS, BM_SETCHECK,
|
|
(WPARAM) Search.bCaseSens, (LPARAM) 0);
|
|
|
|
// Set the "Cancel" flag before returning
|
|
ret = TRUE;
|
|
Search.bCancelPressed = TRUE;
|
|
break;
|
|
case WM_COMMAND:
|
|
switch (wParam)
|
|
{
|
|
case IDOK:
|
|
// Get the search string
|
|
if (Search.pSearchStr)
|
|
{
|
|
free(Search.pSearchStr);
|
|
}
|
|
len = (INT16) SendDlgItemMessage(hDlg, IDE_SEARCH_TEXT,
|
|
WM_GETTEXTLENGTH, 0, 0);
|
|
Search.pSearchStr = (char *)malloc(len + 10);
|
|
SendDlgItemMessage(hDlg, IDE_SEARCH_TEXT, WM_GETTEXT,
|
|
(WPARAM) (len + 1),
|
|
(LPARAM)(LPCSTR) Search.pSearchStr);
|
|
Search.pLastSearch = Search.pText;
|
|
|
|
// Get the search options
|
|
Search.bCaseSens =
|
|
(BOOL) SendDlgItemMessage(hDlg, IDCHK_CASE_SENS,
|
|
BM_GETCHECK, 0, 0);
|
|
|
|
// End the dialog
|
|
ret = TRUE;
|
|
Search.bCancelPressed = FALSE;
|
|
EndDialog(hDlg, TRUE);
|
|
break;
|
|
case IDCANCEL:
|
|
ret = TRUE;
|
|
EndDialog(hDlg, TRUE);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|