home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sysmgmt / sms / smsapi / browser / browser.cpp < prev    next >
C/C++ Source or Header  |  1996-10-15  |  69KB  |  2,120 lines

  1. //***************************************************************************
  2. //
  3. //  File: browser.cpp
  4. //
  5. //  Copyright (c) 1994, 1995 Microsoft Corp.
  6. //
  7. //  Sample Windows application for the SMS API.
  8. //
  9. //  Author:
  10. //      Jonathan Shuval
  11. //
  12. //  This program implements a browser for SMS objects.
  13. //
  14. //  See the readme.txt file in this directory for full details.
  15. //
  16. //***************************************************************************
  17.  
  18.  
  19. // ====================================================================
  20. //
  21. //  Includes
  22. //
  23. // ====================================================================
  24. #include "resource.h"
  25.  
  26. #include <afx.h>
  27. #include <afxcoll.h>
  28. #include <time.h>               // For converting time scalars into strings.
  29.  
  30. #include <smsapi.h>             // SMS API
  31.  
  32. // 3d controls.
  33. // -----------------------
  34. #include <ctl3d.h>
  35.  
  36. // My header.
  37. // -----------------------
  38. #include "browser.h"
  39.  
  40.  
  41. // ====================================================================
  42. //
  43. //  Manifests.
  44. //
  45. // ====================================================================
  46. #define WM_LOGIN_MSG    WM_USER+101     // So we can send ourself an
  47.                                         // instruction to connect.
  48.  
  49.  
  50.  
  51.  
  52.  
  53. // -------------------------------------------------------------
  54. //  Debug utility
  55. // -------------------------------------------------------------
  56. #ifdef DEBUG
  57. #include <io.h>
  58. #include <stdio.h>
  59. #include <time.h>
  60. int  Log( char *pFmt, ... );
  61. #endif  // DEBUG
  62.  
  63.  
  64. // ====================================================================
  65. //
  66. //  The program starts here.
  67. //
  68. // ====================================================================
  69.  
  70. int PASCAL WinMain(
  71.                 HINSTANCE hInstance,
  72.                 HINSTANCE hPrevInstance,
  73.                 LPSTR lpszCmdLine,
  74.                 int nCmdShow)
  75. {
  76.     int rc;
  77.  
  78.     _hInstance = hInstance;
  79.  
  80.     // Register the 3d controls.
  81.     // =========================
  82.     Ctl3dRegister(_hInstance);
  83.     Ctl3dAutoSubclass(_hInstance);
  84.  
  85.  
  86.     // Load the saved db login information into the globals.
  87.     // Change to suite your preference.
  88.     // =========================================================
  89.     strcat( gszServer,   "jonshu2" );
  90.     strcat( gszDbName,   "SMS" );
  91.     strcat( gszUserName, "sa" );
  92.  
  93.     // Dialogue does the work.
  94.     // =======================
  95.     rc = DialogBox( _hInstance,
  96.                     MAKEINTRESOURCE(IDD_MAIN_DIALOG),
  97.                     0,
  98.                     (DLGPROC)MainDlg );
  99.  
  100.  
  101.  
  102.     Ctl3dUnregister(_hInstance);
  103.  
  104.     return(rc);
  105. }
  106.  
  107.  
  108.  
  109. // ====================================================================
  110. //
  111. //  Dialogue to solicit login information for the datasource.
  112. //
  113. // ====================================================================
  114.  
  115. extern "C" BOOL CALLBACK LoginDlg(  HWND hDlg,
  116.                                     UINT message,
  117.                                     WPARAM wParam,
  118.                                     LPARAM lParam)
  119. {
  120.  
  121.     HWND hEdit;
  122.  
  123.     switch (message) {
  124.  
  125.     case WM_INITDIALOG:
  126.         //KLUDGE: set it with the params I most often use.
  127.         SetDlgItemText( hDlg, IDC_SQLSERVER, gszServer );
  128.         SetDlgItemText( hDlg, IDC_DATABASE,  gszDbName );
  129.         SetDlgItemText( hDlg, IDC_LOGINID,   gszUserName);
  130.  
  131.         // Set focus on this control.
  132.         hEdit = GetDlgItem( hDlg, IDC_SQLSERVER );
  133.         SetFocus(hEdit);
  134.         return(TRUE);
  135.  
  136.     case WM_CLOSE:
  137.         EndDialog( hDlg, IDCANCEL );
  138.         return(TRUE);
  139.  
  140.     case WM_SYSCOLORCHANGE:
  141.         Ctl3dColorChange();
  142.         return(TRUE);
  143.  
  144.  
  145.     case WM_COMMAND:
  146.  
  147.         switch (wParam) {
  148.  
  149.         case IDOK:
  150.             // Retrieve the values from the edit controls.
  151.             //LATER: validate.
  152.             gdsParams.sqlParams.ds          = DB_SQL;
  153.             gdsParams.sqlParams.pFunc       = NULL;     // No encryption.
  154.             gdsParams.sqlParams.pszKey      = "";
  155.             gdsParams.sqlParams.pszServer   = gszServer;
  156.             gdsParams.sqlParams.pszDbName   = gszDbName;
  157.             gdsParams.sqlParams.pszUserName = gszUserName;
  158.             gdsParams.sqlParams.pszPasswd   = gszPasswd;
  159.  
  160.             hEdit = GetDlgItem( hDlg, IDC_SQLSERVER );
  161.             SendMessage( hEdit, WM_GETTEXT, sizeof(gszServer), (LPARAM)gszServer );
  162.  
  163.             hEdit = GetDlgItem( hDlg, IDC_DATABASE );
  164.             SendMessage( hEdit, WM_GETTEXT, sizeof(gszDbName), (LPARAM)gszDbName );
  165.  
  166.             hEdit = GetDlgItem( hDlg, IDC_LOGINID );
  167.             SendMessage( hEdit, WM_GETTEXT, sizeof(gszUserName), (LPARAM)gszUserName );
  168.  
  169.             hEdit = GetDlgItem( hDlg, IDC_PASSWORD );
  170.             SendMessage( hEdit, WM_GETTEXT, sizeof(gszPasswd), (LPARAM)gszPasswd );
  171.  
  172.             // Disable the Login button. This will be enabled after a
  173.             // container enumeration has completed.
  174.             hEdit = GetDlgItem( hDlg, IDC_CONNECT );
  175.             EnableWindow( hEdit, FALSE );
  176.  
  177.  
  178.             // And now terminate.
  179.             EndDialog( hDlg, IDOK );
  180.             return(TRUE);
  181.         }
  182.     }
  183.  
  184.     return(FALSE);
  185.  
  186. }  /* LoginDlg */
  187.  
  188.  
  189.  
  190.  
  191. // ====================================================================
  192. //
  193. //  The real work starts here.
  194. //
  195. //  This dialogue allows the user to select a container from the list
  196. //  of available containers. Once selected the user can select filters
  197. //  to be applied to the container.
  198. //  When these steps are completed the container can be viewed by
  199. //  pressing the "View container" button.
  200. // ====================================================================
  201.  
  202. extern "C" BOOL CALLBACK MainDlg(   HWND hDlg,
  203.                                     UINT message,
  204.                                     WPARAM wParam,
  205.                                     LPARAM lParam)
  206. {
  207.  
  208.     // At init we disable all controls except the "Select container" button.
  209.     // Once a container has been selected this button is disabled and the
  210.     // "Select filter" button and associated listbox are enabled.
  211.     // This button enables us to select multiple filters.
  212.     // Pressing the "View container" button causes us to dismiss this
  213.     // dialogue and display the container contents.
  214.     // =====================================================================
  215.     HWND hEdit;
  216.     SMS_STATUS stat;
  217.     DWORD dwI;
  218.     FOLDER_INFO *pCont = NULL;
  219.     FILTER_INFO    *pF = NULL;
  220.     MY_FILTER_INFO *pMyFilter = NULL;
  221.     DWORD ctContainers = 0;
  222.     int index;
  223.     static CObArray aFilters;       // Array of FILTER_INFOs representing
  224.                                     // selected filters.
  225.     // Get the container types and insert them into the menu
  226.     static FOLDER_INFO **pContainerList = NULL;
  227.     int reply;
  228.     HANDLE hFilter;
  229.  
  230.     switch (message) {
  231.     case WM_INITDIALOG:
  232.         // Dialogue initialisation.
  233.  
  234.  
  235.         // Post a message to ourselves. This will be processed after the init
  236.         // completes.
  237.         // This message causes us to connect to the data source.
  238.         PostMessage( hDlg, WM_LOGIN_MSG, 0, 0 );
  239.  
  240.  
  241.         // ==============================================================
  242.         // We need to enumerate the containers and filters
  243.         // and populate the appropriate listboxes.
  244.         // Enumeration is done by calling into the engine.
  245.         // The resulting lists are held in globals.
  246.         // ==============================================================
  247.  
  248.         // Enumerate the container types.
  249.         // ---------------------------------------------------------
  250.  
  251.             // Get the number of containers.
  252.         SmsEnumContainers(NULL, &ctContainers);
  253.  
  254.             // Allocate memory and call the enum again.
  255.         pContainerList = new FOLDER_INFO *[ctContainers];
  256.         SmsEnumContainers(pContainerList, &ctContainers);
  257.  
  258.             // Populate the listbox.
  259.         hEdit = GetDlgItem(hDlg, IDC_AVAIL_CONTAINER_LIST);
  260.  
  261.         for (dwI = 0; dwI < ctContainers; dwI++) {
  262.  
  263.             pCont = pContainerList[dwI];
  264.             SendMessage(hEdit, LB_ADDSTRING, 0, (LPARAM)pCont->pszTag);
  265.         }
  266.  
  267.             // Select the first one in the list.
  268.         SendMessage(hEdit, LB_SETCURSEL, 0, 0);
  269.  
  270.  
  271.         // Enumerate the filter types.
  272.         // ---------------------------------------------------------
  273.             // Get the number of filters.
  274.         SmsEnumFilters(0, &ctFilters);
  275.  
  276.             // Allocate memory and call the enum again.
  277.         gpAvailFilterList = new FILTER_INFO[ctFilters];
  278.         SmsEnumFilters(gpAvailFilterList, &ctFilters);
  279.  
  280.             // Populate the listbox.
  281.         hEdit = GetDlgItem(hDlg, IDC_AVAIL_FILTER_LIST);
  282.  
  283.         for (dwI = 0; dwI < ctFilters; dwI++) {
  284.             pF = &gpAvailFilterList[dwI];
  285.             SendMessage(hEdit, LB_ADDSTRING, 0, (LPARAM)pF->szTag);
  286.             pF++;
  287.         }
  288.  
  289.             // Select the first one in the list.
  290.         SendMessage(hEdit, LB_SETCURSEL, 0, 0);
  291.  
  292.  
  293.         // Disable all except the select container button.
  294.         // ===============================================
  295.             // Container group
  296.             // ---------------
  297.         hEdit = GetDlgItem(hDlg, IDC_SELECT_CONTAINER_BTN);
  298.         EnableWindow( hEdit, TRUE );
  299.  
  300.         hEdit = GetDlgItem(hDlg, IDC_SELECT_CONTAINER_DONE);
  301.         EnableWindow( hEdit, FALSE );
  302.  
  303.             // Filter group.
  304.             // -------------
  305.         hEdit = GetDlgItem(hDlg, IDC_SELECT_FILTER_BTN);
  306.         EnableWindow( hEdit, FALSE );
  307.  
  308.         hEdit = GetDlgItem(hDlg, IDC_DESELECT_FILTER_BTN);
  309.         EnableWindow( hEdit, FALSE );
  310.  
  311.         hEdit = GetDlgItem(hDlg, IDC_SELECT_FILTERS_DONE);
  312.         EnableWindow( hEdit, FALSE );
  313.  
  314.         // Disable the "view container" button.
  315.         hEdit = GetDlgItem(hDlg, IDOK);
  316.         EnableWindow( hEdit, FALSE );
  317.  
  318.         // Disable the "configure filter" button.
  319.         hEdit = GetDlgItem(hDlg, IDC_CONFIG_FILTER_BTN);
  320.         EnableWindow( hEdit, FALSE );
  321.  
  322.         // Disable the "View selected filters" button.
  323.         hEdit = GetDlgItem(hDlg, IDC_VIEW_SEL_FILTERS_BTN);
  324.         EnableWindow( hEdit, FALSE );
  325.  
  326.         return(TRUE);
  327.  
  328.  
  329.     case WM_CLOSE:
  330.         EndDialog( hDlg, IDCANCEL );
  331.         return(TRUE);
  332.  
  333.  
  334.     case WM_SYSCOLORCHANGE:
  335.         Ctl3dColorChange();
  336.         return(TRUE);
  337.  
  338.  
  339.     case WM_LOGIN_MSG:
  340.         // Establish connection to datasource.
  341.         // Done via the Login dialogue.
  342.         // ====================================
  343.         DialogBox( _hInstance,
  344.                    MAKEINTRESOURCE(IDD_LOGIN),
  345.                    hDlg,
  346.                    (DLGPROC)LoginDlg );
  347.  
  348.         stat = SmsDataSourceConnect( &gdsParams, &ghConnect );
  349.         if (stat != SMS_OK) {
  350.             wsprintf(szMsg, "DataSourceConnect fails: %d", stat);
  351.             MessageBox(hDlg, szMsg, "Problem here", MB_OK);
  352.  
  353.         } else {
  354.             // Enable "select container" button.
  355.             hEdit = GetDlgItem(hDlg, IDC_SELECT_CONTAINER_BTN);
  356.             EnableWindow( hEdit, TRUE );
  357.         }
  358.         return(TRUE);
  359.  
  360.     case WM_COMMAND:
  361.  
  362.         switch (wParam) {
  363.  
  364.         case IDC_SELECT_CONTAINER_BTN:
  365.             // This takes the current selection from the avail containers
  366.             // list and puts it in the selected container control.
  367.             hEdit = GetDlgItem(hDlg, IDC_AVAIL_CONTAINER_LIST);
  368.             index = SendMessage(hEdit, LB_GETCURSEL, 0, 0);
  369.             gpCInfo = pContainerList[index];
  370.  
  371.             hEdit = GetDlgItem(hDlg, IDC_SELECTED_CONTAINER);
  372.             SendMessage(hEdit, WM_SETTEXT, 0, (LPARAM)gpCInfo->pszTag);
  373.  
  374.             // Enable the container done button.
  375.             hEdit = GetDlgItem(hDlg, IDC_SELECT_CONTAINER_DONE);
  376.             EnableWindow( hEdit, TRUE );
  377.  
  378.             // Disable the "Connect" button.
  379.             hEdit = GetDlgItem(hDlg, IDC_CONNECT);
  380.             EnableWindow( hEdit, FALSE );
  381.  
  382.             return(TRUE);
  383.  
  384.  
  385.         case IDC_SELECT_CONTAINER_DONE:
  386.  
  387.             // Disable the "Select container" button and enable the
  388.             // "Select filters" button.
  389.             hEdit = GetDlgItem(hDlg, IDC_SELECT_CONTAINER_BTN);
  390.             EnableWindow( hEdit, FALSE );
  391.  
  392.             // Disable container done btn.
  393.             hEdit = GetDlgItem(hDlg, IDC_SELECT_CONTAINER_DONE);
  394.             EnableWindow( hEdit, FALSE );
  395.  
  396.             // Enable the filters buttons.
  397.             // ---------------------------
  398.             hEdit = GetDlgItem(hDlg, IDC_SELECT_FILTER_BTN);
  399.             EnableWindow( hEdit, TRUE );
  400.  
  401.             hEdit = GetDlgItem(hDlg, IDC_SELECT_FILTERS_DONE);
  402.             EnableWindow( hEdit, TRUE );
  403.  
  404.  
  405.  
  406.             // Open the container.
  407.             // -------------------
  408.             stat = SmsOpenContainer( gpCInfo->dwTag, ghConnect, &ghContainer );
  409.             if (stat != SMS_OK) {
  410.                 wsprintf(szMsg, "bad return from OpenContainer: %d", stat);
  411.                 MessageBox(hDlg, szMsg, "Badness", MB_OK );
  412.             }
  413.  
  414.             return(TRUE);
  415.  
  416.  
  417.         case IDC_SELECT_FILTER_BTN:
  418.             // "Select filter" button.
  419.             // This button is grayed-out until a container has
  420.             // been selected.
  421.  
  422.             // Take the currently selected filter from the
  423.             // available filter listbox and add it to the selected
  424.             // filters listbox.
  425.             hEdit = GetDlgItem(hDlg, IDC_AVAIL_FILTER_LIST);
  426.             index = SendMessage(hEdit, LB_GETCURSEL, 0, 0);
  427.             pF = &gpAvailFilterList[index];
  428.  
  429.             hEdit = GetDlgItem(hDlg, IDC_SELECTED_FILTERS);
  430.             index = SendMessage(hEdit, LB_ADDSTRING, 0, (LPARAM)pF->szTag);
  431.  
  432.             // Highlight this selection in the selected box.
  433.             SendMessage(hEdit, LB_SETCURSEL, (WPARAM)index, 0 );
  434.  
  435.  
  436.             // Add the filter entry to a list of filters that we
  437.             // keep handy. Maintain the index for easier access.
  438.             //NOTE: remember to free it all.
  439.             pMyFilter = new MY_FILTER_INFO;
  440.             pMyFilter->pF = pF;
  441.             pMyFilter->hFilter = NULL;
  442.             aFilters.Add( (CObject *)pMyFilter );
  443.  
  444.             // Enable the deselect button.
  445.             // ---------------------------
  446.             hEdit = GetDlgItem(hDlg, IDC_DESELECT_FILTER_BTN);
  447.             EnableWindow( hEdit, TRUE );
  448.  
  449.             // And the "configure filter" button.
  450.             // ----------------------------------
  451.             hEdit = GetDlgItem(hDlg, IDC_CONFIG_FILTER_BTN);
  452.             EnableWindow( hEdit, TRUE );
  453.  
  454.             // Enable the "selected filters" label and combo.
  455.             hEdit = GetDlgItem(hDlg, IDC_SELECTED_FILTERS);
  456.             EnableWindow( hEdit, TRUE );
  457.  
  458.             return(TRUE);
  459.  
  460.  
  461.         case IDC_DESELECT_FILTER_BTN:
  462.             // Remove the current item from the selected filters listbox.
  463.             hEdit = GetDlgItem(hDlg, IDC_SELECTED_FILTERS);
  464.             index = SendMessage(hEdit, LB_GETCURSEL, 0, 0);
  465.             SendMessage(hEdit, LB_DELETESTRING, (WPARAM)index, 0);
  466.  
  467.             // Remove this filter from the selected filters list.
  468.             pMyFilter = (MY_FILTER_INFO *)aFilters.GetAt( index );
  469.             delete pMyFilter;
  470.             pMyFilter = NULL;
  471.             aFilters.RemoveAt( index );
  472.  
  473.             // Select the previous one in the list.
  474.             // If this was the first (index = 0) then leave index alone
  475.             // else decrement it.
  476.             if (index > 0) {
  477.                 index--;
  478.             }
  479.             SendMessage(hEdit, LB_SETCURSEL, (WPARAM)index, 0);
  480.  
  481.             // Check if we need to disable any buttons.
  482.             // If the selected filters listbox is now empty disable
  483.             // the "deselect" and "configure" filter buttons.
  484.             // -----------------------------------------------------
  485.             index = SendMessage(hEdit, LB_GETCOUNT, 0, 0);
  486.             if (index == 0) {
  487.                 // deselect button.
  488.                 // ---------------------------
  489.                 hEdit = GetDlgItem(hDlg, IDC_DESELECT_FILTER_BTN);
  490.                 EnableWindow( hEdit, FALSE );
  491.  
  492.                 // configure filter button.
  493.                 // ----------------------------------
  494.                 hEdit = GetDlgItem(hDlg, IDC_CONFIG_FILTER_BTN);
  495.                 EnableWindow( hEdit, FALSE );
  496.             }
  497.  
  498.  
  499.             return(TRUE);
  500.  
  501.  
  502.         case IDC_CONFIG_FILTER_BTN:
  503.             // Call a dialogue to handle this.
  504.  
  505.             // Retrieve the filter and pass it in a global so that
  506.             // the dlgproc can use it.
  507.             hEdit = GetDlgItem(hDlg, IDC_SELECTED_FILTERS);
  508.             index = SendMessage(hEdit, LB_GETCURSEL, 0, 0);
  509.             gpMyFilter = (MY_FILTER_INFO *)aFilters[index];
  510.  
  511.             reply = DialogBox(  _hInstance,
  512.                                 MAKEINTRESOURCE(IDD_CONFIG_FILTER),
  513.                                 hDlg,
  514.                                 (DLGPROC)ConfigFilterDlg );
  515.  
  516.             //LATER: put in cancel btn
  517.             return(TRUE);
  518.  
  519.  
  520.         case IDC_VIEW_SEL_FILTERS_BTN:
  521.             // User has requested to view filters that have been
  522.             // applied to the container.
  523.             // =================================================
  524.             DialogBox(  _hInstance,
  525.                         MAKEINTRESOURCE(IDD_VIEW_SEL_FILTERS_DLG),
  526.                         hDlg,
  527.                         (DLGPROC)ViewSelFiltersDlg );
  528.             return(TRUE);
  529.  
  530.  
  531.  
  532.         case IDC_SELECT_FILTERS_DONE:
  533.             // Check that all of the filters that we've selected have been
  534.             // configured, warning if not.
  535.             // (NOTE: we should put in a check mark next to selected
  536.             // filters to show if they've been configured.)
  537.             // It is only at this point that we can actually apply the
  538.             // filter to the container.
  539.  
  540.             // Loop through the filters.
  541.             for (dwI = 0; dwI < (DWORD)aFilters.GetSize(); dwI++) {
  542.                 pMyFilter = (MY_FILTER_INFO *)aFilters[dwI];
  543.                 if (pMyFilter->hFilter == NULL) {
  544.                     wsprintf(szMsg, "A %s has not been configured,\ndo you want to configure it now?",
  545.                                     pMyFilter->pF->szTag);
  546.                     reply = MessageBox( hDlg,
  547.                                         szMsg,
  548.                                         "Warning",
  549.                                         MB_ICONEXCLAMATION| MB_YESNO );
  550.                     if (reply == IDYES) {
  551.                         // We want to configure this filter now.
  552.                         // Stubbed: needs implementing.
  553.                         MessageBox(hDlg, "Not implemented", "Go away", MB_OK);
  554.                     }
  555.  
  556.                 } else {
  557.                     // We can apply the filter now.
  558.                     hFilter = pMyFilter->hFilter;
  559.                     stat = SmsSetFilter( ghContainer, hFilter );
  560.                     SmsCloseFilter( hFilter);
  561.                     if (stat != SMS_OK) {
  562.                         wsprintf(szMsg, "SetFilter for %s failed: %d",
  563.                                             pMyFilter->pF->szTag, stat);
  564.                         MessageBox(hDlg, szMsg, "Warning", MB_OK);
  565.                     }
  566.                 }
  567.             }
  568.  
  569.             // Must grey-out all other filter controls.
  570.             hEdit = GetDlgItem(hDlg, IDC_SELECT_FILTERS_DONE);
  571.             EnableWindow( hEdit, FALSE );
  572.  
  573.             hEdit = GetDlgItem(hDlg, IDC_SELECT_FILTER_BTN);
  574.             EnableWindow( hEdit, FALSE );
  575.  
  576.             hEdit = GetDlgItem(hDlg, IDC_DESELECT_FILTER_BTN);
  577.             EnableWindow( hEdit, FALSE );
  578.  
  579.             hEdit = GetDlgItem(hDlg, IDC_CONFIG_FILTER_BTN);
  580.             EnableWindow( hEdit, FALSE );
  581.  
  582.  
  583.             // The view container btn enabled only when filter done btn
  584.             // clicked.
  585.             hEdit = GetDlgItem(hDlg, IDOK);
  586.             EnableWindow( hEdit, TRUE );
  587.  
  588.             // Enable the "Connect" button.
  589.             hEdit = GetDlgItem(hDlg, IDC_CONNECT);
  590.             EnableWindow( hEdit, TRUE );
  591.  
  592.             // Enable the "View selected filters" button.
  593.             // We only want to do this if we have any filters.
  594.             if (aFilters.GetSize() > 0) {
  595.                 hEdit = GetDlgItem(hDlg, IDC_VIEW_SEL_FILTERS_BTN);
  596.                 EnableWindow( hEdit, TRUE );
  597.             }
  598.  
  599.             return(TRUE);
  600.  
  601.         case IDOK:
  602.             // This is the "View Container" button.
  603.  
  604.             // Tell the container to populate himself.
  605.             stat = SmsPopulate( ghContainer, POP_SYNC, NULL );
  606.             if (stat != SMS_OK) {
  607.                 wsprintf(szMsg, "bad return from Populate: %d", stat);
  608.                 MessageBox(hDlg, szMsg, "Badness", MB_OK );
  609.             }
  610.  
  611.             // Enter the container view dialogue.
  612.             DialogBox(  _hInstance,
  613.                         MAKEINTRESOURCE(IDD_THE_CONTAINER),
  614.                         hDlg,
  615.                         (DLGPROC)ContainerViewDlg );
  616.  
  617.             SmsCloseContainer( ghContainer );
  618.  
  619.             // Log off from data source.
  620.             SmsDataSourceDisconnect( ghConnect );
  621.  
  622.  
  623.             ////////////////////////////////////////////////////
  624.             //  Ready for restart.
  625.             ////////////////////////////////////////////////////
  626.  
  627.             // Free all global and static data.
  628.             // -------------------------------------------------
  629.             for (index = 0; index < aFilters.GetSize(); index ++) {
  630.                 pMyFilter = (MY_FILTER_INFO *)aFilters.GetAt( index );
  631.                 delete pMyFilter;
  632.                 pMyFilter = NULL;
  633.             }
  634.             aFilters.RemoveAll();
  635.  
  636.             pCont = NULL;
  637.             pF = NULL;
  638.             gpCInfo = NULL;
  639.             ghConnect = NULL;
  640.  
  641.             // Delete any strings that were in the selected
  642.             // container and filter edit controls.
  643.             // -------------------------------------------------
  644.             SetDlgItemText( hDlg, IDC_SELECTED_CONTAINER, "" );
  645.             hEdit = GetDlgItem(hDlg, IDC_SELECTED_FILTERS);
  646.             SendMessage( hEdit, LB_RESETCONTENT, 0, 0 );
  647.  
  648.             // Disable all controls except Login.
  649.             // -------------------------------------------------
  650.                 // Container group
  651.                 // ---------------
  652.             hEdit = GetDlgItem(hDlg, IDC_SELECT_CONTAINER_BTN);
  653.             EnableWindow( hEdit, FALSE );
  654.  
  655.             hEdit = GetDlgItem(hDlg, IDC_SELECT_CONTAINER_DONE);
  656.             EnableWindow( hEdit, FALSE );
  657.  
  658.                 // Filter group.
  659.                 // -------------
  660.             hEdit = GetDlgItem(hDlg, IDC_SELECT_FILTER_BTN);
  661.             EnableWindow( hEdit, FALSE );
  662.  
  663.             hEdit = GetDlgItem(hDlg, IDC_DESELECT_FILTER_BTN);
  664.             EnableWindow( hEdit, FALSE );
  665.  
  666.             hEdit = GetDlgItem(hDlg, IDC_SELECT_FILTERS_DONE);
  667.             EnableWindow( hEdit, FALSE );
  668.  
  669.             // Disable the "view container" button.
  670.             hEdit = GetDlgItem(hDlg, IDOK);
  671.             EnableWindow( hEdit, FALSE );
  672.  
  673.             // Disable the "configure filter" button.
  674.             hEdit = GetDlgItem(hDlg, IDC_CONFIG_FILTER_BTN);
  675.             EnableWindow( hEdit, FALSE );
  676.  
  677.             // Disable the "View selected filters" button.
  678.             hEdit = GetDlgItem(hDlg, IDC_VIEW_SEL_FILTERS_BTN);
  679.             EnableWindow( hEdit, FALSE );
  680.  
  681.             // Reset listbox selections.
  682.             // -------------------------------------------------
  683.             // Reset listbox selections to first in list.
  684.             hEdit = GetDlgItem(hDlg, IDC_AVAIL_CONTAINER_LIST);
  685.             SendMessage(hEdit, LB_SETCURSEL, 0, 0);
  686.  
  687.             hEdit = GetDlgItem(hDlg, IDC_AVAIL_FILTER_LIST);
  688.             SendMessage(hEdit, LB_SETCURSEL, 0, 0);
  689.  
  690.  
  691.             ////////////////////////////////////////////////////
  692.  
  693.             // Enable the Login button so use can try again.
  694.             hEdit = GetDlgItem( hDlg, IDC_CONNECT );
  695.             EnableWindow( hEdit, TRUE );
  696.  
  697.             return(TRUE);
  698.  
  699.  
  700.         case IDC_CONNECT:
  701.             // This is the "Connect" button.
  702.             SendMessage( hDlg, WM_LOGIN_MSG, 0, 0 );
  703.             return(TRUE);
  704.  
  705.  
  706.         case IDC_ALL_DONE:
  707.             // This is the "done" button.
  708.             EndDialog( hDlg, IDOK );
  709.  
  710.             // And now terminate.
  711.             return(TRUE);
  712.         }
  713.     }
  714.  
  715.     return(FALSE);
  716.  
  717. }
  718.  
  719.  
  720.  
  721.  
  722. // ====================================================================
  723. //
  724. //  This is the view container dialogue that is brought up in response
  725. //  to the "view container" button in the main dialogue.
  726. //
  727. //  We have a listbox for the sub-folders, which we need to populate.
  728. //  We also have a group box containing details about the container.
  729. //
  730. //  The container handle is held in a global "ghContainer".
  731. //
  732. // ====================================================================
  733.  
  734. extern "C" BOOL CALLBACK ContainerViewDlg(
  735.                                     HWND hDlg,
  736.                                     UINT message,
  737.                                     WPARAM wParam,
  738.                                     LPARAM lParam)
  739. {
  740.  
  741.     // We need to fill in the container tag and the number of folders.
  742.     // The first we'll put into a global for now (from MainDlg), the
  743.     // latter is currently unavailable so we'll put in some gunk.
  744.  
  745.     HWND hEdit;
  746.     static DWORD ctFolders = 0;
  747.     SMS_STATUS stat;
  748.     static CStringArray asID;           // Array of CStrings for IDs.
  749.     CString sID;
  750.     char szID[SMS_DATA_BUFF_SIZE+1];    // buffer to read in folder ID.
  751.     DWORD dwI;
  752.     HANDLE handle;                      // Temp holds handle of folder.
  753.     int index;
  754.     static CDWordArray folderList;      // List of opened folder handles.
  755.  
  756.  
  757.     switch (message) {
  758.  
  759.     case WM_INITDIALOG:
  760.         // Dialogue initialisation.
  761.  
  762.         // We have to open all the sub-folders, holding their
  763.         // handles in some array. For each folder we want to extract
  764.         // and display in the listbox it's ID.
  765.         // NOTE: GetFolderCount not yet imnplemented for containers.
  766.         // Instead I'll do GetNextFolder till I run out of folders.
  767.         ctFolders = 0;
  768.  
  769.         for (ctFolders = 0; 1; ctFolders++) {
  770.  
  771.             stat = SmsGetNextFolder( ghContainer, F_ANY, &handle );
  772.             if (stat != SMS_OK) {
  773.                 // assume no more folders for now
  774.                 break;
  775.             }
  776.             // Save the handle.
  777.             folderList.Add( (DWORD)handle );
  778.         }
  779.  
  780.  
  781.         // Get the ID of each folder and insert into listbox.
  782.         // --------------------------------------------------
  783.         hEdit = GetDlgItem(hDlg, IDC_ID_LB);
  784.  
  785.         for (dwI = 0; dwI < ctFolders; dwI++) {
  786.  
  787.             // Retrieve the ID and store in the listbox.
  788.             handle = (HANDLE)folderList.GetAt( dwI );
  789.             stat = SmsGetFolderID( handle, szID );
  790.             if (stat != SMS_OK) {
  791.                 wsprintf(szMsg, "GetID [%d] fails: %d", dwI, stat);
  792.                 MessageBox(hDlg, szMsg, "API problem", MB_OK);
  793.             }
  794.             asID.SetAtGrow( dwI, (CString)szID );
  795.  
  796.             SendMessage(hEdit, LB_ADDSTRING, 0, (LPARAM)szID);
  797.         }
  798.  
  799.  
  800.         // Select the first one in the list.
  801.         SendMessage(hEdit, LB_SETCURSEL, 0, 0);
  802.  
  803.  
  804.         // Set container name and number of folders.
  805.         // -----------------------------------------
  806.         SetDlgItemText( hDlg, IDC_WHAT_CONTAINER, (LPCSTR)gpCInfo->pszTag );
  807.         SetDlgItemInt( hDlg, IDC_CTR_NUM_FOLDERS, ctFolders, FALSE );
  808.  
  809.         // If no folders disable the "View folder" button.
  810.         // -----------------------------------------------
  811.         if (ctFolders == 0) {
  812.             hEdit = GetDlgItem(hDlg, IDOK);
  813.             EnableWindow( hEdit, FALSE );
  814.         }
  815.  
  816.         return(TRUE);
  817.  
  818.  
  819.     case WM_CLOSE:
  820.         // Close all folders.
  821.         for (dwI = 0; dwI < ctFolders; dwI++) {
  822.             handle = (HANDLE)folderList.GetAt( dwI );
  823.             SmsCloseFolder( handle );
  824.         }
  825.         folderList.RemoveAll();
  826.  
  827.         // Clear the ID string array.
  828.         asID.RemoveAll();
  829.  
  830.         EndDialog( hDlg, IDCANCEL );
  831.         return(TRUE);
  832.  
  833.  
  834.     case WM_SYSCOLORCHANGE:
  835.         Ctl3dColorChange();
  836.         return(TRUE);
  837.  
  838.  
  839.     case WM_COMMAND:
  840.  
  841.         switch (wParam) {
  842.  
  843.         case IDOK:
  844.             // Get the current selection and store it in a global
  845.             // so that it can be picked up by FolderViewDlg.
  846.             // --------------------------------------------------
  847.             hEdit = GetDlgItem(hDlg, IDC_ID_LB);
  848.             index = SendMessage(hEdit, LB_GETCURSEL, 0, 0);
  849.             ghFolder = (HANDLE)folderList.GetAt( index );
  850.  
  851.             // Now we rewind the folder. This means that we can re-enumerate
  852.             // the folder's properties (ID, scalars etc).
  853.             SmsRewind( ghFolder, RW_ALL );
  854.  
  855.             // Enter the folder view dialogue.
  856.             DialogBox(  _hInstance,
  857.                         MAKEINTRESOURCE(IDD_FOLDER_VIEW),
  858.                         hDlg,
  859.                         (DLGPROC)FolderViewDlg );
  860.  
  861.             return(TRUE);
  862.  
  863.         case IDC_DONE:
  864.             // We're done with this container. Close all the folders
  865.             // and the container.
  866.             for (dwI = 0; dwI < ctFolders; dwI++) {
  867.                 handle = (HANDLE)folderList.GetAt( dwI );
  868.                 // Close the folder
  869.                 SmsCloseFolder( handle );
  870.             }
  871.             folderList.RemoveAll();
  872.  
  873.  
  874.             // Clear the ID string array.
  875.             asID.RemoveAll();
  876.  
  877.  
  878.             // Container closed in calling dlg.
  879.  
  880.             // This returns us to the previous dialogue.
  881.             EndDialog(hDlg, IDOK);
  882.             return(TRUE);
  883.         }
  884.     }
  885.  
  886.     return(FALSE);
  887.  
  888.  
  889.  
  890. }  /* ContainerViewDlg */
  891.  
  892.  
  893. // ====================================================================
  894. //
  895. //  This is the view folder dialogue that is brought up in response to
  896. //  the "view folder" button in the container dialogue.
  897. //
  898. //  We have a listbox for the sub-folders, which we need to populate.
  899. //  We also have a group box containing details about the folder.
  900. //
  901. //  The handle to the current folder has been placed in the ghFolder
  902. //  global.
  903. //
  904. //  When this dlgproc is entered via INITDIALOG we create a folder
  905. //  frame that contains information that we have gleaned from the
  906. //  folder, including the folder's handle. This frame is stacked.
  907. //  When the 'view sub-folder" button is pressed we will simulate this
  908. //  same action. A 'Done" button press causes us to free the current
  909. //  frame and reload from the top of stack (if any).
  910. //  The WM_CLOSE causes us to walk the stack frame freeing all frames.
  911. //
  912. // ====================================================================
  913.  
  914. // Macro for easier checking of returns from the APIs.
  915. // Not sure about the NO_MORE_DATA. Check it.
  916. #define CHKIT(h, str) if (stat != SMS_OK && stat != SMS_MORE_DATA && stat != SMS_NO_MORE_DATA) { \
  917.     wsprintf(szMsg, "Handle: %08X %s fails: %d", h, str, stat); \
  918.     MessageBox(hDlg, szMsg, "API Error", MB_OK); return((CFrame *)NULL); }
  919.  
  920.  
  921. extern "C" BOOL CALLBACK FolderViewDlg(
  922.                                     HWND hDlg,
  923.                                     UINT message,
  924.                                     WPARAM wParam,
  925.                                     LPARAM lParam)
  926. {
  927.     HWND hEdit;
  928.     DWORD dwI;                          // Loop index.
  929.  
  930.     int index;
  931.     CString sID;                        // Temp sub-folder's ID.
  932.     static CFrame *pf = NULL;           // Current stack frame.
  933.     char *pszTmp;
  934.     char szBuff[SMS_DATA_BUFF_SIZE+1];  // Just for setting window title.
  935.  
  936.     static CFrameStack frameStack(hDlg);
  937.  
  938.     switch (message) {
  939.  
  940.     case WM_INITDIALOG:
  941.         // Dialogue initialisation.
  942.  
  943.         // Set the window title to say "View of folder: <name>".
  944.         SmsGetFolderID( ghFolder, szBuff );
  945.         wsprintf(szMsg, "View of folder: %s", szBuff);
  946.         SetWindowText( hDlg, szMsg );
  947.  
  948.         // Extract requisite information about the folder:
  949.         // ID, type (use tag), scalar count, folder count, folder type count.
  950.         pf = CreateFolderFrame( hDlg, ghFolder );
  951.         if (pf) {
  952.             // And display it.
  953.             DisplayFolderFrame( hDlg, pf );
  954.  
  955.         } else {
  956.             // This is an error.
  957.             wsprintf(szMsg, "CreateFolderFrame failed for handle %08X", ghFolder);
  958.             MessageBox(hDlg, szMsg, "An error", MB_OK);
  959.             EndDialog( hDlg, IDCANCEL );
  960.         }
  961.  
  962.         return(TRUE);
  963.  
  964.  
  965.     case WM_CLOSE:
  966.         // Delete current frame.
  967.         // =====================
  968.         // remove the ID strings from the string array
  969.         for (dwI = 0; dwI < (DWORD)pf->aszID.GetSize(); dwI++) {
  970.             pszTmp = (char *)pf->aszID[dwI];
  971.             delete pszTmp;
  972.         }
  973.         // remove the handles
  974.         delete pf->phFolders;
  975.  
  976.         delete pf;
  977.         pf = NULL;
  978.  
  979.         // Free all previous frames.
  980.         // =========================
  981.         while (pf = frameStack.pop()) {
  982.             // remove the ID strings from the string array
  983.             for (dwI = 0; dwI < (DWORD)pf->aszID.GetSize(); dwI++) {
  984.                 pszTmp = (char *)pf->aszID[dwI];
  985.                 delete pszTmp;
  986.             }
  987.             // Remove the handles
  988.             delete pf->phFolders;
  989.             ghFolder = pf->hFolder;
  990.             delete pf;
  991.  
  992.         }
  993.         EndDialog( hDlg, IDCANCEL );
  994.         return(TRUE);
  995.  
  996.  
  997.     case WM_SYSCOLORCHANGE:
  998.         Ctl3dColorChange();
  999.         return(TRUE);
  1000.  
  1001.  
  1002.     case WM_COMMAND:
  1003.  
  1004.         switch (wParam) {
  1005.  
  1006.         case IDC_VIEW_FOLDER:
  1007.             // We're going down a level so stack our frame.
  1008.             frameStack.push( pf );
  1009.  
  1010.             // Get the current selection index. Use this to locate
  1011.             // the folder's handle.
  1012.             // We must save the existing folder handle in the frame
  1013.             // and re-instate it when we return.
  1014.  
  1015.             hEdit = GetDlgItem( hDlg, IDC_SUBFOLDER_LIST );
  1016.             index = SendMessage(hEdit, LB_GETCURSEL, 0, 0);
  1017.             ghFolder = pf->phFolders[index];
  1018.  
  1019.             // First clear the listbox entries (should clear other entries
  1020.             // as well, but I think they'll just get overwritten.)
  1021.             SendMessage(hEdit, LB_RESETCONTENT, 0, 0);
  1022.  
  1023.             // Create a new stack frame with all the details
  1024.             // that we did in the INITDLG.
  1025.             pf = CreateFolderFrame( hDlg, ghFolder );
  1026.             if (pf) {
  1027.                 // And display it.
  1028.                 DisplayFolderFrame( hDlg, pf );
  1029.  
  1030.             } else {
  1031.                 // This is an error.
  1032.                 wsprintf(szMsg, "CreateFolderFrame failed for handle %08X", ghFolder);
  1033.                 MessageBox(hDlg, szMsg, "An error", MB_OK);
  1034.                 EndDialog( hDlg, IDCANCEL );
  1035.             }
  1036.  
  1037.  
  1038.             // Select the first one in the list and set focus here.
  1039.             SendMessage(hEdit, LB_SETCURSEL, 0, 0);
  1040.             SetFocus(hEdit);
  1041.  
  1042.             return(TRUE);
  1043.  
  1044.  
  1045.         case IDC_VIEW_SCALARS:
  1046.             // So we can enumerate scalars from the beginning.
  1047.             SmsRewind( ghFolder, RW_ALL );
  1048.  
  1049.             DialogBox( _hInstance,
  1050.                        MAKEINTRESOURCE(IDD_SCALARS),
  1051.                        hDlg,
  1052.                        (DLGPROC)ScalarViewDlg );
  1053.             return(TRUE);
  1054.  
  1055.  
  1056.         case IDC_VIEW_EXPRESSION:
  1057.             // So we can enumerate tokens in expression from the beginning.
  1058.             SmsRewind( ghFolder, RW_ALL );
  1059.  
  1060.             DialogBox( _hInstance,
  1061.                        MAKEINTRESOURCE(IDD_EXPRESSION),
  1062.                        hDlg,
  1063.                        (DLGPROC)ExpressionViewDlg );
  1064.             return(TRUE);
  1065.  
  1066.  
  1067.  
  1068.         case IDC_BACK:
  1069.             // This will take us back one level.
  1070.             // We have to free all data from the current stack frame
  1071.             // and then restore the previous one.
  1072.             // When the stack frame is empty we return to the previous
  1073.             // dialogue.
  1074.  
  1075.             // Delete current frame.
  1076.             // =====================
  1077.             // remove the ID strings from the string array
  1078.             for (dwI = 0; dwI < (DWORD)pf->aszID.GetSize(); dwI++) {
  1079.                 pszTmp = (char *)pf->aszID[dwI];
  1080.                 delete pszTmp;
  1081.             }
  1082.             // remove the handles
  1083.             delete pf->phFolders;
  1084.  
  1085.             delete pf;
  1086.             pf = NULL;
  1087.  
  1088.  
  1089.             // Restore the previous frame.
  1090.             // ===========================
  1091.             pf = frameStack.pop();
  1092.             if (pf == NULL) {
  1093.                 // Nothing there, return to previous dialogue.
  1094.                 EndDialog(hDlg, IDOK);
  1095.                 return(TRUE);
  1096.             }
  1097.  
  1098.  
  1099.             DisplayFolderFrame( hDlg, pf );
  1100.             // restore folder handle
  1101.             ghFolder = pf->hFolder;
  1102.  
  1103.             return(TRUE);
  1104.         }
  1105.     }
  1106.  
  1107.     return(FALSE);
  1108.  
  1109. }   /* FolderViewDlg */
  1110.  
  1111.  
  1112.  
  1113. // ====================================================================
  1114. //
  1115. //  Creates a frame for this folder.
  1116. //  Note: We could check if we have already stacked this folder.
  1117. //
  1118. // ====================================================================
  1119.  
  1120. CFrame *CreateFolderFrame( HWND hDlg, HANDLE hFolder )
  1121. {
  1122.     HANDLE hSubFolder = NULL;           // Temp reference to sub-folder.
  1123.     CFrame *pFrame = new CFrame;
  1124.     SMS_STATUS stat;
  1125.  
  1126.  
  1127.     SmsRewind( hFolder, RW_ALL );
  1128.  
  1129.     // Save the folder's handle.
  1130.     pFrame->hFolder = ghFolder;
  1131.  
  1132.     stat = SmsGetFolderID( hFolder, pFrame->szFolderID );
  1133.     CHKIT(hFolder, "GetFolderID");
  1134.  
  1135.     stat = SmsGetFolderType( hFolder, &pFrame->fType, pFrame->szfType );
  1136.     CHKIT(hFolder, "GetFolderType");
  1137.  
  1138.     stat = SmsGetScalarCount( hFolder, &pFrame->ctScalars );
  1139.     CHKIT(hFolder, "GetScalarCount");
  1140.  
  1141.     stat = SmsGetFolderCount( hFolder, F_ANY, &pFrame->ctFolders );
  1142.     CHKIT(hFolder, "GetFolderCount");
  1143.  
  1144.     stat = SmsEnumFolderTypes( hFolder, NULL, &pFrame->ctFolderTypes );
  1145.     CHKIT(hFolder, "EnumFolderTypes");
  1146.  
  1147.     // 02-May-96. Add expression display (inventory folder).
  1148.     stat = SmsGetTokenCount( hFolder, &pFrame->ctTokens );
  1149. //    CHKIT(hFolder, "GetTokenCount");
  1150.  
  1151.  
  1152.     // Enumerate the sub-folders.
  1153.     // -----------------------------------------
  1154.     char szBuff[SMS_DATA_BUFF_SIZE+1];
  1155.  
  1156.     // Allocate a handle for each folder.
  1157.     pFrame->phFolders = (HANDLE *)new HANDLE[pFrame->ctFolders];
  1158.     char *pszTmp;
  1159.  
  1160.     DWORD dwI;
  1161.     for (dwI = 0; dwI < pFrame->ctFolders; dwI++) {
  1162.         // Rewind the folder - just in case.
  1163.  
  1164.         stat = SmsGetNextFolder( hFolder, F_ANY, &hSubFolder );
  1165.         CHKIT(hFolder, "GetNextFolder");
  1166.         pFrame->phFolders[dwI] = hSubFolder;
  1167.  
  1168.         // Get folder's ID and add it to our cstring array and to the listbox.
  1169.         // We want it saved since we will have to redraw the listbox when
  1170.         // drilling down and then up in the folder list.
  1171.         stat = SmsGetFolderID( hSubFolder, szBuff );
  1172.         CHKIT(hFolder, "GetFolderID");
  1173.         pszTmp = new char[strlen(szBuff)+1];        // deleted when we do a BACK or CLOSE
  1174.         strcpy(pszTmp, szBuff);
  1175.         pFrame->aszID.Add( (CObject *)pszTmp );
  1176.  
  1177.     }
  1178.  
  1179.     return(pFrame);
  1180.  
  1181. }  /* CreateFolderFrame */
  1182.  
  1183.  
  1184.  
  1185.  
  1186. // ====================================================================
  1187. //
  1188. //  Display the given folder frame. This is part of the Folder view
  1189. //  dialogue.
  1190. //
  1191. // ====================================================================
  1192.  
  1193. void DisplayFolderFrame( HWND hDlg, CFrame *pFrame )
  1194. {
  1195.     HWND hEdit;
  1196.  
  1197.     // First of all lets clear the listbox (whether needs it or not).
  1198.     hEdit = GetDlgItem( hDlg, IDC_SUBFOLDER_LIST );
  1199.     SendMessage(hEdit, LB_RESETCONTENT, 0, 0);
  1200.  
  1201.  
  1202.     SetDlgItemText( hDlg, IDC_FOLDERID, (LPCSTR)pFrame->szFolderID);
  1203.     SetDlgItemText( hDlg, IDC_FOLDERTYPE, (LPCSTR)pFrame->szfType);
  1204.     SetDlgItemInt( hDlg,  IDC_FOLDERSC_CT, pFrame->ctScalars, FALSE);
  1205.     SetDlgItemInt( hDlg,  IDC_FOLDERFOLDER_CT, pFrame->ctFolders, FALSE);
  1206.     SetDlgItemInt( hDlg,  IDC_FOLDERFT_CT, pFrame->ctFolderTypes, FALSE);
  1207.  
  1208.  
  1209.     // Display the sub-folder IDs.
  1210.     // -----------------------------------------
  1211.     hEdit = GetDlgItem( hDlg, IDC_SUBFOLDER_LIST );
  1212.     char *pszTmp;
  1213.  
  1214.     for (DWORD dwI = 0; dwI < pFrame->ctFolders; dwI++) {
  1215.  
  1216.         pszTmp = (char *)pFrame->aszID.GetAt( dwI );
  1217.         SendMessage(hEdit, LB_ADDSTRING, 0, (LPARAM)pszTmp);
  1218.     }
  1219.  
  1220.     // If there are no sub-folders or no scalars then
  1221.     // disable the appropriate buttons.
  1222.     // -----------------------------------------------------
  1223.     hEdit = GetDlgItem( hDlg, IDC_VIEW_SCALARS );
  1224.     if (pFrame->ctScalars == 0) {
  1225.         EnableWindow( hEdit, FALSE );
  1226.     } else {
  1227.         EnableWindow( hEdit, TRUE );
  1228.     }
  1229.  
  1230.     hEdit = GetDlgItem( hDlg, IDC_VIEW_FOLDER );
  1231.     if (pFrame->ctFolders == 0) {
  1232.         EnableWindow( hEdit, FALSE );
  1233.     } else {
  1234.         EnableWindow( hEdit, TRUE );
  1235.     }
  1236.  
  1237.  
  1238.     // Select the first one in the list and set focus here.
  1239.     hEdit = GetDlgItem( hDlg, IDC_SUBFOLDER_LIST );
  1240.     SendMessage(hEdit, LB_SETCURSEL, 0, 0);
  1241.  
  1242.     // [02-May-96] If there are no tokens in this folder (ie it doesn't
  1243.     // have an expression) then disable the 'View expression' button.
  1244.     // ----------------------------------------------------------------
  1245.     hEdit = GetDlgItem( hDlg, IDC_VIEW_EXPRESSION );
  1246.     if (pFrame->ctTokens == 0) {
  1247.         EnableWindow( hEdit, FALSE );
  1248.     } else {
  1249.         EnableWindow( hEdit, TRUE );
  1250.     }
  1251. }
  1252.  
  1253.  
  1254. // ==========================================================================
  1255. //
  1256. //  Dialogue proc for the scalar view.
  1257. //
  1258. //  We need the hFolder, and preferably it's ID as well. We can put that
  1259. //  in the dlg title.
  1260. //  The hFolder is needed since we're going to enumerate its scalars.
  1261. //  We'll construct 2 string arrays, one for the scalar name, the other
  1262. //  for the value (maybe put in type as well later).
  1263. //
  1264. // ==========================================================================
  1265.  
  1266. extern "C" BOOL CALLBACK ScalarViewDlg(
  1267.                                     HWND hDlg,
  1268.                                     UINT message,
  1269.                                     WPARAM wParam,
  1270.                                     LPARAM lParam)
  1271. {
  1272.  
  1273.     HWND hEditName;                 // Explicit handle to name listbox.
  1274.     HWND hEditVal;                  // Explicit handle to value listbox.
  1275.     HWND hEditType;                 // Explicit handle to type listbox.
  1276.     int index;
  1277.     SCALAR scalar;
  1278.     char szName[SMS_DATA_BUFF_SIZE+1];      // Scalar name.
  1279.     char szValue[SMS_DATA_BUFF_SIZE+1];     // String value.
  1280.     BYTE byValue[SMS_DATA_BUFF_SIZE];       // Binary value.
  1281.     scalar.pszName  = szName;
  1282.     scalar.pszValue = szValue;
  1283.     scalar.pValue   = byValue;
  1284.     SMS_STATUS stat;
  1285.     char szBuff[SMS_DATA_BUFF_SIZE+1];
  1286.  
  1287.     char *pszVal;                   // Point to scalar's value.
  1288.     char *pszType;                  // Point to scalar's type.
  1289.  
  1290.     CTime tTime;                    // For time scalars
  1291.     CString sTime;                  //  ditto
  1292.  
  1293.  
  1294.     switch (message) {
  1295.  
  1296.     case WM_INITDIALOG:
  1297.         // Dialogue initialisation.
  1298.  
  1299.         // 1. Set the window title to say "Scalars for folder <name>".
  1300.         SmsGetFolderID( ghFolder, szBuff );
  1301.         wsprintf(szMsg, "Scalars for folder %s", szBuff);
  1302.         SetWindowText( hDlg, szMsg );
  1303.  
  1304.         // 2. Enumerate the scalars storing the strings (strings only at
  1305.         // the moment) in 2 string lists: name and value.
  1306.  
  1307.         hEditName = GetDlgItem(hDlg, IDC_SCNAME_LB);
  1308.         hEditVal  = GetDlgItem(hDlg, IDC_SCVAL_LB);
  1309.         hEditType = GetDlgItem(hDlg, IDC_SCTYPE_LB);
  1310.  
  1311.         while (1) {
  1312.             scalar.dwLen = sizeof(szValue)-1;
  1313.  
  1314.             stat = SmsGetNextScalar( ghFolder, &scalar );
  1315.             if (stat != SMS_OK) {
  1316.                 break;
  1317.             }
  1318.  
  1319.             // Copy the name and value into the listboxes - don't think I'll
  1320.             // bother with saving them though.
  1321.  
  1322.  
  1323.             switch (scalar.scType) {
  1324.             case SCALAR_STRING:
  1325.                 pszVal = scalar.pszValue;
  1326.                 pszType = "String";
  1327.                 break;
  1328.  
  1329.             case SCALAR_INT:
  1330.                 // Convert to string.
  1331.                 wsprintf(szBuff, "%d", scalar.dwValue);
  1332.                 pszVal = szBuff;
  1333.                 pszType = "Integer";
  1334.                 break;
  1335.  
  1336.             case SCALAR_TIME:
  1337.                 // Check if we have a string equivalence. If so use it.
  1338.                 if (scalar.bStringEquivalence) {
  1339.                     pszVal = scalar.pszValue;
  1340.  
  1341.                 } else {
  1342.                     // Use time functions to make a string out of it.
  1343.                     // NOTE: we really need to get rid of trailing newline.
  1344.                     tTime = scalar.tValue;
  1345.                     sTime = tTime.Format( "%m/%d/%y %I:%M %p" );
  1346.                     pszVal = (char *)(const char *)sTime;
  1347.                 }
  1348.                 pszType = "Time";
  1349.                 break;
  1350.  
  1351.             case SCALAR_BINARY:
  1352.                 // Just print out its length.
  1353.                 pszType = "Binary";
  1354.                 wsprintf( szBuff, "Length of binary data: %ld", scalar.dwLen);
  1355.                 pszVal = szBuff;
  1356.                 break;
  1357.  
  1358.             default:
  1359.                 wsprintf(szBuff, "UNKNOWN TYPE");
  1360.                 pszVal = szBuff;
  1361.                 pszType = "Unknown type";
  1362.                 break;
  1363.             }
  1364.  
  1365.             // Scalar name.
  1366.             SendMessage(hEditName, LB_ADDSTRING, 0, (LPARAM)scalar.pszName);
  1367.  
  1368.             // Scalar type.
  1369.             SendMessage(hEditType, LB_ADDSTRING, 0, (LPARAM)pszType);
  1370.  
  1371.             // Scalar value.
  1372.             SendMessage(hEditVal,  LB_ADDSTRING, 0, (LPARAM)pszVal);
  1373.  
  1374.  
  1375.         }
  1376.  
  1377.         // Set current selections to the first in each list.
  1378.         SendMessage(hEditName, LB_SETCURSEL, (WPARAM)0, 0);
  1379.         SendMessage(hEditType, LB_SETCURSEL, (WPARAM)0, 0);
  1380.         SendMessage(hEditVal,  LB_SETCURSEL, (WPARAM)0, 0);
  1381.  
  1382.         // Set focus on this control.
  1383.         SetFocus(hEditName);
  1384.  
  1385.         return(TRUE);
  1386.  
  1387.  
  1388.     case WM_CLOSE:
  1389.         // Do I need to delete the strings from the listboxes??
  1390.         EndDialog( hDlg, IDCANCEL );
  1391.         return(TRUE);
  1392.  
  1393.     case WM_SYSCOLORCHANGE:
  1394.         Ctl3dColorChange();
  1395.         return(TRUE);
  1396.  
  1397.  
  1398.     case WM_COMMAND:
  1399.  
  1400.         // Whatever listbox is selected we want to select the
  1401.         // corresponding entry in the other.
  1402.         if (HIWORD(wParam) == LBN_SELCHANGE) {
  1403.  
  1404.             index = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0);
  1405.  
  1406.  
  1407.             hEditName = GetDlgItem(hDlg, IDC_SCNAME_LB);
  1408.             hEditType = GetDlgItem(hDlg, IDC_SCTYPE_LB);
  1409.             hEditVal  = GetDlgItem(hDlg, IDC_SCVAL_LB);
  1410.  
  1411.             // Select the corresponding entry all listboxes.
  1412.             SendMessage(hEditName, LB_SETCURSEL, (WPARAM)index, 0);
  1413.             SendMessage(hEditType, LB_SETCURSEL, (WPARAM)index, 0);
  1414.             SendMessage(hEditVal,  LB_SETCURSEL, (WPARAM)index, 0);
  1415.  
  1416.             return(TRUE);
  1417.         }
  1418.  
  1419.  
  1420.         switch (wParam) {
  1421.  
  1422.         case IDOK:
  1423.             // Do I need to delete the strings from the listboxes??
  1424.             EndDialog(hDlg, IDOK);
  1425.             return(TRUE);
  1426.  
  1427.         }
  1428.     }
  1429.  
  1430.     return(FALSE);
  1431.  
  1432. }  /* ScalarViewDlg */
  1433.  
  1434.  
  1435. // ==========================================================================
  1436. //
  1437. //  Dialogue proc for the expression view.
  1438. //##//
  1439. //  We need the hFolder, and preferably it's ID as well. We can put that
  1440. //  in the dlg title.
  1441. //  The hFolder is needed since we're going to enumerate its scalars.
  1442. //  We'll construct 2 string arrays, one for the scalar name, the other
  1443. //  for the value (maybe put in type as well later).
  1444. //
  1445. // ==========================================================================
  1446.  
  1447. extern "C" BOOL CALLBACK ExpressionViewDlg(
  1448.                                     HWND hDlg,
  1449.                                     UINT message,
  1450.                                     WPARAM wParam,
  1451.                                     LPARAM lParam)
  1452. {
  1453.  
  1454.     HWND hEditToken;                // Explicit handle to token listbox.
  1455.     char szBuff[SMS_DATA_BUFF_SIZE+1];  // Just for setting window title.
  1456.     DWORD dwLoop = 0;
  1457.  
  1458.  
  1459.     switch (message) {
  1460.  
  1461.     case WM_INITDIALOG:
  1462.         // Dialogue initialisation.
  1463.  
  1464.         // 1. Set the window title to say "Expression for folder <name>".
  1465.         SmsGetFolderID( ghFolder, szBuff );
  1466.         wsprintf(szMsg, "Expression for folder %s", szBuff);
  1467.         SetWindowText( hDlg, szMsg );
  1468.  
  1469.         // 2. Enumerate the tokens storing them (ie their display strings)
  1470.         // into a string list.
  1471.  
  1472.         hEditToken = GetDlgItem(hDlg, IDC_TOKENS_LB);
  1473.  
  1474.         // Clear the token.
  1475.         // ================
  1476.         TOKEN Token;
  1477.         DWORD ctTokens;
  1478.  
  1479.         // Loop through its tokens, display the token string in the
  1480.         // edit control.
  1481.         // ========================================================
  1482.         SmsGetTokenCount( ghFolder, &ctTokens );
  1483.         for (dwLoop = 0; dwLoop < ctTokens; dwLoop++) {
  1484.  
  1485.             memset(&Token, 0, sizeof(TOKEN));
  1486.             Token.bIndent = 1;                  // Request indentation.
  1487.             // Get token.
  1488.             SmsGetToken( ghFolder, dwLoop, &Token );
  1489.  
  1490.             SendMessage(hEditToken, LB_ADDSTRING, 0, (LPARAM)Token.szTokenString);
  1491.         }
  1492.  
  1493.  
  1494.         // Set focus on this control.
  1495.         SetFocus(hEditToken);
  1496.  
  1497.         return(TRUE);
  1498.  
  1499.  
  1500.     case WM_CLOSE:
  1501.         // Do I need to delete the strings from the listboxes??
  1502.         EndDialog( hDlg, IDCANCEL );
  1503.         return(TRUE);
  1504.  
  1505.     case WM_SYSCOLORCHANGE:
  1506.         Ctl3dColorChange();
  1507.         return(TRUE);
  1508.  
  1509.  
  1510.     case WM_COMMAND:
  1511.  
  1512.         switch (wParam) {
  1513.  
  1514.         case IDOK:
  1515.             // Do I need to delete the strings from the listboxes??
  1516.             EndDialog(hDlg, IDOK);
  1517.             return(TRUE);
  1518.  
  1519.         }
  1520. #ifdef XXX
  1521.         // Whatever listbox is selected we want to select the
  1522.         // corresponding entry in the other.
  1523.         if (HIWORD(wParam) == LBN_SELCHANGE) {
  1524.  
  1525.             index = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0);
  1526.  
  1527.  
  1528.             hEditName = GetDlgItem(hDlg, IDC_SCNAME_LB);
  1529.             hEditType = GetDlgItem(hDlg, IDC_SCTYPE_LB);
  1530.             hEditVal  = GetDlgItem(hDlg, IDC_SCVAL_LB);
  1531.  
  1532.             // Select the corresponding entry all listboxes.
  1533.             SendMessage(hEditName, LB_SETCURSEL, (WPARAM)index, 0);
  1534.             SendMessage(hEditType, LB_SETCURSEL, (WPARAM)index, 0);
  1535.             SendMessage(hEditVal,  LB_SETCURSEL, (WPARAM)index, 0);
  1536.  
  1537.             return(TRUE);
  1538.         }
  1539. #else
  1540.         return(TRUE);
  1541. #endif  // XXX
  1542.  
  1543.  
  1544.         switch (wParam) {
  1545.  
  1546.         case IDOK:
  1547.             // Do I need to delete the strings from the listboxes??
  1548.             EndDialog(hDlg, IDOK);
  1549.             return(TRUE);
  1550.  
  1551.         }
  1552.     }
  1553.  
  1554.     return(FALSE);
  1555.  
  1556. }  /* ExpressionViewDlg */
  1557.  
  1558.  
  1559.  
  1560.  
  1561. // ====================================================================
  1562. //
  1563. // This is the dialogue that is brought up in response to the
  1564. // config filter button in the main dialogue.
  1565. //
  1566. //  A MY_FILTER_INFO struct is passed via a global. This
  1567. //  contains a description of the filter template (ie a FILTER_INFO
  1568. //  structure) and the handle of a particular filter. By examining
  1569. //  the filter info we determine how the filter's tokens are composed.
  1570.  
  1571. //  The dialogue itself has the group name controls set to not-
  1572. //  visible. If this is a Token2 then we make them visible.
  1573. //
  1574. //  For each token there is a name, a value and an operator.
  1575. //  I'll hard-code the operators for the moment.
  1576. //  Not all tokens need the value and operator, this should be
  1577. //  determined by the token processing.
  1578. //  The nature of the value is also dependent on the token, it's
  1579. //  (currently) either a DWORD or a string.
  1580. //
  1581. //  We create the filter and do the add tokens here. The filter
  1582. //  handle is stored in the MY_FILTER_INFO struct. When we
  1583. //  return the invoker of this dialogue will do a SetFilter.
  1584. //
  1585. // ====================================================================
  1586.  
  1587. extern "C" BOOL CALLBACK ConfigFilterDlg(
  1588.                                     HWND hDlg,
  1589.                                     UINT message,
  1590.                                     WPARAM wParam,
  1591.                                     LPARAM lParam)
  1592. {
  1593.  
  1594.     HWND hEdit;
  1595.     FILTER_INFO *pFltr = NULL;
  1596.     static MY_FILTER_INFO *pMyF;
  1597.     int index;
  1598.     SMS_STATUS stat;
  1599.     static HANDLE hFilter = NULL;
  1600.     ANDOR opAndOr;
  1601.     TOKEN Token;                        // Token to add into filter.
  1602.  
  1603.     // We only know what fields the filter supports when we check the
  1604.     // TOKEN_INFO structure. The fields there that contain strings
  1605.     // tell us a) that the field is used by the filter, and b) what
  1606.     // the label should be for that field.
  1607.     // For simplicity we have two dialogues, we use one dialogue proc
  1608.     // to process both. This is only because of the difficulties
  1609.     // involved in moving edit controls around.
  1610.     // Different filter types will use different combinations of the
  1611.     // edit controls.
  1612.     // ===============================================================
  1613.     static BOOL bHasName;
  1614.     static BOOL bHasValue;
  1615.     static BOOL bHasGroupClass;
  1616.     static BOOL bHasArch;
  1617.     static BOOL bHasOp;
  1618.     static BOOL bHasAttribute;
  1619.  
  1620.     int iLoop;                          // Loop index.
  1621.  
  1622.     switch (message) {
  1623.  
  1624.     case WM_INITDIALOG:
  1625.         // Dialogue initialisation.
  1626.         pMyF = gpMyFilter;
  1627.         pFltr = pMyF->pF;
  1628.  
  1629.         // Look at the filter to determine what fields it will use.
  1630.         // make the appropriate fields visible, and set their labels.
  1631.         // ==========================================================
  1632.         bHasName       = FALSE;
  1633.         bHasValue      = FALSE;
  1634.         bHasGroupClass = FALSE;
  1635.         bHasArch       = FALSE;
  1636.         bHasOp         = FALSE;
  1637.         bHasAttribute  = FALSE;
  1638.  
  1639.         // Clear the token.
  1640.         // ================
  1641.         memset(&Token, 0, sizeof(TOKEN));
  1642.  
  1643.         // Name.
  1644.         if (strlen(pFltr->szName)) {
  1645.             hEdit = GetDlgItem(hDlg, IDC_NAME_STATIC);
  1646.             SetWindowText( hEdit, pFltr->szName );
  1647.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1648.  
  1649.             hEdit = GetDlgItem(hDlg, IDC_NAME);
  1650.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1651.             bHasName = TRUE;
  1652.         }
  1653.  
  1654.         // Value.
  1655.         if (strlen(pFltr->szValue)) {
  1656.             hEdit = GetDlgItem(hDlg, IDC_VALUE_STATIC);
  1657.             SetWindowText( hEdit, pFltr->szValue );
  1658.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1659.  
  1660.             hEdit = GetDlgItem(hDlg, IDC_VALUE);
  1661.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1662.             bHasValue = TRUE;
  1663.         }
  1664.  
  1665.         // GroupClass.
  1666.         if (strlen(pFltr->szGroupClass)) {
  1667.             hEdit = GetDlgItem(hDlg, IDC_GROUPCLASS_STATIC);
  1668.             SetWindowText( hEdit, pFltr->szGroupClass );
  1669.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1670.  
  1671.             hEdit = GetDlgItem(hDlg, IDC_GROUPCLASS);
  1672.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1673.             bHasGroupClass = TRUE;
  1674.         }
  1675.  
  1676.         // AttributeName.
  1677.         if (strlen(pFltr->szAttributeName)) {
  1678.             hEdit = GetDlgItem(hDlg, IDC_ATTRIBUTE_STATIC);
  1679.             SetWindowText( hEdit, pFltr->szAttributeName );
  1680.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1681.  
  1682.             hEdit = GetDlgItem(hDlg, IDC_ATTRIBUTE);
  1683.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1684.             bHasAttribute = TRUE;
  1685.         }
  1686.  
  1687.         // Architecture.
  1688.         if (strlen(pFltr->szArchitecture)) {
  1689.             hEdit = GetDlgItem(hDlg, IDC_ARCHITECTURE_STATIC);
  1690.             SetWindowText( hEdit, pFltr->szArchitecture );
  1691.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1692.  
  1693.             hEdit = GetDlgItem(hDlg, IDC_ARCHITECTURE);
  1694.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1695.             bHasArch = TRUE;
  1696.         }
  1697.  
  1698.         // Operator.
  1699.         if (strlen(pFltr->szOperator)) {
  1700.             hEdit = GetDlgItem(hDlg, IDC_OPERATOR_STATIC);
  1701.             SetWindowText( hEdit, pFltr->szOperator );
  1702.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1703.  
  1704.             hEdit = GetDlgItem(hDlg, IDC_OP_CB);
  1705.             ShowWindow( hEdit, SW_SHOWNORMAL );
  1706.             bHasOp = TRUE;
  1707.         }
  1708.  
  1709.  
  1710.  
  1711.         // Create the filter.
  1712.         // If all goes ok then this will be stored in
  1713.         // gpMyFilter, and used in the main dlg.
  1714.         // -----------------------------------------------------
  1715.         stat = SmsCreateFilter( pFltr->filterType, ghConnect, &hFilter );
  1716.         if (stat != SMS_OK) {
  1717.             wsprintf(szMsg, "OpenFilter fails: %d", stat);
  1718.             MessageBox(hDlg, szMsg, "Whoops", MB_OK);
  1719.         }
  1720.  
  1721.  
  1722.         // Insert the operators that we support into the combobox.
  1723.         hEdit = GetDlgItem(hDlg, IDC_OP_CB);
  1724.         for (iLoop = 0; iLoop < QOP_LAST; iLoop++) {
  1725.             SendMessage(hEdit, CB_ADDSTRING, 0, (LPARAM)OpName[iLoop]);
  1726.         }
  1727.  
  1728.         // Default to selecting string equals.
  1729.         SendMessage(hEdit, CB_SETCURSEL, QOP_STR_EQ, 0);
  1730.  
  1731.         // Modify the window text to "Configure <type> filter"
  1732.         // We access the global MyFilter pointer, this points to
  1733.         // the filter type that we're working with.
  1734.         wsprintf(szMsg, "Configuring %s", pFltr->szTag);
  1735.         SetWindowText( hDlg, szMsg );
  1736.  
  1737.         // Disable the "Done" button.
  1738.         hEdit = GetDlgItem(hDlg, IDOK);
  1739.         EnableWindow( hEdit, FALSE );
  1740.  
  1741.         return(TRUE);
  1742.  
  1743.  
  1744.     case WM_CLOSE:
  1745.         EndDialog( hDlg, IDCANCEL );
  1746.         return(TRUE);
  1747.  
  1748.  
  1749.     case WM_SYSCOLORCHANGE:
  1750.         Ctl3dColorChange();
  1751.         return(TRUE);
  1752.  
  1753.     case WM_COMMAND:
  1754.  
  1755.         switch (wParam) {
  1756.  
  1757.         case IDC_ADDAND_BTN:
  1758.         case IDC_ADDOR_BTN:
  1759.             if (wParam == IDC_ADDAND_BTN) {
  1760.                 opAndOr = OP_AND;
  1761.             } else {
  1762.                 opAndOr = OP_OR;
  1763.             }
  1764.  
  1765.             // Extract the fields. We recorded in INITDIALOG which fields
  1766.             // we have.
  1767.                 // Name
  1768.             if (bHasName) {
  1769.                 GetDlgItemText(hDlg, IDC_NAME, (LPTSTR)Token.szName, sizeof(Token.szName));
  1770.             }
  1771.  
  1772.                 // Value (string first)
  1773.             if (bHasValue) {
  1774.                 GetDlgItemText(hDlg, IDC_VALUE, (LPTSTR)Token.szValue, sizeof(Token.szValue));
  1775.             }
  1776.  
  1777.                 // Operator. Get the index of the selection in the listbox
  1778.                 // and convert to operator code.
  1779.             if (bHasOp) {
  1780.                 hEdit = GetDlgItem(hDlg, IDC_OP_CB);
  1781.                 index = SendMessage(hEdit, CB_GETCURSEL, 0, 0);
  1782.                 Token.dwOp = index;
  1783.             }
  1784.  
  1785.                 // GroupClass
  1786.             if (bHasGroupClass) {
  1787.                 GetDlgItemText(hDlg, IDC_GROUPCLASS, (LPTSTR)Token.szGroupClass, sizeof(Token.szGroupClass));
  1788.             }
  1789.  
  1790.                 // Attribute name.
  1791.             if (bHasAttribute) {
  1792.                 GetDlgItemText(hDlg, IDC_ATTRIBUTE, (LPTSTR)Token.szAttributeName, sizeof(Token.szAttributeName));
  1793.             }
  1794.  
  1795.                 // Architecture
  1796.             if (bHasArch) {
  1797.                 GetDlgItemText(hDlg, IDC_ARCHITECTURE, (LPTSTR)Token.szArchitecture, sizeof(Token.szArchitecture));
  1798.             }
  1799.             // Add the token into the filter.
  1800.             // -2 for the index parameter means add the token at the end
  1801.             // of the filter's expression.
  1802.             // ---------------------------------------------------------
  1803.             pMyF = gpMyFilter;
  1804.             pFltr = pMyF->pF;
  1805.  
  1806.             stat = SmsAddToken( hFilter, opAndOr, &Token, -2 ); // -2 = at end.
  1807.             if (stat != SMS_OK) {
  1808.                wsprintf(szMsg, "AddToken fails: %d", stat);
  1809.                MessageBox(hDlg, szMsg, "Whoops", MB_OK);
  1810.             }
  1811.  
  1812.  
  1813.             // Clear the edit controls.
  1814.             // ------------------------
  1815.             SetDlgItemText( hDlg, IDC_NAME        , "" );
  1816.             SetDlgItemText( hDlg, IDC_VALUE       , "" );
  1817.             SetDlgItemText( hDlg, IDC_GROUPCLASS  , "" );
  1818.             SetDlgItemText( hDlg, IDC_ATTRIBUTE   , "" );
  1819.             SetDlgItemText( hDlg, IDC_ARCHITECTURE, "" );
  1820.  
  1821.  
  1822.             // Enable the "Done" button.
  1823.             // -------------------------
  1824.             hEdit = GetDlgItem(hDlg, IDOK);
  1825.             EnableWindow( hEdit, TRUE );
  1826.  
  1827.             return(TRUE);
  1828.  
  1829.         case IDOK:
  1830.             // We need to set the filter handle in the MYFILTER.
  1831.             pMyF = gpMyFilter;
  1832.             pMyF->hFilter = hFilter;
  1833.             hFilter = NULL;
  1834.  
  1835.             EndDialog(hDlg, IDOK);
  1836.             return(TRUE);
  1837.  
  1838.  
  1839.         }
  1840.     }
  1841.  
  1842.     return(FALSE);
  1843.  
  1844. }  /* SelectFilterDlg */
  1845.  
  1846.  
  1847.  
  1848. // ====================================================================
  1849. //
  1850. // This is the dialogue that is brought up in response to the
  1851. // view selected filters button in the main dialogue.
  1852. // It enables the user to view the filters that they have
  1853. // created and applied to the container. It shows the use of the
  1854. // SmsRetrieveFilters and SmsGetToken APIs.
  1855. //
  1856. // ====================================================================
  1857.  
  1858. extern "C" BOOL CALLBACK ViewSelFiltersDlg(
  1859.                                     HWND hDlg,
  1860.                                     UINT message,
  1861.                                     WPARAM wParam,
  1862.                                     LPARAM lParam)
  1863. {
  1864.  
  1865.     HWND hEdit, hEdit1;
  1866.     SMS_STATUS stat;
  1867.     static DWORD ctFilters = 0;     // How many filters there are in the
  1868.                                     // container.
  1869.     DWORD ctTokens;                 // How many tokens in filter.
  1870.     static HANDLE *ahFilters;       // Retrieve an array of handles.
  1871.     DWORD dwLoop;                   // Loop index.
  1872.     TOKEN Token;
  1873.     int index;                      // Get index of selected filter.
  1874.     char szBuff[256];               // Build up filter tokens here.
  1875.  
  1876.  
  1877.  
  1878.  
  1879.     switch (message) {
  1880.  
  1881.     case WM_INITDIALOG:
  1882.         // Dialogue initialisation.
  1883.  
  1884.         // Get the number of filters, then allocate spae and call again.
  1885.         // =============================================================
  1886.         stat = SmsGetAllFilters( ghContainer, NULL, &ctFilters );
  1887.  
  1888.         ahFilters = new HANDLE[ctFilters];
  1889.         stat = SmsGetAllFilters( ghContainer, ahFilters, &ctFilters );
  1890.  
  1891.         // Build up the list of filters. We want to populate the listbox
  1892.         // with the filter tags. When one of these is selected (via the
  1893.         // view button) we'll display its contents in the edit control box.
  1894.  
  1895.             // Populate the listbox.
  1896.         hEdit = GetDlgItem(hDlg, IDC_SEL_FILTERS_LB);
  1897.  
  1898.         HANDLE hFilter;
  1899.         DWORD filterType;               // Current filter's type and tag
  1900.         char szFilterTag[50];           // ...
  1901.  
  1902.         for (dwLoop = 0; dwLoop < ctFilters; dwLoop++) {
  1903.             hFilter = ahFilters[dwLoop];
  1904.             SmsGetFilterType( hFilter, &filterType, szFilterTag );
  1905.  
  1906.             SendMessage(hEdit, LB_ADDSTRING, 0, (LPARAM)szFilterTag);
  1907.         }
  1908.  
  1909.             // Select the first one in the list.
  1910.         SendMessage(hEdit, LB_SETCURSEL, 0, 0);
  1911.  
  1912.             // Send the listbox a focus message. This should cause him
  1913.             // to display the contents of the specified filter.
  1914.         if (ctFilters > 0) {
  1915.             WPARAM wp = MAKEWPARAM( IDC_SEL_FILTERS_LB, LBN_SELCHANGE );
  1916.             SendMessage(hDlg, WM_COMMAND, wp, (LPARAM)hEdit);
  1917.         }
  1918.         return(TRUE);
  1919.  
  1920.  
  1921.     case WM_CLOSE:
  1922.         // Close all the filters that we retrieved in SmsGetAllFilters.
  1923.         for (dwLoop = 0; dwLoop < ctFilters; dwLoop++) {
  1924.             hFilter = ahFilters[dwLoop];
  1925.             SmsCloseFilter( hFilter );
  1926.         }
  1927.         delete ahFilters;
  1928.  
  1929.         EndDialog( hDlg, IDCANCEL );
  1930.         return(TRUE);
  1931.  
  1932.  
  1933.     case WM_SYSCOLORCHANGE:
  1934.         Ctl3dColorChange();
  1935.         return(TRUE);
  1936.  
  1937.     case WM_COMMAND:
  1938.  
  1939.         if ((HIWORD(wParam) == LBN_SELCHANGE) &&
  1940.             (LOWORD(wParam) == IDC_SEL_FILTERS_LB)) {
  1941.  
  1942.             hEdit1 = (HWND)lParam;
  1943.  
  1944.             // Clear the contents of the view listbox.
  1945.             // =======================================
  1946.             szBuff[0] = '\0';
  1947.             hEdit = GetDlgItem(hDlg, IDC_VIEWFILTER);
  1948.             SendMessage(hEdit, WM_SETTEXT, 0, (LPARAM)"");
  1949.  
  1950.             // Find out which filter we've selected and get it's handle.
  1951.             // =========================================================
  1952.             index = SendMessage(hEdit1, LB_GETCURSEL, 0, 0);
  1953.             hFilter = ahFilters[index];
  1954.  
  1955.             // Clear the token.
  1956.             // ================
  1957.             memset(&Token, 0, sizeof(TOKEN));
  1958.  
  1959.             // Loop through its tokens, display the token string in the
  1960.             // edit control.
  1961.             // ========================================================
  1962.             SmsGetTokenCount( hFilter, &ctTokens );
  1963.             for (dwLoop = 0; dwLoop < ctTokens; dwLoop++) {
  1964.                 // Get token.
  1965.                 SmsGetToken( hFilter, dwLoop, &Token );
  1966.  
  1967.                 strcat( szBuff, Token.szTokenString );
  1968.                 strcat( szBuff, " ");
  1969.             }
  1970.             SendMessage(hEdit, WM_SETTEXT, 0, (LPARAM)szBuff);
  1971.  
  1972.             return(TRUE);
  1973.         }
  1974.  
  1975.         switch (wParam) {
  1976.  
  1977.  
  1978.         case IDOK:
  1979.             EndDialog(hDlg, IDOK);
  1980.             return(TRUE);
  1981.  
  1982.  
  1983.         }
  1984.     }
  1985.  
  1986.     return(FALSE);
  1987.  
  1988. }  /* ViewSelFiltersDlg */
  1989.  
  1990.  
  1991.  
  1992.  
  1993.  
  1994. // ====================================================================
  1995. //
  1996. //  CFrameStack class.
  1997. //
  1998. //  This is only used in the folder view dialogue. It enables us to
  1999. //  descend into sub-folders but keep this current folder's data
  2000. //  around.
  2001. //  When we want to look at a sub-folder we just pop the current
  2002. //  folder's data onto the stack. when we return from a sub-folder we
  2003. //  just pop the stack.
  2004. //
  2005. // ====================================================================
  2006. CFrameStack::CFrameStack(HWND hDlg)
  2007. {
  2008.     sp = 0;
  2009.     _hDlg = hDlg;
  2010. }
  2011.  
  2012. CFrameStack::~CFrameStack()
  2013. {
  2014.     // Clear all objects from stack and delete them.
  2015.     CFrame *pFrame;
  2016.     for (int i = 0; i < stack.GetSize(); i++) {
  2017.         pFrame = (CFrame *)stack[i];
  2018.         delete pFrame;
  2019.     }
  2020.     stack.RemoveAll();
  2021. }
  2022.  
  2023.  
  2024. void CFrameStack::push( CFrame *pFrame )
  2025. {
  2026.     stack.Add( (CObject *)pFrame );
  2027.     sp++;
  2028.  
  2029. }
  2030.  
  2031.  
  2032. CFrame *CFrameStack::pop()
  2033. {
  2034.     if (sp == 0) {
  2035.         return(NULL);
  2036.     }
  2037.     --sp;
  2038.     CFrame *pFrame = (CFrame *)stack.GetAt( sp );
  2039.     stack.RemoveAt( sp );
  2040.  
  2041.     return(pFrame);
  2042. }
  2043.  
  2044.  
  2045. //Debug: dump the stack
  2046. void CFrameStack::Dump( const char *psz )
  2047. {
  2048.     CFrame *pf;
  2049.     char *p = szMsg;
  2050.  
  2051.     wsprintf(p, "sp=%d GetUpperBound=%d\n", sp-1, stack.GetUpperBound());
  2052.     p += strlen(p);
  2053.  
  2054.     for (int i = 0; i <= sp-1; i++) {
  2055.         pf = (CFrame *)stack[i];
  2056.         wsprintf(p, "%d ID: %s\n", i, pf->szFolderID);
  2057.         p += strlen(p);
  2058.     }
  2059.     MessageBox( _hDlg, szMsg, psz, MB_OK );
  2060. }
  2061.  
  2062.  
  2063.  
  2064. #ifdef DEBUG
  2065.  
  2066. // ====================================================================
  2067. //
  2068. //  Debug log utility.
  2069. //  Here so people can see an example of such a thing.
  2070. //
  2071. // eg: Log("WM_TIMER GetWindowRect fails: %d", GetLastError());
  2072. //
  2073. // ====================================================================
  2074. int Log(char *fmt, ...)
  2075. {
  2076.     char *buffer = new char[2048];
  2077.  
  2078.     va_list argptr;
  2079.     int cnt;
  2080.     va_start(argptr, fmt);
  2081.     cnt = vsprintf(buffer, fmt, argptr);
  2082.     va_end(argptr);
  2083.  
  2084.     FILE *fp;
  2085.  
  2086.     fp = fopen("browser.log", "at");
  2087.  
  2088.     if (!fp) {
  2089.         delete buffer;
  2090.         return( 0 );
  2091.     }
  2092.  
  2093.     time_t now;
  2094.     time(&now);
  2095.     struct tm *local = localtime(&now);
  2096.  
  2097.     fprintf(fp, "%s\n", buffer);
  2098.  
  2099.     BOOL killfile = FALSE;
  2100.  
  2101.     if (ftell(fp) > 0x10000) {
  2102.         killfile = TRUE;   // 64K Limit on log
  2103.     }
  2104.  
  2105.     fclose(fp);
  2106.  
  2107.     if (killfile) {
  2108.         remove("log.log");
  2109.     }
  2110.  
  2111.     delete buffer;
  2112.  
  2113.     return( cnt );
  2114. }
  2115. #endif  // DEBUG
  2116.  
  2117.  
  2118. /* EOF: browser.cpp */
  2119.  
  2120.