home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / msj / msjv3_3 / windebug / debug.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-02  |  15.5 KB  |  607 lines

  1. /*
  2.  * WINDOWS 2.00 DEBUG UTILITY - SOURCE CODE (DEBUG.C)
  3.  *
  4.  * LANGUAGE : microsoft C 5.0
  5.  * MODEL    : small or medium
  6.  * STATUS   : operational
  7.  *
  8.  * 12/11/87 1.00 - Kevin P. Welch - initial creation.
  9.  *
  10.  */
  11.  
  12. #include <windows.h>
  13. #include <string.h>
  14. #include <fcntl.h>
  15. #include <types.h>
  16. #include <stat.h>
  17. #include "debug.h"
  18.  
  19. /* internal macros */
  20. #define    TOGGLE(x,y)    CheckDlgButton(x,y,!IsDlgButtonChecked(x,y))
  21. #define    ENABLE(x,y,z)    EnableWindow(GetDlgItem(x,y),z)
  22.  
  23. /* general definitions */
  24. #define    SHARED        S_IREAD|S_IWRITE
  25. #define    MODE_APPEND    O_RDWR|O_APPEND|O_BINARY    
  26. #define    MODE_CREATE    O_RDWR|O_CREAT|O_BINARY
  27.  
  28. /* listbox viewport definitions */
  29. #define    PORT_X        20    /* viewport x origin */
  30. #define    PORT_Y        40    /* viewport y origin */
  31. #define    PORT_WIDTH    460    /* viewport width */
  32. #define    PORT_HEIGHT    140    /* viewport height */
  33.  
  34. /* debug statement data structure */
  35. #define    MAX_FILTER    32    /* maximum filter categories */
  36.  
  37. typedef struct {
  38.  
  39.     /* general options */
  40.     BOOL    bSetup;        /* debug setup flag */
  41.     BOOL    bActive;    /* debug active flag */
  42.     
  43.     /* count options */
  44.     BOOL    bCount;        /* count events flag */
  45.     LONG    lMsgCount;    /* debug message count */
  46.  
  47.     /* display options */
  48.     BOOL    bDisplay;    /* display debug events */
  49.     HWND    hListBox;    /* listbox window handle */
  50.     WORD    wEntries;    /* current listbox lines */
  51.     WORD    wMaxEntries;    /* maximum listbox lines */
  52.     
  53.     /* filter options */
  54.     BOOL    bFilter;    /* filter debug events */
  55.     WORD    wFilterSize;    /* size of categories */
  56.     WORD    Filter[MAX_FILTER];    /* list of categories */
  57.  
  58.     /* log-file options */
  59.     BOOL    bLog;        /* log debug events */
  60.     char    szLogFile[64];    /* debug log file name */
  61.  
  62. } OPTIONS;
  63.  
  64. /* global data definitions */
  65. static OPTIONS    Options;    
  66.  
  67. /*
  68.  * DebugSetup( hWnd, wMsg, wMax ) : bResult
  69.  *
  70.  *    hWnd    main application window handle
  71.  *    wMsg    debug control panel system message
  72.  *    wMax    maximum number of debug lines
  73.  *
  74.  * This function is responsible for creating the debug viewport
  75.  * window class and for attaching the control panel to the system
  76.  * menu of the window handle provided (this implies that the window
  77.  * handle provided has a system menu).
  78.  *
  79.  * A boolean value of TRUE is returned if the setup process was
  80.  * successful.
  81.  *
  82.  */
  83.  
  84. BOOL FAR PASCAL DebugSetup( hWnd, wMsg, wMax )
  85.     HWND    hWnd;
  86.     WORD    wMsg;
  87.     WORD    wMax;
  88. {
  89.     /* local variables */
  90.     BOOL        bOk;        /* boolean result */
  91.     HMENU        hSysMenu;    /* temporary menu handle */
  92.     WNDCLASS    WndClass;    /* temporary class 
  93.                         structure */
  94.     HANDLE        hInstance;    /* handle to window 
  95.                         instance */
  96.     char        szModule[64];    /* main module file name */
  97.     
  98.     /* boolean result */
  99.     bOk = FALSE;
  100.     hInstance = GetWindowWord( hWnd, GWW_HINSTANCE );
  101.     
  102.     /* check if debug already activated */
  103.     if ( !Options.bSetup ) {
  104.  
  105.         /* retrieve system menu handle */
  106.         hSysMenu = GetSystemMenu( hWnd, FALSE );
  107.         if ( hSysMenu ) {
  108.         
  109.             /* change system menu to reflect control panel */
  110.             ChangeMenu( hSysMenu, 0, NULL, 999, 
  111.                     MF_APPEND|MF_SEPARATOR );
  112.             ChangeMenu( hSysMenu, 0, "&Debug...", wMsg, 
  113.                     MF_APPEND|MF_STRING);
  114.     
  115.             /* create listbox window -initially hidden */
  116.             Options.hListBox = CreateWindow(
  117.                     "LISTBOX",        /* class name */
  118.                     "",                /* window caption */
  119.                     WS_BORDER|WS_VSCROLL,    /* window style */
  120.                     PORT_X,            /* x position */
  121.                     PORT_Y,            /* y position */
  122.                     PORT_WIDTH,        /* width */
  123.                     PORT_HEIGHT,    /* height */
  124.                     NULL,            /* parent window */
  125.                     NULL,            /* menu */
  126.                     hInstance,        /* instance handle */
  127.                     (LPSTR)NULL        /* other data */
  128.                 );
  129.                     
  130.             /* continue if successful */
  131.             if ( Options.hListBox ) {
  132.                                 
  133.                 /* define options data */
  134.                 bOk = TRUE;
  135.                 Options.bSetup = TRUE;
  136.                 Options.wMaxEntries = wMax;
  137.  
  138.                 /* define default log file name */
  139.                 GetModuleFileName( hInstance, szModule, 
  140.                                     sizeof(szModule) );
  141.                     
  142.                 *strrchr(szModule,'.') = 0;
  143.                 sprintf(
  144.                     Options.szLogFile,
  145.                     "%s.LOG",
  146.                     (char *)(strrchr(szModule,'\\')+1)
  147.                 );
  148.  
  149.             }
  150.         
  151.         } 
  152.  
  153.     } 
  154.  
  155.     /* return final result */
  156.     return( bOk );
  157.  
  158. }
  159.  
  160. /*
  161.  * DebugControl( hWnd ) : BOOL FAR PASCAL
  162.  *
  163.  *        hWnd    main application window handle
  164.  *
  165.  * This function enables the user to monitor and adjust the debug
  166.  * control panel settings.  When this function is called a modal
  167.  * dialog box is displayed which allows the user to set the
  168.  * debug options.
  169.  *
  170.  * The value returned indicates how the user terminated the
  171.  * dialog box - TRUE implies the OK button was pressed, FALSE
  172.  * the CANCEL button.
  173.  *
  174.  */
  175.  
  176. BOOL FAR PASCAL DebugControl( hWnd )
  177.     HWND        hWnd;
  178. {
  179.     /* local variables */
  180.     FARPROC        lpProc;            /* temporary function address */
  181.     BOOL        bResult;        /* boolean result value */
  182.     HANDLE        hInstance;        /* window instance handle */
  183.  
  184.     /* retrieve instance handle */
  185.     hInstance = GetWindowWord( hWnd, GWW_HINSTANCE );
  186.     
  187.     /* display dialog box */
  188.     lpProc = MakeProcInstance( DebugControlDlgFn, hInstance );
  189.     bResult = DialogBox(hInstance,(LPSTR)"DebugControl",hWnd,lpProc);
  190.     FreeProcInstance( lpProc );
  191.  
  192.     /* return final result */
  193.     return( bResult );
  194.  
  195. }
  196.  
  197. /*
  198.  * DebugControlDlgFn( hDlg, wMsg, wParam, lParam ) : BOOL FAR PASCAL
  199.  *
  200.  *        hDlg        window handle
  201.  *        wMsg        dialog message
  202.  *        wParam        word parameter
  203.  *        lParam        long parameter
  204.  *
  205.  * This function processes all the messages related to the
  206.  * debug control panel dialog box.  With the dialog box the
  207.  * user can add, change, and remove debugging channels.
  208.  *
  209.  */
  210.  
  211. BOOL FAR PASCAL DebugControlDlgFn( hDlg, wMsg, wParam, lParam )
  212.     HWND        hDlg;
  213.     WORD        wMsg;
  214.     WORD        wParam;
  215.     LONG        lParam;
  216. {
  217.     /* local variables */
  218.     BOOL        bResult;    /* boolean result variable */
  219.     
  220.     /* initialization */
  221.     bResult = TRUE;
  222.  
  223.     /* process message */
  224.     switch( wMsg )
  225.         {
  226.     case WM_INITDIALOG :    /* initialize dialog box */
  227.         
  228.         {
  229.             /* local variables */
  230.             WORD    i;            /* loop variable */
  231.             int        xPopup;        /* popup x position */
  232.             int        yPopup;        /* popup y position */
  233.             int        cxPopup;    /* width of popup window */
  234.             int        cyPopup;    /* height of popup window */
  235.             RECT    rectWnd;    /* temporary window rect */
  236.             char    szToken[8];    /* character token */
  237.             char    szFilterList[64];    /* filter list string */
  238.             
  239.             /* The following code centers the dialog box in the
  240.              * middle of the screen.  It uses the dimensions of 
  241.              * the display and the dialog box and repositions the
  242.              * dialog box accordingly.
  243.              */
  244.             
  245.             /* retrieve popup rectangle  */
  246.             GetWindowRect( hDlg, (LPRECT)&rectWnd );
  247.             
  248.             /* calculate popup extents */
  249.             cxPopup = rectWnd.right - rectWnd.left;
  250.             cyPopup = rectWnd.bottom - rectWnd.top;
  251.     
  252.             /* calculate new location & move dialog box */
  253.             xPopup = ( GetSystemMetrics(SM_CXSCREEN) - cxPopup) / 2;
  254.             yPopup = ( GetSystemMetrics(SM_CYSCREEN) - cyPopup) / 2;
  255.             
  256.             MoveWindow( hDlg, xPopup, yPopup, cxPopup, cyPopup, TRUE);
  257.  
  258.             /* define filter list */
  259.             szFilterList[0] = 0;
  260.             if ( Options.wFilterSize ) {
  261.                 sprintf( szFilterList, "%u", Options.Filter[0] );
  262.                 for ( i=1; i<Options.wFilterSize; i++ ) {
  263.                     sprintf( szToken, ",%u", Options.Filter[i] );
  264.                     strcat( szFilterList, szToken );
  265.                 }
  266.             }
  267.             
  268.             /* check ON-OFF radio buttons */
  269.             CheckRadioButton(
  270.                 hDlg, 
  271.                 BUG_OFF, 
  272.                 BUG_ON, 
  273.                 (Options.bActive) ? BUG_ON :BUG_OFF
  274.             );
  275.         
  276.             /* define check boxes */
  277.             CheckDlgButton( hDlg, BUG_COUNT, Options.bCount );
  278.             CheckDlgButton( hDlg, BUG_DISPLAY, Options.bDisplay );
  279.             CheckDlgButton( hDlg, BUG_FILTER, Options.bFilter );
  280.             CheckDlgButton( hDlg, BUG_LOG, Options.bLog );
  281.     
  282.             /* display filter categories & log file name */
  283.             SetDlgItemText( hDlg, BUG_FILTERLIST, szFilterList );
  284.             SetDlgItemText( hDlg, BUG_LOGFILE, Options.szLogFile );
  285.         
  286.             /* disable check boxes & edit fields if debug inactive */
  287.             if ( !Options.bActive ) {
  288.  
  289.                 /* disable check boxes */
  290.                 ENABLE( hDlg, BUG_COUNT, FALSE );
  291.                 ENABLE( hDlg, BUG_DISPLAY, FALSE );
  292.                 ENABLE( hDlg, BUG_FILTER, FALSE );
  293.                 ENABLE( hDlg, BUG_LOG, FALSE );
  294.     
  295.                 /* disable edit fields */
  296.                 ENABLE( hDlg, BUG_FILTERLIST, FALSE );
  297.                 ENABLE( hDlg, BUG_LOGFILE, FALSE );
  298.     
  299.             } else {
  300.         
  301.                 /* enable edits field */
  302.                 ENABLE( hDlg, BUG_FILTERLIST, IsDlgButtonChecked(hDlg,
  303.                         BUG_FILTER) );
  304.                 ENABLE( hDlg, BUG_LOGFILE, IsDlgButtonChecked(hDlg,
  305.                         BUG_LOG) );
  306.         
  307.             }
  308.         
  309.         }
  310.                 
  311.         break;
  312.     case WM_COMMAND : /* dialog box command */
  313.  
  314.         /* process sub-message */
  315.         switch( wParam )
  316.             {
  317.         case BUG_ON : /* turn debug on */
  318.             
  319.             /* redefine radio button */
  320.             CheckRadioButton( hDlg, BUG_OFF, BUG_ON, BUG_ON );
  321.             
  322.             /* enable check boxes */
  323.             ENABLE( hDlg, BUG_COUNT, TRUE );
  324.             ENABLE( hDlg, BUG_DISPLAY, TRUE );
  325.             ENABLE( hDlg, BUG_FILTER, TRUE );
  326.             ENABLE( hDlg, BUG_LOG, TRUE );
  327.             
  328.             /* enable edits field */
  329.             ENABLE( hDlg, BUG_FILTERLIST, IsDlgButtonChecked(hDlg,
  330.                     BUG_FILTER) );
  331.             ENABLE( hDlg, BUG_LOGFILE, IsDlgButtonChecked(hDlg,
  332.                     BUG_LOG) );
  333.                 
  334.             break;
  335.         case BUG_OFF : /* turn debug off */
  336.             
  337.             /* redefine radio button */
  338.             CheckRadioButton( hDlg, BUG_OFF, BUG_ON, BUG_OFF );
  339.             
  340.             /* enable check boxes */
  341.             ENABLE( hDlg, BUG_COUNT, FALSE );
  342.             ENABLE( hDlg, BUG_DISPLAY, FALSE );
  343.             ENABLE( hDlg, BUG_FILTER, FALSE );
  344.             ENABLE( hDlg, BUG_LOG, FALSE );
  345.             
  346.             /* enable edit fields */
  347.             ENABLE( hDlg, BUG_FILTERLIST, FALSE );
  348.             ENABLE( hDlg, BUG_LOGFILE, FALSE );
  349.             
  350.             break;
  351.         case BUG_COUNT : /* count debug events */
  352.             TOGGLE( hDlg, BUG_COUNT );                        
  353.             break;
  354.         case BUG_DISPLAY : /* display debug events */
  355.             TOGGLE( hDlg, BUG_DISPLAY );
  356.             break;
  357.         case BUG_FILTER : /* filter debug events */
  358.             TOGGLE( hDlg, BUG_FILTER );
  359.             ENABLE( hDlg, BUG_FILTERLIST, IsDlgButtonChecked(hDlg,
  360.                     BUG_FILTER) );
  361.             break;
  362.         case BUG_LOG : /* log debug events */
  363.             TOGGLE( hDlg, BUG_LOG );
  364.             ENABLE( hDlg, BUG_LOGFILE, IsDlgButtonChecked(hDlg,
  365.                     BUG_LOG) );
  366.             break;
  367.         case BUG_OK : /* done with debug control panel */
  368.             
  369.             {
  370.                 /* local variables */
  371.                 WORD        i;
  372.                 char *        spToken;
  373.                 char        szToken[8];
  374.                 char        szCaption[64];
  375.                 char        szFilterList[32];
  376.  
  377.                 /* capture radio button state */
  378.                 Options.bActive = IsDlgButtonChecked( hDlg, BUG_ON );
  379.             
  380.                 /* capture check box states */
  381.                 Options.bCount = IsDlgButtonChecked( hDlg, BUG_COUNT);
  382.                 Options.bDisplay=IsDlgButtonChecked(hDlg,BUG_DISPLAY);
  383.                 Options.bFilter=IsDlgButtonChecked( hDlg,BUG_FILTER);
  384.                 Options.bLog = IsDlgButtonChecked( hDlg, BUG_LOG );
  385.  
  386.                 /* capture filter list changes - no limit checking! */
  387.                 GetDlgItemText(
  388.                     hDlg,
  389.                     BUG_FILTERLIST,
  390.                     szFilterList,
  391.                     sizeof(szFilterList)
  392.                 );
  393.             
  394.                 Options.wFilterSize = 0;
  395.                 spToken = strtok( szFilterList, " ,;" );
  396.                 while ( spToken ) {
  397.                     Options.Filter[ Options.wFilterSize++ ] = 
  398.                                                     atoi( spToken );
  399.                     spToken = strtok( NULL, " ,;" );
  400.                 }
  401.                     
  402.                 /* capture log file changes */
  403.                 GetDlgItemText(
  404.                     hDlg,
  405.                     BUG_LOGFILE,
  406.                     Options.szLogFile,
  407.                     sizeof(Options.szLogFile)
  408.                 );
  409.             
  410.                 /* display listbox if necessary */
  411.                 if ( Options.bActive ) {
  412.  
  413.             
  414.                     /* update viewport window caption */
  415.                     if ( Options.bFilter && Options.wFilterSize ) {
  416.                         
  417.                         /* define filter list */
  418.                         szFilterList[0] = 0;
  419.                         if ( Options.wFilterSize ) {
  420.                             sprintf( szFilterList, "%u", 
  421.                                         Options.Filter[0] );
  422.                             for ( i=1; i<Options.wFilterSize; i++ ) {
  423.                                 sprintf( szToken, ",%u", 
  424.                                         Options.Filter[i] );
  425.                                 strcat( szFilterList, szToken );
  426.                             }
  427.                         }    
  428.                         
  429.                         sprintf( 
  430.                             szCaption, 
  431.                             "%s - (%s)", 
  432.                             Options.szLogFile, 
  433.                             szFilterList 
  434.                         );
  435.                     
  436.                     } else
  437.                         sprintf( szCaption, "%s - (ALL)", 
  438.                                     Options.szLogFile );
  439.                     
  440.                     /* define caption & make window visible */
  441.                     SetWindowText( Options.hListBox, szCaption );
  442.                     ShowWindow( Options.hListBox, SHOW_OPENWINDOW );
  443.                     
  444.                 } else
  445.                     ShowWindow( Options.hListBox, HIDE_WINDOW );
  446.                 
  447.                 /* exit */
  448.                 EndDialog( hDlg, TRUE );
  449.             
  450.             }
  451.             
  452.             break;
  453.         case BUG_CANCEL :    /* cancel control panel */
  454.         case IDCANCEL :
  455.             EndDialog( hDlg, FALSE );
  456.             break;
  457.         default :            /* ignore all others */
  458.             bResult = FALSE;
  459.             break;
  460.         }
  461.         
  462.         break;
  463.     default :
  464.         bResult = FALSE;
  465.         break;
  466.     }
  467.  
  468.     /* return final result */
  469.     return( bResult );
  470.  
  471. }
  472.  
  473. /*
  474.  * Debug( wCategory, ParmList) : BOOL FAR
  475.  *
  476.  *        wCategory        debug message classification
  477.  *        ParmList        debug parameter list
  478.  *
  479.  * This function outputs a formatted message to the debug
  480.  * utility routines.  The wCategory variable determines 
  481.  * how the message is filtered.  The ParmList is a standard
  482.  * printf parameter list.  A value of TRUE is returned if
  483.  * the message was successfully processed and not filtered.
  484.  *
  485.  * Note that this function CANNOT be declared of type
  486.  * PASCAL as it uses a variable number of arguments!  Also
  487.  * note that alternative methods are available for handling
  488.  * a variable number of function parameters.
  489.  *
  490.  */
  491.  
  492. BOOL FAR Debug( wCategory, ParmList )
  493.     WORD        wCategory;
  494.     struct {
  495.         char    cBytes[64];
  496.     } ParmList;
  497. {
  498.     /* local variables */
  499.     WORD        i;                    /* temporary loop variable */
  500.     int            hFile;                /* log file handle */
  501.     BOOL        bResult;            /* result of function */
  502.     BOOL        bInclude;            /* include message flag */
  503.     char        szStatement[132];    /* temporary statement */
  504.  
  505.     /* initialization */
  506.     bResult = FALSE;
  507.  
  508.     /* process statement if debug active */
  509.     if ( Options.bSetup && Options.bActive ) {
  510.     
  511.         bInclude = TRUE;
  512.  
  513.         /* check for inclusion in filter list */
  514.         if ( Options.bFilter ) {
  515.             
  516.             /* search filter list */
  517.             for (
  518.                 i=0; 
  519.                 (i<Options.wFilterSize)&&(Options.Filter[i]!=
  520.                                                         wCategory); 
  521.                 i++ 
  522.             );
  523.         
  524.             /* turn off include if not found */
  525.             if ( i >= Options.wFilterSize )
  526.                 bInclude = FALSE;
  527.         
  528.         }
  529.         
  530.         /* format debug statement if included */
  531.         if ( bInclude ) {
  532.         
  533.             /* prepare for debug statement */
  534.             i = 0;
  535.             bResult = TRUE;
  536.             Options.lMsgCount++;
  537.             
  538.             /* define debug statement */
  539.             if ( Options.bCount ) 
  540.                 i = sprintf( szStatement, "%ld ", Options.lMsgCount );
  541.             i += sprintf( &szStatement[i], ParmList );
  542.                 
  543.             /* display debug statement in listbox */
  544.             if ( Options.bDisplay ) {            
  545.                 
  546.                 /* Note: since we are passing the formatted
  547.                  * debugging statement to the listbox using
  548.                  * a SendMessage we cannot do anything which
  549.                  * would cause memory to be shuffled - this
  550.                  * invalidates the pointer!
  551.                  */
  552.                 
  553.                 /* add new statement to listbox */
  554.                 SendMessage(
  555.                     Options.hListBox,
  556.                     LB_ADDSTRING,
  557.                     (WORD)0,
  558.                     (LONG)(LPSTR)szStatement
  559.                 );
  560.                         
  561.                 /* remove first statement from listbox if necessary */
  562.                 if ( Options.wEntries >= Options.wMaxEntries ) {
  563.                     SendMessage(
  564.                         Options.hListBox,
  565.                         LB_DELETESTRING,
  566.                         0,
  567.                         (LONG)0
  568.                     );
  569.                 } else
  570.                     Options.wEntries++; 
  571.             
  572.                 /* make last statement visible */
  573.                 SendMessage(
  574.                     Options.hListBox,
  575.                     LB_SETCURSEL,
  576.                     (WORD)Options.wEntries-1,
  577.                     (LONG)0
  578.                 );
  579.  
  580.             }
  581.             
  582.             /* output debug statement to logfile */
  583.             if ( Options.bLog ) {
  584.             
  585.                 /* open or create log file */
  586.                 hFile = open( Options.szLogFile, MODE_APPEND, SHARED);
  587.                 if ( hFile < 0 )
  588.                     hFile=open(Options.szLogFile,MODE_CREATE,SHARED);
  589.                     
  590.                 /* write message to file if sucessful */
  591.                 if ( hFile > 0 ) {
  592.                     write( hFile, szStatement, i );
  593.                     write( hFile, "\r\n", 2 );
  594.                     close( hFile );
  595.                 } 
  596.             
  597.             }
  598.         
  599.         } 
  600.     
  601.     } 
  602.     
  603.     /* return result */
  604.     return( bResult );
  605.  
  606. }    
  607.