/////////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 1996-2000 Microsoft Corporation
//
//  Module Name:
//      TraceDlg.cpp
//
//  Abstract:
//      Implementation of the CTraceDialog class.
//
//  Author:
//      David Potter (davidp)   May 29, 1996
//
//  Revision History:
//
//  Notes:
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"
#define _RESOURCE_H_
#include "TraceDlg.h"
#include "TraceTag.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;

/////////////////////////////////////////////////////////////////////////////
// CTraceDialog dialog
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
// Message Maps

BEGIN_MESSAGE_MAP(CTraceDialog, CDialog)
    //{{AFX_MSG_MAP(CTraceDialog)
    ON_BN_CLICKED(IDC_TS_SELECT_ALL, OnSelectAll)
    ON_NOTIFY(LVN_ITEMCHANGED, IDC_TS_LISTBOX, OnItemChangedListbox)
    ON_BN_CLICKED(IDC_TS_TRACE_TO_DEBUG, OnClickedTraceToDebug)
    ON_BN_CLICKED(IDC_TS_TRACE_DEBUG_BREAK, OnClickedTraceDebugBreak)
    ON_BN_CLICKED(IDC_TS_TRACE_TO_COM2, OnClickedTraceToCom2)
    ON_BN_CLICKED(IDC_TS_TRACE_TO_FILE, OnClickedTraceToFile)
    ON_CBN_SELCHANGE(IDC_TS_TAGS_TO_DISPLAY_CB, OnSelChangeTagsToDisplay)
    ON_NOTIFY(LVN_COLUMNCLICK, IDC_TS_LISTBOX, OnColumnClickListbox)
    ON_BN_CLICKED(IDC_TS_DEFAULT, OnDefault)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::CTraceDialog
