home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bde / snipit.pak / SNIPMAIN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  53.2 KB  |  1,540 lines

  1. // BDE - (C) Copyright 1995 by Borland International
  2.  
  3. #include "snipit.h"
  4. #include <ctype.h>
  5. #include <ctl3d.h>
  6. #include <commdlg.h>
  7.  
  8. #define FILEHANDLESNEEDED 40
  9.  
  10. // Prototypes for static functions.
  11. static void CreateResources(HINSTANCE hInstance, HWND hWnd);
  12. static void InitMainWnd(HWND hWnd);
  13. static BOOL InitApp(int nCmdShow, HINSTANCE hInst);
  14. static void get_search_text(void);
  15.  
  16. //===================================================================
  17. //  Function:
  18. //          WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  19. //
  20. //  Input:  hInstance       - The handle that represents the
  21. //                            application's unique instance ID
  22. //          hPrevInstance   - Indicates if this is the first instance
  23. //                            of the application
  24. //          lpCmdLine       - Command line parameters (it is the
  25. //                            application's responsibility to parse them)
  26. //          nCmdShow        - TRUE = Show as non-icon application
  27. //
  28. //  Return: int             - Success?
  29. //  
  30. //  Description:
  31. //          Application entry point. Init the app, main window, and
  32. //          global variables.
  33. //===================================================================
  34. int PASCAL
  35. WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
  36.          int nCmdShow)
  37. {
  38.     MSG     msg;
  39.     HACCEL  hAccel;
  40.  
  41.     // Avoid warning: Parameter not used
  42.     lpCmdLine = lpCmdLine;
  43.  
  44.     // Make this a single instance program
  45.     if (hPrevInstance)
  46.     {
  47.         MessageBox(GetFocus(), "This application is already running!",
  48.                    "Windows Driver", MB_OK);
  49.         return FALSE;
  50.     }
  51.  
  52.     // Register CTL3D
  53.     Ctl3dRegister(hInstance);
  54.     Ctl3dAutoSubclass(hInstance);
  55.     Ctl3dColorChange();
  56.  
  57.     // Start the application
  58.     if (InitApp(nCmdShow, hInstance) == FALSE)
  59.         return FALSE;
  60.  
  61.     // Load the keyboard accelerators
  62.     hAccel = LoadAccelerators(hInstance, "MenuAccel");
  63.  
  64.     // Process all event driven messages...
  65.     while (GetMessage(&msg, NULL, NULL, NULL))
  66.     {
  67.         if ((! TranslateAccelerator(hMainWnd, hAccel, &msg)) &&
  68.             (! IsDialogMessage(hMainWnd, &msg)))
  69.         {
  70.             TranslateMessage(&msg);
  71.             DispatchMessage(&msg);
  72.         }
  73.     }
  74.  
  75.     // Clean up and return
  76.     if (GlobBuf)
  77.     {
  78.         free(GlobBuf);
  79.     }
  80.     if (Search.pText)
  81.     {
  82.         free(Search.pText);
  83.     }
  84.     if (Search.pSearchStr)
  85.     {
  86.         free(Search.pSearchStr);
  87.     }
  88.  
  89.     DestroyWindow(hMainWnd);
  90.  
  91.     // Unregister CTL3D
  92.     Ctl3dUnregister(hInstance);
  93.     return msg.wParam;
  94. }
  95.  
  96. //===================================================================
  97. //  Function:
  98. //          get_array_offset(void);
  99. //
  100. //  Input:  None.
  101. //
  102. //  Return: The array element    -OR-
  103. //          -1 if the element is not found
  104. //
  105. //  Description:
  106. //          Return the array element for InputData[]. The element
  107. //          returned is determined by scanning the array for the
  108. //          currently selected code sample.
  109. //===================================================================
  110. INT16
  111. get_array_offset (void)
  112. {
  113.     INT32   Index;
  114.     INT16   i;
  115.     INT16   ret = -1;
  116.  
  117.     // Get the currently selected code sample 
  118.     Index = SendMsg(IDL_SELECT_CODE, LB_GETCURSEL, 0, 0);
  119.     SendMsg(IDL_SELECT_CODE, LB_GETTEXT, (WORD) Index,
  120.             (LONG)(LPSTR)GlobBuf);
  121.  
  122.     // Search for the text in the input array
  123.     if (GlobBuf[0])
  124.     {
  125.         for (i = 0; i < MAX_VIEW_CODE_MODULES; i++)
  126.         {
  127.             // Scan for a match
  128.             if (lstrcmp(InputData[i].pCodeName, GlobBuf) ==
  129.                 GOOD_STR_COMPARE)
  130.             {
  131.                 ret = i;
  132.                 i = MAX_VIEW_CODE_MODULES;  // End the loop...
  133.             }
  134.         }
  135.     }
  136.     return ret;
  137. }
  138.  
  139. //===================================================================
  140. //  Function:
  141. //          yield_control(void);
  142. //
  143. //  Input:  None.
  144. //
  145. //  Return: None.
  146. //
  147. //  Description:
  148. //          This routine will give Windows a chance to yield control
  149. //          of the CPU to other applications.
  150. //===================================================================
  151. void
  152. yield_control (void)
  153. {
  154.     MSG     msg;
  155.  
  156.     // Process all messages for the suite "dialog"
  157.     while (PeekMessage(&msg, hMainWnd, 0, 0, PM_REMOVE))
  158.     {
  159.         TranslateMessage(&msg);
  160.         DispatchMessage(&msg);
  161.     }
  162. }
  163.  
  164. //===================================================================
  165. //  Function:
  166. //          clear_multi_line_edit_box(hWnd, EditId);
  167. //
  168. //  Input:  hWnd    - The dialog handle
  169. //          EditId  - The edit box to clear
  170. //
  171. //  Return: None.
  172. //
  173. //  Description:
  174. //          Clear the specified multi-line edit box selected code. If
  175. //          no description is available, then the text box will be left
  176. //          blank.
  177. //===================================================================
  178. void
  179. clear_multi_line_edit_box (HWND hWnd, INT16 EditId)
  180. {
  181.     // Select all text in the edit box, then replace it with ""
  182.     SendDlgItemMessage(hWnd, EditId, EM_SETSEL, (WPARAM)(UINT) 1,
  183.                        MAKELPARAM(0, -1));
  184.     SendDlgItemMessage(hWnd, EditId, EM_REPLACESEL, 0,
  185.                        (LPARAM)(LPCSTR)"");
  186.  
  187.     // Allow Windows to process above messages
  188.     yield_control();
  189. }
  190.  
  191. //===================================================================
  192. //  Function:
  193. //          fill_in_description(void);
  194. //
  195. //  Input:  None.
  196. //
  197. //  Return: None.
  198. //
  199. //  Description:
  200. //          Fill in the brief description for the currently selected
  201. //          code. If no description is available, then the text box
  202. //          will be left blank.
  203. //===================================================================
  204. void
  205. fill_in_description (void)
  206. {
  207.     INT16   Offset;
  208.  
  209.     // First clear the text
  210.     SendMsg(IDE_DESCRIBE_CODE, WM_SETTEXT, (WPARAM) 0,
  211.             (LPARAM)(LPCSTR)"");
  212.  
  213.     // Get the array offset of the code selected
  214.     Offset = get_array_offset();
  215.     if ((Offset != -1) && (InputData[Offset].CodeDescId > 0))
  216.     {
  217.         // Display the text if it loads
  218.         if (LoadString(hInst, InputData[Offset].CodeDescId,
  219.                        (LPSTR) GlobBuf, 256) > 0)
  220.         {
  221.             SendMsg(IDE_DESCRIBE_CODE, WM_SETTEXT, (WPARAM) 0,
  222.                     (LPARAM)(LPCSTR) GlobBuf);
  223.         }
  224.  
  225.         // Display the sample code file
  226.         SendMsg(IDT_FILE_NAME, WM_SETTEXT, (WPARAM) 0,
  227.                 (LPARAM)(LPCSTR) InputData[Offset].pSourceFile);
  228.     }
  229. }
  230.  
  231. //===================================================================
  232. //  Function:
  233. //          get_search_text(void);
  234. //
  235. //  Input:  None.
  236. //
  237. //  Return: None.
  238. //
  239. //  Description:
  240. //          Retrieve the text from the main edit box. The text will
  241. //          be used during the "Search First" and "Search Next" calls.
  242. //===================================================================
  243. static void
  244. get_search_text (void)
  245. {
  246.     UINT16  TextLen;
  247.  
  248.     // Allocate buffer for edit box text (add extra space just
  249.     // in case)
  250.     if (Search.pText)
  251.     {
  252.         free(Search.pText);
  253.     }
  254.     TextLen = (UINT16) SendMsg(IDE_VIEWER_OUTPUT, WM_GETTEXTLENGTH, 0, 0);
  255.     Search.pText = (char *)malloc(TextLen + 10);
  256.  
  257.     // Retrieve the edit box text (used for searching)
  258.     SendMsg(IDE_VIEWER_OUTPUT, WM_GETTEXT, (WPARAM)(TextLen + 1),
  259.             (LPARAM)(LPCSTR) Search.pText);
  260.  
  261.     // Reset the "last search" pointer
  262.     Search.pLastSearch = Search.pText;
  263. }
  264.  
  265. //===================================================================
  266. //  Function:
  267. //          run_sample_code(void);
  268. //
  269. //  Input:  None.
  270. //
  271. //  Return: None.
  272. //
  273. //  Description:
  274. //          Fill in the brief description for the currently selected
  275. //          code. If no description is available, then the text box
  276. //          will be left blank.
  277. //===================================================================
  278. void
  279. run_sample_code (void)
  280. {
  281.     INT16   Offset;
  282.  
  283.     Offset = get_array_offset();
  284.     if ((Offset != -1) && InputData[Offset].pFunc)
  285.     {
  286.         // Set the header
  287.         SendMsg(IDT_OUTPUT_HEADER, WM_SETTEXT, (WPARAM) 0,
  288.                 (LPARAM)(LPCSTR) "Sample Code Output");
  289.  
  290.         // Run the sample code
  291.         (*InputData[Offset].pFunc)();
  292.  
  293.         // Cache the program output (for searching)
  294.         get_search_text();
  295.     }
  296. }
  297.  
  298. //===================================================================
  299. //  Function:
  300. //          view_sample_code(void);
  301. //
  302. //  Input:  None.
  303. //
  304. //  Return: None.
  305. //
  306. //  Description:
  307. //          Put a copy of the sample code into the edit box.
  308. //===================================================================
  309. void
  310. view_sample_code (void)
  311. {
  312.     pCHAR           pBuf;
  313.     HFILE           hFile;
  314.     INT16           Offset;
  315.     UINT16          BytesRead;
  316.  
  317.     Offset = get_array_offset();
  318.     if ((Offset != -1) && InputData[Offset].pSourceFile)
  319.     {
  320.         // Open the file in question
  321.         hFile = _lopen(InputData[Offset].pSourceFile, OF_READ);
  322.         if (hFile >= 0)
  323.         {
  324.             SendMsg(IDT_OUTPUT_HEADER, WM_SETTEXT, 0,
  325.                     (LPARAM)(LPCSTR) "Sample Code Viewer");
  326.  
  327.             // Allocate a 64k buffer
  328.             pBuf = (pCHAR) malloc(64000U);
  329.  
  330.             // Read in a chunk of file data and get rid of EOF
  331.             BytesRead = _lread(hFile, pBuf, (UINT) 64000U);
  332.             pBuf[BytesRead] = '\0';
  333.  
  334.             // Echo the code to the screen 
  335.             SendMsg(IDE_VIEWER_OUTPUT, WM_SETTEXT, 0,
  336.                     (LPARAM)(LPCSTR) pBuf);
  337.  
  338.             // Trap for any possible errors
  339.             if (BytesRead == 64000U)
  340.             {
  341.                 WinMsg("Sample code has been trimmed (too large to fit).",
  342.                        MSG_INFO, BTN_OK);
  343.             }
  344.             
  345.             // Clean up and return 
  346.             free(pBuf);
  347.             _lclose(hFile);
  348.  
  349.             // Cache the program output (for searching)
  350.             get_search_text();
  351.         }
  352.         else
  353.         {
  354.             WinMsg("Could not open sample code file.", MSG_STOP, BTN_OK);
  355.         }
  356.     }    
  357. }
  358.  
  359. //===================================================================
  360. //  Function:
  361. //          resize_resources(MainWidth, MainHeight);
  362. //
  363. //  Input:  MainWidth   - Height of the main window
  364. //          MainHeight  - Width of the main window
  365. //
  366. //  Return: None.
  367. //
  368. //  Description:
  369. //          The size of the main window has changed. Go ahead and
  370. //          resize the child windows.
  371. //===================================================================
  372. void
  373. resize_resources (int MainWidth, int MainHeight)
  374. {
  375.     BOOL    ResizeMe;
  376.     INT16   i, Offset, X1, Y1, X2, Y2;
  377.  
  378.     // Scan through the resources and resize specific ones. Note that the
  379.     // starting X and Y positions will never change. Resizing will only
  380.     // occur on the right and bottom borders.
  381.     for (i = 0; i < NUM_RESOURCES; i++)
  382.     {
  383.         ResizeMe = FALSE;
  384.         switch (MainRes[i].Id)
  385.         {
  386.             case IDT_HEADER_1:
  387.             case IDT_FILE_NAME:
  388.             case IDE_DESCRIBE_CODE:
  389.                 Offset = 9;
  390.                 ResizeMe = TRUE;
  391.                 X1 = (MainRes[i].X1 * DialogWidthUnits);
  392.                 X2 = ((MainWidth - (Offset * DialogWidthUnits)) - X1);
  393.                 Y1 = (MainRes[i].Y1 * DialogHeightUnits);
  394.                 Y2 = (MainRes[i].Y2 * DialogHeightUnits);
  395.                 break;
  396.             case IDS_SHADE:
  397.             case IDT_HEADER_2:
  398.             case IDT_OUTPUT_HEADER:
  399.                 Offset = 3;
  400.                 ResizeMe = TRUE;
  401.                 X1 = (MainRes[i].X1 * DialogWidthUnits);
  402.                 X2 = ((MainWidth - (Offset * DialogWidthUnits)) - X1);
  403.                 Y1 = (MainRes[i].Y1 * DialogHeightUnits);
  404.                 Y2 = (MainRes[i].Y2 * DialogHeightUnits);
  405.                 break;
  406.             case IDE_VIEWER_OUTPUT:
  407.                 Offset = 6;
  408.                 ResizeMe = TRUE;
  409.                 X1 = (MainRes[i].X1 * DialogWidthUnits);
  410.                 X2 = (MainWidth - (Offset * DialogWidthUnits));
  411.                 Y1 = (MainRes[i].Y1 * DialogHeightUnits);
  412.                 Y2 = ((MainHeight - (4 * DialogHeightUnits)) - Y1);
  413.                 break;
  414.         }
  415.  
  416.         if (ResizeMe)
  417.         {
  418.             MoveWindow(GetDlgItem(hMainWnd, MainRes[i].Id),
  419.                        X1, Y1, X2, Y2, TRUE);
  420.         }
  421.     }
  422. }
  423.  
  424. //===================================================================
  425. //  Function:
  426. //          search_text(hWnd, bSearchFirst);
  427. //
  428. //  Input:  hWnd            - A dialog handle
  429. //          bSearchFirst    - TRUE means "define the search" before you
  430. //                              start the search
  431. //
  432. //  Return: None.
  433. //
  434. //  Description:
  435. //          Search the edit box for the first instance of a specific
  436. //          string.
  437. //===================================================================
  438. void
  439. search_text (HWND hWnd, BOOL bSearchFirst)
  440. {
  441.     FARPROC lpTempProc;
  442.     LONG    iStart, iEnd;
  443.  
  444.     // Make sure the search text is available
  445.     if (Search.pText == NULL)
  446.     {
  447.         WinMsg("You must VIEW or RUN sample code before you can search.",
  448.                MSG_INFO, BTN_OK);
  449.         return;
  450.     }
  451.  
  452.     // Define the search criteria
  453.     if (bSearchFirst || (Search.pSearchStr == NULL))
  454.     {
  455.         // Define the search criteria
  456.         lpTempProc = MakeProcInstance((FARPROC) SearchDlgProc, hInst);
  457.         DialogBox(hInst, "SearchDlg", hWnd, (DLGPROC) lpTempProc);
  458.         FreeProcInstance((FARPROC) lpTempProc);
  459.  
  460.         // Return if the "Cancel" button was pressed
  461.         if (Search.bCancelPressed)
  462.             return;
  463.     }
  464.  
  465.     // Only search if the search string is defined
  466.     if (Search.pSearchStr)
  467.     {
  468.         if (!Search.pLastSearch)
  469.         {
  470.             WinMsg("Search string not found!", MSG_INFO, BTN_OK);
  471.             return;
  472.         }
  473.  
  474.         if (!bSearchFirst)
  475.             Search.pLastSearch += strlen(Search.pSearchStr);
  476.             Search.pLastSearch = StrStr(Search.pLastSearch, Search.pSearchStr);
  477.  
  478.         if (!Search.pLastSearch)
  479.         {
  480.             WinMsg("Search string not found!", MSG_INFO, BTN_OK);
  481.             return;
  482.         }
  483.         else
  484.         {
  485.             iStart = (Search.pLastSearch - Search.pText);
  486.             iEnd = (iStart + strlen(Search.pSearchStr));
  487.             SendDlgItemMessage(hWnd, IDE_VIEWER_OUTPUT, EM_SETSEL, 0,
  488.                                MAKELPARAM((UINT16) iStart, (UINT16) iEnd));
  489.         }
  490.     }
  491.     else
  492.         WinMsg("Search string not defined!", MSG_INFO, BTN_OK);
  493. }
  494.  
  495. //===================================================================
  496. //  Function:
  497. //          StrStr(pSourceString, pSearchString);
  498. //
  499. //  Input:  pSourceString - A pointer to the source string
  500. //          pSearchString - A pointer to the search string
  501. //
  502. //  Return: A pointer to the string found in the source string.
  503. //
  504. //  Description:
  505. //          Find the search string in the source string.
  506. //===================================================================
  507. char *
  508. StrStr (pCHAR pSourceString, pCHAR pSearchString)
  509. {
  510.     pCHAR   ptrSource = NULL, ptrSearch = NULL;
  511.  
  512.     //  bCaseSens is TRUE
  513.     if (Search.bCaseSens)
  514.     {
  515.         return strstr(pSourceString, pSearchString);
  516.     }
  517.  
  518.     // bCaseSens is not TRUE
  519.     for( ; *pSourceString ; pSourceString++ )
  520.     {
  521.         if (CaseInsensitiveCompare(*pSourceString, *pSearchString))
  522.         {
  523.             ptrSource = pSourceString + 1;
  524.             ptrSearch = pSearchString + 1;
  525.             for ( ; *ptrSearch ; ptrSearch ++, ptrSource++ )
  526.             {
  527.                 if (!CaseInsensitiveCompare(*ptrSource, *ptrSearch))
  528.                 {
  529.                     break;
  530.                 }
  531.             }
  532.             if (!(*ptrSearch))
  533.             {
  534.                 return pSourceString;
  535.             }
  536.         }
  537.     }
  538.     return NULL;
  539. }
  540.  
  541. //===================================================================
  542. //  Function:
  543. //          CaseInsensitiveCompare(Char1, Char2);
  544. //
  545. //  Input:  Char1 - A character
  546. //          Char2 - A character
  547. //
  548. //  Return: Boolean TRUE/FALSE.
  549. //
  550. //  Description:
  551. //          Compare these two characters case insensitively.
  552. //===================================================================
  553. BOOL
  554. CaseInsensitiveCompare (CHAR Char1, CHAR Char2)
  555. {
  556.     if (isalpha(Char1))
  557.     {
  558.         if (isupper(Char1))
  559.         {
  560.             return(((Char1 == Char2) || (Char1 == Char2 - 32)) ? TRUE : FALSE);
  561.         }
  562.         else
  563.         {
  564.             return(((Char1 == Char2) || (Char1 == Char2 + 32)) ? TRUE : FALSE);
  565.         }
  566.     }
  567.     else
  568.     {
  569.         return ((Char1 == Char2) ? TRUE : FALSE);
  570.     }
  571. }
  572.  
  573. //===================================================================
  574. //  Function:
  575. //          setup_tab_edit_box(hDlg, EditId);
  576. //
  577. //  Input:  hWnd    - A dialog handle
  578. //          EditId  - The edit box that is to be customized
  579. //
  580. //  Return: The newly assigned procedure pointer
  581. //
  582. //  Description:
  583. //          Set up an edit box so that tab keys change focus to
  584. //          another resource.
  585. //===================================================================
  586. FARPROC
  587. setup_tab_edit_box (HWND hWnd, int EditId)
  588. {
  589.     HWND    hTempWnd;   // Handle of the Edit control
  590.     FARPROC EditProc;   // The TabEditBox Windows procedure
  591.  
  592.     // If the standard edit box function has not yet been saved, save it.
  593.     hTempWnd = GetDlgItem(hWnd, EditId);
  594.     if (fpStdEditBoxProc == NULL)
  595.         fpStdEditBoxProc = (WNDPROC) GetWindowLong(hTempWnd, GWL_WNDPROC);
  596.  
  597.     // Force the edit box processing to the sub-class function
  598.     EditProc = (FARPROC) MakeProcInstance((FARPROC) TabEditBox, hInst);
  599.     SetWindowLong(hTempWnd, GWL_WNDPROC, (LONG) EditProc);
  600.  
  601.     // Return the variable created by MakeProcInstance()
  602.     return EditProc;
  603. }
  604.  
  605. //===================================================================
  606. //  Function:
  607. //          TabEditBox(hDlg, msg, wParam, lParam);
  608. //
  609. //  Input:  hWnd        - The Window handle
  610. //          msg         - Message to process
  611. //          wParam      - Word Parameter
  612. //          lParam      - Long Parameter
  613. //
  614. //  Return: Long        - Value returned from Message - depends on
  615. //                          message.
  616. //
  617. //  Description:
  618. //          This routine will change focus away from the edit box when
  619. //          a TAB, or BACKTAB, is hit.
  620. //===================================================================
  621. long FAR PASCAL _export
  622. TabEditBox (HWND hWnd, UINT msg, WORD wParam, LONG lParam)
  623. {
  624.     int     Id;             // ID of currently selected control
  625.     long    ret = FALSE;    // Return value
  626.  
  627.     // Check for special cases
  628.     switch (msg)
  629.     {
  630.         case WM_GETDLGCODE:
  631.             return DLGC_WANTMESSAGE;
  632.  
  633.         case WM_CHAR:
  634.             if (wParam == VK_TAB)
  635.             {
  636.                 ret = TRUE;
  637.                 Id = GetDlgCtrlID(hWnd);
  638.                 if (GetKeyState(VK_SHIFT) < 0)
  639.                 {
  640.                     if (Id == IDE_DESCRIBE_CODE)
  641.                         Id = IDL_SELECT_CODE;
  642.                     else
  643.                         Id = IDE_DESCRIBE_CODE;
  644.                 }
  645.                 else                        // Standard TAB
  646.                 {
  647.                     if (Id == IDE_DESCRIBE_CODE)
  648.                         Id = IDE_VIEWER_OUTPUT;
  649.                     else
  650.                         Id = IDB_VIEW_CODE;
  651.                 }
  652.  
  653.                 // Change resource focus
  654.                 SetFocus(GetDlgItem(hMainWnd, Id));
  655.             }
  656.  
  657.             // Don't want to exit the app on escape.
  658.             if (wParam == VK_ESCAPE)
  659.             {
  660.                 MessageBeep(1);
  661.             }                      
  662.             break;
  663.     }
  664.  
  665.     // Send unprocessed messages to standard edit box processor
  666.     if (ret == FALSE)
  667.         ret = CallWindowProc(fpStdEditBoxProc, hWnd, msg, wParam, lParam);
  668.     return ret;
  669. }
  670.  
  671. //===================================================================
  672. //  Function:
  673. //          SendMsg(Id, Msg, wParam, lParam);
  674. //
  675. //  Input:  Id      - Child ID to send the message to
  676. //          Msg     - Windows message (i.e. EM_SETSEL)
  677. //          wParam  - Message Parameter
  678. //          lParam  - Message parameter
  679. //
  680. //  Return: None
  681. //
  682. //  Description:
  683. //          Send a message to a child of the main window.
  684. //===================================================================
  685. LRESULT
  686. SendMsg (int Id, UINT Msg, WPARAM wParam, LPARAM lParam)
  687. {
  688.     return SendMessage(GetDlgItem(hMainWnd, Id), Msg, wParam, lParam);
  689. }
  690.  
  691. //===================================================================
  692. //  Name:   CreateResources(hInstance, hWnd);
  693. //
  694. //  Input:  hInstance   - Application instance handle
  695. //          hWnd        - Handle for the main window
  696. //
  697. //  Return: None
  698. //
  699. //  Description:
  700. //          Create child resources on main window.
  701. //===================================================================
  702. static void
  703. CreateResources (HINSTANCE hInstance, HWND hWnd)
  704. {
  705.     HWND        hResWnd;        // Window Handle to the resource
  706.     char        TypeRes[20];    // Type of the resource
  707.     int         i;              // Loop counter - iterate throught the
  708.                                 //   number of resources
  709.     int         X1;             // Horizontal position of top left
  710.     int         X2;             // Horizontal position of bottom right
  711.     int         Y1;             // Vertical position of top left
  712.     int         Y2;             // Vertical position of bottom right
  713.     HINSTANCE   hTempPtr;       // Pointer used in creating an edit control
  714.                                 //   which dynamically allocates memory 
  715.     HGLOBAL     TextAlloc;      // Global handle to memory - used in
  716.                                 //   creating a 64K edit control
  717.     void*       TextPtr;        // Pointer used in allocating space for the
  718.                                 //   large (64K) edit control
  719.     UINT16      uTextBufferSize;// The number of bytes in the 64K edit
  720.                                 //   control.
  721.  
  722.     hTempPtr = hInstance;   // Use the application instance in all cases
  723.                             // except when creating an edit control to not
  724.                             // use the heap.
  725.     // Create all resources
  726.     for (i = 0; i < NUM_RESOURCES; i++)
  727.     {
  728.         switch (MainRes[i].Res)
  729.         {
  730.             case resBUTTON:
  731.                 strcpy(TypeRes, "BUTTON");
  732.                 break;
  733.             case resCOMBOBOX:
  734.                 strcpy(TypeRes, "COMBOBOX");
  735.                 break;
  736.             case resEDIT:
  737.                 strcpy(TypeRes, "EDIT");
  738.                 break;
  739.             case resEDIT64:
  740.                 strcpy(TypeRes, "EDIT");
  741.  
  742.                 // Allow the edit control to contain up to 64000 bytes of
  743.                 // information.
  744.                 uTextBufferSize = 64000U; // Set the size of the buffer
  745.  
  746.                 // Allocate the memory for the edit control.
  747.                 // Edit control takes ownership of this memory, so
  748.                 // this memory is not released explicitly by this
  749.                 // application.
  750.                 // WARNING! A GPF will occur if the application is
  751.                 // terminated after the memory is freed.
  752.                 TextAlloc = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE,
  753.                                         uTextBufferSize);
  754.                 TextPtr = GlobalLock(TextAlloc);
  755.                 LocalInit(HIWORD((LONG) TextPtr), 0,
  756.                           (WORD) GlobalSize(TextAlloc) - 16);
  757.                 UnlockSegment(HIWORD((LONG) TextPtr));
  758.  
  759.                 hTempPtr = (HINSTANCE) HIWORD(TextPtr); // Set the hInstance
  760.                                                         // for the edit control.
  761.                 break;
  762.             case resGROUP:
  763.                 strcpy(TypeRes, "BUTTON");
  764.                 break;
  765.             case resLISTBOX:
  766.                 strcpy(TypeRes, "LISTBOX");
  767.                 break;
  768.             case resSTATIC:
  769.                 strcpy(TypeRes, "STATIC");
  770.                 break;
  771.             case resSHADE:
  772.                 strcpy(TypeRes, "BorShade");
  773.                 break;
  774.             default:
  775.                 return;
  776.         }
  777.  
  778.         // Adjust resource size with standard dialog units
  779.         X1 = (MainRes[i].X1 * DialogWidthUnits);
  780.         X2 = (MainRes[i].X2 * DialogWidthUnits);
  781.         Y1 = (MainRes[i].Y1 * DialogHeightUnits);
  782.         Y2 = (MainRes[i].Y2 * DialogHeightUnits);
  783.  
  784.         // Create the child window
  785.         hResWnd = CreateWindow(TypeRes, MainRes[i].Text, MainRes[i].Attrib,
  786.                                X1, Y1, X2, Y2, hWnd, (HMENU)MainRes[i].Id,
  787.                                hTempPtr, NULL);
  788.         if (hResWnd)
  789.         {
  790.             ShowWindow(hResWnd, SW_SHOW);
  791.  
  792.             // Sub-class the edit boxes
  793.             if (MainRes[i].Id == IDE_VIEWER_OUTPUT)
  794.             {
  795.                 hViewEdit = hResWnd;
  796.                 fnTabEditBox[0] =
  797.                            (WNDPROC)setup_tab_edit_box(hWnd,
  798.                                                        IDE_VIEWER_OUTPUT);
  799.             }
  800.             else if (MainRes[i].Id == IDE_DESCRIBE_CODE)
  801.             {
  802.                 hDescEdit = hResWnd;
  803.                 fnTabEditBox[1] =
  804.                            (WNDPROC)setup_tab_edit_box(hWnd,
  805.                                                        IDE_DESCRIBE_CODE);
  806.             }
  807.         }
  808.         else
  809.             i = NUM_RESOURCES;      // End the loop...
  810.     }
  811. }
  812.  
  813. //===================================================================
  814. //  Function:
  815. //          InitMainWnd(hWnd);
  816. //
  817. //  Input:  hWnd - Handle for main window
  818. //
  819. //  Return: None
  820. //
  821. //  Description:
  822. //          Init the main window. Fill list boxes, set the focus of
  823. //          the default window.
  824. //===================================================================
  825. static void
  826. InitMainWnd (HWND hWnd)
  827. {
  828.     INT16   i;      // Loop counter - iterate through the number of
  829.                     //   resources
  830.     HFONT   hFont;  // Handle to the font
  831.  
  832.     // Fill the list box with the code available
  833.     for (i = 0; i < MAX_VIEW_CODE_MODULES; i++)
  834.     {
  835.         if (InputData[i].pCodeName[0])
  836.         {
  837.             SendDlgItemMessage(hWnd, IDL_SELECT_CODE, LB_ADDSTRING, 0,
  838.                                (LPARAM)(LPCSTR) InputData[i].pCodeName);
  839.         }
  840.         else
  841.             i = MAX_VIEW_CODE_MODULES;  // No more code mods;
  842.                                         // end the loop...
  843.     }
  844.  
  845.     // Select the first item of the list box
  846.     SendDlgItemMessage(hWnd, IDL_SELECT_CODE, LB_SETCURSEL, 0, 0);
  847.  
  848.     // Use a non-proportional font in the main edit box
  849.     hFont = (HFONT) GetStockObject(ANSI_FIXED_FONT);
  850.     SendDlgItemMessage(hWnd, IDE_VIEWER_OUTPUT, WM_SETFONT,
  851.                        (WPARAM) hFont, FALSE);
  852.  
  853.     // Set the focus to the dialog to the "select code" list box
  854.     SetFocus(GetDlgItem(hWnd, IDL_SELECT_CODE));
  855.  
  856.     // Set the description for the first item
  857.     fill_in_description();
  858. }
  859.  
  860. //=================================================================
  861. //  Function:
  862. //          InitApp(nCmdShow, hInst);
  863. //
  864. //  Input:  nCmdShow    - Whether to show the window after it is created
  865. //          hInst       - The current instance for the application
  866. //
  867. //  Return: TRUE - Init worked
  868. //          FALSE - Init failed
  869. //
  870. //  Description:
  871. //          Create the application window (in this case a dialog).
  872. //================================================================
  873. static BOOL
  874. InitApp (int nCmdShow, HINSTANCE hInstance)
  875. {
  876.     WNDCLASS    wc;         // Window class
  877.     HWND        hWnd;       // Handle to the main window
  878.     BOOL        ret = TRUE; // Return value
  879.     unsigned    uCount;     // Number of available file handles
  880.     char        szMessage[DBIMAXMSGLEN * 2 + 1]; // Allocate enough space for
  881.                                                  //   the message.
  882.     // The directory relative to the SNIPIT directory which contains the
  883.     //   tables.
  884.     CHAR szRelativeTblDirectory[DBIMAXPATHLEN+1];
  885.  
  886.     // Init the application and create the needed windows
  887.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  888.     wc.lpfnWndProc   = MainWndProc;
  889.     wc.cbClsExtra    = 0;
  890.     wc.cbWndExtra    = 0;
  891.     wc.hInstance     = hInstance;
  892.     wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(1100));
  893.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  894.     wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  895.     wc.lpszMenuName  = "MainMenu";
  896.     wc.lpszClassName = "SnipIt";
  897.  
  898.     if (! RegisterClass(&wc))
  899.     {
  900.         MessageBox(NULL, "RegisterClass failed!",  "System Error",
  901.                    MB_OK | MB_ICONHAND);
  902.         return FALSE;
  903.     }
  904.  
  905.     // Get the base horizontal and vertical dialog units
  906.     DialogWidthUnits = (LOWORD(GetDialogBaseUnits()) / 4);
  907.     DialogHeightUnits = (HIWORD(GetDialogBaseUnits()) / 8);
  908.  
  909.     // Create windows used for I/O
  910.     GetWindowRect(GetDesktopWindow(), &DeskRect);
  911.     MinWidth = (BASE_MIN_WIDTH * DialogWidthUnits);
  912.     MinHeight = (BASE_MIN_HEIGHT * DialogHeightUnits);
  913.     hWnd = CreateWindow("SnipIt", "SnipIt Code Viewer",
  914.                         WS_OVERLAPPEDWINDOW,
  915.                         DeskRect.left, DeskRect.top,
  916.                         DeskRect.right, DeskRect.bottom,
  917.                         NULL, NULL, hInstance, NULL);
  918.     if (hWnd)
  919.     {
  920.         hMainWnd = hWnd;
  921.         hInst = hInstance;
  922.         GlobBuf = (pCHAR) malloc(1024);
  923.         ShowWindow(hMainWnd, nCmdShow);
  924.         UpdateWindow(hMainWnd);
  925.         InitMainWnd(hMainWnd);
  926.     }
  927.     else
  928.     {
  929.         MessageBox(NULL, "CreateWindow failed!",  "System Error",
  930.                    MB_OK | MB_ICONHAND);
  931.         ret = FALSE;
  932.     }
  933.  
  934.     // Increase the number of file handles that are available to the
  935.     //   system.  
  936.     uCount = SetHandleCount(FILEHANDLESNEEDED);
  937.     if (uCount < FILEHANDLESNEEDED)
  938.     {
  939.         MessageBox(NULL, "Not enough file handles available. 'Set files=40' in"
  940.                    " CONFIG.SYS.",  "System Error", MB_OK | MB_ICONHAND);
  941.         return FALSE;
  942.     }
  943.  
  944.     // Get the directory which contains the tables. 
  945.     GetPrivateProfileString("SNIPIT", "TblDir",
  946.                             "..\\TABLES",
  947.                             (LPSTR)szRelativeTblDirectory,
  948.                             sizeof(szRelativeTblDirectory),
  949.                             "bde.ini");
  950.  
  951.     // Create a fully qualified path for the table directory.
  952.     if (MakeFullPath(szTblDirectory, szRelativeTblDirectory))
  953.     {
  954.         sprintf(szMessage, "Working Directory does not exist: %s",
  955.                 szTblDirectory);
  956.         MessageBox(NULL, szMessage, "System Error", MB_OK | MB_ICONHAND);
  957.         return FALSE;
  958.     }
  959.  
  960.     // Get the Private directory. 
  961.     GetPrivateProfileString("SNIPIT", "PrivateDir",
  962.                             ".",
  963.                             (LPSTR)szRelativeTblDirectory,
  964.                             sizeof(szRelativeTblDirectory),
  965.                             "bde.ini");
  966.  
  967.     // Create a fully qualified path for the private directory.
  968.     if (MakeFullPath(szPrivDirectory, szRelativeTblDirectory))
  969.     {
  970.         sprintf(szMessage, "Private Directory does not exist: %s",
  971.                 szPrivDirectory);
  972.         MessageBox(NULL, szMessage, "System Error", MB_OK | MB_ICONHAND);
  973.         return FALSE;
  974.     }
  975.     
  976.     return ret;
  977. }
  978.  
  979. //===================================================================
  980. //  Function:
  981. //          MainWndProc(hWnd, msg, wParam, lParam);
  982. //
  983. //  Input:  hWnd        - The Window handle
  984. //          msg         - Message to handle
  985. //          wParam      - Word Parameter
  986. //          lParam      - Long Parameter
  987. //
  988. //  Return: BOOL        - Was message handled?
  989. //
  990. //  Description:
  991. //          This routine will process all messages for
  992. //          the primary application window. Included in this are all
  993. //          menu commands.
  994. //===================================================================
  995. long FAR PASCAL _export
  996. MainWndProc (HWND hWnd, UINT msg, UINT wParam,
  997.              LONG lParam)
  998. {
  999.     HWND            hFocus;         // Child window which currently has
  1000.                                     //   focus.
  1001.     HWND            hwnd;           // Variable used to iterate through
  1002.                                     //   list of child windows
  1003.     MINMAXINFO*     pMinMax;        // Used to determine the minimum and
  1004.                                     //   maximum size of the window
  1005.     FARPROC         lpTempProc;     // Temporary windows procedure used
  1006.                                     //   for child dialogs and windows
  1007.     INT32           ret = FALSE;    // Return Value
  1008.     HBRUSH          hBrush;         // Handle to the brush
  1009.  
  1010.     long            lMinMax;        // Contains both starting and ending
  1011.                                     //   selected positions in edit
  1012.                                     //   control
  1013.     unsigned int    iStart;         // Starting position of selected text
  1014.     unsigned int    iEnd;           // Ending position of selected text                                    
  1015.  
  1016.     switch (msg)
  1017.     {
  1018.         case WM_CREATE:
  1019.             CreateResources(((LPCREATESTRUCT) lParam)->hInstance, hWnd);
  1020.             hwnd = GetWindow(hWnd, GW_CHILD);
  1021.             while (hwnd != NULL)
  1022.             {
  1023.                 Ctl3dSubclassCtl(hwnd);
  1024.                 hwnd = GetWindow(hwnd, GW_HWNDNEXT);
  1025.             }
  1026.             break;
  1027.         case WM_CTLCOLOR:
  1028.             hBrush = Ctl3dCtlColorEx(msg, wParam, lParam);
  1029.             if (hBrush != (HBRUSH)0)
  1030.             {
  1031.                 return (long)(WORD)hBrush;
  1032.             }
  1033.             else
  1034.             {
  1035.                 return DefWindowProc(hWnd, msg, wParam, lParam);
  1036.             }
  1037.         case WM_SYSCOLORCHANGE:
  1038.             Ctl3dColorChange();
  1039.             return TRUE;
  1040.         case WM_NCPAINT:
  1041.         case WM_NCACTIVATE:
  1042.         case WM_SETTEXT:
  1043.             return Ctl3dDlgFramePaint(hWnd, msg, wParam, lParam);
  1044.         case WM_SETFOCUS:
  1045.             SetFocus(GetDlgItem(hWnd, IDL_SELECT_CODE));
  1046.             break;
  1047.         case WM_GETMINMAXINFO:
  1048.             pMinMax = (MINMAXINFO *) lParam;
  1049.             pMinMax->ptMinTrackSize.x = MinWidth;
  1050.             pMinMax->ptMinTrackSize.y = MinHeight;
  1051.             ret = DefWindowProc(hWnd, msg, wParam, lParam);
  1052.             break;
  1053.         case WM_SIZE:
  1054.             resize_resources(LOWORD(lParam), HIWORD(lParam));
  1055.             break;
  1056.         case WM_COMMAND:
  1057.             // Process the menu commands
  1058.             hFocus = GetFocus();
  1059.             switch(wParam)
  1060.             {
  1061.                 case IDL_SELECT_CODE:
  1062.                     if (HIWORD(lParam) == LBN_SELCHANGE)
  1063.                         fill_in_description();
  1064.                     else if (HIWORD(lParam) == LBN_DBLCLK)
  1065.                         view_sample_code();
  1066.                     break;
  1067.                 case IDB_RUN_CODE:
  1068.                 case IDM_RUN_CODE:
  1069.                     clear_multi_line_edit_box(hWnd, IDE_VIEWER_OUTPUT);
  1070.                     run_sample_code();
  1071.                     break;
  1072.                 case IDB_VIEW_CODE:
  1073.                 case IDM_VIEW_CODE:
  1074.                     clear_multi_line_edit_box(hWnd, IDE_VIEWER_OUTPUT);
  1075.                     view_sample_code();
  1076.                     break;
  1077.                 case IDB_COPY:
  1078.                 case IDM_COPY:
  1079.                     // Determine which characters are selected
  1080.                     lMinMax = SendDlgItemMessage(hWnd, IDE_VIEWER_OUTPUT,
  1081.                                                  EM_GETSEL, 0, 0L);
  1082.  
  1083.                     // Get the first and last selected character
  1084.                     iStart = LOWORD(lMinMax);
  1085.                     iEnd   = HIWORD(lMinMax);
  1086.  
  1087.                     // If nothing is selected, select all
  1088.                     if (iStart == iEnd)
  1089.                     {
  1090.                         SendDlgItemMessage(hWnd, IDE_VIEWER_OUTPUT,
  1091.                                            EM_SETSEL, 0, 0xfffeL);
  1092.                     }
  1093.  
  1094.                     SendDlgItemMessage(hWnd, IDE_VIEWER_OUTPUT, WM_COPY,
  1095.                                        0, 0L);
  1096.                     break;
  1097.                 case IDM_SEARCH_FIRST:
  1098.                 case IDB_SEARCH_TEXT:
  1099.                     hFocus = GetDlgItem(hWnd, IDE_VIEWER_OUTPUT);
  1100.                     search_text(hWnd, TRUE);
  1101.                     break;
  1102.                 case IDM_SEARCH_NEXT:
  1103.                     hFocus = GetDlgItem(hWnd, IDE_VIEWER_OUTPUT);
  1104.                     search_text(hWnd, FALSE);
  1105.                     break;
  1106.                 case IDM_ABOUT:
  1107.                     lpTempProc =
  1108.                         MakeProcInstance((FARPROC) AboutDlgProc, hInst);
  1109.                     DialogBox(hInst, "AboutDlg", hMainWnd,
  1110.                               (DLGPROC)lpTempProc);
  1111.                     FreeProcInstance((FARPROC) lpTempProc);
  1112.                     break;
  1113.                 case IDM_EXIT:
  1114.                     PostQuitMessage(0);
  1115.                     break;
  1116.                 default:
  1117.                     ret = DefWindowProc(hWnd, msg, wParam, lParam);
  1118.                     break;
  1119.             }
  1120.             SetFocus(hFocus);
  1121.             break;
  1122.         case WM_DESTROY:
  1123.             PostQuitMessage(0);
  1124.             break;
  1125.         default:
  1126.             ret = DefWindowProc(hWnd, msg, wParam, lParam);
  1127.             break;
  1128.     }
  1129.     return ret;
  1130. }
  1131.  
  1132. //===============================================================
  1133. //  Function:
  1134. //          About(hDlg, msg, wParam, lParam);
  1135. //
  1136. //  Input:  hDlg        - The dialog handle
  1137. //          msg         - Message to handle
  1138. //          wParam      - Word Parameter
  1139. //          lParam      - Long Parameter
  1140. //
  1141. //  Return: BOOL        - Was message handled?
  1142. //
  1143. //  Description:    This routine will process all I/O for the
  1144. //  ABOUT dialog.
  1145. //================================================================
  1146. BOOL FAR PASCAL _export
  1147. AboutDlgProc (HWND hDlg, WORD msg, WORD wParam,
  1148.               LONG lParam)
  1149. {
  1150.     int     ret = FALSE;
  1151.  
  1152.     lParam = lParam; // Avoid warning - Parameter not used
  1153.     switch (msg)
  1154.     {
  1155.         case WM_INITDIALOG:
  1156.             ret = TRUE;
  1157.             break;
  1158.         case WM_COMMAND:
  1159.             switch (wParam)
  1160.             {
  1161.                 case IDOK:
  1162.                 case IDCANCEL:
  1163.                     EndDialog(hDlg, TRUE);
  1164.                     ret = TRUE;
  1165.                     break;
  1166.             }
  1167.             break;
  1168.     }
  1169.     return ret;
  1170. }
  1171.  
  1172. //===================================================================
  1173. //  Fuction:
  1174. //          reset_connect_dialog(hWnd, bResetAll);
  1175. //
  1176. //  Input:  hWnd        - The dialog handle
  1177. //          bResetAll   - TRUE means to repaint the entire dialog
  1178. //                        FALSE means to repaint alias information
  1179. //
  1180. //  Return: None
  1181. //
  1182. //  Description:    Reset the "connect to the database" dialog based
  1183. //                  on the current driver selected.
  1184. //===================================================================
  1185. void
  1186. reset_connect_dialog (HWND hWnd, BOOL bResetAll)
  1187. {
  1188.     hDBICur     hList;
  1189.     DBDesc      DbData;
  1190.     pFLDDesc    pCfgInfo;
  1191.     WORD        ListIndex;
  1192.     pCHAR       pCfgRecBuf;
  1193.     pCHAR       Driver;
  1194.     pCHAR       Alias;
  1195.     pCHAR       CfgPath;
  1196.  
  1197.     // Allocate resources
  1198.     Alias = (pCHAR) malloc((DBIMAXSCFLDLEN + 1) * sizeof(CHAR));
  1199.     Driver = (pCHAR) malloc((DBIMAXSCFLDLEN + 1) * sizeof(CHAR));
  1200.     CfgPath = (pCHAR) malloc((DBIMAXPATHLEN + 1) * sizeof(CHAR));
  1201.     pCfgRecBuf = (pCHAR) malloc((DBIMAXSCRECSIZE + 1) * sizeof(CHAR));
  1202.     pCfgInfo = (pFLDDesc) malloc(sizeof(FLDDesc) * DBIMAXSCFIELDS);
  1203.  
  1204.     // Get the driver currently selected
  1205.     ListIndex = (WORD) SendDlgItemMessage(hWnd, IDL_DRIVERS, LB_GETCURSEL,
  1206.                                                         0,0);
  1207.     SendDlgItemMessage(hWnd, IDL_DRIVERS, LB_GETTEXT, (WPARAM) ListIndex,
  1208.                        (LPARAM) Driver);
  1209.  
  1210.     // Reset the driver to "STANDARD" if Paradox or dBASE
  1211.     if ((strncmp(Driver, szDBASE, DBIMAXSCFLDLEN) == GOOD_STR_COMPARE) ||
  1212.         (strncmp(Driver, szPARADOX, DBIMAXSCFLDLEN) == GOOD_STR_COMPARE))
  1213.     {
  1214.         strcpy(Driver, "STANDARD");
  1215.     }
  1216.  
  1217.     // Leave the alias list alone if not resetting entire listbox
  1218.     if (bResetAll)
  1219.     {
  1220.         // Reset info displayed (based on the driver type)
  1221.         if (strncmp(Driver, "STANDARD", DBIMAXSCFLDLEN) == GOOD_STR_COMPARE)
  1222.         {
  1223.             // Remove the user name and password if alias is STANDARD
  1224.             ShowWindow(GetDlgItem(hWnd, IDE_PASSWORD), SW_HIDE);
  1225.             ShowWindow(GetDlgItem(hWnd, IDT_PASSWORD_HDR), SW_HIDE);
  1226.         }
  1227.         else
  1228.         {
  1229.             // Make sure all is displayed
  1230.             ShowWindow(GetDlgItem(hWnd, IDE_PASSWORD), SW_SHOW);
  1231.             ShowWindow(GetDlgItem(hWnd, IDT_PASSWORD_HDR), SW_SHOW);
  1232.         }
  1233.  
  1234.         // Clear and fill the alias listbox
  1235.         SendDlgItemMessage(hWnd, IDL_ALIASES, LB_RESETCONTENT, 0, 0);
  1236.         if (DbiOpenDatabaseList(&hList) == DBIERR_NONE)
  1237.         {
  1238.             // Scan the list of aliases for matching drivers
  1239.             while (DbiGetNextRecord(hList, dbiNOLOCK, (pBYTE) &DbData,
  1240.                                     NULL) == DBIERR_NONE)
  1241.             {
  1242.                 if (strncmp(DbData.szDbType, Driver, DBIMAXSCFLDLEN) == GOOD_STR_COMPARE)
  1243.                 {
  1244.                     SendDlgItemMessage(hWnd, IDL_ALIASES, LB_INSERTSTRING,
  1245.                                        0, (LPARAM) DbData.szName);
  1246.                 }
  1247.             }
  1248.             DbiCloseCursor(&hList);
  1249.             SendDlgItemMessage(hWnd, IDL_ALIASES, LB_SETCURSEL, 0, 0);
  1250.         }
  1251.     }
  1252.  
  1253.     // Free resources used
  1254.     free(Alias);
  1255.     free(Driver);
  1256.     free(CfgPath);
  1257.     free(pCfgRecBuf);
  1258.     free((pCHAR) pCfgInfo);
  1259. }
  1260.  
  1261. //===================================================================
  1262. //  Function:
  1263. //          ConnectDlgProc(hDlg, msg, wParam, lParam);
  1264. //
  1265. //  Input:  hDlg        - The dialog handle
  1266. //          msg         - Message to handle
  1267. //          wParam      - Word Parameter
  1268. //          lParam      - Long Parameter
  1269. //
  1270. //  Return: BOOL        - Was message handled?
  1271. //
  1272. //  Description:    This routine will make a connection
  1273. //                  to a database (setting a global handle).
  1274. //===================================================================
  1275. BOOL FAR PASCAL _export
  1276. ConnectDlgProc (HWND hDlg, WORD msg, WORD wParam,
  1277.                 LONG lParam)
  1278. {
  1279.     DBIResult   rslt;
  1280.     hDBICur     hList;
  1281.     WORD        ListIndex;
  1282.     int         ret = FALSE;
  1283.     pCHAR       Driver;
  1284.     pCHAR       Alias;
  1285.     pCHAR       Password;
  1286.     pCHAR       Message;
  1287.     DBIMSG      dbi_status;
  1288.     DBIErrInfo  ErrInfo;
  1289.  
  1290.     // Process dialog
  1291.     switch (msg)
  1292.     {
  1293.         case WM_INITDIALOG:
  1294.             // This code assumes that IDAPI is already initialized.
  1295.             // Fill the listbox with the drivers available 
  1296.             ret = TRUE;
  1297.             Driver = (pCHAR) malloc(DBIMAXSCFLDLEN + 1);
  1298.             if (Driver)
  1299.             {
  1300.                 if (DbiOpenDriverList(&hList) == DBIERR_NONE)
  1301.                 {
  1302.                     while (DbiGetNextRecord(hList, dbiNOLOCK, (pBYTE)Driver,
  1303.                                             NULL) == DBIERR_NONE)
  1304.                     {
  1305.                         // Make certain driver name is terminated -
  1306.                         //   max driver length is DBIMAXNAMELEN (32)
  1307.                         Driver[DBIMAXNAMELEN] = 0;
  1308.                         SendDlgItemMessage(hDlg, IDL_DRIVERS,
  1309.                                            LB_INSERTSTRING, 0,
  1310.                                            (LPARAM) Driver);
  1311.                     }
  1312.                     DbiCloseCursor(&hList);
  1313.                 }
  1314.                 free(Driver);
  1315.             }
  1316.  
  1317.             // Select the first items of the list boxes
  1318.             SendDlgItemMessage(hDlg, IDL_DRIVERS, LB_SETCURSEL, 0, 0);
  1319.  
  1320.             // Fill the listbox with the aliases
  1321.             reset_connect_dialog(hDlg, TRUE);
  1322.             break;
  1323.         case WM_COMMAND:
  1324.             switch (wParam)
  1325.             {
  1326.                 case IDL_DRIVERS:
  1327.                     if (HIWORD(lParam) == LBN_SELCHANGE)
  1328.                         reset_connect_dialog(hDlg, TRUE);
  1329.                     break;
  1330.                 case IDL_ALIASES:
  1331.                     if (HIWORD(lParam) == LBN_SELCHANGE)
  1332.                         reset_connect_dialog(hDlg, FALSE);
  1333.                     break;
  1334.                 case IDOK:
  1335.                     // Init the strings
  1336.                     Alias = (pCHAR) malloc(DBIMAXSCFLDLEN * sizeof(BYTE));
  1337.                     Driver = (pCHAR) malloc(DBIMAXSCFLDLEN * sizeof(BYTE));
  1338.                     Password = (pCHAR) malloc(DBIMAXSCFLDLEN * sizeof(BYTE));
  1339.                     Alias[0] = '\0';
  1340.                     Driver[0] = '\0';
  1341.                     Password[0] = '\0';
  1342.  
  1343.                     // Get the selected driver
  1344.                     ListIndex =
  1345.                         (WORD) SendDlgItemMessage(hDlg, IDL_DRIVERS,
  1346.                                                   LB_GETCURSEL, 0, 0);
  1347.                     SendDlgItemMessage(hDlg, IDL_DRIVERS, LB_GETTEXT,
  1348.                                        (WPARAM) ListIndex, (LPARAM) Driver);
  1349.  
  1350.                           if ((strncmp(Driver, szDBASE, DBIMAXSCFLDLEN) == GOOD_STR_COMPARE) ||
  1351.                                 (strncmp(Driver, szPARADOX, DBIMAXSCFLDLEN) == GOOD_STR_COMPARE))
  1352.                     {
  1353.                         Driver[0] = '\0';
  1354.                         ListIndex =
  1355.                             (WORD) SendDlgItemMessage(hDlg, IDL_ALIASES,
  1356.                                                       LB_GETCURSEL, 0, 0);
  1357.                         SendDlgItemMessage(hDlg, IDL_ALIASES, LB_GETTEXT,
  1358.                                            (WPARAM) ListIndex,
  1359.                                            (LPARAM)Alias);
  1360.                     }
  1361.                     else        // SQL database...
  1362.                     {
  1363.                         // SQL database needs the alias & password
  1364.                         ListIndex =
  1365.                             (WORD) SendDlgItemMessage(hDlg, IDL_ALIASES,
  1366.                                                       LB_GETCURSEL, 0, 0);
  1367.                         SendDlgItemMessage(hDlg, IDL_ALIASES, LB_GETTEXT,
  1368.                                            (WPARAM) ListIndex,
  1369.                                            (LPARAM)Alias);
  1370.                         SendDlgItemMessage(hDlg, IDE_PASSWORD, WM_GETTEXT,
  1371.                                            80, (LPARAM) Password);
  1372.                     }
  1373.  
  1374.                     // Try to open the database
  1375.                     SetCursor(LoadCursor(NULL, IDC_WAIT));
  1376.                     SnipItDb = NULL;
  1377.                     rslt = DbiOpenDatabase(Alias, Driver, dbiREADWRITE,
  1378.                                            dbiOPENSHARED, Password, 0,
  1379.                                            NULL, NULL, &SnipItDb);
  1380.                     SetCursor(LoadCursor(NULL, IDC_ARROW));
  1381.                     if (rslt == DBIERR_NONE)
  1382.                     {
  1383.                         ret = TRUE;
  1384.                         EndDialog(hDlg, TRUE);
  1385.                     }
  1386.                     else
  1387.                     {
  1388.                         // Make certain to allocate enough space for all the
  1389.                         // Error contexts
  1390.                         Message = (pCHAR)malloc(8 * DBIMAXMSGLEN *
  1391.                                                 sizeof(BYTE));
  1392.                         if (!Message)
  1393.                         {
  1394.                             MessageBox(hDlg, "Out of memory!", "Initialization"
  1395.                                        " Error", MB_OK | MB_ICONSTOP);
  1396.                         }
  1397.                         else
  1398.                         {
  1399.                             // Get as much error information as possible
  1400.                             DbiGetErrorInfo(TRUE, &ErrInfo);
  1401.  
  1402.                             // Make certain information is returned on the
  1403.                             // correct error
  1404.                             if (ErrInfo.iError == rslt)
  1405.                             {
  1406.                                 wsprintf(Message, "Cat:Code = [%xh:%xh]\r\n%s",
  1407.                                          ErrCat(ErrInfo.iError),
  1408.                                          ErrCode(ErrInfo.iError),
  1409.                                          ErrInfo.szErrCode);
  1410.  
  1411.                                 if (strncmp(ErrInfo.szContext1, "", DBIMAXMSGLEN))
  1412.                                 {
  1413.                                     strcat(Message, ErrInfo.szContext1);
  1414.                                 }
  1415.                                 if (strncmp(ErrInfo.szContext2, "", DBIMAXMSGLEN))
  1416.                                 {
  1417.                                     strcat(Message, ErrInfo.szContext2);
  1418.                                 }
  1419.                                 if (strncmp(ErrInfo.szContext3, "", DBIMAXMSGLEN))
  1420.                                 {
  1421.                                     strcat(Message, ErrInfo.szContext3);
  1422.                                 }
  1423.                                 if (strncmp(ErrInfo.szContext4, "", DBIMAXMSGLEN))
  1424.                                 {
  1425.                                     strcat(Message, ErrInfo.szContext4);
  1426.                                 }
  1427.                             }
  1428.                             else
  1429.                             {
  1430.                                 DbiGetErrorString(rslt, dbi_status);
  1431.                                 wsprintf(Message, "%s\r\nCat:Code = [%xh:%xh]"
  1432.                                          "\r\n\r\n   %s", "Failed to connect!",
  1433.                                          ErrCat(rslt), ErrCode(rslt),
  1434.                                          dbi_status);
  1435.                             }
  1436.                             MessageBox(hDlg, (LPSTR) Message, "Initialization"
  1437.                                        " Error", MB_OK | MB_ICONSTOP);
  1438.                             free(Message);
  1439.                         }
  1440.                     }
  1441.                     // Free up resources
  1442.                     free(Alias);
  1443.                     free(Driver);
  1444.                     free(Password);
  1445.                     break;
  1446.                 case IDCANCEL:
  1447.                     ret = TRUE;
  1448.                     SnipItDb = NULL;
  1449.                     EndDialog(hDlg, TRUE);
  1450.                     break;
  1451.         }
  1452.         break;
  1453.     }
  1454.     return ret;
  1455. }
  1456.  
  1457. //===================================================================
  1458. //  Function:
  1459. //          SearchDlgProc(hDlg, msg, wParam, lParam);
  1460. //
  1461. //  Input:  hDlg        - The dialog handle
  1462. //          msg         - Message to handle
  1463. //          wParam      - Word Parameter
  1464. //          lParam      - Long Parameter
  1465. //
  1466. //  Return: BOOL        - Was message handled?
  1467. //
  1468. //  Description:    This routine will process all messages for the
  1469. //                  dialog used to define search criteria.
  1470. //===================================================================
  1471. BOOL FAR PASCAL _export
  1472. SearchDlgProc (HWND hDlg, WORD msg, WORD wParam, LONG lParam)
  1473. {
  1474.     INT16   len;
  1475.     BOOL    ret = FALSE;
  1476.  
  1477.     // Avoid warning: Parameter not used
  1478.     lParam = lParam;
  1479.  
  1480.     // Process dialog
  1481.     switch (msg)
  1482.     {
  1483.         case WM_INITDIALOG:
  1484.             // Set search value to what it was previously
  1485.             if (Search.pSearchStr)
  1486.             {
  1487.                 SendDlgItemMessage(hDlg, IDE_SEARCH_TEXT, WM_SETTEXT, 0,
  1488.                                    (LPARAM)(LPCSTR) Search.pSearchStr);
  1489.             }
  1490.             else
  1491.             {
  1492.                 SendDlgItemMessage(hDlg, IDE_SEARCH_TEXT, WM_SETTEXT, 0,
  1493.                                    (LPARAM)(LPCSTR) "Dbi");
  1494.             }
  1495.  
  1496.             // Set check boxes to previous values
  1497.             SendDlgItemMessage(hDlg, IDCHK_CASE_SENS, BM_SETCHECK,
  1498.                                (WPARAM) Search.bCaseSens, (LPARAM) 0);
  1499.  
  1500.             // Set the "Cancel" flag before returning
  1501.             ret = TRUE;
  1502.             Search.bCancelPressed = TRUE;
  1503.             break;
  1504.         case WM_COMMAND:
  1505.             switch (wParam)
  1506.             {
  1507.                 case IDOK:
  1508.                     // Get the search string
  1509.                     if (Search.pSearchStr)
  1510.                     {
  1511.                         free(Search.pSearchStr);
  1512.                     }
  1513.                     len = (INT16) SendDlgItemMessage(hDlg, IDE_SEARCH_TEXT,
  1514.                                                      WM_GETTEXTLENGTH, 0, 0);
  1515.                     Search.pSearchStr = (char *)malloc(len + 10);
  1516.                     SendDlgItemMessage(hDlg, IDE_SEARCH_TEXT, WM_GETTEXT,
  1517.                                        (WPARAM) (len + 1),
  1518.                                        (LPARAM)(LPCSTR) Search.pSearchStr);
  1519.                     Search.pLastSearch = Search.pText;
  1520.  
  1521.                     // Get the search options
  1522.                     Search.bCaseSens =
  1523.                         (BOOL) SendDlgItemMessage(hDlg, IDCHK_CASE_SENS,
  1524.                                                   BM_GETCHECK, 0, 0);
  1525.  
  1526.                     // End the dialog
  1527.                     ret = TRUE;
  1528.                     Search.bCancelPressed = FALSE;
  1529.                     EndDialog(hDlg, TRUE);
  1530.                     break;
  1531.                 case IDCANCEL:
  1532.                     ret = TRUE;
  1533.                     EndDialog(hDlg, TRUE);
  1534.                     break;
  1535.             }
  1536.             break;
  1537.     }
  1538.     return ret;
  1539. }
  1540.