home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / EXPENSE / EXPENSE.C_ / EXPENSE.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  26.1 KB  |  954 lines

  1. /************************************************************
  2.  
  3.    PROGRAM: EXPENSE.C
  4.  
  5.    PURPOSE:
  6.    
  7.       An expense reporting program demonstrating the use
  8.       different dictionaries for different edit control fields.
  9.  
  10.    COMMENTS:
  11.  
  12.       EXPENSE has several edit fields, typical of a generic
  13.       expense report (name, employee #, dept. items, etc.).  The
  14.       application registers itself as a pen aware application
  15.       so that the edit controls will be replaced by hedit
  16.       controls.
  17.  
  18.       This application will run under Win 3.0.  When running
  19.       under Win 3.0, the edit control functionality will be
  20.       present.  The boxed edit field and the picture field
  21.       will not be present.
  22.  
  23.       The Delay Recognition menu, when checked, will cause
  24.       ink to be captured in the inking field.  When the
  25.       menu item is unchecked, the first tap in the field
  26.       will cause recognition.  After that, the field will
  27.       behave like a normal HEDIT control.
  28.  
  29.  
  30. ************************************************************/
  31.  
  32. #include <windows.h>
  33. #include <penwin.h>
  34. #include "expres.h"
  35. #include "expense.h"
  36.  
  37. /******** Module Variables *********/
  38.  
  39. char *   szAppName         = "Expense";
  40. char *   szIniFile         = "penwin.ini";
  41. char *   szUserDictLib     = "userdict.dll";
  42. char *   szUserDictProc    = "DictionaryProc";
  43. char *   szCustomDictLib   = "custdict.dll";
  44. char *   szCustomDictProc  = "DictionaryProc";
  45. char *   szExpenseClass    = "ExpenseClass";
  46. char *   szExpenseWnd      = "Sample Expense Report";
  47. BOOL     fUpdateTotalValue = FALSE;
  48. HANDLE   hAccel;           /* Menu Accelerator Table */ 
  49. HANDLE   hwndMain;         /* Parent window to all fields */ 
  50. HANDLE   hPenWin           = NULL;
  51. HANDLE   hUserDictLib;
  52. HANDLE   hCustomDictLib;
  53. int      iLastInUserDict   = DictParam_None; 
  54.  
  55. LPDF lpdfUserDictProc;
  56. LPDF lpdfCustomDictProc;
  57.  
  58. BOOL fUserInit=FALSE;
  59. BOOL fCustomInit=FALSE;
  60.  
  61. VOID (FAR PASCAL *RegPenApp)(WORD, BOOL) = NULL;
  62.  
  63. WORDLIST rgwordlist[] =
  64.    {
  65.    {"namedict", "names.dic", 0 },
  66.    {"deptnamedict", "deptname.dic", 0 }
  67.    };
  68.  
  69. TEXT rgtext[cTexts] =   
  70.    {
  71.    {"Name:",               7,    8 },
  72.    {"Employee",            135,  4 },
  73.    {"Number:",             135,  12 },
  74.    {"Dept.",               7,    28 },
  75.    {"Name:",               7,    36 },
  76.    {"Dept.",               135,  28 },
  77.    {"Number:",             135,  36 },
  78.    {"DATE",                29,   62 },
  79.    {"EXPENSE ITEM",        95,   62 },
  80.    {"VALUE ($)",           185,  62 },
  81.    {"Signature:",          9,    165 },
  82.    {"Date",                156,  157 },
  83.    {"Submitted:",          156,  165 },
  84.    };
  85.  
  86. char lpDateDelimiter[] = "/:.-";
  87. char lpMoneyDelimter[] = "$.,";
  88.  
  89. EDITFIELD rgeditfield[cEditFields] =   
  90.    {
  91.    /* Name */
  92.    { 37,  6, 75, 13, 
  93.      ES_LEFT | ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP,
  94.      ALC_DEFAULT, NULL, NULL, DICT_USER, IWORDLIST_NAME,   
  95.      FIELDEDIT, NULL},
  96.  
  97.    /* Employee # */
  98.    { 177, 7, BXD_CELLWIDTH*EmployNumDigits+1, BXD_CELLHEIGHT, 
  99.      0, 
  100.      ALC_NUMERIC | ALC_GESTURE, NULL, NULL, DICT_NULL, IWORDLIST_NONE, 
  101.      FIELDBEDIT, NULL},
  102.  
  103.    /* Dept. Name */
  104.    { 37,  30, 75, 13, 
  105.      ES_LEFT | ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP,
  106.      ALC_DEFAULT, NULL, NULL, DICT_USER, IWORDLIST_DEPTNAME, 
  107.      FIELDEDIT, NULL},
  108.  
  109.    /* Dept. # */
  110.    { 177,  31, BXD_CELLWIDTH*DeptNumDigits+1, BXD_CELLHEIGHT, 
  111.      0,
  112.      ALC_NUMERIC | ALC_GESTURE, NULL, NULL, DICT_NULL, IWORDLIST_NONE, 
  113.      FIELDBEDIT, NULL},
  114.  
  115.    /* Date #1 */
  116.    { 7, 74, 64, 12,
  117.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  118.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpDateDelimiter, NULL, DICT_NULL, IWORDLIST_NONE, 
  119.      FIELDEDIT, NULL},
  120.  
  121.    /* Expense Item #1 */
  122.    { 71, 74, 95, 12, 
  123.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  124.      ALC_DEFAULT, NULL, RCO_SUGGEST, DICT_CUSTOM, IWORDLIST_NONE, 
  125.      FIELDEDIT, NULL},
  126.  
  127.    /* Value #1 */
  128.    { 166, 74, 68, 12, 
  129.      ES_MULTILINE | ES_RIGHT | WS_BORDER | WS_TABSTOP,
  130.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpMoneyDelimter, NULL, DICT_NULL, IWORDLIST_NONE, 
  131.      FIELDEDIT, NULL},
  132.                   
  133.    /* Date #2 */
  134.    { 7, 86, 64, 12,
  135.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  136.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpDateDelimiter, NULL, DICT_NULL, IWORDLIST_NONE, 
  137.      FIELDEDIT, NULL},
  138.  
  139.    /* Expense Item #2 */
  140.    { 71, 86, 95, 12,
  141.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  142.      ALC_DEFAULT, NULL, RCO_SUGGEST,  DICT_CUSTOM, IWORDLIST_NONE, 
  143.      FIELDEDIT, NULL},
  144.  
  145.    /* Value #2 */
  146.    { 166, 86, 68, 12,
  147.      ES_MULTILINE | ES_RIGHT | WS_BORDER | WS_TABSTOP,
  148.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpMoneyDelimter, NULL, DICT_NULL, IWORDLIST_NONE, 
  149.      FIELDEDIT, NULL},
  150.  
  151.    /* Date #3 */
  152.    { 7, 98, 64, 12,
  153.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  154.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpDateDelimiter, NULL, DICT_NULL, IWORDLIST_NONE, 
  155.      FIELDEDIT, NULL},
  156.  
  157.    /* Expense Item #3 */
  158.    { 71, 98, 95, 12,
  159.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  160.      ALC_DEFAULT, NULL, RCO_SUGGEST, DICT_CUSTOM, IWORDLIST_NONE, 
  161.      FIELDEDIT, NULL},
  162.  
  163.    /* Value #3 */
  164.    { 166, 98, 68, 12,
  165.      ES_MULTILINE | ES_RIGHT | WS_BORDER | WS_TABSTOP,
  166.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpMoneyDelimter, NULL, DICT_NULL, IWORDLIST_NONE,  
  167.      FIELDEDIT, NULL},
  168.  
  169.    /* Date #4 */
  170.    { 7, 110, 64, 12,
  171.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  172.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpDateDelimiter, NULL, DICT_NULL, IWORDLIST_NONE, 
  173.      FIELDEDIT, NULL},
  174.  
  175.    /* Expense Item #4 */
  176.    { 71, 110, 95, 12, 
  177.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  178.      ALC_DEFAULT, NULL, RCO_SUGGEST, DICT_CUSTOM, IWORDLIST_NONE, 
  179.      FIELDEDIT, NULL},
  180.  
  181.    /* Value #4 */
  182.    { 166, 110, 68, 12, 
  183.      ES_MULTILINE | ES_RIGHT | WS_BORDER | WS_TABSTOP,
  184.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpMoneyDelimter, NULL, DICT_NULL, IWORDLIST_NONE, 
  185.      FIELDEDIT, NULL},
  186.                   
  187.    /* Date #5 */
  188.    { 7, 122, 64, 12,
  189.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  190.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpDateDelimiter, NULL, DICT_NULL, IWORDLIST_NONE, 
  191.      FIELDEDIT, NULL},
  192.  
  193.    /* Expense Item #5 */
  194.    { 71, 122, 95, 12,
  195.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  196.      ALC_DEFAULT, NULL, RCO_SUGGEST, DICT_CUSTOM, IWORDLIST_NONE, 
  197.      FIELDEDIT, NULL},
  198.  
  199.    /* Value #5 */
  200.    { 166, 122, 68, 12,
  201.      ES_MULTILINE | ES_RIGHT | WS_BORDER | WS_TABSTOP,
  202.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpMoneyDelimter, NULL, DICT_NULL, IWORDLIST_NONE, 
  203.      FIELDEDIT, NULL},
  204.  
  205.    /* Date #6 */
  206.    { 7, 134, 64, 12,
  207.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  208.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpDateDelimiter, NULL, DICT_NULL, IWORDLIST_NONE, 
  209.      FIELDEDIT, NULL},
  210.  
  211.    /* Expense Item #6 */
  212.    { 71, 134, 95, 12,
  213.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  214.      ALC_DEFAULT, NULL, RCO_SUGGEST, DICT_CUSTOM, IWORDLIST_NONE, 
  215.      FIELDEDIT, NULL},
  216.  
  217.    /* Value #6 */
  218.    { 166, 134, 68, 12,
  219.      ES_MULTILINE | ES_RIGHT | WS_BORDER | WS_TABSTOP,
  220.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpMoneyDelimter, DICT_NULL, IWORDLIST_NONE, NULL, 
  221.      FIELDEDIT, NULL},
  222.  
  223.    /* Signature */
  224.    { 47, 153, 100, 20,
  225.      ES_LEFT | WS_BORDER | WS_TABSTOP, 
  226.      ALC_DEFAULT, NULL, NULL, DICT_NULL, IWORDLIST_NONE, 
  227.      FIELDPIC, NULL},
  228.  
  229.    /* Date Submitted */
  230.    { 194, 161, 40, 12,
  231.      ES_LEFT | WS_BORDER | WS_TABSTOP,
  232.      ALC_USEBITMAP | ALC_NUMERIC | ALC_GESTURE, lpDateDelimiter, NULL, DICT_NULL, IWORDLIST_NONE, 
  233.      FIELDEDIT, NULL},
  234.    };
  235.  
  236. /*********************************************************************/
  237.  
  238.  
  239.  
  240. /*----------------------------------------------------------
  241. Purpose: Main Windows function
  242. Returns: Exit code
  243. */
  244. int PASCAL WinMain(
  245.    HANDLE hInstance,       /* Instance handle  */ 
  246.    HANDLE hPrevInstance,   /* Previous instance handle */ 
  247.    LPSTR lpszCommandLine,  /* Command line string */ 
  248.    int cmdShow)            /* ShowWindow flag */ 
  249.    {
  250.    MSG   msg;
  251.  
  252.    Unused(lpszCommandLine);
  253.  
  254.    if (!hPrevInstance)
  255.       {
  256.       if (!FInitApp(hInstance))
  257.      {
  258.      return 1;
  259.      }
  260.       }
  261.  
  262.    /* If running on a Pen Windows system, register this app so all
  263.    ** EDIT controls in dialogs are replaced by HEDIT controls.
  264.    ** (Notice the CONTROL statement in the RC file is "EDIT",
  265.    ** RegisterPenApp will automatically change that control to
  266.    ** an HEDIT.
  267.    */ 
  268.  
  269.    if ((hPenWin = GetSystemMetrics(SM_PENWINDOWS)) != NULL)
  270.       /* We do this fancy GetProcAddress simply because we don't
  271.       ** know if we're running Pen Windows.
  272.       */ 
  273.       if ( ((FARPROC)RegPenApp = GetProcAddress(hPenWin, "RegisterPenApp"))!= NULL)
  274.      (*RegPenApp)(RPA_DEFAULT, TRUE);
  275.  
  276.    if (FInitInstance(hInstance, cmdShow))
  277.       {
  278.       while (GetMessage((LPMSG)&msg, NULL, 0, 0) )
  279.      {
  280.      /* Check for menu accelerator message
  281.      */ 
  282.      if (!TranslateAccelerator(hwndMain, hAccel, &msg))
  283.         {
  284.         TranslateMessage((LPMSG)&msg);
  285.         DispatchMessage((LPMSG)&msg);
  286.         }
  287.      }
  288.       }
  289.    else
  290.       {
  291.       /* Close the dictionary DLLs
  292.       */
  293.       CloseUserDictionary();
  294.       CloseCustomDictionary();
  295.       msg.wParam = 0;
  296.       }
  297.    return msg.wParam;
  298.    }
  299.  
  300.  
  301.  
  302. /*----------------------------------------------------------
  303. Purpose: Initialize application data and register window classes
  304. Returns: TRUE if all successful
  305. */
  306. BOOL FInitApp(HANDLE hInstance)     /* Instance handle */ 
  307.    {
  308.    WNDCLASS wc;
  309.    HCURSOR  hcursor;
  310.    
  311.    hcursor = LoadCursor(NULL, IDC_ARROW);
  312.  
  313.    /* Register Main window class
  314.    */
  315.    wc.style = 0;
  316.    wc.hCursor = hcursor;
  317.    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(iconExpense));
  318.    wc.lpszMenuName = MAKEINTRESOURCE(menuMain);
  319.    wc.lpszClassName = (LPSTR)szExpenseClass;
  320.    wc.hbrBackground = (HBRUSH)COLOR_WINDOW+1;
  321.    wc.hInstance = hInstance;
  322.    wc.lpfnWndProc = ExpenseWndProc;
  323.    wc.cbClsExtra = 0;
  324.    wc.cbWndExtra = 0;
  325.  
  326.    return RegisterClass((LPWNDCLASS) &wc);
  327.    }
  328.  
  329.  
  330. /*----------------------------------------------------------
  331. Purpose: Initialize data structures; create windows; load dictionary
  332. Returns: TRUE if all successful
  333. */
  334. BOOL FInitInstance(
  335.    HANDLE hInstance,       /* Instance handle */ 
  336.    int cmdShow)            /* ShowWindow flag */ 
  337.    {
  338.    char  szWordListPath[MAXWORDLISTPATH];
  339.    int   i;
  340.    LONG  lT          = GetDialogBaseUnits();
  341.    int   cxDlgBase   = LOWORD(lT);
  342.    int   cyDlgBase   = HIWORD(lT);
  343.    char  szErrMessage[cERRSIZE];
  344.    UINT uSavErrMode;
  345.  
  346.    /* Load the libarary containing the user dictionary procedure
  347.    */
  348.  
  349.     /* Set error mode so that windows does not show the file not
  350.         found dialog if userdict.dll is not on the path
  351.     */
  352.     uSavErrMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  353.  
  354.     /* Try to load the userdict.dll */
  355.    if ((hUserDictLib = LoadLibrary(szUserDictLib)) >= 32)
  356.       {
  357.         /*Try getting the entry point and try using it to initialize
  358.           the dictionary dll
  359.         */
  360.       if ((((FARPROC)lpdfUserDictProc = GetProcAddress(hUserDictLib, szUserDictProc)) == NULL)
  361.      || !(fUserInit = (*lpdfUserDictProc)(DIRQ_INIT, NULL, NULL, NULL, NULL, NULL)))
  362.             {
  363.             /* Cleanup but go on if either of the above steps failed
  364.             */
  365.             FreeLibrary(hUserDictLib);
  366.             lpdfUserDictProc = NULL;
  367.             }
  368.         }
  369.     /* Restore the error mode to the original
  370.     */
  371.     SetErrorMode(uSavErrMode);
  372.  
  373.    /* Load the libarary containing the custom dictionary procedure
  374.    */
  375.    if ((hCustomDictLib = LoadLibrary(szCustomDictLib)) >= 32)
  376.       {
  377.       if ((((FARPROC)lpdfCustomDictProc = GetProcAddress(hCustomDictLib, szCustomDictProc)) == NULL)
  378.      || !(fCustomInit = (*lpdfCustomDictProc)(DIRQ_INIT, NULL, NULL, 0, NULL, NULL)))
  379.      return FALSE;
  380.       }
  381.    else
  382.       {
  383.       wsprintf (szErrMessage, "Error loading %s", (LPSTR)szCustomDictLib);
  384.       MessageBox (0, szErrMessage, szAppName, MB_OK | MB_ICONEXCLAMATION);
  385.       return FALSE;
  386.       }
  387.  
  388.    /* Open all the user dictionary word lists if userdict.dll is
  389.         loaded and initialized
  390.    */
  391.     if(fUserInit)
  392.         {
  393.       for (i = 0; i < SIZE_WORDLIST; i++)
  394.      {
  395.      if (GetPrivateProfileString((LPSTR)szAppName, (LPSTR)rgwordlist[i].szProfileString, (LPSTR)rgwordlist[i].szDefault, 
  396.            szWordListPath, sizeof(szWordListPath), (LPSTR)szIniFile))
  397.         {
  398.         if (!((*lpdfUserDictProc)(DIRQ_OPEN, szWordListPath, 
  399.           &rgwordlist[i].iList, NULL, NULL, NULL)))
  400.            {
  401.            wsprintf (szErrMessage, "Cannot open the word list file %s. Check your %s.", (LPSTR)szWordListPath, (LPSTR)szIniFile);
  402.            MessageBox (0, szErrMessage, szAppName, MB_OK | MB_ICONEXCLAMATION);
  403.            return FALSE;
  404.            }
  405.         }
  406.      }
  407.         }   
  408.  
  409.    /* Convert dialog units of field and text coordinates
  410.    ** to window coordinates.
  411.    */
  412.    for (i = 0; i < cTexts; i++)                                 
  413.       {
  414.       rgtext[i].x = (rgtext[i].x * cxDlgBase)/4;
  415.       rgtext[i].y = (rgtext[i].y * cyDlgBase)/8;
  416.       }
  417.  
  418.    for (i = 0; i < cEditFields; i++)
  419.       {
  420.       rgeditfield[i].x = (rgeditfield[i].x * cxDlgBase)/4;
  421.       rgeditfield[i].y = (rgeditfield[i].y * cyDlgBase)/8;
  422.       rgeditfield[i].cx = (rgeditfield[i].cx * cxDlgBase)/4;
  423.       rgeditfield[i].cy = (rgeditfield[i].cy * cyDlgBase)/8;
  424.       }
  425.     
  426.  
  427.    /* Create Main window
  428.    */
  429.    if (hwndMain = CreateWindow((LPSTR)szExpenseClass, 
  430.       (LPSTR)szExpenseWnd,   
  431.       WS_CLIPCHILDREN | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,
  432.       CW_USEDEFAULT, 0, (cReportWidth*cxDlgBase)/4, (cReportHeight*cyDlgBase)/8,
  433.       (HWND)NULL,
  434.       (HWND)NULL,
  435.       (HANDLE)hInstance,
  436.       (LPSTR)NULL
  437.       ))
  438.       {
  439.       hAccel = LoadAccelerators (hInstance, IDEXPENSE);
  440.  
  441.       ShowWindow(hwndMain, cmdShow);
  442.       UpdateWindow(hwndMain);
  443.       }
  444.  
  445.    return hwndMain != NULL;
  446.    }
  447.  
  448.  
  449. /*----------------------------------------------------------
  450. Purpose: Window procedure for main window
  451. Returns: Varies
  452. */
  453. LRESULT __export CALLBACK ExpenseWndProc(
  454.    HWND hwnd,        /* Window handle */ 
  455.    UINT message,     /* Message */ 
  456.    WPARAM wParam,    /* Varies */ 
  457.    LPARAM lParam)    /* Varies */ 
  458.    {
  459.    int   i;
  460.    LONG  lRet  = 0L;
  461.  
  462.    static HWND hwndFocusField = NULL;
  463.    static FARPROC lpfnAboutDlgProc;
  464.    static HANDLE  hInstance;
  465.  
  466.    switch (message)
  467.       {
  468.    case WM_CREATE:
  469.       /* Create fields
  470.       */
  471.       if (!FCreateReport(hwnd))
  472.      {
  473.      lRet = 1L;  /* Failed */
  474.      break;   
  475.      }
  476.  
  477.       hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
  478.       lpfnAboutDlgProc = MakeProcInstance (AboutDlgProc, hInstance);
  479.  
  480.       /* Initialize focus to first edit control
  481.       */
  482.       hwndFocusField = rgeditfield[0].hwnd;
  483.       SetFocus(hwndFocusField);
  484.       break;
  485.  
  486.    case WM_COMMAND:
  487.       {
  488.       /* Edit control commands
  489.       */
  490.       if (HIWORD(lParam) == EN_SETFOCUS)
  491.      {
  492.      /* Field focus is being set */
  493.      hwndFocusField = LOWORD(lParam);
  494.      break;
  495.      }
  496.       
  497.       /* Menu commands
  498.       */
  499.       switch (wParam)
  500.      {
  501.      case miAbout:
  502.         DialogBox (hInstance, "AboutBox", hwnd, lpfnAboutDlgProc);
  503.         break;
  504.  
  505.      case miExit:
  506.         DestroyWindow(hwnd);
  507.         break;
  508.  
  509.      case miClearSig:
  510.         /* Clear the Signature Field
  511.         */
  512.         SendMessage(rgeditfield[SIG_FIELD].hwnd, WM_HEDITCTL, HE_SETINKMODE, (LONG)0L);
  513.         break;
  514.  
  515.      case miClearAll:
  516.         /* Clear all edit fields
  517.         */
  518.         for (i = 0; i < cEditFields; i++)
  519.            {
  520.            if (rgeditfield[i].hwnd != NULL)
  521.           if (rgeditfield[i].wFieldType==FIELDPIC)
  522.              SendMessage(rgeditfield[i].hwnd, WM_HEDITCTL, HE_SETINKMODE, (LONG)0L);
  523.           else
  524.              SendMessage(rgeditfield[i].hwnd, WM_SETTEXT, 0, (LONG)(LPSTR)"");
  525.            }
  526.         SetFocus(rgeditfield[0].hwnd);
  527.         break;
  528.  
  529.      case miNextField:
  530.         /* Focus on the next field
  531.         */ 
  532.         ProcessFieldChange(hwndFocusField, (WORD) chNextField);
  533.         break;
  534.  
  535.      case miPrecField:
  536.         /* Set Focus on the preceeding field
  537.         */ 
  538.         ProcessFieldChange(hwndFocusField, (WORD) chPrecField);
  539.         break;
  540.  
  541.      default:
  542.         break;
  543.      }
  544.       break;
  545.       }
  546.  
  547.    case WM_PAINT:
  548.       {
  549.       PAINTSTRUCT ps;
  550.       HDC         hdc;
  551.  
  552.       hdc = BeginPaint(hwnd, &ps);
  553.       SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  554.       SetBkMode(hdc, TRANSPARENT);
  555.  
  556.       for (i = 0; i < cTexts; i++)
  557.      {
  558.      PTEXT ptext = &rgtext[i];
  559.  
  560.      TextOut(hdc, ptext->x, ptext->y, ptext->szDataStr,
  561.         lstrlen(ptext->szDataStr));
  562.      }
  563.  
  564.       EndPaint(hwnd, &ps);
  565.       break;
  566.       }
  567.  
  568.    case WM_SETFOCUS:
  569.       SetFocus(hwndFocusField);
  570.       break;
  571.  
  572.    case WM_DESTROY:
  573.       {
  574.       if (hPenWin)
  575.      {
  576.      /* Unregister this app
  577.      */ 
  578.      if (RegPenApp != NULL)
  579.         (*RegPenApp)(RPA_DEFAULT, FALSE);
  580.  
  581.      CloseUserDictionary();
  582.      CloseCustomDictionary();
  583.      }
  584.  
  585.       PostQuitMessage(0);
  586.       break;
  587.       }
  588.  
  589.    default:
  590.       lRet = DefWindowProc(hwnd, message, wParam, lParam);
  591.       break;
  592.       }
  593.  
  594.    return lRet;
  595.    }
  596.  
  597.  
  598. /*----------------------------------------------------------
  599. Purpose: Create the fields
  600. Returns: TRUE if successful
  601. */
  602. BOOL FCreateReport(HWND hwndParent)    /* Window handle to main window */
  603.    {
  604.    int   i;
  605.    RC    rcin;
  606.    LONG  lT    = GetDialogBaseUnits();
  607.    int   cx    = LOWORD(lT)/2;
  608.    int   cy    = HIWORD(lT)/2;
  609.    RECTOFS  rectofs;
  610.    
  611.    for (i = 0; i < cEditFields; i++)
  612.       {
  613.       PEDITFIELD peditfield = &rgeditfield[i];
  614.       DWORD dwStyle = WS_CHILD | WS_VISIBLE | (hPenWin ? 0L : WS_BORDER) | peditfield->dwStyle;
  615.  
  616.       switch (peditfield->wFieldType)
  617.      {
  618.       case FIELDPIC:
  619.       case FIELDEDIT:
  620.      /* Create (H)edit window.
  621.      **
  622.      ** If running on a Pen Windows system, this app will have
  623.      ** been registered, so all EDIT controls will be changed to
  624.      ** HEDIT controls.
  625.      */
  626.      peditfield->hwnd = CreateWindow(
  627.            (LPSTR)"edit",
  628.            (LPSTR)NULL,
  629.            dwStyle,
  630.            peditfield->x,
  631.            peditfield->y,
  632.            peditfield->cx,
  633.            peditfield->cy,
  634.            hwndParent, 
  635.            (HMENU)NULL,
  636.            GetWindowWord(hwndParent, GWW_HINSTANCE),
  637.            (LPSTR)NULL);
  638.      
  639.      /* Place control in delayed recognition mode
  640.      */ 
  641.      if (peditfield->wFieldType == FIELDPIC)
  642.         {
  643.         SendMessage(peditfield->hwnd, WM_HEDITCTL, HE_SETINKMODE, (LONG)0L);
  644.         }
  645.      break;
  646.  
  647.       case FIELDBEDIT:   /* Comb field */
  648.      /* Create Bedit window.
  649.      **
  650.      ** Unlike hedits, we cannot simply create an edit control
  651.      ** and expect Pen Windows to change to a bedit.  So we must
  652.      ** explicitly create a bedit or an edit control depending
  653.      ** on whether Pen Windows is installed.
  654.      */
  655.  
  656.      peditfield->hwnd = CreateWindow(
  657.            (LPSTR)(hPenWin ? "bedit" : "edit"),
  658.            (LPSTR)NULL,
  659.            dwStyle,
  660.            peditfield->x,
  661.            peditfield->y,
  662.            peditfield->cx,
  663.            peditfield->cy,
  664.            hwndParent, 
  665.            (HMENU)NULL,
  666.            GetWindowWord(hwndParent, GWW_HINSTANCE),
  667.            (LPSTR)NULL);
  668.      break;
  669.       }
  670.      
  671.       if (!peditfield->hwnd)
  672.      {
  673.      continue;
  674.      }
  675.  
  676.       /* Set RC preferences for this edit control
  677.       */
  678.       if (hPenWin)
  679.      {
  680.      if (SendMessage(peditfield->hwnd, WM_HEDITCTL, HE_GETRC, (LONG)((LPRC)&rcin)))
  681.         {
  682.         rcin.alc = peditfield->alc;
  683.         rcin.lRcOptions = rcin.lRcOptions | peditfield->lRcOptions;
  684.         if (rcin.alc&ALC_USEBITMAP)
  685.            SetAlcBits(rcin.rgbfAlc, peditfield->lpCh);
  686.  
  687.         switch (peditfield->iDictType)
  688.            {
  689.         case DICT_USER:
  690.            /* To determine when a word list needs to be set in
  691.            ** the User dictionary, the ExpenseDictionaryProc
  692.            ** (subclassed DictionaryProc) is called.  The
  693.            ** dwDictParam is used to signal which edit field
  694.            ** is being used.
  695.            */
  696.                     if(fUserInit)
  697.                         {
  698.                (FARPROC)rcin.rglpdf[0] = MakeProcInstance(ExpenseDictionaryProc, GetWindowWord(peditfield->hwnd, GWW_HINSTANCE));
  699.             rcin.rglpdf[1] = NULL;
  700.                rcin.dwDictParam = i;
  701.                         }
  702.                     else
  703.                         {
  704.                         rcin.rglpdf[0] = NULL;
  705.                rcin.dwDictParam = 0L;
  706.                         }
  707.            break;
  708.  
  709.         case DICT_CUSTOM:
  710.            rcin.rglpdf[0] = lpdfCustomDictProc;
  711.            rcin.rglpdf[1] = NULL;
  712.            break;
  713.  
  714.         default:
  715.            rcin.rglpdf[0] = NULL;
  716.            break;
  717.            }
  718.         SendMessage(peditfield->hwnd, WM_HEDITCTL, HE_SETRC, (LONG)((LPRC)&rcin));
  719.         }
  720.  
  721.      /* Change default inflation rectangle offset so it is 
  722.      ** half the base dialog unit for each respective axis.
  723.      */
  724.      rectofs.dLeft = -cx;
  725.      rectofs.dTop = -cy;
  726.      rectofs.dRight = cx;
  727.      rectofs.dBottom = cy;
  728.      SendMessage(peditfield->hwnd, WM_HEDITCTL, HE_SETINFLATE, (LONG)((LPRECTOFS)&rectofs));
  729.  
  730.      /* If no border, put underline in
  731.      */ 
  732.      if (((peditfield->dwStyle & WS_BORDER) == 0) && (peditfield->wFieldType == FIELDEDIT))
  733.         SendMessage(peditfield->hwnd, WM_HEDITCTL, HE_SETUNDERLINE, (LONG)(1));
  734.      }
  735.  
  736.       }
  737.  
  738.    return TRUE;
  739.    }
  740.  
  741. /*----------------------------------------------------------
  742. Purpose: Set the focus on next or previous field
  743. Returns: TRUE if successful
  744. Comment: Direction is based on the value of wParam. wParam can
  745.      be set to chNextField or chPrecField.  The hwndFocusField
  746.      parameter is assigned the value of the newly focused field.
  747. */
  748. BOOL ProcessFieldChange(
  749.    HWND hwndFocusField,    /* Newly focused field */
  750.    WORD wParam)            /* chNextField or chPrecField */
  751.    {
  752.    int i, inc, iCount;
  753.    WORD wRet = FALSE;
  754.    LONG lInkData;
  755.    
  756.    if ((wParam != chNextField) && (wParam != chPrecField))
  757.       return FALSE;
  758.  
  759.    inc = wParam ==chPrecField? cEditFields-1 : 1;
  760.    i = (IFromHwnd(hwndFocusField)+inc) %(cEditFields);
  761.  
  762.    /* Move to next or preceeding field.  If field is in cold
  763.    ** recognition mode, we do not set focus to it, but skip
  764.    ** to the next available field.
  765.    ** 
  766.    ** To determine if an hedit is in cold recognition mode, send
  767.    ** a GETINKHANDLE message to the control.  If the loword of the
  768.    ** return code is NULL, then the control is not in cold recognition
  769.    ** mode, and the focus can be set. If it is in cold mode, skip
  770.    ** over it and check the next field.  iCount is used to break
  771.    ** the loop if all fields are in cold mode.
  772.    */
  773.    iCount=0;
  774.    while (iCount<cEditFields && !wRet)
  775.       {
  776.       if (!LOWORD(SendMessage(rgeditfield[i].hwnd, WM_HEDITCTL, HE_GETINKHANDLE, (LONG)(LPSTR)&lInkData)))
  777.      {
  778.      hwndFocusField = rgeditfield[i].hwnd;
  779.      SetFocus(hwndFocusField);
  780.      wRet = TRUE;
  781.      }
  782.       else
  783.      i = (i+inc) %(cEditFields);      /* Calculate the next field */ 
  784.       iCount++;
  785.       }
  786.  
  787.    return wRet;
  788.    }
  789.  
  790. /*----------------------------------------------------------
  791. Purpose: Get the index into the rgfield which corresponds to
  792.      the entry containing parameter hwnd.
  793. Returns: Index into rgfield based on hwnd, 0 if a match is not
  794.      found
  795. */
  796. int IFromHwnd(HWND hwnd)   /* Window handle of control */
  797.    {
  798.    register int i;
  799.     LPEDITFIELD lpeditfield;
  800.  
  801.    for (lpeditfield = rgeditfield, i = 0; i < cEditFields; i++, lpeditfield++)
  802.       if (lpeditfield->hwnd == hwnd)
  803.      return i;
  804.  
  805.    return 0;    /* default on err */ 
  806.    }
  807.  
  808.  
  809. /*----------------------------------------------------------
  810. Purpose: Dialog window procedure
  811. Returns: Varies
  812. */
  813. BOOL __export CALLBACK AboutDlgProc(
  814.    HWND hDlg,        /* Dialog handle */
  815.    UINT message,     /* Message */
  816.    WPARAM wParam,    /* Varies */
  817.    LPARAM lParam)    /* Varies */
  818.    {
  819.    switch (message)
  820.       {
  821.    case WM_INITDIALOG:
  822.       return TRUE;
  823.  
  824.    case WM_COMMAND:
  825.       switch (wParam)
  826.      {
  827.      case IDOK:
  828.      case IDCANCEL:
  829.         EndDialog (hDlg, 0);
  830.         return TRUE;
  831.      }
  832.       break;
  833.       }
  834.    return FALSE;
  835.    }
  836.  
  837.  
  838. /*----------------------------------------------------------
  839. Purpose: Subclassed DictionaryProc for the User Dictionary.
  840. Returns: Varies
  841. Comment: Determines if a new wordlist needs to be set based
  842.      on the global variable, iLastInUserDict which is
  843.      initialized to DictParam_None.
  844.  
  845.      Returns whatever is returned from calling the user
  846.      dictionary's DictionaryProc.
  847. */
  848. int __export CALLBACK ExpenseDictionaryProc(
  849.    int irq,          /* Subfunction number */
  850.    LPVOID lpIn,      /* Input parameter */
  851.    LPVOID lpOut,     /* Output parameter */
  852.    int cbMax,        /* Size of lpOut */
  853.    DWORD lContext,   /* Reserved */
  854.    DWORD lD)         /* Dictionary-specific data */
  855.    {
  856.  
  857.     /* This call is never made if userdict.dll is not loaded and initialized
  858.         but we do this anyway
  859.     */
  860.     if(!fUserInit)
  861.         return(0);
  862.  
  863.    if (iLastInUserDict != (int)lD)
  864.       {
  865.       iLastInUserDict = (int)lD;
  866.       (*lpdfUserDictProc)(DIRQ_SETWORDLISTS, 
  867.                &rgwordlist[rgeditfield[lD].iWordList].iList,
  868.                NULL, 1, NULL, NULL);
  869.       }
  870.  
  871.    return((*lpdfUserDictProc)(irq, lpIn, lpOut, cbMax, lContext, lD));
  872.    }
  873.  
  874.  
  875. /*----------------------------------------------------------
  876. Purpose: Set the bits for ALC_USEBITMAP field
  877. Returns: --
  878. */
  879. VOID SetAlcBits(
  880.    LPBYTE rgb,
  881.    LPSTR lp)
  882.    {
  883.    int ib;
  884.  
  885.    for (ib=0; ib<32; ib++)
  886.       rgb[ib] = 0;
  887.  
  888.    for ( ; *lp != 0; lp++)
  889.       {
  890.       BYTE uch = *lp;
  891.       int iByte = uch/8;
  892.       int iBit = uch%8;
  893.  
  894.       rgb[iByte] |= (BYTE)(1<<iBit);
  895.       }
  896.    }
  897.  
  898. /*----------------------------------------------------------
  899. Purpose: Free the Custom Dictionary DLL
  900. Returns: --
  901. */
  902. VOID CloseCustomDictionary(VOID)
  903.    {
  904.    if(fCustomInit)
  905.       (*lpdfCustomDictProc)(DIRQ_CLEANUP, NULL, NULL, NULL, NULL, NULL);
  906.  
  907.    /* Free the library
  908.    */
  909.    if(hCustomDictLib)
  910.       FreeLibrary(hCustomDictLib);
  911.  
  912.    fCustomInit = FALSE;
  913.    lpdfCustomDictProc = NULL;
  914.    hCustomDictLib = NULL;
  915.    }
  916.  
  917.  
  918. /*----------------------------------------------------------
  919. Purpose: Close all the wordlists opened and free the User
  920.      Dictionary DLL
  921. Returns: --
  922. */
  923. VOID CloseUserDictionary(VOID)
  924.    {
  925.    if(fUserInit)
  926.       {
  927.       int i;
  928.  
  929.       /* Close all the wordlists we opened
  930.       */
  931.       for(i = 0; i < SIZE_WORDLIST; ++i)
  932.      {
  933.      unsigned uTemp;
  934.  
  935.      if(uTemp = rgwordlist[i].iList)
  936.         (*lpdfUserDictProc)(DIRQ_CLOSE, (LPVOID)&uTemp, NULL, NULL, NULL, NULL);
  937.      rgwordlist[i].iList = 0;
  938.      }
  939.  
  940.       /* Ask the dictionary DLL to do cleanup on our behalf
  941.       */
  942.       (*lpdfUserDictProc)(DIRQ_CLEANUP, NULL, NULL, NULL, NULL, NULL);
  943.       }
  944.  
  945.    /* Free the library
  946.    */
  947.    if(hUserDictLib)
  948.       FreeLibrary(hUserDictLib);
  949.  
  950.    fUserInit = FALSE;
  951.    lpdfUserDictProc = NULL;
  952.    hUserDictLib = NULL;
  953.    }
  954.