//
//  Routine Description:
//      Constructor.  Initializes the dialog class.
//
//  Arguments:
//      pParent     [IN OUT] Parent window.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTraceDialog::CTraceDialog(CWnd * pParent /*=NULL*/)
    : CDialog(CTraceDialog::IDD, pParent)
{
    //{{AFX_DATA_INIT(CTraceDialog)
    m_strFile = _T("");
    //}}AFX_DATA_INIT

}  //*** CTraceDialog::CTraceDialog()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::DoDataExchange
//
//  Routine Description:
//      Do data exchange between the dialog and the class.
//
//  Arguments:
//      pDX     [IN OUT] Data exchange object 
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::DoDataExchange(CDataExchange * pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CTraceDialog)
    DDX_Control(pDX, IDC_TS_LISTBOX, m_lcTagList);
    DDX_Control(pDX, IDC_TS_TRACE_TO_DEBUG, m_chkboxTraceToDebugWin);
    DDX_Control(pDX, IDC_TS_TRACE_DEBUG_BREAK, m_chkboxDebugBreak);
    DDX_Control(pDX, IDC_TS_TRACE_TO_COM2, m_chkboxTraceToCom2);
    DDX_Control(pDX, IDC_TS_TRACE_TO_FILE, m_chkboxTraceToFile);
    DDX_Control(pDX, IDC_TS_FILE, m_editFile);
    DDX_Control(pDX, IDC_TS_TAGS_TO_DISPLAY_CB, m_cboxDisplayOptions);
    DDX_Text(pDX, IDC_TS_FILE, m_strFile);
    //}}AFX_DATA_MAP

}  //*** CTraceDialog::DoDataExchange()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnInitDialog
//
//  Routine Description:
//      Handler for the WM_INITDIALOG message.
//
//  Arguments:
//      None.
//
//  Return Value:
//      TRUE        We need the focus to be set for us.
//      FALSE       We already set the focus to the proper control.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CTraceDialog::OnInitDialog(void)
{
    CDialog::OnInitDialog();

    // Set the dialog flags.
    {
        CTraceTag * ptag;

        ptag = CTraceTag::s_ptagFirst;
        while (ptag != NULL)
        {
            ptag->m_uiFlagsDialog = ptag->m_uiFlags;
            ptag = ptag->m_ptagNext;
        }  // while:  more tags in the list
    }  // Set the dialog flags

    // Change list view control extended styles.
    {
        DWORD   dwExtendedStyle;

        dwExtendedStyle = m_lcTagList.SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE);
        m_lcTagList.SendMessage(
            LVM_SETEXTENDEDLISTVIEWSTYLE,
            0,
            dwExtendedStyle
                | LVS_EX_FULLROWSELECT
                | LVS_EX_HEADERDRAGDROP
            );
    }  // Change list view control extended styles

    // Set the columns in the listbox.
    VERIFY(m_lcTagList.InsertColumn(0, TEXT("Section"), LVCFMT_LEFT, 75) != -1);
    VERIFY(m_lcTagList.InsertColumn(1, TEXT("Name"), LVCFMT_LEFT, 125) != -1);
    VERIFY(m_lcTagList.InsertColumn(2, TEXT("State"), LVCFMT_CENTER, 50) != -1);

    // Load the combobox.
    /*0*/ VERIFY(m_cboxDisplayOptions.AddString(TEXT("All Tags")) != CB_ERR);
    /*1*/ VERIFY(m_cboxDisplayOptions.AddString(TEXT("Debug Window Enabled")) != CB_ERR);
    /*2*/ VERIFY(m_cboxDisplayOptions.AddString(TEXT("Break Enabled")) != CB_ERR);
    /*3*/ VERIFY(m_cboxDisplayOptions.AddString(TEXT("COM2 Enabled")) != CB_ERR);
    /*4*/ VERIFY(m_cboxDisplayOptions.AddString(TEXT("File Enabled")) != CB_ERR);
    /*5*/ VERIFY(m_cboxDisplayOptions.AddString(TEXT("Anything Enabled")) != CB_ERR);
    VERIFY(m_cboxDisplayOptions.SetCurSel(0) != CB_ERR);
    m_nCurFilter = 0;

    // Set maximum length of the file edit control.
    m_editFile.LimitText(_MAX_PATH);

    // Load the listbox.
    LoadListbox();

    // Set sort info.
    m_nSortDirection = -1;
    m_nSortColumn = -1;

    m_strFile = CTraceTag::PszFile();
    m_nCurFilter = -1;

    UpdateData(FALSE);

    return TRUE;    // return TRUE unless you set the focus to a control
                    // EXCEPTION: OCX Property Pages should return FALSE

}  //*** CTraceDialog::OnInitDialog()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::ConstructStateString [static]
//
//  Routine Description:
//      Construct a string to display from the state of the trace tag.
//
//  Arguments:
//      ptag        [IN] Tag from which to construct the state string.
//      rstr        [OUT] String in which to return the state string.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::ConstructStateString(
    IN const CTraceTag *    ptag,
    OUT CString &           rstr
    )
{
    rstr = "";
    if (ptag->BDebugDialog())
        rstr += "D";
    if (ptag->BBreakDialog())
        rstr += "B";
    if (ptag->BCom2Dialog())
        rstr += "C";
    if (ptag->BFileDialog())
        rstr += "F";

}  //*** CTraceDialog::ConstructStateString()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnOK
//
//  Routine Description:
//      Handler for the BN_CLICKED message on the OK button.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::OnOK(void)
{
    CTraceTag * ptag;
    CString     strSection;
    CString     strState;

    // Write tag states.
    ptag = CTraceTag::s_ptagFirst;
    while (ptag != NULL)
    {
        if (ptag->m_uiFlags != ptag->m_uiFlagsDialog)
        {
            ptag->m_uiFlags = ptag->m_uiFlagsDialog;
            strSection.Format(TRACE_TAG_REG_SECTION_FMT, ptag->PszSubsystem());
            ptag->ConstructRegState(strState);
            AfxGetApp()->WriteProfileString(strSection, ptag->PszName(), strState);
        }  // if:  tag state changed
        ptag = ptag->m_ptagNext;
    }  // while:  more tags int he list.

    // Write the file.
    if (m_strFile != CTraceTag::PszFile())
    {
        g_strTraceFile = m_strFile;
        AfxGetApp()->WriteProfileString(TRACE_TAG_REG_SECTION, TRACE_TAG_REG_FILE, m_strFile);
    }  // if:  file changed

    CDialog::OnOK();

}  //*** CTraceDialog::OnOK()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnSelectAll
//
//  Routine Description:
//      Handler for the BN_CLICKED message on the Select All button.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::OnSelectAll(void)
{
    int     ili;

    // Select all the items in the list control.
    ili = m_lcTagList.GetNextItem(-1, LVNI_ALL);
    while (ili != -1)
    {
        m_lcTagList.SetItemState(ili, LVIS_SELECTED, LVIS_SELECTED);
        ili = m_lcTagList.GetNextItem(ili, LVNI_ALL);
    }  // while:  more items in the list

}  //*** CTraceDialog::OnSelectAll()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnDefault
//
//  Routine Description:
//      Handler for the BN_CLICKED message on the Default button.
//      Resets the trace tags to their default settings.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::OnDefault(void)
{
    CTraceTag * ptag;
    
    ptag = CTraceTag::s_ptagFirst;
    while (ptag != NULL)
    {
        ptag->m_uiFlagsDialog = ptag->m_uiFlagsDefault;
        ptag = ptag->m_ptagNext;
    }  // while:  more tags int he list.

    // Reload the listbox, keeping the same items
    LoadListbox();

}  //*** CTraceDialog::OnDefault()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnItemChangedListbox
//
//  Routine Description:
//      Handler for the LVN_ITEMCHANGED message on the listbox.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::OnItemChangedListbox(NMHDR * pNMHDR, LRESULT * pResult)
{
    NM_LISTVIEW *   pNMListView = (NM_LISTVIEW *) pNMHDR;

    // If the item just became unselected or selected, change the checkboxes to match.
    if ((pNMListView->uChanged & LVIF_STATE)
            && ((pNMListView->uOldState & LVIS_SELECTED)
                || (pNMListView->uNewState & LVIS_SELECTED)))
    {
        // Handle a selection change.
        OnSelChangedListbox();
    }  // if:  item received the focus

    *pResult = 0;

}  //*** CTraceDialog::OnItemChangedListbox()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnSelChangedListbox
//
//  Routine Description:
//      Handles all that needs to when the listbox selection changes. That
//      is adjust the checkbox to their new value and determine if they need
//      to be simple or TRI-state checkboxes.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::OnSelChangedListbox(void)
{
    int         ili;
    int         nDebugWin       = BST_UNCHECKED;
    int         nDebugBreak     = BST_UNCHECKED;
    int         nCom2           = BST_UNCHECKED;
    int         nFile           = BST_UNCHECKED;
    BOOL        bFirstItem      = TRUE;
    CTraceTag * ptag;

    ili = m_lcTagList.GetNextItem(-1, LVNI_SELECTED);
    while (ili != -1)
    {
        // Get the tag for the selected item.
        ptag = (CTraceTag *) m_lcTagList.GetItemData(ili);
        ASSERT(ptag != NULL);

        ptag->m_uiFlagsDialogStart = ptag->m_uiFlagsDialog;
        if (bFirstItem)
        {
            nDebugWin = ptag->BDebugDialog();
            nDebugBreak = ptag->BBreakDialog();
            nCom2 = ptag->BCom2Dialog();
            nFile = ptag->BFileDialog();
            bFirstItem = FALSE;
        }  // if:  first selected item
        else
        {
            if (ptag->BDebugDialog() != nDebugWin)
                nDebugWin = BST_INDETERMINATE;
            if (ptag->BBreakDialog() != nDebugBreak)
                nDebugBreak = BST_INDETERMINATE;
            if (ptag->BCom2Dialog() != nCom2)
                nCom2 = BST_INDETERMINATE;
            if (ptag->BFileDialog() != nFile)
                nFile = BST_INDETERMINATE;
        }  // else:  not first selected item

        // Get the next selected item.
        ili = m_lcTagList.GetNextItem(ili, LVNI_SELECTED);
    }  // while:  more selected items

    AdjustButton(!bFirstItem, m_chkboxTraceToDebugWin, nDebugWin);
    AdjustButton(!bFirstItem, m_chkboxDebugBreak, nDebugBreak);
    AdjustButton(!bFirstItem, m_chkboxTraceToCom2, nCom2);
    AdjustButton(!bFirstItem, m_chkboxTraceToFile, nFile);

}  //*** CTraceDialog::OnSelChangedListbox()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::AdjustButton
//
//  Routine Description:
//      Configures the checkboxes of the dialog.  This includes setting the
//      style and the value of the buttons.
//
//  Arguments:
//      bEnable     [IN] Determines if the given checkbox is enabled or not
//                    (not when the selection is NULL!).
//      rchkbox     [IN OUT] Checkbox to adjust.
//      nState      [IN] State of the button (BST_CHECKED, BST_UNCHECKED,
//                    or BST_INDETERMINATE).
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::AdjustButton(
    IN BOOL             bEnable,
    IN OUT CButton &    rchkbox,
    IN int              nState
    )
{
    rchkbox.EnableWindow(bEnable);
    
    if (nState == BST_INDETERMINATE)
        rchkbox.SetButtonStyle(BS_AUTO3STATE, FALSE);
    else
        rchkbox.SetButtonStyle(BS_AUTOCHECKBOX, FALSE);

    rchkbox.SetCheck(nState);

}  //*** CTraceDialog::AdjustButton()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnColumnClickListbox
//
//  Routine Description:
//      Handler for the LVN_COLUMNCLICK message on the listbox.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::OnColumnClickListbox(NMHDR * pNMHDR, LRESULT * pResult)
{
    NM_LISTVIEW * pNMListView = (NM_LISTVIEW *) pNMHDR;

    // Save the current sort column and direction.
    if (pNMListView->iSubItem == NSortColumn())
        m_nSortDirection ^= -1;
    else
    {
        m_nSortColumn = pNMListView->iSubItem;
        m_nSortDirection = 0;
    }  // else:  different column

    // Sort the list.
    VERIFY(m_lcTagList.SortItems(CompareItems, (LPARAM) this));

    *pResult = 0;

}  //*** CTraceDialog::OnColumnClickListbox()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::CompareItems [static]
//
//  Routine Description:
//      Callback function for the CListCtrl::SortItems method.
//
//  Arguments:
//      lparam1     First item to compare.
//      lparam2     Second item to compare.
//      lparamSort  Sort parameter.
//
//  Return Value:
//      -1          First parameter comes before second.
//      0           First and second parameters are the same.
//      1           First parameter comes after second.
//
//--
/////////////////////////////////////////////////////////////////////////////
int CALLBACK CTraceDialog::CompareItems(
    LPARAM  lparam1,
    LPARAM  lparam2,
    LPARAM  lparamSort
    )
{
    CTraceTag *     ptag1   = (CTraceTag *) lparam1;
    CTraceTag *     ptag2   = (CTraceTag *) lparam2;
    CTraceDialog *  pdlg    = (CTraceDialog *) lparamSort;
    int             nResult;

    ASSERT(ptag1 != NULL);
    ASSERT(ptag2 != NULL);
    ASSERT_VALID(pdlg);
    ASSERT(pdlg->NSortColumn() >= 0);

    switch (pdlg->NSortColumn())
    {
        // Sorting by subsystem.
        case 0:
            nResult = lstrcmp(ptag1->PszSubsystem(), ptag2->PszSubsystem());
            break;

        // Sorting by name.
        case 1:
            nResult = lstrcmp(ptag1->PszName(), ptag2->PszName());
            break;

        // Sorting by state.
        case 2:
        {
            CString strState1;
            CString strState2;

            ConstructStateString(ptag1, strState1);
            ConstructStateString(ptag2, strState2);

            // Compare the two strings.
            // Use CompareString() so that it will sort properly on localized builds.
            nResult = CompareString(
                        LOCALE_USER_DEFAULT,
                        0,
                        strState1,
                        strState1.GetLength(),
                        strState2,
                        strState2.GetLength()
                        );
            if ( nResult == CSTR_LESS_THAN )
            {
                nResult = -1;
            }
            else if ( nResult == CSTR_EQUAL )
            {
                nResult = 0;
            }
            else if ( nResult == CSTR_GREATER_THAN )
            {
                nResult = 1;
            }
            else
            {
                // An error occurred.  Ignore it.
                nResult = 0;
            }
            break;
        }  // if:  sorting by state

        default:
            nResult = 0;
            break;
    }  // switch:  pdlg->NSortColumn()

    // Return the result based on the direction we are sorting.
    if (pdlg->NSortDirection() != 0)
        nResult = -nResult;

    return nResult;

}  //*** CTraceDialog::CompareItems()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnClickedTraceToDebug
//
//  Routine Description:
//      Handler for the BN_CLICKED message on the Trace to Debug Window checkbox.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::OnClickedTraceToDebug(void)
{
    ChangeState(m_chkboxTraceToDebugWin, CTraceTag::tfDebug);

}  //*** CTraceDialog::OnClickedTraceToDebug()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnClickedTraceDebugBreak
//
//  Routine Description:
//      Handler for the BN_CLICKED message on the Debug Break checkbox.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::OnClickedTraceDebugBreak(void)
{
    ChangeState(m_chkboxDebugBreak, CTraceTag::tfBreak);

}  //*** CTraceDialog::OnClickedTraceDebugBreak()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnClickedTraceToCom2
//
//  Routine Description:
//      Handler for the BN_CLICKED message on the Trace to COM2 checkbox.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::OnClickedTraceToCom2(void)
{
    ChangeState(m_chkboxTraceToCom2, CTraceTag::tfCom2);

}  //*** CTraceDialog::OnClickedTraceToCom2()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnClickedTraceToFile
//
//  Routine Description:
//      Handler for the BN_CLICKED message on the Trace to File checkbox.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::OnClickedTraceToFile(void)
{
    ChangeState(m_chkboxTraceToFile, CTraceTag::tfFile);

}  //*** CTraceDialog::OnClickedTraceToFile()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::ChangeState
//
//  Routine Description:
//      Change the state of selected items.
//
//  Arguments:
//      rchkbox     [IN OUT] Checkbox whose state is changing.
//      tfMask      [IN] Mask of state flags to change.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::ChangeState(
    IN OUT CButton &            rchkbox,
    IN CTraceTag::TraceFlags    tfMask
    )
{
    int             ili;
    CTraceTag *     ptag;
    CString         strState;
    int             nState;

    nState = rchkbox.GetCheck();

    // Set the proper flag on all selected items.
    ili = m_lcTagList.GetNextItem(-1, LVNI_SELECTED);
    while (ili != -1)
    {
        // Get the selected item.
        ptag = (CTraceTag *) m_lcTagList.GetItemData(ili);
        ASSERT(ptag != NULL);

        // Set the proper flag in the trace tag.
        if (nState == BST_INDETERMINATE)
        {
            ptag->m_uiFlagsDialog &= ~tfMask;
            ptag->m_uiFlagsDialog |= (tfMask & ptag->m_uiFlagsDialogStart);
        }  // if:  checkbox is in an indeterminate state
        else
            ptag->SetFlagsDialog(tfMask, nState);

        // Set the State column.
        ConstructStateString(ptag, strState);
        VERIFY(m_lcTagList.SetItem(ili, 2, LVIF_TEXT, strState, 0, 0, 0, 0) != 0);

        // Get the next item.
        ili = m_lcTagList.GetNextItem(ili, LVNI_SELECTED);
    }  // while:  more items in the list

}  //*** CTraceDialog::ChangeState()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::OnSelChangeTagsToDisplay
//
//  Routine Description:
//      Handler for the CBN_SELCHANGE message on the Tags To Display combobox.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::OnSelChangeTagsToDisplay(void)
{
    int             nCurFilter;

    // If a change was actually made, reload the listbox.
    nCurFilter = m_cboxDisplayOptions.GetCurSel();
    if (nCurFilter != m_nCurFilter)
    {
        m_nCurFilter = nCurFilter;
        LoadListbox();
    }  // if:  filter changed

}  //*** CTraceDialog::OnSelChangeTagsToDisplay()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::LoadListbox
//
//  Routine Description:
//      Load the listbox.
//
//  Arguments:
//      None.
//
//  Return Value:
//      None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTraceDialog::LoadListbox(void)
{
    int             ili;
    int             iliReturn;
    CTraceTag *     ptag;
    CString         strState;

    m_lcTagList.DeleteAllItems();
    ptag = CTraceTag::s_ptagFirst;
    for (ili = 0 ; ptag != NULL ; )
    {
        // Insert the item in the list if it should be displayed.
        if (BDisplayTag(ptag))
        {
            iliReturn = m_lcTagList.InsertItem(
                                        LVIF_TEXT | LVIF_PARAM,
                                        ili,
                                        ptag->PszSubsystem(),
                                        0,
                                        0,
                                        0,
                                        (LPARAM) ptag
                                        );
            ASSERT(iliReturn != -1);
            VERIFY(m_lcTagList.SetItem(iliReturn, 1, LVIF_TEXT, ptag->PszName(), 0, 0, 0, 0) != 0);
            ConstructStateString(ptag, strState);
            VERIFY(m_lcTagList.SetItem(iliReturn, 2, LVIF_TEXT, strState, 0, 0, 0, 0) != 0);
            ili++;
        }  // if:  tag shold be displayed

        // Get the next tag.
        ptag = ptag->m_ptagNext;
    }  // while:  more tags in the list

    // If the list is not empty, select the first item.
    if (m_lcTagList.GetItemCount() > 0)
        VERIFY(m_lcTagList.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED) != 0);

}  //*** CTraceDialog::LoadListbox()

