home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / 32QUERY.PAK / QUERY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  54.1 KB  |  1,541 lines

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