home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bde / sdkqry.pak / QUERY.C < prev    next >
C/C++ Source or Header  |  1997-07-23  |  54KB  |  1,508 lines

  1. // BDE - (C) Copyright 1994 by Borland International
  2.  
  3. #include "query.h"
  4.  
  5. #define FILEHANDLESNEEDED 40
  6.  
  7. static char szStandard[] = "<STANDARD>";
  8.  
  9. static DBStructArray dbarray;   // Global array of structures containing
  10.                                 //   database connections (hDb's) and names.
  11.  
  12. static int iSelectedDbIndex;    // Index to currently selected
  13.                                 //   database connection.
  14.  
  15. void SetSelected(HWND hDlg);
  16.  
  17. //=================================================================
  18. //  Function:
  19. //          WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  20. //
  21. //  Input:  hInstance       - The handle that represents the applications
  22. //                            unique instance ID
  23. //          hPrevInstance   - Indicates if this is the first instance
  24. //                            of the app
  25. //          lpCmdLine       - Command line parameters (up to the app
  26. //                            to parse)
  27. //          nCmdShow        - TRUE = Show as non-icon application
  28. //
  29. //  Return: Exit code (wParam value of WM_QUIT message)
  30. //
  31. //  Description:
  32. //          This is the application entry point for the Query sample
  33. //          application. It will set up the app, init the instance,
  34. //          process all event driven messages, and clean up the
  35. //          application prior to returning to Windows.
  36. //=================================================================
  37. int _pascal
  38. WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
  39.             int nCmdShow)
  40. {
  41.     MSG     msg;
  42.  
  43.     lpCmdLine = lpCmdLine;
  44.     nCmdShow = nCmdShow;
  45.  
  46.     // Register CTL3D
  47.     Ctl3dRegister(hInstance);
  48.     Ctl3dAutoSubclass(hInstance);
  49.  
  50.     // Make this a single instance program
  51.     if (hPrevInstance)
  52.     {
  53.         MessageBox(GetFocus(), "This application is already running!",
  54.                    "Windows Driver", MB_OK | MB_ICONHAND);
  55.         return FALSE;
  56.     }
  57.  
  58.     // Start the application, and set the main dialog to not show until
  59.     //   everything is setup.
  60.     hInst = hInstance;
  61.     if (InitApp(SW_SHOW) == FALSE)
  62.     {
  63.         return FALSE;
  64.     }
  65.  
  66.     // Process all event driven messages.
  67.     while (GetMessage(&msg, NULL, NULL, NULL))
  68.     {
  69.         if ((hMainWnd == NULL) || (!IsDialogMessage(hMainWnd, &msg)))
  70.         {
  71.             TranslateMessage(&msg);
  72.             DispatchMessage(&msg);
  73.         }
  74.     }
  75.  
  76.     // Unregister CTL3D.
  77.     Ctl3dUnregister(hInstance);
  78.  
  79.     return msg.wParam;
  80. }
  81.  
  82. //====================================================================
  83. //  Function:
  84. //          InitApp(nCmdShow);
  85. //
  86. //  Input:  nCmdShow    - Show the main window
  87. //
  88. //  Return: TRUE    - Init worked
  89. //          FALSE   - Init failed
  90. //
  91. //  Description:
  92. //          Create the application window & init any default
  93. //          of the main window.
  94. //====================================================================
  95. BOOL
  96. InitApp (int nCmdShow)
  97. {
  98.     WNDCLASS    wc;
  99.     UINT16      i;
  100.     UINT16      uCount;
  101.     // Path returned by the GetPrivateProfileString() function
  102.     CHAR        szRelativeTblDirectory[DBIMAXPATHLEN+1];
  103.     CHAR        szMessage[(DBIMAXMSGLEN * 2)];  // Allocate enough space to
  104.                                                 //   contain message
  105.  
  106.     // Init the application & create the needed windows.
  107.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  108.     wc.lpfnWndProc   = MainWndProc;
  109.     wc.cbClsExtra    = 0;
  110.     wc.cbWndExtra    = DLGWINDOWEXTRA;
  111.     wc.hInstance     = hInst;
  112.     wc.hIcon         = LoadIcon(hInst, MAKEINTRESOURCE(9999));
  113.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  114.     wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  115.     wc.lpszMenuName  = NULL;
  116.     wc.lpszClassName = "MainWindowClass";
  117.  
  118.     // Register the class.
  119.     if (!RegisterClass(&wc))
  120.     {
  121.         MessageBox(NULL, "RegisterClass failed!",  "System Error",
  122.                    MB_OK | MB_ICONHAND);
  123.         return FALSE;
  124.     }
  125.  
  126.     // Increase the number of file handles that are available to the
  127.     //   system.  
  128.     uCount = SetHandleCount(FILEHANDLESNEEDED);
  129.     if (uCount < FILEHANDLESNEEDED)
  130.     {
  131.         MessageBox(NULL, "Not enough file handles available. Please set"
  132.                    " FILES=40 in your CONFIG.SYS.",  "System Error",
  133.                    MB_OK | MB_ICONHAND);
  134.         return FALSE;
  135.     }
  136.  
  137.     // Get the directory which contains the tables. 
  138.     GetPrivateProfileString("QUERY",
  139.                             "TblDir",
  140.                             "..\\TABLES", 
  141.                             (LPSTR)szRelativeTblDirectory,
  142.                             sizeof(szRelativeTblDirectory),
  143.                             "bde.ini");
  144.  
  145.     // Create a fully qualified pathname for the table directory.
  146.     if (MakeFullPath(szTblDirectory, szRelativeTblDirectory))
  147.     {
  148.         sprintf(szMessage, "Table Directory does not exist: %s",
  149.                 szTblDirectory);
  150.         MessageBox(NULL, szMessage, "System Error", MB_OK | MB_ICONHAND);
  151.         return FALSE;
  152.     }
  153.  
  154.     // Get the private directory. 
  155.     GetPrivateProfileString("QUERY",
  156.                             "PrivateDir",
  157.                             ".",
  158.                             (LPSTR)szRelativeTblDirectory,
  159.                             sizeof(szRelativeTblDirectory),
  160.                             "bde.ini");
  161.  
  162.     // Create a fully qualified pathname for the table directory.
  163.     if (MakeFullPath(szPrivDirectory, szRelativeTblDirectory))
  164.     {
  165.         sprintf(szMessage, "Private Directory does not exist: %s."
  166.                 "\r\nPlease check BDE.INI in your Windows directory.",
  167.                 szPrivDirectory);
  168.         MessageBox(NULL, szMessage, "System Error", MB_OK | MB_ICONHAND);
  169.         return FALSE;
  170.     }
  171.     
  172.     // Initialize Database Engine.
  173.     if (QueryDbiInit() != DBIERR_NONE)
  174.     {
  175.         MessageBox(NULL, "Application will terminate", "Error", MB_OK);
  176.         return FALSE;
  177.     }
  178.  
  179.     // Explicitly initialize global array.
  180.     for (i = 0; i < MAX_DATABASE_HANDLES; i++)
  181.     {
  182.         dbarray[i].hdb = 0;
  183.         dbarray[i].szDatabaseName[0] = '\0';
  184.     }
  185.  
  186.     // Create the dialog that serves as the main window.
  187.     hMainWnd = CreateDialog(hInst, "MainDlg", 0, NULL);
  188.     if (hMainWnd == NULL)
  189.     {
  190.         MessageBox(NULL, "CreateDialog failed!",  "System Error",
  191.                    MB_OK | MB_ICONHAND);
  192.         return FALSE;
  193.     }
  194.  
  195.     _wpOrigWndProc = SubClassWindow(GetDlgItem(hMainWnd, IDC_QUERY_EDIT),
  196.                                     EditSubClassProc);
  197.  
  198.     _wpOrigWndProc1 = SubClassWindow(GetDlgItem(hMainWnd, IDC_RESULT_EDIT),
  199.                                     EditSubClassProc);
  200.  
  201.     ShowWindow(hMainWnd, nCmdShow);
  202.     return TRUE;
  203. }                                                       
  204.  
  205. // ===============================================================
  206. //  Function:
  207. //          MainWndProc(hWnd, msg, wParam, lParam);
  208. //
  209. //  Description:
  210. //          This routine will process all messages for the primary
  211. //          application window. Included in this are all menu
  212. //          commands.
  213. // ===============================================================
  214. LRESULT CALLBACK
  215. MainWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  216. {
  217.     static FARPROC         lpfnConnectDlgProc;
  218.     static DLGPROC         lpfnAboutDlgProc;
  219.     static DBIQryLang      eQryLang;
  220.     static CBPROGRESSDesc  CbBuf;
  221.     char *                 szQuery = NULL;
  222.     static hDBICur         hCur = 0;
  223.     DBIResult              rslt;
  224.     LONG                   lTextLength;
  225.     static char            szOutputErrorString[(DBIMAXMSGLEN * 6) + 80];
  226.     static char            szSelectedDatabase[80];
  227.     static HFONT           hFont;
  228.     DWORD                  lMinMax;    // Contains both offset of first and
  229.                                        // last selected characters
  230.     WORD                   iStart;     // Offset of first selected character
  231.     WORD                   iEnd;       // Offset of last selected character
  232.     HWND                   hwnd;
  233.     HBRUSH                 hBrush;
  234.  
  235.     switch (msg)
  236.     {
  237.         case WM_CREATE:
  238.             eQryLang = qrylangSQL;
  239.  
  240.             // Set up default database.
  241.             dbarray[0].hdb = QueryGetStandardConnection();
  242.             iSelectedDbIndex = 0;
  243.             strcpy(dbarray[iSelectedDbIndex].szDatabaseName, szStandard);
  244.  
  245.             if (dbarray[iSelectedDbIndex].hdb == 0)
  246.             {
  247.                 MessageBox(NULL, "Unable to create STANDARD standard "
  248.                            "database.", "Application Error",
  249.                            MB_ICONHAND);
  250.             }
  251.             PostMessage(hWnd, WM_SETUP, 0, 0);
  252.             return FALSE;
  253.  
  254.         case WM_SETUP:
  255.             hwnd = GetWindow(hWnd, GW_CHILD);
  256.             while (hwnd != NULL)
  257.             {
  258.                 Ctl3dSubclassCtl(hwnd);
  259.                 hwnd = GetWindow(hwnd, GW_HWNDNEXT);
  260.             }
  261.  
  262.             if (! SendDlgItemMessage(hWnd, IDC_RADIO_QBE, BM_GETCHECK, 0, 0))
  263.             {
  264.                 SendDlgItemMessage(hWnd, IDC_RADIO_SQL, BM_SETCHECK, 1, 0);
  265.             }
  266.  
  267.             // Set the font of the edit controls to be a fixed pitch font.
  268.             hFont = (HFONT) GetStockObject(ANSI_FIXED_FONT);
  269.             SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_SETFONT,
  270.                               (WPARAM) hFont, FALSE);
  271.             SendDlgItemMessage(hWnd, IDC_RESULT_EDIT, WM_SETFONT,
  272.                                (WPARAM) hFont, FALSE);
  273.  
  274.             break;
  275.  
  276.         case WM_CTLCOLOR:
  277.             hBrush = Ctl3dCtlColorEx(msg, wParam, lParam);
  278.             if (hBrush != (HBRUSH)0)
  279.             {
  280.                 return (long)(WORD)hBrush;
  281.             }
  282.             else
  283.             {
  284.                 return DefWindowProc(hWnd, msg, wParam, lParam);
  285.             }
  286.  
  287.         case WM_SYSCOLORCHANGE:
  288.             Ctl3dColorChange();
  289.             return TRUE;
  290.  
  291.         case WM_NCPAINT:
  292.         case WM_NCACTIVATE:
  293.         case WM_SETTEXT:
  294.             return Ctl3dDlgFramePaint(hWnd, msg, wParam, lParam);
  295.  
  296.         case WM_SETFOCUS:
  297.             // Need to set the focus to the first element of the dialog box.
  298.             SetFocus(GetDlgItem(hWnd, IDC_QUERY_EDIT));
  299.  
  300.             // Set static control displaying currently selected database.
  301.             if (dbarray[iSelectedDbIndex].hdb == NULL)
  302.             {
  303.                 sprintf(szSelectedDatabase, "No connection established");
  304.             }
  305.             else
  306.             {
  307.                 sprintf(szSelectedDatabase, "Current connection: %s", 
  308.                         dbarray[iSelectedDbIndex].szDatabaseName);
  309.             }
  310.             SendDlgItemMessage(hWnd, IDS_CURRENT_CONNECTION, 
  311.                                WM_SETTEXT, 0, (LPARAM) szSelectedDatabase);
  312.             
  313.             return FALSE;
  314.  
  315.         case WM_CLOSE:
  316.             // Done to get rid of the "Parameter Not used" warning.
  317.             //   Done in this way in order to work with both BC++ and VC++.
  318.             lParam = lParam;
  319.             DestroyWindow(hWnd);
  320.             return FALSE;
  321.  
  322.         case WM_DESTROY:
  323.             CleanUpAnswer(&hCur);
  324.             QueryDbiExit();
  325.             PostQuitMessage(0);
  326.             return FALSE;
  327.  
  328.         case WM_COMMAND:
  329.             switch (wParam)
  330.             {
  331.                 case IDC_EXIT:
  332.                     DestroyWindow(hWnd);
  333.                     return TRUE;
  334.  
  335.                 case IDC_RUN:
  336.                     // Allow query to be run only if we have a
  337.                     //   valid database handle.
  338.                     if (dbarray[0].hdb == 0)
  339.                     {
  340.                         MessageBox(NULL,
  341.                                    "No database connection established",
  342.                                    "Query SQL/QBE Example", MB_OK);
  343.                     }
  344.                     else
  345.                     {
  346.                         Cls();
  347.                         DisplayProgress("");
  348.  
  349.                         // Get the length of the query from the Query edit
  350.                         //   control.
  351.                         lTextLength = SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
  352.                                                          WM_GETTEXTLENGTH,
  353.                                                          0, 0);
  354.  
  355.                         // Allocate space to contain the query.
  356.                         if ((szQuery = (char*) malloc((int) lTextLength + 1))
  357.                             == NULL)
  358.                         {
  359.                             MessageBox(NULL, "Out of Memory!",
  360.                                        "Fatal Error", MB_ICONHAND);
  361.                             return TRUE;
  362.                         }
  363.  
  364.                         HourGlassCursor(TRUE);
  365.  
  366.                         // Setup the callback.
  367.                         RegisterCallBack(hCur, cbGENPROGRESS,
  368.                                          (UINT32)"Query Data",
  369.                                          sizeof(CBPROGRESSDesc),
  370.                                          (pVOID)&CbBuf, GenProgCallBack);
  371.  
  372.                         // Get the text of the query from the Query edit
  373.                         //   control.
  374.                         SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_GETTEXT,
  375.                                            (int) lTextLength + 1,
  376.                                            (LPARAM) szQuery);
  377.  
  378.                         // Close the cursor if it is open.
  379.                         CleanUpAnswer(&hCur);
  380.  
  381.                         // Execute the query.
  382.                         rslt = QueryQExec(dbarray[iSelectedDbIndex].hdb,
  383.                                           eQryLang, szQuery,
  384.                                           szOutputErrorString, &hCur);
  385.  
  386.  
  387.                         // Remove Callback function.
  388.                         RegisterCallBack(hCur, cbGENPROGRESS,
  389.                                          (UINT32)"Query Data",
  390.                                          sizeof(CBPROGRESSDesc),
  391.                                          (pVOID)&CbBuf, NULL);
  392.  
  393.                         if (szQuery)
  394.                         {
  395.                             free(szQuery);
  396.                         }
  397.  
  398.                         // Check if query failed.
  399.                         if (rslt != DBIERR_NONE)
  400.                         {
  401.                             Cls();
  402.                             Screen(szOutputErrorString);
  403.  
  404.                             HourGlassCursor(FALSE);
  405.                             return TRUE;
  406.                         }
  407.  
  408.                         // Terminate if no cursor was returned.
  409.                         if (hCur == 0)
  410.                         {
  411.                             Cls();
  412.                             Screen("No information returned from Query.");
  413.  
  414.                             HourGlassCursor(FALSE);
  415.                             return TRUE;
  416.                         }
  417.  
  418.                         Cls();
  419.                         DisplayTable(hCur, 0);
  420.                     }
  421.                     HourGlassCursor(FALSE);
  422.                     return TRUE;
  423.  
  424.                 case IDC_LOADQUERY:
  425.                     LoadQuery(eQryLang);
  426.                     return TRUE;
  427.  
  428.                 case IDC_SAVEQUERY:
  429.                     SaveQuery(eQryLang);
  430.                     return TRUE;
  431.  
  432.                 case IDC_SAVERESULT:
  433.                     if (!hCur || !dbarray[0].hdb)
  434.                     {
  435.                         MessageBox(NULL, "No result set to save.",
  436.                                    "Error", MB_ICONHAND);
  437.                     }
  438.                     else
  439.                     {
  440.                         if (!SaveResultSet (hCur, dbarray[0].hdb))
  441.                         {
  442.                             MessageBox(NULL, "Error saving result set",
  443.                                        "Error", MB_ICONHAND);
  444.                         }
  445.                     }
  446.                     return TRUE;
  447.  
  448.                 case IDC_CONNECT:
  449.                     lpfnConnectDlgProc = MakeProcInstance
  450.                             ((FARPROC)ConnectDlgProc, hInst);
  451.  
  452.                     DialogBox(hInst, szConnectDialogName,
  453.                                hWnd, (DLGPROC)lpfnConnectDlgProc);
  454.  
  455.                     FreeProcInstance(lpfnConnectDlgProc);
  456.                     return TRUE;
  457.  
  458.                 case IDC_HELP:
  459.                     MessageBox(NULL, szMainHelpText,
  460.                                "Query SQL/QBE Example", MB_OK);
  461.                     return TRUE;
  462.  
  463.                 case IDC_ABOUT:
  464.                     lpfnAboutDlgProc = (DLGPROC)MakeProcInstance((FARPROC)
  465.                                         AboutDlg, hInst);
  466.                     DialogBox(hInst, "AboutDlg", hWnd, lpfnAboutDlgProc);
  467.                     FreeProcInstance((FARPROC)lpfnAboutDlgProc);
  468.                     return TRUE;
  469.  
  470.                 case IDC_RADIO_QBE:
  471.                     eQryLang = qrylangQBE;
  472.                     return TRUE;
  473.  
  474.                 case IDC_RADIO_SQL:
  475.                     eQryLang = qrylangSQL;
  476.                     return TRUE;
  477.  
  478.                 case IDM_COPY:
  479.                     // Determine which characters are selected.
  480.                     lMinMax = SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
  481.                                                  EM_GETSEL, 0, 0L);
  482.  
  483.                     // Get the first and last selected character.
  484.                     iStart = LOWORD(lMinMax);
  485.                     iEnd   = HIWORD(lMinMax);
  486.  
  487.                     // If nothing is selected, select all.
  488.                     if (iStart == iEnd)
  489.                     {
  490.                         SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
  491.                                            EM_SETSEL, 0, 0xfffeL);
  492.                     }
  493.  
  494.                     // Copy the selected text in the QUERY edit box.
  495.                     SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_COPY, 0, 0L);
  496.                     return TRUE;
  497.  
  498.                 case IDM_PASTE:
  499.                     SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
  500.                                        WM_PASTE, 0, 0L);
  501.                     return TRUE;
  502.  
  503.                 case IDM_CLEAR:
  504.                     SendDlgItemMessage(hWnd, IDC_QUERY_EDIT,
  505.                                        WM_SETTEXT, 0, (LPARAM)(LPCSTR)"");
  506.                     return TRUE;
  507.                     
  508.                 case IDM_CLEARRESULT:
  509.                     SendDlgItemMessage(hWnd, IDC_RESULT_EDIT,
  510.                                        WM_SETTEXT, 0, (LPARAM)(LPCSTR)"");
  511.                     return TRUE;
  512.                     
  513.                 case IDM_DELETE:
  514.                     PostMessage(hWnd, WM_COMMAND, IDM_CLEAR, 0l);
  515.                     PostMessage(hWnd, WM_COMMAND, IDM_CLEARRESULT, 0l);
  516.                     return TRUE;
  517.  
  518.                 case IDM_CUT:
  519.                     SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, WM_COPY, 0, 0L);
  520.                     SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, EM_REPLACESEL, 0,
  521.                                        (LPARAM)(LPCSTR)"");
  522.                     return TRUE;
  523.  
  524.                 case IDM_UNDO:
  525.                     SendDlgItemMessage(hWnd, IDC_QUERY_EDIT, EM_UNDO, 0, 0L);
  526.                     return TRUE;
  527.             }
  528.     }
  529.     return DefWindowProc(hWnd, msg, wParam, lParam);
  530. }
  531.  
  532. //======================================================================
  533. //  Function:
  534. //          EditSubClassProc(hWnd, msg, wParam, lParam)
  535. //
  536. //  Input:  hWnd    - Handle of the window
  537. //          msg     - Message
  538. //          wParam  - WPARAM
  539. //          lParam  - LPARAM
  540. //
  541. //  Return: It returns the result of the procedure.  It can return the
  542. //          result of the original edit control if the WM_CHAR is not a
  543. //          tab character.
  544. //
  545. //  Description:
  546. //          This routine will process all I/O for the Comments edit
  547. //          control.  It does this by first checking if the tab key was
  548. //          hit inside of the comment edit control.  If it was it moves
  549. //          control to the next control item and then does NOT let the
  550. //          original edit control process the message.  However, if the
  551. //          WM_CHAR is not a tab then it lets the original edit control
  552. //          process the message.
  553. //======================================================================
  554. long FAR _pascal _export
  555. EditSubClassProc (HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  556. {
  557.     LRESULT lResult = 0;
  558.     BOOL    fCallOrigWndProc = TRUE;
  559.     INT16   iId;
  560.     UINT32  lType;
  561.     WNDPROC WndProc;
  562.  
  563.     iId = GetDlgCtrlID(hWnd);
  564.     if (iId == IDC_QUERY_EDIT)
  565.     {
  566.         WndProc = (WNDPROC)_wpOrigWndProc;
  567.     }
  568.     else
  569.     {
  570.         WndProc = (WNDPROC)_wpOrigWndProc1;
  571.     }
  572.  
  573.     switch (msg)
  574.     {
  575.         case WM_GETDLGCODE:
  576.             return DLGC_WANTMESSAGE;
  577.  
  578.         case WM_CHAR:
  579.             if (wParam == '\t')
  580.             {
  581.                 if (GetKeyState(VK_SHIFT)<0)
  582.                 {
  583.                     if (iId == IDC_QUERY_EDIT)
  584.                     {
  585.                         iId = IDC_RESULT_EDIT;
  586.                     }
  587.                     else
  588.                     {
  589.                         iId = IDC_RUN;
  590.                     }
  591.                 }
  592.                 else
  593.                 {
  594.                     if (iId == IDC_QUERY_EDIT)
  595.                     {
  596.                         lType = SendDlgItemMessage(hMainWnd, IDC_RADIO_SQL,
  597.                                                    BM_GETCHECK, 0, 0L);
  598.                         if (lType == 1)
  599.                         {
  600.                             iId = IDC_RADIO_SQL;
  601.                         }
  602.                         else
  603.                         {
  604.                             iId = IDC_RADIO_QBE;
  605.                         }
  606.                     }
  607.                     else
  608.                     {
  609.                         iId = IDC_QUERY_EDIT;
  610.                     }
  611.                 }
  612.  
  613.                 SetFocus(GetDlgItem(hMainWnd, iId));
  614.                 fCallOrigWndProc = FALSE;
  615.                 lResult = TRUE;
  616.             }
  617.  
  618.             if (wParam == VK_ESCAPE)
  619.             {
  620.                 MessageBeep(1);
  621.             }
  622.             break;
  623.     }
  624.  
  625.     if (fCallOrigWndProc)
  626.     {
  627.         lResult = CallWindowProc(WndProc, hWnd, msg, wParam, lParam);
  628.     }
  629.     
  630.     return lResult;
  631. }
  632.  
  633. //======================================================================
  634. //  Function:
  635. //          AboutDlg(hWnd, msg, wParam, lParam)
  636. //
  637. //  Input:  hWnd, msg, wParam, lParam
  638. //
  639. //  Return: TRUE -  Dialog Created.
  640. //          FALSE - Dialog Failed to create.
  641. //
  642. //  Description:
  643. //          This routine will process all I/O for the ABOUT dialog.
  644. //======================================================================
  645. BOOL FAR _pascal _export
  646. AboutDlg (HWND hWnd, WORD msg, WORD wParam, LONG lParam)
  647. {
  648.     BOOL    ret = FALSE;
  649.  
  650.     // Done to clear the unused warning.
  651.     lParam = lParam;
  652.  
  653.     switch (msg)
  654.     {
  655.         case WM_COMMAND:
  656.             switch (wParam)
  657.             {
  658.                 case IDOK:
  659.                 case IDCANCEL:
  660.                     ret = TRUE;
  661.                     EndDialog(hWnd, ret);
  662.                     break;
  663.             }
  664.             break;
  665.     }
  666.     return ret;
  667. }
  668.  
  669. //======================================================================
  670. //  Function:
  671. //          ConnectDlgProc(hDlg, message, wParam, lParam)
  672. //
  673. //  Input:  hDlg, message, wParam, lParam
  674. //
  675. //  Return: TRUE if dialog procedure processes a message
  676. //          FALSE otherwise.
  677. //
  678. //  Description:
  679. //          Dialog box procedure for the dialog box that establishes
  680. //          and removes connections to databases based on ALIASES
  681. //          defined in IDAPI.CFG.
  682. //======================================================================
  683. BOOL CALLBACK _export
  684. ConnectDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  685. {
  686.     int                  i;
  687.     char                 szAliasName[81];
  688.     WORD                 ListIndex;
  689.     int                  nIndex;
  690.     char                 szConnectionName[DBIMAXPATHLEN + 1];
  691.     static char          szDirectory[DBIMAXPATHLEN+1];
  692.     char                 szTemp[DBIMAXPATHLEN + 1];
  693.  
  694.     switch (message)
  695.     {
  696.         case WM_INITDIALOG:
  697.             QueryResetConnectDialog(hDlg, dbarray, iSelectedDbIndex);
  698.             if (dbarray[0].hdb != 0)
  699.             {
  700.                 GetWorkingDirectory(dbarray[0].hdb, szDirectory);
  701.             }
  702.             ShowWindow(hDlg, SW_HIDE);
  703.             PostMessage(hDlg, WM_MYSETUP, 0, 0);
  704.             return TRUE;
  705.  
  706.         case WM_MYSETUP:
  707.       
  708.             SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION,
  709.                                WM_GETTEXT,
  710.                                DBIMAXPATHLEN, (LPARAM)szConnectionName);
  711.  
  712.             // Check if this is the standard database.
  713.             if (!strcmp(szConnectionName, szStandard))
  714.             {
  715.                 // Show the Directory controls.
  716.                 ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
  717.                            SW_SHOW);
  718.                 ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
  719.                            SW_SHOW);
  720.             }
  721.             else
  722.             {
  723.                 // Hide the Directory controls.
  724.                 ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
  725.                            SW_HIDE);
  726.                 ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
  727.                            SW_HIDE);
  728.             }
  729.  
  730.             // Set the directory.
  731.             SendDlgItemMessage(hDlg, IDC_EDIT_DIRECTORY, WM_SETTEXT, 0,
  732.                                (LPARAM)(LPCSTR)szDirectory);
  733.  
  734.             ShowWindow(hDlg, SW_SHOW);
  735.  
  736.             return TRUE;
  737.  
  738.         case WM_CLOSE:
  739.             EndDialog(hDlg, 0);
  740.             return TRUE;
  741.  
  742.         case WM_COMMAND:
  743.             switch (wParam)
  744.             {
  745.                 case IDC_LB_CONNECTIONS:
  746.                     if (HIWORD(lParam) == LBN_SELCHANGE)
  747.                     {
  748.                         SetSelected(hDlg);
  749.                     }
  750.                     return TRUE;
  751.  
  752.                 case IDC_BTN_CONNECT:
  753.                     // First check to see if any alias is selected,
  754.                     //   if not, beep.
  755.                     ListIndex = (WORD)
  756.                                  SendDlgItemMessage(hDlg, IDC_LB_ALIASES,
  757.                                                     LB_GETCURSEL, 0, 0);
  758.                     if (ListIndex == (WORD) LB_ERR)
  759.                     {
  760.                         MessageBeep(MB_ICONEXCLAMATION);
  761.                         return TRUE;
  762.                     }
  763.  
  764.                     // If an alias is selected, run through
  765.                     //   the array of handles/descriptions to see if we
  766.                     //   have any free one's left.
  767.                     for (i = 1; i < MAX_DATABASE_HANDLES; i++)
  768.                     {
  769.                         if (dbarray[i].hdb == 0)
  770.                         {
  771.                             break;
  772.                         }
  773.                     }
  774.  
  775.                     // If we don't, provide an error message.
  776.                     if (i == MAX_DATABASE_HANDLES)
  777.                     {
  778.                         MessageBox(NULL, "Maximum database handles limit "
  779.                                    "reached.", "Error", MB_OK);
  780.                     }
  781.                     else
  782.                     {
  783.                         // If we do have room left in our array,
  784.                         //   try to establish connection.  If successful,
  785.                         //   add database name to connections list.
  786.  
  787.                         HourGlassCursor(TRUE);
  788.                         if ((dbarray[i].hdb =
  789.                             QueryConnectToDatabase(hDlg)) != 0)
  790.                         {
  791.                             ListIndex = (WORD)
  792.                                         SendDlgItemMessage(hDlg, IDC_LB_ALIASES,
  793.                                                            LB_GETCURSEL, 0, 0);
  794.                             SendDlgItemMessage(hDlg, IDC_LB_ALIASES,
  795.                                                LB_GETTEXT,
  796.                                                (WPARAM)ListIndex,
  797.                                                (LPARAM)szAliasName);
  798.  
  799.                             strcpy(dbarray[i].szDatabaseName, szAliasName);
  800.                             SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS,
  801.                                                LB_ADDSTRING, 0,
  802.                                                (LPARAM)szAliasName);
  803.                             SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS,
  804.                                                LB_SELECTSTRING, 
  805.                                                (WPARAM)-1,
  806.                                                (LPARAM)szAliasName);
  807.                             SetSelected(hDlg);                                               
  808.                         }
  809.                         HourGlassCursor(FALSE);
  810.                     }
  811.                  
  812.                     return TRUE;
  813.  
  814.                 case IDC_BTN_REMOVE:
  815.                     // Disconnect from the selected connection.
  816.                     nIndex = (WORD)
  817.                               SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS,
  818.                                                  LB_GETCURSEL, 0, 0);
  819.  
  820.                     RemoveConnection(hDlg, dbarray, nIndex);
  821.                     return TRUE;
  822.  
  823.                 case IDC_BTN_HELP:
  824.                     // Display information on this application.
  825.                     MessageBox(NULL, szConnectHelpText, "Help", MB_OK);
  826.                     return TRUE;
  827.  
  828.                 case IDOK:
  829.                     // find currently selected database based
  830.                     //   on the string in the static control
  831.                     //   displaying this information.
  832.  
  833.                     // Get currently selected database.
  834.                     SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION,
  835.                                        WM_GETTEXT, 80,
  836.                                        (LPARAM) szConnectionName);
  837.  
  838.                     // Compare currently selected database
  839.                     //   to the strings in the array and
  840.                     //   set iSelectedDbIndex based on that.
  841.                     //   iSelectedDbIndex is in turn used
  842.                     //   as the database handle used to
  843.                     //   execute queries.
  844.                     for (i = 0; i < MAX_DATABASE_HANDLES,
  845.                          dbarray[i].hdb != 0; i++)
  846.                     {
  847.                         if (strcmpi(dbarray[i].szDatabaseName,
  848.                                      szConnectionName) == 0)
  849.                         {
  850.                             iSelectedDbIndex = i;
  851.                             break;
  852.                         }
  853.                     }
  854.  
  855.                     if (i == MAX_DATABASE_HANDLES)
  856.                     {
  857.                         iSelectedDbIndex = 0;
  858.                     }
  859.  
  860.                     // Check if this is the standard database.
  861.                     if (!strcmp(szConnectionName, szStandard))
  862.                     {
  863.                         // Get currently selected directory.
  864.                         SendDlgItemMessage(hDlg, IDC_EDIT_DIRECTORY,
  865.                                            WM_GETTEXT, DBIMAXPATHLEN,
  866.                                            (LPARAM)szTemp);
  867.                         // Only set if changed.
  868.                         if (strcmp(szTemp, szDirectory))
  869.                         {
  870.                             // Check if the directory exists.
  871.                             if (!access(szTemp, 00))
  872.                             {
  873.                                 if (SetWorkingDirectory(
  874.                                     dbarray[iSelectedDbIndex].hdb, szTemp))
  875.                                 {
  876.                                     SendDlgItemMessage(hDlg,
  877.                                                       IDC_STATIC_STATUS,
  878.                                                        WM_SETTEXT, 0,
  879.                                             (LPARAM) "Invalid Directory");
  880.                                     return FALSE;
  881.                                 }
  882.                             }
  883.                             else
  884.                             {
  885.                                 // Display message if directory does not exist.
  886.                                 SendDlgItemMessage(hDlg, IDC_STATIC_STATUS,
  887.                                                    WM_SETTEXT, 0,
  888.                                           (LPARAM) "Invalid Directory");
  889.                                 return FALSE;
  890.                             }
  891.                         }
  892.                     }
  893.                     else
  894.                     {
  895.                     }
  896.                     EndDialog (hDlg, 0);
  897.                     return TRUE;
  898.  
  899.                 case IDCANCEL:
  900.                     EndDialog (hDlg, 0);
  901.                     return TRUE;
  902.             }
  903.     }
  904.     return FALSE;
  905. }
  906.  
  907. //======================================================================
  908. //  Function:
  909. //          SetSelected (hDlg)
  910. //
  911. //  Input:  hDlg    - Handle of the Dialog
  912. //
  913. //  Return: None
  914. //
  915. //  Description:
  916. //          This routine sets which connection the application uses
  917. //          for processing the query.
  918. //======================================================================
  919. void
  920. SetSelected (HWND hDlg)
  921. {
  922.     WORD ListIndex;
  923.     char                 szConnectionName[DBIMAXPATHLEN + 1];
  924.  
  925.     // Determine which connection is selected.
  926.     ListIndex = (WORD)SendDlgItemMessage(hDlg,
  927.                                          IDC_LB_CONNECTIONS,
  928.                                          LB_GETCURSEL, 0, 0);
  929.     // Get the selected connection.
  930.     SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS, LB_GETTEXT,
  931.                        (WPARAM)ListIndex,
  932.                        (LPARAM)szConnectionName);
  933.  
  934.     // Set the Static control with the selected connection.
  935.     SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION,
  936.                        WM_SETTEXT,
  937.                        0, (LPARAM) szConnectionName);
  938.  
  939.     // Check if this is the standard database.
  940.     if (!strcmp(szConnectionName, szStandard))
  941.     {
  942.         // Show the Directory controls.
  943.         ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
  944.                    SW_SHOW);
  945.         ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
  946.                    SW_SHOW);
  947.     }
  948.     else
  949.     {
  950.         // Hide the directory controls.
  951.         ShowWindow(GetDlgItem(hDlg, IDC_EDIT_DIRECTORY),
  952.                    SW_HIDE);
  953.         ShowWindow(GetDlgItem(hDlg, IDC_DIRECTORY),
  954.                    SW_HIDE);
  955.     }
  956. }
  957. //======================================================================
  958. //  Function:
  959. //          HourGlassCursor(turnOn)
  960. //
  961. //  Input:  turnOn  - Turn on or off the Hourglass cursor
  962. //
  963. //  Return: TRUE
  964. //
  965. //  Description:
  966. //          Turns the hourglass cursor on or off according to value
  967. //          specified in turnOn.
  968. //======================================================================
  969. BOOL CALLBACK
  970. HourGlassCursor (BOOL turnOn)
  971. {
  972.     if (turnOn)
  973.     {
  974.        if (SetCursor(LoadCursor(NULL, IDC_WAIT)))
  975.        {
  976.            ShowCursor(TRUE);
  977.        }
  978.     }
  979.     else
  980.     {
  981.         if (SetCursor(LoadCursor(NULL, IDC_ARROW)))
  982.         {
  983.             ShowCursor(TRUE);
  984.         }
  985.     }
  986.     return TRUE;
  987. }
  988.  
  989. //======================================================================
  990. //  Function:
  991. //          LoadQuery(QryType)
  992. //
  993. //  Input:  Query Type (DBIQryLang).
  994. //
  995. //  Return: 1 if succesful,
  996. //          0 if error
  997. //
  998. //  Description:
  999. //          Using a Windows 3.1 Common Dialog, opens a file open
  1000. //          dialog box to read a .QBE or .SQL query file into the
  1001. //          query edit window.
  1002. //======================================================================
  1003. UINT16
  1004. LoadQuery (DBIQryLang QryType)
  1005. {
  1006.     // File types for file open dialog box.
  1007.     char*           SQLFilter   =    "SQL Script(*.SQL)\0*.SQL\0"
  1008.                                      "QBE Script(*.QBE)\0*.QBE\0";
  1009.     char*           QBEFilter   =    "QBE Script(*.QBE)\0*.QBE\0"
  1010.                                      "SQL Script(*.SQL)\0*.SQL\0";
  1011.     HFILE           hFile;          // Handle to the returned file
  1012.     static char     pBuf[256];      // filename
  1013.     LONG            flength;        // length of file
  1014.     char            ch[1];          // input character
  1015.     OPENFILENAME    ofn;            // structure used by File Open
  1016.                                     //   common dialog
  1017.     char*           szInputBuffer;  // pointer to input buffer
  1018.     char*           start;          // pointer used as a marker
  1019.  
  1020.     // Init the structure used by File Open dialog.
  1021.     ofn.lStructSize = sizeof(OPENFILENAME);
  1022.     ofn.hwndOwner = hMainWnd;
  1023.     ofn.hInstance = hInst;
  1024.     if (QryType == qrylangQBE)
  1025.     {
  1026.         ofn.lpstrFilter = QBEFilter;
  1027.     }
  1028.     else
  1029.     {
  1030.         ofn.lpstrFilter = SQLFilter;
  1031.     }
  1032.     ofn.lpstrCustomFilter = NULL;
  1033.     ofn.nFilterIndex = 1L;
  1034.     ofn.lpstrFile = pBuf;
  1035.     ofn.nMaxFile = 256;
  1036.     ofn.lpstrFileTitle = NULL;
  1037.     ofn.nMaxFileTitle = 0;
  1038.     ofn.lpstrInitialDir = NULL;
  1039.     ofn.lpstrTitle = NULL;
  1040.     ofn.lpstrDefExt = NULL;
  1041.  
  1042.     ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
  1043.                 OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR;
  1044.  
  1045.     // Use the FileOpen common dialog box to get the file name.
  1046.     if (GetOpenFileName(&ofn))
  1047.     {
  1048.         // Open the selected file
  1049.         hFile = _lopen(ofn.lpstrFile, READ);
  1050.  
  1051.         if (hFile == HFILE_ERROR)
  1052.         {
  1053.             MessageBox(NULL, "Could Not Open File", "File Open",
  1054.                        MB_ICONHAND);
  1055.             return 0;
  1056.         }
  1057.  
  1058.         // Compute length of string needed for file text.
  1059.         flength = 0;
  1060.         while (_lread(hFile, ch, 1) != 0)
  1061.         {
  1062.             if (ch[0] == '\n')
  1063.             {
  1064.                 flength += 2;   // Need two for newline so
  1065.                                 //   we can format for edit control.
  1066.             }
  1067.             else
  1068.             {
  1069.                 flength++;      // Otherwise length equals one per char.
  1070.             }
  1071.         }
  1072.         // Add one for null.
  1073.         flength += 1;
  1074.  
  1075.         // Return to beginning of file.
  1076.         _llseek(hFile, 0, 0);
  1077.  
  1078.         // Allocate memory, pointer "start" will remember our place.
  1079.         start = szInputBuffer = (char *) malloc((int) flength + 1);
  1080.         memset(szInputBuffer, 0, (int) flength + 1);
  1081.  
  1082.         if (!szInputBuffer)
  1083.         {
  1084.             MessageBox(NULL, "Unable to allocate memory", "Error", MB_ICONHAND);
  1085.             return FALSE;
  1086.         }
  1087.  
  1088.         while ( _lread(hFile, ch, 1) != 0)
  1089.         {
  1090.             if (ch[0] == '\n')
  1091.             {
  1092.                 *szInputBuffer = '\r';
  1093.                 szInputBuffer++;
  1094.                 *szInputBuffer = '\n';
  1095.                 szInputBuffer++;
  1096.  
  1097.             }
  1098.             else // Otherwise just read in characters.
  1099.             {
  1100.                 *szInputBuffer = ch[0];
  1101.                 szInputBuffer++;
  1102.             }
  1103.         }
  1104.  
  1105.         // Reset to beginning of string.
  1106.         szInputBuffer = start;
  1107.  
  1108.         // Put the string into the edit control.
  1109.         SendDlgItemMessage(hMainWnd, IDC_QUERY_EDIT, WM_SETTEXT,
  1110.                            0, (LPARAM) szInputBuffer);
  1111.  
  1112.         // Cleanup.
  1113.         free(szInputBuffer);
  1114.  
  1115.         _lclose(hFile);
  1116.         return TRUE;
  1117.     }
  1118.  
  1119.     return FALSE;
  1120. }
  1121.  
  1122. //======================================================================
  1123. //  Function:
  1124. //          SaveQuery(QryType)
  1125. //
  1126. //  Input:  Query Type (DBIQryLang).
  1127. //
  1128. //  Return: 1 if succesful,
  1129. //          0 if error
  1130. //
  1131. //  Description:
  1132. //          Using a Windows 3.1 Common Dialog, opens a file save
  1133. //          dialog box to save the contents of the query edit
  1134. //          window to a .QBE or .SQL query file
  1135. //======================================================================
  1136. UINT16
  1137. SaveQuery (DBIQryLang QryType)
  1138. {
  1139.     // File types for File Save dialog box.
  1140.     char*           SQLFilter   =    "SQL Script(*.SQL)\0*.SQL\0"
  1141.                                      "QBE Script(*.QBE)\0*.QBE\0";
  1142.     char*           QBEFilter   =    "QBE Script(*.QBE)\0*.QBE\0"
  1143.                                      "SQL Script(*.SQL)\0*.SQL\0";
  1144.     static char     pBuf[256];      // filename
  1145.     HFILE           hFile;          // Handle to the file
  1146.     OFSTRUCT        ofStruct;       // OpenFile structure
  1147.     OPENFILENAME    ofn;            // structure used by File Open common dialog
  1148.     char*           szQuery;        // pointer to text buffer
  1149.     char*           szSeek;         // equals szQuery at first
  1150.     LONG            lTextLength;    // length of text
  1151.  
  1152.     // Init the structure used by File Open dialog.
  1153.     ofn.lStructSize = sizeof(OPENFILENAME);
  1154.     ofn.hwndOwner = hMainWnd;
  1155.     ofn.hInstance = hInst;
  1156.     if (QryType == qrylangQBE)
  1157.     {
  1158.         ofn.lpstrFilter = QBEFilter;
  1159.     }
  1160.     else
  1161.     {
  1162.         ofn.lpstrFilter = SQLFilter;
  1163.     }
  1164.     ofn.lpstrCustomFilter = NULL;
  1165.     ofn.nFilterIndex = 1L;
  1166.     ofn.lpstrFile = pBuf;
  1167.     ofn.nMaxFile = 256;
  1168.     ofn.lpstrFileTitle = NULL;
  1169.     ofn.nMaxFileTitle = 0;
  1170.     ofn.lpstrInitialDir = NULL;
  1171.     ofn.lpstrTitle = NULL;
  1172.     ofn.lpstrDefExt = NULL;
  1173.  
  1174.     ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
  1175.                 OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
  1176.  
  1177.     if (GetSaveFileName(&ofn))
  1178.     {
  1179.         // Determine the length of the text.
  1180.         lTextLength = SendDlgItemMessage(hMainWnd, IDC_QUERY_EDIT,
  1181.                                   WM_GETTEXTLENGTH,
  1182.                                   0, 0);
  1183.         // Allocate memory to contain the query.
  1184.         if ((szQuery = szSeek = (char*) malloc((int)lTextLength + 1))
  1185.            == NULL)
  1186.         {
  1187.             MessageBox(NULL, "Out of Memory!",
  1188.                       "Fatal Error", MB_ICONHAND);
  1189.             return FALSE;
  1190.         }
  1191.  
  1192.         // Get the query from the edit control.
  1193.         SendDlgItemMessage(hMainWnd, IDC_QUERY_EDIT, WM_GETTEXT,
  1194.                     (int)lTextLength + 1, (LPARAM)szQuery);
  1195.  
  1196.         // Open the selected file.
  1197.         hFile = OpenFile(ofn.lpstrFile, &ofStruct, OF_CREATE);
  1198.  
  1199.         // Check for errors.
  1200.         if (hFile == HFILE_ERROR)
  1201.         {
  1202.             MessageBox(NULL, "Could Not Open File", "File Open",
  1203.                        MB_ICONHAND);
  1204.             return FALSE;
  1205.         }
  1206.  
  1207.         // Format the query and write to file.
  1208.         while (*szQuery)
  1209.         {
  1210.             if (*szQuery == '\r')
  1211.             {
  1212.                 szQuery++;  // Ignore extra newline.  
  1213.             }
  1214.             else
  1215.             {
  1216.                 _lwrite(hFile, (void huge *)(szQuery++), 1);
  1217.             }
  1218.         }
  1219.  
  1220.         // Close the file.
  1221.         _lclose(hFile);
  1222.         // Free memory.
  1223.         free(szSeek);
  1224.     }
  1225.  
  1226.     return TRUE;
  1227. }
  1228.  
  1229. //======================================================================
  1230. //  Function:
  1231. //          SaveResultSet(hCur, hDb)
  1232. //
  1233. //  Input:  hCur    - Handle to the cursor of the in-memory table representing
  1234. //                    the result set of the last query.
  1235. //          hDb     - Handle to a STANDARD database.
  1236. //
  1237. //  Return: 1 on success
  1238. //          0 on failure
  1239. //
  1240. //  Description:
  1241. //          Using a Windows 3.1 Common Dialog, opens a file save 
  1242. //          dialog box to save the contents of the query edit
  1243. //          window to a .QBE or .SQL query file 
  1244. //======================================================================
  1245. UINT16
  1246. SaveResultSet (hDBICur hCur, hDBIDb hDb)
  1247. {
  1248.     static char     pBuf[256];     // filename
  1249.     char            pString[300];  // Message String
  1250.     OPENFILENAME    ofn;           // structure used by File Open common dialog
  1251.     char*           ScriptFilter = "Paradox Database(*.DB)|*.DB|";
  1252.     CHAR            chWildChar = '|'; // This is the wildcard separator
  1253.     UINT16          uCtr = 0;
  1254.  
  1255.     while (ScriptFilter[uCtr])
  1256.     {
  1257.         if (ScriptFilter[uCtr]==chWildChar)
  1258.         {
  1259.             ScriptFilter[uCtr]=0;
  1260.         }
  1261.         uCtr++;
  1262.     }
  1263.  
  1264.     // Init the structure used by File Open dialog.
  1265.     ofn.lStructSize = sizeof(OPENFILENAME);
  1266.     ofn.hwndOwner = hMainWnd;
  1267.     ofn.hInstance = hInst;
  1268.     ofn.lpstrFilter = ScriptFilter;
  1269.     ofn.lpstrCustomFilter = NULL;
  1270.     ofn.nFilterIndex = 1L;
  1271.     ofn.lpstrFile = pBuf;
  1272.     ofn.nMaxFile = 256;
  1273.     ofn.lpstrFileTitle = NULL;
  1274.     ofn.nMaxFileTitle = 0;
  1275.     ofn.lpstrInitialDir = NULL;
  1276.     ofn.lpstrTitle = NULL;
  1277.     ofn.lpstrDefExt = "DB";
  1278.  
  1279.     ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | 
  1280.                 OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
  1281.  
  1282.     if (GetSaveFileName(&ofn))
  1283.     {
  1284.         if (!QuerySaveResultSet(hCur, hDb, pBuf))
  1285.         {
  1286.             return FALSE;
  1287.         }
  1288.         else
  1289.         {
  1290.             wsprintf(pString, "%s was successfully created.", pBuf);
  1291.             MessageBox(hMainWnd, pString, "Query SQL/QBE Example", MB_OK);
  1292.         }    
  1293.     }
  1294.  
  1295.     return TRUE;
  1296. }
  1297.  
  1298. //======================================================================
  1299. //  Function:
  1300. //          RemoveConnection(hDlg, array, nIndex)
  1301. //
  1302. //  Input:  hDlg    - Handle to the connection dialog box.
  1303. //          array   - A DBStructArray, i.e., an array of structures
  1304. //                    containing valid database names and handles
  1305. //          nIndex  - Index into the connection dialog box of
  1306. //                    the database connection to be removed.
  1307. //
  1308. //  Return: 1 on success
  1309. //
  1310. //  Description:
  1311. //          Removes a database connection from the connection listbox
  1312. //          inside the connection dialog box.  Also removes the 
  1313. //          corrseponding structure from the array of structures passed
  1314. //          via the array parameter and resets the currently selected
  1315. //          selection to the STANDARD database.
  1316. //======================================================================
  1317. UINT16
  1318. RemoveConnection (HWND hDlg, DBStructArray array, int nIndex)
  1319. {
  1320.     int i;
  1321.     int j;
  1322.  
  1323.     switch(nIndex)
  1324.     {
  1325.         case 0:
  1326.             MessageBeep(MB_ICONEXCLAMATION);
  1327.             MessageBox(NULL, "Cannot delete STANDARD database", "Error",
  1328.                        MB_ICONEXCLAMATION);
  1329.             break;
  1330.  
  1331.         case LB_ERR:
  1332.             MessageBeep(MB_ICONEXCLAMATION);
  1333.             break;
  1334.  
  1335.         default:
  1336.             // Reset the static control showing currently selected dialog
  1337.             //   box back to the default.
  1338.             SendDlgItemMessage(hDlg, IDS_SELECTED_CONNECTION, WM_SETTEXT,
  1339.                                0, (LPARAM) szStandard);
  1340.  
  1341.             // Remove item from list box.
  1342.             SendDlgItemMessage(hDlg, IDC_LB_CONNECTIONS, LB_DELETESTRING,
  1343.                                nIndex, 0);
  1344.  
  1345.             // Close database handle.
  1346.             QueryDbiCloseDatabase(&array[nIndex].hdb);
  1347.                            
  1348.             // Pack array.
  1349.             for (i = nIndex, j = nIndex + 1; j < MAX_DATABASE_HANDLES;
  1350.                  i++, j++)
  1351.             {
  1352.                 array[i].hdb = array[j].hdb;
  1353.                 strcpy(array[i].szDatabaseName, array[j].szDatabaseName);
  1354.             }
  1355.  
  1356.             // Last member is now blank.
  1357.             array[j].hdb = 0;
  1358.             strcpy(array[j].szDatabaseName, "");
  1359.     }
  1360.  
  1361.     return TRUE;
  1362. }
  1363. //======================================================================
  1364. //  Function:
  1365. //          GenProgCallBack(ecbType, iClientData, pCbInfo)
  1366. //
  1367. //  Input:  ecbType     - Callback type (CBType)
  1368. //          iClientData - Pointer to client information that is passed into
  1369. //                        the callback function (UINT32)
  1370. //          pCbInfo     - The callback structure that holds the information
  1371. //                        about the current state of affairs with
  1372. //                        IDAPI(pVOID)
  1373. //
  1374. //  Return: The action that should be taken (CBRType)
  1375. //
  1376. //  Description:
  1377. //          This function is called when IDAPI is running an internal
  1378. //          process and the application setup the callback.  The callback
  1379. //          is sent the current CallBack type (ecbType) so that it can
  1380. //          react appropriatly.  It is sent the pointer to data that was
  1381. //          passed into the DbiRegisterCallBack function.  This data can
  1382. //          be a Window handle, pointer to a structure etc.  In this case
  1383. //          it is simply a string.  It is also sent information about the
  1384. //          state of this callback in the structure that was passed into
  1385. //          the DbiRegisterCallBack() function.  In our example the
  1386. //          callback is a progress callback - therefore, we passed a
  1387. //          progress structure into DbiRegisterCallBack().  We always
  1388. //          return cbrUSEDEF as we do not want to worry about the callback.
  1389. //          However, if this was another callback return type you may want
  1390. //          to return a different callback return type.
  1391. //======================================================================
  1392. CBRType DBIFN
  1393. GenProgCallBack (CBType ecbType, UINT32 iClientData, pVOID pCbInfo)
  1394. {
  1395.     CBPROGRESSDesc   *eCBPROGRESSDesc;
  1396.     CHAR      szMessage[DBIMAXMSGLEN + 1 + 30];  // Reserve space for max
  1397.                                                  //   Message plus client
  1398.                                                  //   data
  1399.  
  1400.     memset(szMessage, 0, DBIMAXMSGLEN + 1);
  1401.  
  1402.     // Set to stop a Unused variable warning.
  1403.     iClientData=iClientData;
  1404.  
  1405.     switch (ecbType)
  1406.     {
  1407.         // In case this is a General Progress callback display the progress
  1408.         //   information.
  1409.         case cbGENPROGRESS:
  1410.  
  1411.             // First cast the pVOID structure as a General Progress structure.
  1412.             eCBPROGRESSDesc = (CBPROGRESSDesc far *)pCbInfo;
  1413.  
  1414.             // Next if the percent done is -1 then the only relevent data is in
  1415.             //   the message string (szMsg).
  1416.             if (eCBPROGRESSDesc->iPercentDone < 0)
  1417.             {
  1418.                 wsprintf(szMessage, "%s", eCBPROGRESSDesc->szMsg);
  1419.                 DisplayProgress(szMessage);
  1420.             }
  1421.             else
  1422.             {
  1423.                 // Otherwise you can use the percent done.  Here we simply
  1424.                 //   display the percent complete.  But you can use this number
  1425.                 //   to display a moving bar to graphically display the amount
  1426.                 //   complete.
  1427.                 wsprintf(szMessage, "%s:%i",
  1428.                          eCBPROGRESSDesc->szMsg, eCBPROGRESSDesc->iPercentDone);
  1429.                 DisplayProgress(szMessage);
  1430.             }
  1431.             break;
  1432.  
  1433.         default:
  1434.             DisplayProgress(" ### In the Callback function");
  1435.     }
  1436.     return cbrUSEDEF;
  1437. }
  1438.  
  1439. //=====================================================================
  1440. //  Function:
  1441. //          MakeFullPath (pszDirectory, pszRelativeDirectory)
  1442. //
  1443. //  Input:  pszDirectory            - String to contain the path to the tables
  1444. //                                      directory
  1445. //          pszRelativeDirectory    - String which contains the relative offset
  1446. //                                      from the current directory
  1447. //
  1448. //  Return: int     - If the directory exists
  1449. //
  1450. //  Description:
  1451. //          This function is used to get the fully qualified path to
  1452. //          the directory which will contain the tables. This function
  1453. //          will only work when pszRelativeDirectory contains either "."
  1454. //          an absolute path, or <..\\..\\>TABLES.
  1455. //=====================================================================
  1456. int
  1457. MakeFullPath (pCHAR pszDirectory, pCHAR pszRelativeDirectory)
  1458. {
  1459.     int     iExists;    // Does the directory exist?
  1460.     int     iLen;       // Length of the path
  1461.     int     iLoop;      // Loop counter
  1462.     int     iDepth = 0; // How many ..\\ in the directory
  1463.     
  1464.     // Assume absolute path if second character is a ':'.
  1465.     if (pszRelativeDirectory[1] == ':')
  1466.     {
  1467.         strcpy(pszDirectory, pszRelativeDirectory);
  1468.     }
  1469.     else if (!strcmp(pszRelativeDirectory, "."))
  1470.     {
  1471.         // Get the current working directory.
  1472.         getcwd(pszDirectory, DBIMAXPATHLEN);
  1473.     }
  1474.     else
  1475.     {
  1476.         // Get the current working directory.
  1477.         getcwd(pszDirectory, DBIMAXPATHLEN);
  1478.         
  1479.         iLen = strlen(pszDirectory);
  1480.  
  1481.         // Remove relative parts of the path.
  1482.         iDepth = 0;
  1483.         while (!strncmp(&pszRelativeDirectory[iDepth * 3], "..\\", 3))
  1484.         {
  1485.             for (iLoop = iLen; iLoop > -1; iLoop = iLoop - 1)
  1486.             {
  1487.                 if (pszDirectory[iLoop] == '\\')
  1488.                 {
  1489.                     break;
  1490.                 }
  1491.             }
  1492.             iLen = iLoop - 1;
  1493.             iDepth++;
  1494.         }
  1495.  
  1496.         // Copy the 'TABLES' directory to form the full path to the tables.
  1497.         //   Need to move szDirectory past the '\\' and szTblDirectory
  1498.         //   past the '..\\'.
  1499.         strcpy(&pszDirectory[iLoop+1], &pszRelativeDirectory[(3 * iDepth)]);
  1500.     }
  1501.  
  1502.     // Check if the directory exists
  1503.     iExists = access(pszDirectory, 00);
  1504.  
  1505.     return iExists;
  1506. }
  1507.  
  1508.