/////////////////////////////////////////////////////////////////////////////
//++
//
//  CTraceDialog::BDisplayTag
//
//  Purpose:
//      Determines if a given tag should be displayed based on
//      the current filter selection.
//
//  Arguments:
//      ptag        [IN] Pointer to the tag to test
//
//  Return Value:
//      TRUE        Display the tag.
//      FALSE       Don't display the tag.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CTraceDialog::BDisplayTag(IN const CTraceTag * ptag)
{
    BOOL    bDisplay        = TRUE;
    
    switch (m_nCurFilter)
    {
        default:
//          AssertAlways(LITERAL("Unknown Filter, adjust CTraceDialog::FDisplayFilter"));
            break;

        case 0:
            break;

        case 1:
            if (!ptag->BDebugDialog())
                bDisplay = FALSE;
            break;
            
        case 2:
            if (!ptag->BBreakDialog())
                bDisplay = FALSE;
            break;

        case 3:
            if (!ptag->BCom2Dialog())
                bDisplay = FALSE;
            break;

        case 4:
            if (!ptag->BFileDialog())
                bDisplay = FALSE;
            break;

        case 5:
            if (!ptag->m_uiFlagsDialog)
                bDisplay = FALSE;
            break;
    }
    
    return bDisplay;

}  //*** CTraceDialog::BDisplayTag()

#endif // _DEBUG