home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / MSJV5-6.ZIP / FORM2.ZIP / FORM4.C < prev    next >
C/C++ Source or Header  |  1990-11-01  |  27KB  |  989 lines

  1. /*
  2.  * Form Library - UTILITY FUNCTIONS MODULE
  3.  *
  4.  * LANGUAGE      : Microsoft C 5.1
  5.  * MODEL         : small
  6.  * ENVIRONMENT   : Microsoft Windows 2.1 SDK
  7.  * STATUS        : operational
  8.  *
  9.  *    Eikon Systems, Inc.
  10.  *    989 East Hillsdale Blvd, Suite 260
  11.  *    Foster City, California 94404
  12.  *    415-349-4664
  13.  *
  14.  * 07/12/90 1.00 - Kevin P. Welch - initial creation.
  15.  *
  16.  */
  17.  
  18. #define  NOCOMM
  19.  
  20. #include <windows.h>
  21.  
  22. #include "form.h"
  23. #include "form.d"
  24.  
  25. /* local dialog box data structures */
  26. #define  CT_MASK        0x80
  27. #define  CT_BUTTON      0x80
  28. #define  CT_EDIT        0x81
  29. #define  CT_STATIC      0x82
  30. #define  CT_LIST        0x83
  31. #define  CT_SCROLL      0x84
  32. #define  CT_COMBOBOX    0x85
  33.  
  34. typedef struct {
  35.    LONG        lStyle;
  36.    BYTE        bItems;
  37.    WORD        wX;
  38.    WORD        wY;
  39.    WORD        wCX;
  40.    WORD        wCY;
  41.    char        szText[1];
  42. } PACKEDDLGBOX;
  43.  
  44. typedef struct {
  45.    WORD        wX;
  46.    WORD        wY;
  47.    WORD        wCX;
  48.    WORD        wCY;
  49.    WORD        wID;
  50.    LONG        lStyle;
  51.    char        szClass[1];
  52.    char        szWndText[1];
  53.    BYTE        bInfo;
  54. } PACKEDDLGCTL;
  55.  
  56. typedef PACKEDDLGBOX FAR *    LPPACKEDDLGBOX;
  57. typedef PACKEDDLGCTL FAR *    LPPACKEDDLGCTL;
  58.  
  59. /* */
  60.  
  61. /* DIALOG BOX HANDLING FUNCTIONS */
  62.  
  63. /*
  64.  * GetDlg( lpResData, lpDlgBox ) : BOOL;
  65.  *
  66.  *    lpResData      long pointer to packed dialog box structure
  67.  *    lpDlgBox       long pointer to unpacked dialog box structure
  68.  *
  69.  * This function unpacks the dialog box data structure defined by
  70.  * the specified resource and fills in the appropriate fields in the
  71.  * structure provided.  A value of TRUE is returned if the process
  72.  * was successful.
  73.  *
  74.  * Note that this function assumes that no menu name, class name, or
  75.  * font information is specified with the dialog box template.
  76.  *
  77.  */
  78.  
  79. BOOL FAR PASCAL GetDlg(
  80.    LPSTR             lpResData,  
  81.    LPDLGBOX          lpDlgBox )
  82. {
  83.    LPSTR             lpResource;
  84.    LPPACKEDDLGBOX    lpPackedDlgBox;
  85.  
  86.    /* coerce pointers */
  87.    lpPackedDlgBox = (LPPACKEDDLGBOX)lpResData;
  88.  
  89.    /* extract fixed portions */
  90.    lpDlgBox->lStyle = lpPackedDlgBox->lStyle;
  91.    lpDlgBox->wControls = lpPackedDlgBox->bItems;
  92.    lpDlgBox->wX = lpPackedDlgBox->wX;
  93.    lpDlgBox->wY = lpPackedDlgBox->wY;
  94.    lpDlgBox->wCX = lpPackedDlgBox->wCX;
  95.    lpDlgBox->wCY = lpPackedDlgBox->wCY;
  96.  
  97.    /* extract variable portion */
  98.    lpResource = (LPSTR)lpPackedDlgBox->szText;
  99.    lpResource = (*lpResource == -1) ? lpResource+3 : lpResource+lstrlen(lpResource)+1;
  100.    lpResource += lstrlen(lpResource) + 1;
  101.  
  102.    StringCopy( lpDlgBox->szCaption, lpResource, MAX_CAPTION );
  103.  
  104.    /* return result */
  105.    return( TRUE );
  106.  
  107. }
  108.  
  109. /* */
  110.  
  111. /*
  112.  * GetDlgData( hDlg ) : HANDLE;
  113.  *
  114.  *    hDlg           handle to dialog box 
  115.  *
  116.  * This function retrieves information from the data entry form and
  117.  * returns a handle referencing a global block of memory.  A NULL
  118.  * value is returned if the process was unsuccessful.
  119.  *
  120.  * Note that this function will not retrieve a combined field name
  121.  * and data value larger than MAX_DATA.
  122.  *
  123.  */
  124.  
  125. HANDLE FAR PASCAL GetDlgData(
  126.    HWND        hDlg )
  127. {
  128.    WORD        wPage;
  129.    WORD        wControl;
  130.    WORD        wValueSize;
  131.    WORD        wDlgDataSize;
  132.    HANDLE      hDlgData;
  133.    HWND FAR *  lpCtlList;
  134.    LPSTR       lpDlgData;
  135.  
  136.    char        szCtlData[MAX_DATA];
  137.  
  138.    /* initialization */
  139.    wDlgDataSize = 0;
  140.  
  141.    /* allocate memory block */
  142.    hDlgData = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, (DWORD)32 );
  143.    if ( hDlgData ) {
  144.       
  145.       /* loop through each dialog box page */
  146.       for ( wPage=1; wPage<=FormInfo.wPages; wPage++ ) {
  147.  
  148.          /* access list of dialog page controls */
  149.          lpCtlList = (HWND FAR *)GlobalLock( GET_CTLLIST(hDlg,wPage) );
  150.          if ( lpCtlList ) {
  151.  
  152.             /* loop through each control */
  153.             for ( wControl=1; wControl<(WORD)lpCtlList[0]; wControl++ ) {
  154.  
  155.                /* retrieve data associated with control */
  156.                if ( GetDlgCtlData(hDlg,lpCtlList[wControl],szCtlData,sizeof(szCtlData)) ) {
  157.  
  158.                   /* calculate data value size */
  159.                   wValueSize = lstrlen(szCtlData) + 1;
  160.  
  161.                   /* update global data block */
  162.                   hDlgData = GlobalReAlloc( hDlgData, (DWORD)(wDlgDataSize+wValueSize+32), NULL );
  163.                   if ( hDlgData ) {
  164.                      lpDlgData = GlobalLock( hDlgData );
  165.                      if ( lpDlgData ) {
  166.                         lstrcpy( lpDlgData+wDlgDataSize, szCtlData );
  167.                         wDlgDataSize = wDlgDataSize + wValueSize;
  168.                         GlobalUnlock( hDlgData );
  169.                      } else
  170.                         WARNING( hDlg, "Unable to access data block!" );
  171.                   } else
  172.                      WARNING( hDlg, "Unable to reallocate data block!" );
  173.                
  174.                } 
  175.             
  176.             }
  177.          
  178.             /* unlock control list */
  179.             GlobalUnlock( GET_CTLLIST(hDlg,wPage) );
  180.          
  181.          }
  182.       
  183.       }
  184.       
  185.       /* append final NULL */
  186.       hDlgData = GlobalReAlloc( hDlgData, (DWORD)(wDlgDataSize+32), NULL );
  187.       if ( hDlgData ) {
  188.          lpDlgData = GlobalLock( hDlgData );
  189.          if ( lpDlgData ) {
  190.             *(lpDlgData+wDlgDataSize) = NULL;
  191.             GlobalUnlock( hDlgData );
  192.          } else
  193.             WARNING( hDlg, "Unable to access data block! (null)" );
  194.       } else
  195.          WARNING( hDlg, "Unable to reallocate data block! (null)" );
  196.  
  197.    }
  198.  
  199.    /* return final result */
  200.    return( hDlgData );
  201.  
  202. }
  203.  
  204. /* */
  205.  
  206. /*
  207.  * GetDlgCtlData( hDlg, hWndCtl, lpszData, wMaxData ) : BOOL;
  208.  *
  209.  *    hDlg           handle to dialog box containing control
  210.  *    hWndCtl        handle to control window
  211.  *    lpszData       combined field name and data value
  212.  *    wMaxData       maximum field name and data size
  213.  *
  214.  * This function retrieves the field name and data associated with the
  215.  * control window provided.  If the control is unlisted then it is
  216.  * assumed to be unimportant and a value of FALSE is returned.
  217.  *
  218.  * If the control is listed, but no data is defined then a VALUE of
  219.  * TRUE is returned.  The resulting data value consists of the field
  220.  * name followed by the appropriate default data value (in most cases,
  221.  * this is nothing).
  222.  *
  223.  * Note that the following control types are NOT supported:
  224.  *
  225.  *    Scrollbars
  226.  *    ComboBoxes
  227.  *    ListBoxes
  228.  *
  229.  */
  230.  
  231. BOOL FAR PASCAL GetDlgCtlData(
  232.    HWND        hDlg,
  233.    HWND        hWndCtl,
  234.    LPSTR       lpszData,
  235.    WORD        wMaxData )
  236. {
  237.    BOOL        bResult;
  238.    WORD        wCtlStyle;
  239.    char        szCtlName[MAX_NAME];
  240.    char        szCtlData[MAX_DATA];
  241.    char        szClassName[MAX_NAME];
  242.  
  243.    /* initialization */
  244.    bResult = FALSE;
  245.    *lpszData = NULL;
  246.  
  247.    /* retrieve control name */
  248.    if ( GetCtlName(INSTANCE(hDlg),ID(hWndCtl),szCtlName,sizeof(szCtlName)) ) {
  249.  
  250.       /* normal return */
  251.       bResult = TRUE;
  252.       szCtlData[0] = NULL;
  253.  
  254.       /* retrieve control class name & style flags */
  255.       GetClassName( hWndCtl, szClassName, sizeof(szClassName) );
  256.       wCtlStyle = LOWORD( GetWindowLong(hWndCtl,GWL_STYLE) );
  257.    
  258.       /* extract control data */
  259.       if ( !lstrcmp(szClassName,"Button") ) {
  260.  
  261.          /* extract button control data */
  262.          switch( wCtlStyle&0x000F )
  263.             {
  264.          case BS_CHECKBOX :
  265.          case BS_AUTOCHECKBOX :
  266.          case BS_RADIOBUTTON :
  267.          case BS_3STATE :
  268.          case BS_AUTO3STATE :
  269.          case BS_AUTORADIOBUTTON :
  270.  
  271.             /* define TRUE-FALSE result */
  272.             if ( SendMessage(hWndCtl,BM_GETCHECK,0,0L) )
  273.                StringCopy( szCtlData, "TRUE", sizeof(szCtlData) );
  274.             else
  275.                StringCopy( szCtlData, "FALSE", sizeof(szCtlData) );
  276.  
  277.             break;
  278.          case BS_PUSHBUTTON :
  279.          case BS_DEFPUSHBUTTON :
  280.          case BS_GROUPBOX :
  281.          case BS_USERBUTTON :
  282.          case BS_PUSHBOX :
  283.          case BS_OWNERDRAW :
  284.          default:
  285.             GetWindowText( hWndCtl, szCtlData, sizeof(szCtlData) );
  286.             break;
  287.          }
  288.  
  289.  
  290.       } else
  291.          GetWindowText( hWndCtl, szCtlData, sizeof(szCtlData) );
  292.       
  293.       /* combine control name & data value */
  294.       StringCopy( lpszData, szCtlName, wMaxData );
  295.       StringCat( lpszData, ":", wMaxData );
  296.       StringCat( lpszData, szCtlData, wMaxData );
  297.  
  298.    }
  299.  
  300.    /* return result */
  301.    return( bResult );
  302.  
  303. }
  304.  
  305. /* */
  306.  
  307. /* CONTROL HANDLING FUNCTIONS */
  308.  
  309. /*
  310.  * GetCtl( lpDlgData, wControl, lpDlgCtl ) : BOOL;
  311.  *
  312.  *    lpDlgData      long pointer to packed dialog box structure
  313.  *    wControl       index to desired control
  314.  *    lpDlgCtl       long pointer to unpacked control structure
  315.  *
  316.  * This function retrieves and unpacks a the specified dialog box
  317.  * control data structure, returning the resulting data in the
  318.  * unpacked control structure provided.  A value of TRUE is returned
  319.  * if the process was successful.
  320.  *                                                         
  321.  */
  322.  
  323. BOOL FAR PASCAL GetCtl(
  324.    LPSTR             lpDlgData,
  325.    WORD              wControl,
  326.    LPDLGCTL          lpDlgCtl )
  327. {
  328.    BYTE              bType;
  329.    WORD              wEntry;
  330.    BOOL              bResult;
  331.    LPPACKEDDLGBOX    lpPackedDlgBox;
  332.    LPPACKEDDLGCTL    lpPackedDlgCtl;
  333.  
  334.    /* initialization */
  335.    bResult = FALSE;
  336.  
  337.    /* coerce pointers */
  338.    lpPackedDlgBox = (LPPACKEDDLGBOX)lpDlgData;
  339.    
  340.    /* skip to control section */
  341.    lpDlgData = (LPSTR)lpPackedDlgBox->szText;
  342.    lpDlgData = (*lpDlgData == -1) ? lpDlgData+3 : lpDlgData+lstrlen(lpDlgData)+1;
  343.  
  344.    lpDlgData += lstrlen(lpDlgData) + 1;
  345.    lpDlgData += lstrlen(lpDlgData) + 1;
  346.  
  347.    lpPackedDlgCtl = (LPPACKEDDLGCTL)lpDlgData;
  348.  
  349.    /* loop through controls */
  350.    for ( wEntry=0; (wEntry<wControl)&&(wEntry<lpPackedDlgBox->bItems); wEntry++ ) {
  351.  
  352.       /* skip through data */
  353.       lpDlgData = lpPackedDlgCtl->szClass;
  354.       lpDlgData = (*lpDlgData & CT_MASK) ? lpDlgData+1 : lpDlgData+lstrlen(lpDlgData)+1;
  355.       lpDlgData += lstrlen(lpDlgData) + 1;
  356.       lpDlgData += sizeof( lpPackedDlgCtl->bInfo );
  357.  
  358.       /* define pointer to next control */
  359.       lpPackedDlgCtl = (LPPACKEDDLGCTL)lpDlgData;
  360.  
  361.    }
  362.  
  363.    /* extract desired control */
  364.    if ( wEntry == wControl ) {
  365.  
  366.       /* define return value */
  367.       bResult = TRUE;
  368.  
  369.       /* extract fixed portions */
  370.       lpDlgCtl->wX = lpPackedDlgCtl->wX;
  371.       lpDlgCtl->wY = lpPackedDlgCtl->wY;
  372.       lpDlgCtl->wCX = lpPackedDlgCtl->wCX;
  373.       lpDlgCtl->wCY = lpPackedDlgCtl->wCY;
  374.       lpDlgCtl->wID = lpPackedDlgCtl->wID;
  375.       lpDlgCtl->lStyle = lpPackedDlgCtl->lStyle;
  376.  
  377.       /* define control class name */
  378.       bType = (unsigned char) *lpPackedDlgCtl->szClass;
  379.       if ( !(bType&CT_MASK) ) 
  380.          if ( lstrcmp(lpPackedDlgCtl->szClass,"scrollbar") == 0 )
  381.             bType = CT_SCROLL;
  382.  
  383.       switch( bType )
  384.          {
  385.       case CT_BUTTON :
  386.          StringCopy( lpDlgCtl->szClass, "Button", MAX_CLASS );
  387.          break;
  388.       case CT_EDIT :
  389.          StringCopy( lpDlgCtl->szClass, "Edit", MAX_CLASS );
  390.          break;
  391.       case CT_STATIC :
  392.          StringCopy( lpDlgCtl->szClass, "Static", MAX_CLASS );
  393.          break;
  394.       case CT_LIST :
  395.          StringCopy( lpDlgCtl->szClass, "ListBox", MAX_CLASS );
  396.          break;
  397.       case CT_SCROLL :
  398.          StringCopy( lpDlgCtl->szClass, "ScrollBar", MAX_CLASS );
  399.          break;
  400.       case CT_COMBOBOX :
  401.          StringCopy( lpDlgCtl->szClass, "ComboBox", MAX_CLASS );
  402.          break;
  403.       default :
  404.          StringCopy( lpDlgCtl->szClass, "?", MAX_CLASS );
  405.          break;
  406.       }
  407.  
  408.       /* define control text */
  409.       lpDlgData = lpPackedDlgCtl->szClass;
  410.       lpDlgData = (*lpDlgData & CT_MASK) ? lpDlgData+1 : lpDlgData+lstrlen(lpDlgData)+1;
  411.  
  412.       StringCopy( lpDlgCtl->szText, lpDlgData, MAX_TEXT );
  413.  
  414.    }
  415.  
  416.    /* return result */
  417.    return( bResult );
  418.  
  419. }
  420.  
  421. /* */
  422.  
  423. /*
  424.  * GetCtlName( hInstance, wCtlID, lpszCtlName, wMaxCtlName ) : BOOL;
  425.  *
  426.  *    hInstance      instance handle of module
  427.  *    wCtlID         child window control ID
  428.  *    szCtlName      long pointer to control name
  429.  *    wMaxCtlName    maximum size of control name
  430.  *
  431.  * Retrieves the control name from the applications string table
  432.  * that references a particular control based on the child window
  433.  * identifier provided.  A value of TRUE is returned if the search
  434.  * was successful.
  435.  *
  436.  */
  437.  
  438. BOOL FAR PASCAL GetCtlName(
  439.    HANDLE      hInstance,
  440.    WORD        wCtlID,
  441.    LPSTR       lpszCtlName,
  442.    WORD        wMaxCtlName )
  443. {
  444.    WORD        w;
  445.    BOOL        bResult;
  446.    char        szString[MAX_TITLE];
  447.  
  448.    /* initialization */
  449.    bResult = TRUE;
  450.    *lpszCtlName = NULL;
  451.    
  452.    /* attempt to load string */
  453.    if ( LoadString(hInstance,wCtlID,szString,sizeof(szString)) ) {
  454.       for (w=0; (szString[w])&&(szString[w]!=':'); w++);
  455.       szString[w] = NULL;
  456.       StringCopy( lpszCtlName, szString, wMaxCtlName );
  457.    } else
  458.       bResult = FALSE;
  459.  
  460.    /* return result */
  461.    return( bResult );
  462.    
  463. }
  464.  
  465. /* */
  466.  
  467. /*
  468.  * GetCtlData( hData, lpszCtlName, lpszData, wMaxData ) : BOOL;
  469.  *
  470.  *    hData          handle to global data block
  471.  *    lpszCtlName    long pointer to control name
  472.  *    lpszData       long pointer to data block to define
  473.  *    wMaxData       maximum size of data block
  474.  *
  475.  * This function retrieve a data value from the global data block
  476.  * using the control name provided.  A value of TRUE is returned if the
  477.  * search was successful. 
  478.  *
  479.  * This function is typically called when the initial dialog box
  480.  * control data values are being defined.
  481.  *
  482.  * Also note that this function assumes that the data is correctly
  483.  * formatted as follows:
  484.  *
  485.  *    <FIELDNAME>:<FIELDDATA> NULL
  486.  *    <FIELDNAME>:<FIELDDATA> NULL
  487.  *    NULL
  488.  *
  489.  */
  490.  
  491. BOOL FAR PASCAL GetCtlData(
  492.    HANDLE      hData,
  493.    LPSTR       lpszCtlName,
  494.    LPSTR       lpszData,
  495.    WORD        wMaxData )
  496. {
  497.    WORD        w;
  498.    BOOL        bResult;
  499.    LPSTR       lpszDataBlock;
  500.  
  501.    char        szCrntCtlName[MAX_NAME];
  502.  
  503.    /* initialization */
  504.    bResult = FALSE;
  505.  
  506.    /* attempt to lock global data block */
  507.    lpszDataBlock = GlobalLock( hData );
  508.    if ( lpszData ) {
  509.  
  510.       /* search for desired entry */
  511.       while ( (*lpszDataBlock)&&(bResult==FALSE) ) {
  512.  
  513.          /* extract field identifier */
  514.          for ( w=0; (*lpszDataBlock)&&(*lpszDataBlock!=':'); lpszDataBlock++ )
  515.             if ( w < MAX_NAME-1 )
  516.                szCrntCtlName[w++] = *lpszDataBlock;
  517.  
  518.          szCrntCtlName[w] = NULL;
  519.          lpszDataBlock++;
  520.  
  521.          /* compare to desired field name */
  522.          if ( !lstrcmp(lpszCtlName,szCrntCtlName) ) {
  523.             bResult = TRUE;
  524.             StringCopy( lpszData, lpszDataBlock, wMaxData );
  525.          } 
  526.  
  527.          /* skip to next record (plus one more character) */
  528.          while ( *lpszDataBlock++ )
  529.             ;
  530.  
  531.       }
  532.  
  533.       /* unlock data */
  534.       GlobalUnlock( hData );
  535.  
  536.    }
  537.    
  538.    /* return value */
  539.    return( bResult );
  540.  
  541. }
  542.  
  543. /* */
  544.  
  545. /*
  546.  * GetCtlComment( hInstance, wCtlID, lpszComment, wMaxComment ) : BOOL;
  547.  *
  548.  *    hInstance      instance handle of module
  549.  *    wCtlID         child window control ID
  550.  *    lpszComment    long pointer to string variable
  551.  *    wMaxComment    maximum size of string
  552.  *
  553.  * Retrieve string comment describing a particular control based on the
  554.  * child window identifier provided.  A value of TRUE is returned if
  555.  * the search was successful.
  556.  *
  557.  */
  558.  
  559. BOOL FAR PASCAL GetCtlComment(
  560.    HANDLE      hInstance,
  561.    WORD        wCtlID,
  562.    LPSTR       lpszComment,
  563.    WORD        wMaxComment )
  564. {
  565.    WORD        w;
  566.    BOOL        bResult;
  567.    char        szComment[MAX_TITLE];
  568.  
  569.    /* initialization */
  570.    bResult = TRUE;
  571.    *lpszComment = NULL;
  572.    
  573.    /* attempt to load string */
  574.    if ( LoadString(hInstance,wCtlID,szComment,sizeof(szComment)) ) {
  575.       for (w=0; (szComment[w])&&(szComment[w]!=':'); w++);
  576.       StringCopy( lpszComment, &szComment[w+1], wMaxComment );
  577.    } else
  578.       bResult = FALSE;
  579.  
  580.    /* return result */
  581.    return( bResult );
  582.    
  583. }
  584.  
  585. /* */
  586.  
  587. /*
  588.  * SetCtlData( hDlg, hWndCtl, lpDlgCtl, lpszData ) : BOOL;
  589.  *
  590.  *    hDlg           handle to dialog box
  591.  *    hWndCtl        handle to control
  592.  *    lpDlgCtl       pointer to control template
  593.  *    lpszData       data associated with the control
  594.  *
  595.  * This function is responsible for defining the information
  596.  * associated with a particular control when the dialog box
  597.  * is initially displayed.
  598.  *
  599.  * This function does not support control classes:
  600.  *
  601.  *    Scrollbars
  602.  *    ComboBoxes
  603.  *    ListBoxes
  604.  *
  605.  * A value of TRUE is returned if the operation was successful.
  606.  *
  607.  */
  608.  
  609. BOOL FAR PASCAL SetCtlData(
  610.    HWND        hDlg,
  611.    HWND        hWndCtl,
  612.    LPDLGCTL    lpDlgCtl,
  613.    LPSTR       lpszData )
  614. {
  615.    
  616.    /* output data based on control type */
  617.    if ( !lstrcmp(lpDlgCtl->szClass,"Button") ) {
  618.    
  619.       /* process different types of buttons */
  620.       switch( LOWORD(lpDlgCtl->lStyle)&0x000F )
  621.          {
  622.       case BS_CHECKBOX :
  623.       case BS_AUTOCHECKBOX :
  624.       case BS_3STATE :
  625.       case BS_AUTO3STATE :
  626.          CheckDlgButton( hDlg, lpDlgCtl->wID, (lpszData[0]=='T')?TRUE:FALSE );
  627.          break;
  628.       case BS_RADIOBUTTON :
  629.       case BS_AUTORADIOBUTTON :
  630.          if ( lpszData[0] == 'T' )
  631.             CheckRadioButton( hDlg, lpDlgCtl->wID, lpDlgCtl->wID, lpDlgCtl->wID );
  632.          break;
  633.       case BS_PUSHBUTTON :
  634.       case BS_DEFPUSHBUTTON :
  635.       case BS_GROUPBOX :
  636.       case BS_USERBUTTON :
  637.       case BS_PUSHBOX :
  638.          SetWindowText( hWndCtl, lpszData );
  639.          break;
  640.       }
  641.    
  642.    } else
  643.       SetWindowText( hWndCtl, lpszData );
  644.  
  645.    /* return result */
  646.    return( TRUE );
  647.  
  648. }
  649.  
  650. /* */
  651.  
  652. /* STRING HANDLING UTILITY FUNCTIONS */
  653.  
  654. /*
  655.  * StringMatch( lpszString, lpszPattern ) : BOOL;
  656.  *
  657.  *    lpszString        base string
  658.  *    lpszPattern       pattern string
  659.  *
  660.  * This function returns TRUE if the pattern provided is replicated
  661.  * in the first set of characters in the base string.
  662.  *
  663.  */
  664.  
  665. BOOL FAR PASCAL StringMatch(
  666.    LPSTR       lpszString,
  667.    LPSTR       lpszPattern )
  668. {
  669.  
  670.    /* find first difference between strings */
  671.    while ( (*lpszPattern)&&(*lpszPattern==*lpszString) ) {
  672.       lpszString++;
  673.       lpszPattern++;
  674.    }
  675.  
  676.    /* return comparison */
  677.    return( (*lpszPattern) ? FALSE : TRUE );
  678.  
  679. }
  680.  
  681. /* */
  682.  
  683. /*
  684.  * StringCat( lpszDest, lpszSrce, wMaxDest ) : VOID;
  685.  *
  686.  *    lpszDest       string to append characters
  687.  *    lpszSrce       string to copy from
  688.  *    wMaxDest       maximum length of destination string
  689.  *
  690.  * This function appends the source string onto the end of the
  691.  * destination string, while checking that the maximum length of
  692.  * the destination string is not exceeded.
  693.  *
  694.  */
  695.  
  696. VOID FAR PASCAL StringCat(
  697.    LPSTR       lpszDest,
  698.    LPSTR       lpszSrce,
  699.    WORD        wMaxDest )
  700. {
  701.  
  702.    /* move to end of string */
  703.    while ( *lpszDest ) {
  704.       lpszDest++;
  705.       wMaxDest--;
  706.    }
  707.  
  708.    /* copy string & append null */
  709.    while ( (--wMaxDest)&&(*lpszDest++=*lpszSrce++) );
  710.    *lpszDest = NULL;
  711.  
  712. }
  713.  
  714. /* */
  715.  
  716. /*
  717.  * StringCopy( lpszDest, lpszSrce, wMax ) : VOID;
  718.  *
  719.  *    lpszDest       string to copy characters
  720.  *    lpszSrce       string to copy from
  721.  *    wMaxDest       maximum number of characters to copy
  722.  *
  723.  * This function copies the source string to the destination
  724.  * string while checking that less than the maximum number of
  725.  * characters are transfered.  In an overflow case, a NULL is
  726.  * automatically appended.
  727.  *
  728.  */
  729.  
  730. VOID FAR PASCAL StringCopy(
  731.    LPSTR    lpszDest,
  732.    LPSTR    lpszSrce,
  733.    WORD     wMaxDest )
  734. {
  735.  
  736.    /* copy string until null encountered */
  737.    while ( (--wMaxDest)&&(*lpszDest++=*lpszSrce++) );
  738.    *lpszDest = NULL;
  739.  
  740. }
  741.  
  742. /* */
  743.  
  744. /*
  745.  * StringJoin( lpszDest, lpszSrce, wMaxDest ) : VOID;
  746.  *
  747.  *    lpszDest       string to append characters
  748.  *    lpszSrce       string to copy from
  749.  *    wMaxDest       maximum length of destination string
  750.  *
  751.  * This function appends the source string onto the end of the
  752.  * destination string, including terminating null characters.  During
  753.  * this process, the maximum size of the destination string is
  754.  * checked to ensure that an overflow does not occur.
  755.  *
  756.  */
  757.  
  758. VOID FAR PASCAL StringJoin(
  759.    LPSTR       lpszDest,
  760.    LPSTR       lpsSrce,
  761.    WORD        wMaxDest )
  762. {
  763.  
  764.    /* search for double null characters */
  765.    while ( *lpszDest )
  766.       while ( (--wMaxDest)&&(*lpszDest++) );
  767.  
  768.    /* copy string & append null */
  769.    while ( (--wMaxDest)&&(*lpszDest++=*lpsSrce++) );
  770.    *lpszDest = NULL;
  771.  
  772. }
  773.  
  774. /* */
  775.  
  776. /* MISC UTILITY FUNCTIONS */
  777.  
  778. /*
  779.  * GetPrinterDC() : HDC;
  780.  *
  781.  *
  782.  * This function creates a printer display context for the current
  783.  * default printer and returns it to the calling routine. 
  784.  *
  785.  */
  786.  
  787. HDC FAR PASCAL GetPrinterDC()
  788. {
  789.    LPSTR    lpszDevice;
  790.    LPSTR    lpszDriver;
  791.    LPSTR    lpszOutput;
  792.    char     szPrinter[64];
  793.  
  794.    /* retrieve profile string */
  795.    GetProfileString( "windows", "device", "", szPrinter, sizeof(szPrinter) );
  796.  
  797.    /* extract device name */
  798.    lpszDevice = szPrinter;
  799.    lpszOutput = szPrinter;
  800.  
  801.    while ( *lpszOutput != ',' )
  802.       lpszOutput++;
  803.    *lpszOutput++ = NULL;
  804.  
  805.    /* extract driver name */
  806.    lpszDriver = lpszOutput;
  807.  
  808.    while ( *lpszOutput != ',' )
  809.       lpszOutput++;
  810.    *lpszOutput++ = NULL;
  811.  
  812.    /* return value */
  813.    return( CreateDC(lpszDriver,lpszDevice,lpszOutput,NULL) );
  814.  
  815. }
  816.  
  817. /* */
  818.  
  819. /*
  820.  * CenterPopup( hWnd, hWndParent ) : VOID;
  821.  *
  822.  *    hWnd           window handle
  823.  *    hWndParent     parent window handle
  824.  *
  825.  * This routine centers the popup window in the screen or display
  826.  * using the window handles provided.  The window is centered over
  827.  * the parent if the parent window is valid.  Special provision
  828.  * is made for the case when the popup would be centered outside
  829.  * the screen - in this case it is positioned at the appropriate
  830.  * border.
  831.  *
  832.  */
  833.  
  834. VOID FAR PASCAL CenterPopup(
  835.    HWND        hWnd,
  836.    HWND        hWndParent )
  837. {
  838.    int         xPopup;
  839.    int         yPopup;
  840.    int         cxPopup;
  841.    int         cyPopup;
  842.    int         cxScreen;
  843.    int         cyScreen;
  844.    int         cxParent;
  845.    int         cyParent;
  846.    RECT        rcWindow;
  847.  
  848.    /* retrieve main display dimensions */
  849.    cxScreen = GetSystemMetrics( SM_CXSCREEN );
  850.    cyScreen = GetSystemMetrics( SM_CYSCREEN );
  851.  
  852.    /* retrieve popup rectangle  */
  853.    GetWindowRect( hWnd, (LPRECT)&rcWindow );
  854.  
  855.    /* calculate popup size */
  856.    cxPopup = rcWindow.right - rcWindow.left;
  857.    cyPopup = rcWindow.bottom - rcWindow.top;
  858.  
  859.    /* calculate bounding rectangle */
  860.    if ( hWndParent ) {
  861.  
  862.       /* retrieve parent rectangle */
  863.       GetWindowRect( hWndParent, (LPRECT)&rcWindow );
  864.  
  865.       /* calculate parent extents */
  866.       cxParent = rcWindow.right - rcWindow.left;
  867.       cyParent = rcWindow.bottom - rcWindow.top;
  868.  
  869.       /* center within parent window */
  870.       xPopup = rcWindow.left + ((cxParent - cxPopup)/2);
  871.       yPopup = rcWindow.top + ((cyParent - cyPopup)/2);
  872.  
  873.       /* adjust popup x-location for screen size */
  874.       if ( xPopup+cxPopup > cxScreen )
  875.          xPopup = cxScreen - cxPopup;
  876.  
  877.       /* adjust popup y-location for screen size */
  878.       if ( yPopup+cyPopup > cyScreen )
  879.          yPopup = cyScreen - cyPopup;
  880.  
  881.    } else {
  882.  
  883.       /* center within entire screen */
  884.       xPopup = (cxScreen - cxPopup) / 2;
  885.       yPopup = (cyScreen - cyPopup) / 2;
  886.  
  887.    }
  888.  
  889.    /* move window to new location & display */
  890.    MoveWindow(
  891.       hWnd,
  892.       ( xPopup > 0 ) ? xPopup : 0,
  893.       ( yPopup > 0 ) ? yPopup : 0,
  894.       cxPopup,
  895.       cyPopup,
  896.       TRUE
  897.    );
  898.  
  899. }
  900.  
  901. /* */
  902.  
  903. /*
  904.  * FormMsgHookFn( wContext, wCode, lData ) : WORD;
  905.  *
  906.  *    wContext       message context
  907.  *    wCode          message code
  908.  *    lData          supplemental information
  909.  *
  910.  * This function intercepts the following set of function keys and
  911.  * responds with the appropriate action:
  912.  *
  913.  *    PgUp           move to previous form page
  914.  *    PgDn           move to next form page
  915.  *
  916.  */
  917.  
  918. WORD FAR PASCAL FormMsgHookFn(
  919.    WORD        wContext,
  920.    WORD        wCode,
  921.    LONG        lData )
  922. {
  923.    WORD        wResult;
  924.  
  925.    /* initialization */
  926.    wResult = TRUE;
  927.  
  928.    /* check if message is of interest */
  929.    if ( (wContext==MSGF_DIALOGBOX)&&(wCode==HC_ACTION) ) {
  930.  
  931.       if ( ((MSG FAR *)lData)->message==WM_KEYDOWN ) {
  932.       
  933.          /* process virtual key code */
  934.          switch( ((MSG FAR *)lData)->wParam )
  935.             {
  936.          case VK_PRIOR :
  937.             SendMessage( GetDlgItem(PARENT(((MSG FAR *)lData)->hwnd),ID0_PAGE), WM_KEYDOWN, VK_PRIOR, 0L );
  938.             break;
  939.          case VK_NEXT :
  940.             SendMessage( GetDlgItem(PARENT(((MSG FAR *)lData)->hwnd),ID0_PAGE), WM_KEYDOWN, VK_NEXT, 0L );
  941.             break;
  942.          default :
  943.             wResult = (WORD)DefHookProc( wContext, wCode, lData, (FARPROC FAR *)&FormInfo.fnOldMsgHook );
  944.             break;
  945.          }
  946.    
  947.       } else 
  948.          if ( ((MSG FAR *)lData)->message!=WM_KEYUP ) 
  949.             wResult = (WORD)DefHookProc( wContext, wCode, lData, (FARPROC FAR *)&FormInfo.fnOldMsgHook );
  950.  
  951.    } else
  952.       wResult = (WORD)DefHookProc( wContext, wCode, lData, (FARPROC FAR *)&FormInfo.fnOldMsgHook );
  953.    
  954.    /* pass message to default hook function */
  955.    return( wResult );
  956.  
  957. }
  958.  
  959. /* */
  960.  
  961. /*
  962.  * Warning( hWndParent, lpszMessage, lpszFile, wLine ) : VOID;
  963.  *
  964.  *    hWndParent     parent window handle
  965.  *    lpszMessage    pointer to error message
  966.  *    lpszFile       pointer to current file
  967.  *    wLine          line number of error
  968.  *
  969.  * This function displays a message box that describes the error
  970.  * encountered.  Included with the error is an identifier that can
  971.  * be used to track down the file and line-number in question.
  972.  *
  973.  */
  974.  
  975. VOID FAR PASCAL Warning(
  976.    HWND        hWndParent,
  977.    LPSTR       lpszMessage,
  978.    LPSTR       lpszFile,
  979.    WORD        wLine )
  980. {
  981.    char        szWarning[256];
  982.  
  983.    /* create error message & display in a message box */
  984.    wsprintf( szWarning, "%s  [%s:%u]", lpszFile, lpszMessage, wLine );
  985.    MessageBox( hWndParent, szWarning, FormInfo.szTitle, MB_OK|MB_ICONHAND );
  986.  
  987. }
  988.  
  989.