home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / PMCARD.ZIP / PMCARD.C < prev    next >
C/C++ Source or Header  |  1990-08-27  |  62KB  |  2,137 lines

  1. /****************************************************************************
  2.  
  3.                                    PMCARD
  4.  
  5.                Copyright (c) 1990 Ziff Communications Company
  6.                          Jeff Prosise * PC Magazine
  7.  
  8. PMCARD allows you to store names, addresses, and phone numbers using
  9. a Rolodex metaphor.  On PCs with modems attached, it will also dial
  10. the phone.  PMCARD requires OS/2 version 1.2 or later.
  11.  
  12. Source Files:  PMCARD          Make file
  13.                PMCARD.DEF      Module definition file
  14.                PMCARD.H        C header file
  15.                PMCARD.C        C source file
  16.                PMCARD.RC       Resource script file
  17.  
  18. Binary Files:  PMCARD.ICO      Icon file
  19.                PMCARD.RES      Compiled resource file
  20.                PMCARD.OBJ      Compiled source file
  21.  
  22. Executable:    PMCARD.EXE
  23.  
  24. Note:  PMCARD was developed using Microsoft C 5.1. Compiling it with
  25.        C 5.1 requires the use of preprocessor C1L.EXE rather than C1.EXE.
  26.        To compile it with C 6.0, use a /B1 switch.
  27.  
  28. ****************************************************************************/
  29.  
  30. #define INCL_WIN
  31. #define INCL_GPILCIDS
  32. #define INCL_GPICONTROL
  33. #define INCL_DOSDEVICES
  34.  
  35. #include <os2.h>
  36. #include <string.h>
  37. #include <stdlib.h>
  38. #include <stdio.h>
  39. #include "pmcard.h"
  40.  
  41. MRESULT EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM);
  42. MRESULT EXPENTRY AboutDlgProc (HWND, USHORT, MPARAM, MPARAM);
  43. MRESULT EXPENTRY SearchDlgProc (HWND, USHORT, MPARAM, MPARAM);
  44. MRESULT EXPENTRY SaveAsDlgProc (HWND, USHORT, MPARAM, MPARAM);
  45. MRESULT EXPENTRY OpenDlgProc (HWND, USHORT, MPARAM, MPARAM);
  46. MRESULT EXPENTRY ConfigDlgProc (HWND, USHORT, MPARAM, MPARAM);
  47. MRESULT EXPENTRY StatusDlgProc (HWND, USHORT, MPARAM, MPARAM);
  48. MRESULT EXPENTRY GotoDlgProc (HWND, USHORT, MPARAM, MPARAM);
  49. MRESULT EXPENTRY DialDlgProc (HWND, USHORT, MPARAM, MPARAM);
  50.  
  51. VOID    UpdateMLE (void);
  52. VOID    ShowCardNo (HPS);
  53. USHORT    ReadFile (CHAR *);
  54. USHORT    SaveFile (CHAR *);
  55. USHORT    SaveBeforeExit (CHAR *);
  56. VOID    PackBuffer (void);
  57. USHORT    ProcessCard (HWND);
  58. USHORT    DialPhone (CHAR *);
  59. USHORT    BuildPhoneList (CHAR *);
  60. VOID    CountDigits (CHAR far *, USHORT *, USHORT *);
  61. VOID    CopyToList (USHORT, CHAR *, CHAR far *);
  62. USHORT    FindPrevCard (void);
  63. USHORT    FindNextCard (void);
  64. USHORT    CheckCard (USHORT);
  65. VOID     FillDriveListBox (HWND, USHORT);
  66. VOID     FillDirListBox (HWND, USHORT);
  67. VOID     FillFileListBox (HWND, USHORT);
  68. USHORT     MakePath (CHAR *, USHORT);
  69. USHORT    MakeQFN (CHAR *, CHAR *, USHORT);
  70. VOID    ExtractFileName (CHAR *, CHAR *);
  71.  
  72. HAB        hab;
  73. HWND    hwndClient, hwndMLE, hwndButton[4];
  74. SHORT    cxChar, cyChar;
  75. SHORT    CardCount = 1, CardNo = 0;
  76. USHORT    usTopOffset;
  77. USHORT    usCardLength[1000] = { 0x00 };
  78. USHORT    usCardOffset[1000] = { 0x00 };
  79. USHORT    usSelector1, usPhoneCount;
  80. USHORT    usDeletedTextLength;
  81. CHAR    far *chBufferPtr;
  82. CHAR    szSearchText[41] = "";
  83. CHAR    szCurrentFile[512] = "";
  84. CHAR    chDeleteBuffer[1024], szTextBuffer[640];
  85. CHAR    szPhoneNumber[17], szPhoneList[200];
  86. BOOL    fEditing = FALSE, fCardInBuffer = FALSE, fCaseSensitive = FALSE;
  87.  
  88. CHAR    szAppName[] = "PMCARD";
  89. CHAR    szKeyName1[] = "Settings";
  90. CHAR    szKeyName2[] = "DialCmd";
  91. CHAR    szKeyName3[] = "HangUpCmd";
  92. CHAR    szKeyName4[] = "DefDataFile";
  93. CHAR    szKeyName5[] = "DialPrefix";
  94.  
  95. CHAR     szDialCmd[17];                        // Modem dial command
  96. CHAR     szHangUpCmd[17];                    // Modem hangup command
  97. CHAR    szDefDataFile[129];                    // Default data file
  98. CHAR    szDialPrefix[7];                    // Dial prefix
  99.  
  100. struct    CommParms {
  101.     SHORT    BaudRate;                        // Baud Rate (1200)
  102.     SHORT    COMPort;                        // COM port (1)
  103.     SHORT    Parity;                            // Parity setting (None)
  104.     SHORT    DataBits;                        // Number of data bits (8)
  105.     SHORT    StopBits;                        // Number of stop bits (1)
  106. } GblParms = { 1, 0, 0, 1, 0 };
  107.  
  108. CHAR    Signature[] = { 0xBC, 0x9E, 0x8D, 0x9B, 0xB9, 0x96, 0x93, 0x9A };
  109.  
  110. CHAR    szErrMsg1[] = " was not found or could not be opened";
  111. CHAR    szErrMsg2[] = "There's not enough memory to run PMCARD";
  112. CHAR    szErrMsg3[] = "You've reached PMCARD's limit of 999 cards";
  113. CHAR    szErrMsg4[] = " not found";
  114. CHAR    szErrMsg6[] = " was not created by PMCARD";
  115. CHAR    szErrMsg7[] = "There's not enough space on the disk to store the file";
  116. CHAR    szErrMsg8[] = " could not be saved.  Check the path and filename for validity.";
  117. CHAR    szErrMsg9[] = "There's not enough space to store the changes.  Delete some text and try again.";
  118. CHAR    szErrMsg10[] = "You must first position the cursor where you want the text to be pasted";
  119. CHAR    szErrMsg11[] = "There's not enough space to add this card";
  120. CHAR    szErrMsg12[] = " doesn't exist or is in use by another process";
  121. CHAR    szErrMsg13[] = "Your modem is not ready";
  122. CHAR    szErrMsg14[] = "Your modem will not accept commands";
  123. CHAR    szErrMsg15[] = "The selected text exceeds PMCARD's internal buffer length of 64 characters";
  124.  
  125. CHAR    szMsg1[] = "Save the current card stack?";
  126. CHAR    szMsg2[] = "Pick up the handset and press OK";
  127.  
  128. /*---------------------------------------------------------------------------
  129.     Function main
  130. ---------------------------------------------------------------------------*/
  131.  
  132. int main (int argc, char *argv[])
  133. {
  134.     static ULONG flFrameFlags = FCF_TITLEBAR        | FCF_SYSMENU    |
  135.                                 FCF_BORDER            | FCF_MINBUTTON    |
  136.                                 FCF_SHELLPOSITION    | FCF_TASKLIST    |
  137.                                 FCF_MENU            | FCF_ICON        |
  138.                                 FCF_ACCELTABLE        ;
  139.  
  140.     HMQ                hmq;
  141.     HWND            hwndFrame;
  142.     QMSG            qmsg;
  143.     MLEFORMATRECT     MLEFormatRect;
  144.  
  145.     if (argc >= 2)
  146.         MakeQFN (argv[1], szCurrentFile, sizeof szCurrentFile);
  147.  
  148.     hab = WinInitialize (NULL);
  149.     hmq = WinCreateMsgQueue (hab, DEFAULT_QUEUE_SIZE);
  150.  
  151.     WinRegisterClass (hab, szAppName, ClientWndProc, 0L, 0);
  152.  
  153.     hwndFrame = WinCreateStdWindow (HWND_DESKTOP, NULL, &flFrameFlags,
  154.                                     szAppName, NULL, 0L, NULL,
  155.                                     ID_RESOURCE, &hwndClient);
  156.  
  157.     if (CardCount == -1) {
  158.         WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg2,
  159.                        NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  160.         WinDestroyWindow (hwndFrame);
  161.         WinDestroyMsgQueue (hmq);
  162.         WinTerminate (hab);
  163.         return (1);
  164.     }
  165.  
  166.     hwndButton[0] = WinCreateWindow (hwndClient, WC_BUTTON, "Srch",
  167.                             WS_VISIBLE | BS_PUSHBUTTON, cxChar * 1, cyChar/2,
  168.                             9 * cxChar, 2 * cyChar, hwndClient, HWND_BOTTOM,
  169.                             SRCH_BUTTON, NULL, NULL);
  170.  
  171.     hwndButton[1] = WinCreateWindow (hwndClient, WC_BUTTON, "Dial",
  172.                             WS_VISIBLE | BS_PUSHBUTTON, cxChar * 11, cyChar/2,
  173.                             9 * cxChar, 2 * cyChar, hwndClient, HWND_BOTTOM,
  174.                             DIAL_BUTTON, NULL, NULL);
  175.  
  176.     hwndButton[2] = WinCreateWindow (hwndClient, WC_BUTTON, "Prev",
  177.                             WS_VISIBLE | BS_PUSHBUTTON, cxChar * 36, cyChar/2,
  178.                             9 * cxChar, 2 * cyChar, hwndClient, HWND_BOTTOM,
  179.                             PREV_BUTTON, NULL, NULL);
  180.  
  181.     hwndButton[3] = WinCreateWindow (hwndClient, WC_BUTTON, "Next",
  182.                             WS_VISIBLE | BS_PUSHBUTTON, cxChar * 46, cyChar/2,
  183.                             9 * cxChar, 2 * cyChar, hwndClient, HWND_BOTTOM,
  184.                             NEXT_BUTTON, NULL, NULL);
  185.  
  186.     hwndMLE = WinCreateWindow (hwndClient, WC_MLE, "", WS_VISIBLE,
  187.                         cxChar, 3 * cyChar, 54 * cxChar, 8 * cyChar,
  188.                         hwndClient, HWND_BOTTOM, ID_MLE, NULL, NULL);
  189.  
  190.     WinSendMsg (hwndMLE, MLM_SETFORMATRECT, MPFROMP (&MLEFormatRect),
  191.                 MPFROMLONG (MLFFMTRECT_FORMATRECT));
  192.  
  193.     WinSendMsg (hwndMLE, MLM_FORMAT, MPFROMSHORT (MLFIE_NOTRANS), 0L);
  194.  
  195.     WinSendMsg (hwndMLE, MLM_SETTEXTCOLOR, MPFROMLONG ((COLOR) CLR_DARKBLUE), 0L);
  196.  
  197.     UpdateMLE ();
  198.  
  199.     while (TRUE) {
  200.         while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
  201.             WinDispatchMsg (hab, &qmsg);
  202.         if (SaveBeforeExit (szCurrentFile) < 2)
  203.             break;
  204.         WinCancelShutdown (hmq, FALSE);
  205.     }
  206.  
  207.     WinDestroyWindow (hwndFrame);
  208.     WinDestroyMsgQueue (hmq);
  209.     WinTerminate (hab);
  210.  
  211.     return (0);
  212. }
  213.  
  214. /*---------------------------------------------------------------------------
  215.     UpdateMLE writes the text of the current card to the MLE.
  216. ---------------------------------------------------------------------------*/
  217.  
  218. VOID UpdateMLE (void)
  219. {
  220.     HPS        hps;
  221.     LONG    lOffset = 0;
  222.  
  223.     WinSendMsg (hwndMLE, MLM_DELETE, MPFROMLONG (0L),
  224.                 MPFROMLONG (WinSendMsg (hwndMLE, MLM_QUERYTEXTLENGTH, 0L, 0L)));
  225.  
  226.     if (usCardLength[CardNo] != 0) {
  227.  
  228.         WinSendMsg (hwndMLE, MLM_SETIMPORTEXPORT,
  229.                     MPFROMP (chBufferPtr + usCardOffset[CardNo]),
  230.                     MPFROMSHORT (2048));
  231.  
  232.         WinSendMsg (hwndMLE, MLM_IMPORT, MPFROMP (&lOffset),
  233.                     MPFROMLONG ((LONG) usCardLength[CardNo]));
  234.     }
  235.  
  236.     hps = WinGetPS (hwndClient);
  237.     ShowCardNo (hps);
  238.     WinReleasePS (hps);
  239. }
  240.  
  241. /*---------------------------------------------------------------------------
  242.     ShowCardNo displays "X of X" in the client window
  243. ---------------------------------------------------------------------------*/
  244.  
  245. VOID ShowCardNo (HPS hps)
  246. {
  247.     CHAR    szBuffer[32];
  248.     RECTL    rcl;
  249.  
  250.     sprintf (szBuffer, "%u of %u", CardNo+1, CardCount);
  251.  
  252.     rcl.xLeft = 21 * cxChar;
  253.     rcl.yBottom = cyChar/2;
  254.     rcl.xRight = rcl.xLeft + (14 * cxChar);
  255.     rcl.yTop = rcl.yBottom + (2 * cyChar);
  256.  
  257.     WinDrawText (hps, -1, szBuffer, &rcl, 0L, 0L,
  258.                  DT_ERASERECT | DT_CENTER | DT_VCENTER | DT_TEXTATTRS);
  259. }
  260.  
  261. /*---------------------------------------------------------------------------
  262.     ReadFile reads a PMCARD data file from disk.
  263.  
  264.     Input:    szFileName = Pointer to ASCIIZ filename
  265.  
  266.     Return: 0 = Call succeeded
  267.             1 = Error (file was not found or could not be opened)
  268.             2 = Error (not a PMCARD data file)
  269. ---------------------------------------------------------------------------*/
  270.  
  271. USHORT ReadFile (CHAR *szFileName)
  272. {
  273.     USHORT        hFile, usAction, usBytesRead, i;
  274.     FILESTATUS    fs;
  275.  
  276.     static CHAR    SigBuffer[] = { 0x00, 0x00, 0x00, 0x00,
  277.                                 0x00, 0x00, 0x00, 0x00 };
  278.  
  279.     if (DosOpen (szFileName, &hFile, &usAction, 0L, 0, FILE_OPEN,
  280.             OPEN_ACCESS_READONLY | OPEN_SHARE_DENYREADWRITE, 0L))
  281.         return (1);
  282.  
  283.     DosQFileInfo (hFile, 0x01, &fs, sizeof fs);
  284.  
  285.     DosRead (hFile, SigBuffer, 8, &usBytesRead);
  286.     if (strncmp (SigBuffer, Signature, 8)) {
  287.         DosClose (hFile);
  288.         return (2);
  289.     }
  290.  
  291.     DosRead (hFile, &CardCount, 2, &usBytesRead);
  292.     DosRead (hFile, usCardLength, 2 * CardCount, &usBytesRead);
  293.     DosRead (hFile, chBufferPtr, (USHORT) fs.cbFile - 10 -
  294.              (2 * (USHORT) CardCount), &usBytesRead);
  295.     DosClose (hFile);
  296.  
  297.     usCardOffset[0] = 0;
  298.  
  299.     if (CardCount > 1)
  300.         for (i=0; i<(CardCount-1); i++)
  301.             usCardOffset[i+1] = usCardOffset[i] + usCardLength[i];
  302.  
  303.     usTopOffset = usCardOffset[CardCount-1] + usCardLength[CardCount-1];
  304.  
  305.     return (0);
  306. }
  307.  
  308. /*---------------------------------------------------------------------------
  309.     SaveFile saves a PMCARD data file to disk.
  310.  
  311.     Input:    szFileName = Pointer to ASCIIZ filename
  312.  
  313.     Return: 0 = Call succeeded
  314.             1 = Error (invalid path or filename)
  315.             2 = Error (disk full)
  316. ---------------------------------------------------------------------------*/
  317.  
  318. USHORT SaveFile (CHAR *szFileName)
  319. {
  320.     USHORT    hFile, usAction, usBytesWritten, i;
  321.  
  322.     if (DosOpen (szFileName, &hFile, &usAction, 0L, FILE_NORMAL,
  323.                   FILE_TRUNCATE | FILE_CREATE, OPEN_ACCESS_WRITEONLY
  324.                   | OPEN_SHARE_DENYREADWRITE, 0L))
  325.         return (1);
  326.  
  327.     DosWrite (hFile, Signature, 8, &usBytesWritten);
  328.     if (usBytesWritten < 8) {
  329.         DosClose (hFile);
  330.         return (2);
  331.     }
  332.  
  333.     DosWrite (hFile, &CardCount, 2, &usBytesWritten);
  334.     if (usBytesWritten < 2) {
  335.         DosClose (hFile);
  336.         return (2);
  337.     }
  338.  
  339.     DosWrite (hFile, usCardLength, 2 * CardCount, &usBytesWritten);
  340.     if (usBytesWritten < 2 * CardCount) {
  341.         DosClose (hFile);
  342.         return (2);
  343.     }
  344.  
  345.     for (i=0; i<CardCount; i++)
  346.         if (usCardLength[i] != 0) {
  347.             DosWrite (hFile, chBufferPtr + usCardOffset[i], usCardLength[i],
  348.                       &usBytesWritten);
  349.             if (usBytesWritten < usCardLength[i]) {
  350.                 DosClose (hFile);
  351.                 return (2);
  352.             }
  353.         }
  354.  
  355.     DosClose (hFile);
  356.     return (0);
  357. }
  358.  
  359. /*---------------------------------------------------------------------------
  360.     SaveBeforeExit invokes a dialog box that gives the user a chance to
  361.     save a file before proceeding.  If the answer is yes, SaveBeforeExit
  362.     calls SaveFile to save the file.
  363.  
  364.     Input:    szFileName = Pointer to ASCIIZ filename
  365.  
  366.     Return: 0 = User pressed "Yes"
  367.             1 = User pressed "No"
  368.             2 = User pressed "Cancel"
  369.             3 = User pressed "Yes" but the file was not saved or
  370.                 ProcessCard failed for lack of buffer space
  371. ---------------------------------------------------------------------------*/
  372.  
  373. USHORT SaveBeforeExit (CHAR *szFileName)
  374. {
  375.     USHORT    usResult;
  376.  
  377.     switch (WinMessageBox (HWND_DESKTOP, hwndClient, szMsg1, " ", NULL,
  378.                            MB_ICONQUESTION | MB_YESNOCANCEL)) {
  379.  
  380.     case MBID_YES:
  381.         if (fEditing)
  382.             if (ProcessCard (hwndButton[3]))
  383.                 return (3);
  384.  
  385.         if (strlen (szFileName) == 0)
  386.             if (!WinDlgBox (HWND_DESKTOP, hwndClient, SaveAsDlgProc,
  387.                     NULL, IDD_SAVEAS, NULL))
  388.                 return (2);
  389.  
  390.         if ((usResult = SaveFile (szFileName)) != 0)
  391.  
  392.             switch (usResult) {
  393.  
  394.             case (1):
  395.                 strcpy (szTextBuffer, szFileName);
  396.                 strcat (szTextBuffer, szErrMsg8);
  397.                 WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  398.                     NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  399.                 return (3);
  400.  
  401.             case (2):
  402.                 DosDelete (szFileName, 0L);
  403.                 WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg7,
  404.                     NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  405.                 return (3);
  406.             }
  407.  
  408.         return (0);
  409.  
  410.     case MBID_NO:
  411.         if (fEditing) {
  412.             fEditing = FALSE;
  413.             WinSetFocus (HWND_DESKTOP, hwndButton[3]);
  414.         }
  415.         return (1);
  416.  
  417.     case MBID_CANCEL:
  418.         return (2);
  419.     }
  420. }
  421.  
  422. /*---------------------------------------------------------------------------
  423.     PackBuffer packs the card data currently in the buffer.
  424. ---------------------------------------------------------------------------*/
  425.  
  426. VOID PackBuffer (void)
  427. {
  428.     USHORT    usSelector2, usOffset, i, j;
  429.     CHAR    far *chPtr;
  430.  
  431.     if ((CardCount == 1) && (usCardLength[0] == 0))
  432.         return;
  433.  
  434.     if (DosAllocSeg (usTopOffset+1, &usSelector2, 0))
  435.         return;
  436.  
  437.     chPtr = (CHAR far *) (((ULONG)(usSelector2)) << 16);
  438.     
  439.     usOffset = 0;
  440.  
  441.     for (i=0; i<CardCount; i++)
  442.         if (usCardLength[i] != 0) {
  443.             for (j=0; j<usCardLength[i]; j++)
  444.                 *(chPtr + usOffset + j) = *(chBufferPtr + usCardOffset[i] + j);
  445.             usOffset += usCardLength[i];
  446.         }
  447.  
  448.     for (i=0; i<(usOffset+1); i++)
  449.         *(chBufferPtr + i) = *(chPtr + i);
  450.  
  451.     usCardOffset[0] = 0;
  452.  
  453.     if (CardCount > 1)
  454.         for (i=0; i<(CardCount-1); i++)
  455.             usCardOffset[i+1] = usCardOffset[i] + usCardLength[i];
  456.  
  457.     usTopOffset = usCardOffset[CardCount-1] + usCardLength[CardCount-1];
  458.  
  459.     DosFreeSeg (usSelector2);
  460. }
  461.  
  462. /*---------------------------------------------------------------------------
  463.     ProcessCard processes the card currently in the MLE.
  464.  
  465.     Input:  hwnd = handle of window to receive the input focus
  466.  
  467.     Return: 0 = Call succeeded
  468.             1 = Error (Not enough buffer space)
  469. ---------------------------------------------------------------------------*/
  470.  
  471. USHORT ProcessCard (HWND hwnd)
  472. {
  473.     LONG        lOffset = 0;
  474.     ULONG        ulByteCount;
  475.     USHORT        usCardSize;
  476.     CHAR        chFirstChar;
  477.  
  478.     ulByteCount = (ULONG) WinSendMsg (hwndMLE, MLM_QUERYTEXTLENGTH, 0L, 0L);
  479.     usCardSize = (USHORT) ulByteCount;
  480.  
  481.     if (usCardSize == usCardLength[CardNo]) {
  482.         usCardLength[CardNo] = usCardSize;
  483.         chFirstChar = *(chBufferPtr + usCardOffset[CardNo] + usCardSize);
  484.  
  485.         WinSendMsg (hwndMLE, MLM_SETIMPORTEXPORT,
  486.                     MPFROMP (chBufferPtr + usCardOffset[CardNo]),
  487.                     MPFROMSHORT (2048));
  488.  
  489.         WinSendMsg (hwndMLE, MLM_EXPORT, MPFROMP (&lOffset),
  490.                     MPFROMP (&ulByteCount));
  491.  
  492.         *(chBufferPtr + usCardOffset[CardNo] + usCardSize) = chFirstChar;
  493.  
  494.         WinSetFocus (HWND_DESKTOP, hwnd);
  495.         fEditing = FALSE;
  496.         return (0);
  497.     }
  498.  
  499.     if (usCardSize < usCardLength[CardNo]) {
  500.         usCardLength[CardNo] = usCardSize;
  501.  
  502.         WinSendMsg (hwndMLE, MLM_SETIMPORTEXPORT,
  503.                     MPFROMP (chBufferPtr + usCardOffset[CardNo]),
  504.                     MPFROMSHORT (2048));
  505.  
  506.         WinSendMsg (hwndMLE, MLM_EXPORT, MPFROMP (&lOffset),
  507.                     MPFROMP (&ulByteCount));
  508.  
  509.         WinSetFocus (HWND_DESKTOP, hwnd);
  510.         fEditing = FALSE;
  511.         return (0);
  512.     }
  513.  
  514.     if (ulByteCount > (0xFFFE - usTopOffset)) {
  515.         WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg9,
  516.                        NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  517.         return (1);
  518.     }
  519.  
  520.     usCardLength[CardNo] = usCardSize;
  521.  
  522.     WinSendMsg (hwndMLE, MLM_SETIMPORTEXPORT,
  523.                 MPFROMP (chBufferPtr + usTopOffset),
  524.                 MPFROMSHORT (2048));
  525.  
  526.     WinSendMsg (hwndMLE, MLM_EXPORT, MPFROMP (&lOffset),
  527.                 MPFROMP (&ulByteCount));
  528.  
  529.     usCardOffset[CardNo] = usTopOffset;
  530.     usTopOffset += usCardSize;
  531.     WinSetFocus (HWND_DESKTOP, hwnd);
  532.     fEditing = FALSE;
  533.     return (0);
  534. }
  535.  
  536. /*---------------------------------------------------------------------------
  537.     DialPhone dials the phone number whose address is passed.
  538.  
  539.     Input:    szPhone = Pointer to ASCIIZ phone number string
  540.  
  541.     Return:    0 = Call succeeded
  542.             1 = Error (COM port not available)
  543.             2 = Error (Modem not ready)
  544.             3 = Error (Write error)
  545. ---------------------------------------------------------------------------*/
  546.  
  547. USHORT DialPhone (CHAR *szPhone)
  548. {
  549.     DCBINFO            DCBInfo;
  550.     LINECONTROL     lc;
  551.     static USHORT    usBaudRate[5] = { 300, 1200, 2400, 4800, 9600 };
  552.     static CHAR        *szCOMPortID[4] = { "COM1", "COM2", "COM3", "COM4" };
  553.     USHORT            hFile, usAction, usBytesWritten, usLineStatus;
  554.     static CHAR        szBuffer[41];
  555.     static CHAR        szEOL[3] = { 0x3B, 0x0D, 0x00 };
  556.  
  557.     if (DosOpen (szCOMPortID[GblParms.COMPort], &hFile, &usAction, 0L,
  558.         FILE_NORMAL, FILE_OPEN, OPEN_ACCESS_READWRITE |
  559.         OPEN_SHARE_DENYREADWRITE, 0L)) {
  560.  
  561.         strcpy (szTextBuffer, szCOMPortID[GblParms.COMPort]);
  562.         strcat (szTextBuffer, szErrMsg12);
  563.         WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  564.                        NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  565.         return (1);
  566.     }
  567.  
  568.     DosDevIOCtl (&usLineStatus, 0L, ASYNC_GETMODEMINPUT, 0x01, hFile);
  569.  
  570.     if ((usLineStatus & CTS_ON) == 0) {
  571.         WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg13,
  572.                        NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  573.         DosClose (hFile);
  574.         return (2);
  575.     }
  576.  
  577.     DosDevIOCtl (0L, &usBaudRate[GblParms.BaudRate],
  578.                  ASYNC_SETBAUDRATE, 0x01, hFile);
  579.  
  580.     lc.bDataBits = (BYTE) GblParms.DataBits + 7;
  581.     lc.bParity = (BYTE) GblParms.Parity;
  582.     lc.bStopBits = (BYTE) GblParms.StopBits * 2;
  583.     DosDevIOCtl (0L, &lc, ASYNC_SETLINECTRL, 0x01, hFile);
  584.  
  585.     DosDevIOCtl (&DCBInfo, 0L, ASYNC_GETDCBINFO, 0x01, hFile);
  586.     DCBInfo.usWriteTimeout = 100;
  587.     DCBInfo.fbCtlHndShake = 0 | MODE_DTR_CONTROL;
  588.     DCBInfo.fbFlowReplace = 0 | MODE_RTS_CONTROL;
  589.     DosDevIOCtl (0L, &DCBInfo, ASYNC_SETDCBINFO, 0x01, hFile);
  590.  
  591.     strcpy (szBuffer, szDialCmd);
  592.     strcat (szBuffer, szDialPrefix);
  593.     strcat (szBuffer, szPhone);
  594.     strcat (szBuffer, szEOL);
  595.  
  596.     if (DosWrite (hFile, szBuffer, strlen (szBuffer), &usBytesWritten)) {
  597.         WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg14,
  598.                        NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  599.         DosClose (hFile);
  600.         return (3);
  601.     }
  602.  
  603.     WinMessageBox (HWND_DESKTOP, hwndClient, szMsg2, " ", NULL, MB_OK);
  604.  
  605.     strcpy (szBuffer, szHangUpCmd);
  606.     strcat (szBuffer, &szEOL[1]);
  607.  
  608.     if (DosWrite (hFile, szBuffer, strlen (szBuffer), &usBytesWritten)) {
  609.         WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg14,
  610.                        NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  611.         DosClose (hFile);
  612.         return (3);
  613.     }
  614.  
  615.     DosClose (hFile);
  616.     return (0);
  617. }
  618.  
  619. /*---------------------------------------------------------------------------
  620.     BuildPhoneList builds a list of phone numbers from the text of the
  621.     current card.
  622.  
  623.     Input:    szBuffer = Pointer to list buffer
  624.  
  625.     Return:    Number of entries in list
  626. ---------------------------------------------------------------------------*/
  627.  
  628. USHORT BuildPhoneList (CHAR *szBuffer)
  629. {
  630.     USHORT    usDigits, usChars, usCount = 0, i = 0;
  631.     CHAR    chFirstChar;
  632.  
  633.     if (usCardLength[CardNo] < 6)
  634.         return (0);    
  635.  
  636.     chFirstChar = *(chBufferPtr + usCardOffset[CardNo] +
  637.             usCardLength[CardNo]);
  638.  
  639.     *(chBufferPtr + usCardOffset[CardNo] + usCardLength[CardNo]) = 0x0A;
  640.  
  641.     while ((i <= usCardLength[CardNo]-5) && (usCount < 10)) {
  642.  
  643.         if ((*(chBufferPtr+usCardOffset[CardNo]+i) < 0x30) ||
  644.             (*(chBufferPtr+usCardOffset[CardNo]+i) > 0x39)) {
  645.             i++;
  646.             continue;
  647.         }
  648.  
  649.         CountDigits (chBufferPtr+usCardOffset[CardNo]+i, &usDigits, &usChars);
  650.  
  651.         if (usDigits < 5) {
  652.             i++;
  653.             continue;
  654.         }
  655.  
  656.         if ((usDigits == 5) &&
  657.             (*(chBufferPtr+usCardOffset[CardNo]+i) >= 0x30) &&
  658.             (*(chBufferPtr+usCardOffset[CardNo]+i) <= 0x39) &&
  659.             (*(chBufferPtr+usCardOffset[CardNo]+i+1) >= 0x30) &&
  660.             (*(chBufferPtr+usCardOffset[CardNo]+i+1) <= 0x39) &&
  661.             (*(chBufferPtr+usCardOffset[CardNo]+i+2) >= 0x30) &&
  662.             (*(chBufferPtr+usCardOffset[CardNo]+i+2) <= 0x39) &&
  663.             (*(chBufferPtr+usCardOffset[CardNo]+i+3) >= 0x30) &&
  664.             (*(chBufferPtr+usCardOffset[CardNo]+i+3) <= 0x39) &&
  665.             (*(chBufferPtr+usCardOffset[CardNo]+i+4) >= 0x30) &&
  666.             (*(chBufferPtr+usCardOffset[CardNo]+i+4) <= 0x39)) {
  667.                 i += usChars;
  668.                 continue;
  669.         }
  670.  
  671.         if ((usDigits == 9) &&
  672.             (*(chBufferPtr+usCardOffset[CardNo]+i) >= 0x30) &&
  673.             (*(chBufferPtr+usCardOffset[CardNo]+i) <= 0x39) &&
  674.             (*(chBufferPtr+usCardOffset[CardNo]+i+1) >= 0x30) &&
  675.             (*(chBufferPtr+usCardOffset[CardNo]+i+1) <= 0x39) &&
  676.             (*(chBufferPtr+usCardOffset[CardNo]+i+2) >= 0x30) &&
  677.             (*(chBufferPtr+usCardOffset[CardNo]+i+2) <= 0x39) &&
  678.             (*(chBufferPtr+usCardOffset[CardNo]+i+3) >= 0x30) &&
  679.             (*(chBufferPtr+usCardOffset[CardNo]+i+3) <= 0x39) &&
  680.             (*(chBufferPtr+usCardOffset[CardNo]+i+4) >= 0x30) &&
  681.             (*(chBufferPtr+usCardOffset[CardNo]+i+4) <= 0x39) &&
  682.             (*(chBufferPtr+usCardOffset[CardNo]+i+5) == 0x2D) &&
  683.             (*(chBufferPtr+usCardOffset[CardNo]+i+6) >= 0x30) &&
  684.             (*(chBufferPtr+usCardOffset[CardNo]+i+6) <= 0x39) &&
  685.             (*(chBufferPtr+usCardOffset[CardNo]+i+7) >= 0x30) &&
  686.             (*(chBufferPtr+usCardOffset[CardNo]+i+7) <= 0x39) &&
  687.             (*(chBufferPtr+usCardOffset[CardNo]+i+8) >= 0x30) &&
  688.             (*(chBufferPtr+usCardOffset[CardNo]+i+8) <= 0x39) &&
  689.             (*(chBufferPtr+usCardOffset[CardNo]+i+9) >= 0x30) &&
  690.             (*(chBufferPtr+usCardOffset[CardNo]+i+9) <= 0x39)) {
  691.                 i += usChars;
  692.                 continue;
  693.         }
  694.  
  695.         CopyToList (usChars, szBuffer+(usCount*20),
  696.                     chBufferPtr+usCardOffset[CardNo]+i);
  697.         i += usChars;
  698.         usCount++;
  699.     }
  700.  
  701.     *(chBufferPtr + usCardOffset[CardNo] + usCardLength[CardNo])
  702.         = chFirstChar;
  703.  
  704.     return (usCount);
  705. }
  706.  
  707. /*---------------------------------------------------------------------------
  708.     CountDigits counts the number of consecutive digits in a string
  709.     ignoring spaces, commas, hyphens, and parentheses.
  710.  
  711.     Input:    szBuffer = Pointer to text string
  712.             usDigits = Pointer to variable to receive digit count
  713.             usChars = Pointer to variable to receive raw character count
  714.  
  715.     Return:    usDigits = Number of consecutive digits
  716.             usChars = Number of characters comprising those digits
  717. ---------------------------------------------------------------------------*/
  718.  
  719. VOID CountDigits (CHAR far *szBuffer, USHORT *usDigits, USHORT *usChars)
  720. {
  721.     CHAR    ch;
  722.  
  723.     *usDigits = *usChars = 0;
  724.  
  725.     while (TRUE) {
  726.         ch = *szBuffer++;
  727.         if ((ch >= 0x30) && (ch <= 0x39)) {
  728.             (*usDigits)++;
  729.             (*usChars)++;
  730.         }
  731.         else
  732.             if ((ch == 0x20) || (ch == 0x2D) ||
  733.                 (ch == 0x28) || (ch == 0x29) ||
  734.                 (ch == 0x2C))
  735.                 (*usChars)++;
  736.             else
  737.                 break;
  738.     }
  739. }
  740.  
  741. /*---------------------------------------------------------------------------
  742.     CopyToList copies a string from one location to another and
  743.     filters out non-numeric characters in the process.
  744.  
  745.     Input:    usChars = Number of characters to process
  746.             szDest = Pointer to destination buffer
  747.             szSource = Pointer to source string
  748. ---------------------------------------------------------------------------*/
  749.  
  750. VOID CopyToList (USHORT usChars, CHAR *szDest, CHAR far *szSource)
  751. {
  752.     USHORT    i, usCount = 0;
  753.  
  754.     for (i=0; i<usChars && usCount<16; i++)
  755.         if (((*szSource >= 0x30) && (*szSource <= 0x39)) ||
  756.              (*szSource == 0x2C)) {
  757.             *szDest++ = *szSource++;
  758.             usCount++;
  759.         }
  760.         else
  761.             *szSource++;
  762.  
  763.     *szDest = 0x00;
  764. }
  765.  
  766.  
  767. /*---------------------------------------------------------------------------
  768.     FindPrevCard finds the last card that meets the search criteria.
  769.  
  770.     Return:    0 = No matching card found
  771.             1 = Match found (CardNo set to card number)
  772. ---------------------------------------------------------------------------*/
  773.  
  774. USHORT FindPrevCard (void)
  775. {
  776.     SHORT    CurrentCard, CardsSearched = 0;
  777.  
  778.     CurrentCard = (CardNo == 0) ? CardCount-1 : CardNo-1;
  779.  
  780.     while (CardsSearched++ < CardCount)
  781.         if (CheckCard (CurrentCard) != 0) {
  782.             CardNo = CurrentCard;
  783.             return (1);
  784.         }
  785.         else
  786.             CurrentCard = (CurrentCard == 0) ? CardCount-1 : CurrentCard-1;
  787.  
  788.     return (0);
  789. }
  790.  
  791. /*---------------------------------------------------------------------------
  792.     FindNextCard finds the next card that meets the search criteria.
  793.  
  794.     Return:    0 = No matching card found
  795.             1 = Match found (CardNo set to card number)
  796. ---------------------------------------------------------------------------*/
  797.  
  798. USHORT FindNextCard (void)
  799. {
  800.     SHORT    CurrentCard, CardsSearched = 0;
  801.  
  802.     CurrentCard = (CardNo == CardCount-1) ? 0 : CardNo+1;
  803.  
  804.     while (CardsSearched++ < CardCount)
  805.         if (CheckCard (CurrentCard) != 0) {
  806.             CardNo = CurrentCard;
  807.             return (1);
  808.         }
  809.         else
  810.             CurrentCard = (CurrentCard == CardCount-1) ? 0 : CurrentCard + 1;
  811.  
  812.     return (0);
  813. }
  814.  
  815. /*---------------------------------------------------------------------------
  816.     CheckCard checks a card for a search string.
  817.  
  818.     Input:    usCurrentCard = Card number to check
  819.  
  820.     Return:    0 = Card does not contain the search text
  821.             1 = Card does contain the search text
  822. ---------------------------------------------------------------------------*/
  823.  
  824. USHORT CheckCard (USHORT usCurrentCard)
  825. {
  826.     USHORT    i, usSearchLength;
  827.  
  828.     if ((usSearchLength = strlen (szSearchText)) > usCardLength[usCurrentCard])
  829.         return (0);
  830.  
  831.     if (fCaseSensitive) {
  832.         for (i=0; i < (usCardLength[usCurrentCard] - usSearchLength + 1); i++)
  833.             if (strncmp (szSearchText, chBufferPtr + usCardOffset[usCurrentCard] + i,
  834.                 usSearchLength) == 0)
  835.                     return (1);
  836.     }
  837.     else {
  838.         for (i=0; i < (usCardLength[usCurrentCard] - usSearchLength + 1); i++)
  839.             if (strnicmp (szSearchText, chBufferPtr + usCardOffset[usCurrentCard] + i,
  840.                 usSearchLength) == 0)
  841.                     return (1);
  842.     }
  843.  
  844.     return (0);
  845. }
  846.  
  847. /*---------------------------------------------------------------------------
  848.     FillDriveListBox fills a list box with letters identifying all
  849.     currently defined drives.
  850.  
  851.     Input:    hwnd = Handle of window where list box appears
  852.             id = List box ID
  853. ---------------------------------------------------------------------------*/
  854.  
  855. VOID FillDriveListBox (HWND hwnd, USHORT id)
  856. {
  857.     USHORT        usCurrentDrive, i;
  858.     ULONG        ulDriveMap;
  859.     static CHAR    szDriveID[] = " ::";
  860.  
  861.     DosQCurDisk (&usCurrentDrive, &ulDriveMap);
  862.     WinSendDlgItemMsg (hwnd, id, LM_DELETEALL, NULL, NULL);
  863.  
  864.     for (i=0; i<26; i++)
  865.  
  866.         if (ulDriveMap & (1L << i)) {
  867.  
  868.             szDriveID[1] = (CHAR) i + 0x41;
  869.             WinSendDlgItemMsg (hwnd, id, LM_INSERTITEM,
  870.                                MPFROM2SHORT (LIT_END, 0),
  871.                                MPFROMP (szDriveID));
  872.         }
  873. }
  874.  
  875. /*---------------------------------------------------------------------------
  876.     FillDirListBox fills a list box with strings identifying all
  877.     directories stemming from the current directory.
  878.  
  879.     Input:    hwnd = Handle of window where list box appears
  880.             id = List box ID
  881. ---------------------------------------------------------------------------*/
  882.  
  883. VOID FillDirListBox (HWND hwnd, USHORT id)
  884. {
  885.     HDIR        hDir = HDIR_CREATE;
  886.     FILEFINDBUF    FileFindBuf;
  887.     USHORT        usSearchCount = 1;
  888.  
  889.     DosFindFirst ("*.*", &hDir, FILE_DIRECTORY, &FileFindBuf,
  890.                   sizeof FileFindBuf, &usSearchCount, 0L);
  891.  
  892.     WinSendDlgItemMsg (hwnd, id, LM_DELETEALL, NULL, NULL);
  893.  
  894.     while (usSearchCount) {
  895.  
  896.         if (((FileFindBuf.attrFile & FILE_DIRECTORY) != 0) &&
  897.              (strcmp(FileFindBuf.achName, ".") != 0))
  898.  
  899.             WinSendDlgItemMsg (hwnd, id, LM_INSERTITEM,
  900.                                MPFROM2SHORT (LIT_SORTASCENDING, 0),
  901.                                MPFROMP (FileFindBuf.achName));
  902.  
  903.         DosFindNext (hDir, &FileFindBuf, sizeof FileFindBuf, &usSearchCount);
  904.     }
  905.     DosFindClose (hDir);
  906. }
  907.  
  908. /*---------------------------------------------------------------------------
  909.     FillFileListBox fills a list box with strings identifying all
  910.     files present in the current directory.
  911.  
  912.     Input:    hwnd = Handle of window where list box appears
  913.             id = List box ID
  914. ---------------------------------------------------------------------------*/
  915.  
  916. VOID FillFileListBox (HWND hwnd, USHORT id)
  917. {
  918.     HDIR        hDir = HDIR_CREATE;
  919.     FILEFINDBUF    FileFindBuf;
  920.     USHORT        usSearchCount = 1;
  921.  
  922.     DosFindFirst ("*.*", &hDir, FILE_NORMAL, &FileFindBuf,
  923.                   sizeof (FileFindBuf), &usSearchCount, 0L);
  924.  
  925.     WinSendDlgItemMsg (hwnd, id, LM_DELETEALL, NULL, NULL);
  926.  
  927.     while (usSearchCount) {
  928.  
  929.         WinSendDlgItemMsg (hwnd, id, LM_INSERTITEM,
  930.                            MPFROM2SHORT (LIT_SORTASCENDING, 0),
  931.                            MPFROMP (FileFindBuf.achName));
  932.  
  933.         DosFindNext (hDir, &FileFindBuf, sizeof (FileFindBuf), &usSearchCount);
  934.     }
  935.     DosFindClose (hDir);
  936. }
  937.  
  938. /*---------------------------------------------------------------------------
  939.     MakePath constructs an ASCIIZ string denoting the current path.
  940.  
  941.     Input:    szDest = Pointer to buffer where string will be placed
  942.             cbDest = size of buffer where path will be stored
  943.  
  944.     Return:    0 = Call succeeded
  945.             1 = Error (buffer too small)
  946.  
  947. ---------------------------------------------------------------------------*/
  948.  
  949. USHORT MakePath (CHAR *szDest, USHORT cbDest)
  950. {
  951.     USHORT        usCurrentDrive, usBufferSize;
  952.     ULONG        ulDriveMap;
  953.  
  954.     usBufferSize = cbDest - 3;
  955.  
  956.     DosQCurDisk (&usCurrentDrive, &ulDriveMap);
  957.     *szDest++ = (CHAR) usCurrentDrive + 0x40;
  958.     *szDest++ = 0x3A;
  959.     *szDest++ = 0x5C;
  960.  
  961.     if (DosQCurDir (usCurrentDrive, szDest, &usBufferSize))
  962.         return (1);
  963.  
  964.     return (0);
  965. }
  966.  
  967. /*---------------------------------------------------------------------------
  968.     MakeQFN    generates a fully qualified filename from a filename string.
  969.  
  970.     Input:    szSource = Pointer to original filename
  971.             szDest = Pointer to buffer where QFN will be stored
  972.             usSize = Size of buffer where QFN will be stored
  973.  
  974.     Return:    0 = Call succeeded
  975.             1 = Error (QFN buffer too small)
  976. ---------------------------------------------------------------------------*/
  977.  
  978. USHORT MakeQFN (CHAR *szSource, CHAR *szDest, USHORT usSize)
  979. {
  980.     USHORT    usCurrentDrive, usPathlen;
  981.     ULONG    ulDriveMap;
  982.     CHAR    *chPtr;
  983.  
  984.     chPtr = szDest;
  985.     usPathlen = usSize - 3;
  986.     DosQCurDisk (&usCurrentDrive, &ulDriveMap);
  987.  
  988.     if (szSource[1] == 0x3A && strlen (szSource) > 1 ) {
  989.         *szDest++ = *szSource++;
  990.         *szDest++ = *szSource++;
  991.     }
  992.     else {
  993.         *szDest++ = (CHAR) usCurrentDrive + 0x40;
  994.         *szDest++ = 0x3A;
  995.     }
  996.  
  997.     *szDest = 0x00;
  998.  
  999.     if (szSource[0] != 0x5C) {
  1000.         *szDest++ = 0x5C;
  1001.         if (DosQCurDir (usCurrentDrive, szDest, &usPathlen))
  1002.             return (1);
  1003.         if (szDest[strlen(szDest)-1] != 0x5C)
  1004.             strcat (szDest, "\\");
  1005.     }
  1006.  
  1007.     strcat (szDest, szSource);
  1008.     strupr (chPtr);
  1009.     return (0);
  1010. }
  1011.  
  1012. /*---------------------------------------------------------------------------
  1013.     ExtractFileName extracts a filename from a fully qualified filename
  1014.  
  1015.     Input:    szSource = Pointer to original filename
  1016.             szDest = Pointer to buffer where filename will be stored
  1017. ---------------------------------------------------------------------------*/
  1018.  
  1019. VOID ExtractFileName (CHAR *szSource, CHAR *szDest)
  1020. {
  1021.     SHORT    i;
  1022.  
  1023.     if (szSource[0] == 0x00)
  1024.         szDest[0] = 0x00;
  1025.     else {
  1026.         for (i=strlen(szSource)-1; szSource[i] != 0x5C; i--);
  1027.         strncpy (szDest, &szSource[i+1], strlen(szSource)-i+1);
  1028.     }
  1029. }
  1030.  
  1031. /*---------------------------------------------------------------------------
  1032.     ClientWndProc processes messages sent to the client window.
  1033. ---------------------------------------------------------------------------*/
  1034.  
  1035. MRESULT EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1036. {
  1037.     static HWND    hwndFrame;
  1038.     static HWND hwndMenu;
  1039.     static HPS    hps;
  1040.     FONTMETRICS    fm;
  1041.     USHORT        usResult, usInfo, i;
  1042.     SHORT        cxWidth, cyHeight, j;
  1043.     ULONG        ulReturn, ulBytesCopied, ulTextLength;
  1044.     CHAR        achBuffer[64];
  1045.  
  1046.     switch (msg) {
  1047.  
  1048.     case WM_CREATE:
  1049.         hwndFrame = WinQueryWindow (hwnd, QW_PARENT, FALSE);
  1050.         hwndMenu = WinWindowFromID (hwndFrame, FID_MENU);
  1051.         WinSetWindowText (hwndFrame, szAppName);
  1052.  
  1053.         if (DosAllocSeg (0xFFFF, &usSelector1, 0)) {
  1054.             CardCount = -1;
  1055.             return (0);
  1056.         }
  1057.  
  1058.         chBufferPtr = (CHAR far *) (((ULONG)(usSelector1)) << 16);
  1059.  
  1060.         WinQueryProfileData (hab, szAppName, szKeyName1, &GblParms, &i);
  1061.         WinQueryProfileString (hab, szAppName, szKeyName2, "ATS11=55DT",
  1062.                                szDialCmd, sizeof (szDialCmd));
  1063.         WinQueryProfileString (hab, szAppName, szKeyName3, "ATH0",
  1064.                                szHangUpCmd, sizeof (szHangUpCmd));
  1065.         WinQueryProfileString (hab, szAppName, szKeyName4, "",
  1066.                                szDefDataFile, sizeof (szDefDataFile));
  1067.         WinQueryProfileString (hab, szAppName, szKeyName5, "",
  1068.                                szDialPrefix, sizeof (szDialPrefix));
  1069.  
  1070.         if ((strlen (szDefDataFile) != 0) && (strlen (szCurrentFile) == 0))
  1071.             MakeQFN (szDefDataFile, szCurrentFile, sizeof szCurrentFile);
  1072.  
  1073.         if (strlen (szCurrentFile) != 0)
  1074.             if ((i = ReadFile (szCurrentFile)) != 0)
  1075.                 switch (i) {
  1076.  
  1077.                 case (1):
  1078.                     strcpy (szTextBuffer, szCurrentFile);
  1079.                     strcat (szTextBuffer, szErrMsg1);
  1080.                     WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  1081.                                    NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1082.                     break;
  1083.  
  1084.                 case (2):
  1085.                     strcpy (szTextBuffer, szCurrentFile);
  1086.                     strcat (szTextBuffer, szErrMsg6);
  1087.                     WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  1088.                                    NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1089.                     break;
  1090.                 }
  1091.  
  1092.         hps = WinGetPS (hwnd);
  1093.         GpiQueryFontMetrics (hps, (LONG) sizeof fm, &fm);
  1094.         cxChar = (SHORT) fm.lAveCharWidth;
  1095.         cyChar = (SHORT) fm.lMaxBaselineExt - (SHORT) fm.lMaxDescender;
  1096.         WinReleasePS (hps);
  1097.  
  1098.         cyHeight = (cyChar * 11) + (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CYTITLEBAR)
  1099.                          + (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CYMENU)
  1100.                          + (2 * (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CYBORDER));
  1101.  
  1102.         cxWidth = (cxChar * 56) + (2 * (SHORT) WinQuerySysValue (HWND_DESKTOP, SV_CXBORDER));
  1103.  
  1104.         WinSetWindowPos (hwndFrame, HWND_TOP, 0, 0, cxWidth, cyHeight,
  1105.                          SWP_SIZE | SWP_SHOW);
  1106.  
  1107.         return (0);
  1108.  
  1109.     case WM_PAINT:
  1110.         hps = WinBeginPaint (hwnd, NULL, NULL);
  1111.         GpiErase (hps);
  1112.         ShowCardNo (hps);
  1113.         WinEndPaint (hps);
  1114.         return (0);
  1115.  
  1116.     case WM_INITMENU:
  1117.  
  1118.         switch (SHORT1FROMMP (mp1)) {
  1119.  
  1120.         case IDM_EDIT:
  1121.             ulReturn = (ULONG) WinSendMsg (hwndMLE, MLM_QUERYSEL,
  1122.                                     (MPARAM) MLFQS_MINMAXSEL, 0L);
  1123.  
  1124.             if ((USHORT) (ulReturn & 0xFFFF) != (USHORT) (ulReturn >> 16)) {
  1125.                 WinSendMsg (hwndMenu, MM_SETITEMATTR,
  1126.                             MPFROM2SHORT (IDM_CUT, TRUE),
  1127.                             MPFROM2SHORT (MIA_DISABLED, 0));
  1128.                 WinSendMsg (hwndMenu, MM_SETITEMATTR,
  1129.                             MPFROM2SHORT (IDM_COPY, TRUE),
  1130.                             MPFROM2SHORT (MIA_DISABLED, 0));
  1131.                 WinSendMsg (hwndMenu, MM_SETITEMATTR,
  1132.                             MPFROM2SHORT (IDM_CLEAR, TRUE),
  1133.                             MPFROM2SHORT (MIA_DISABLED, 0));
  1134.             }
  1135.             else {
  1136.                 WinSendMsg (hwndMenu, MM_SETITEMATTR,
  1137.                             MPFROM2SHORT (IDM_CUT, TRUE),
  1138.                             MPFROM2SHORT (MIA_DISABLED, MIA_DISABLED));
  1139.                 WinSendMsg (hwndMenu, MM_SETITEMATTR,
  1140.                             MPFROM2SHORT (IDM_COPY, TRUE),
  1141.                             MPFROM2SHORT (MIA_DISABLED, MIA_DISABLED));
  1142.                 WinSendMsg (hwndMenu, MM_SETITEMATTR,
  1143.                             MPFROM2SHORT (IDM_CLEAR, TRUE),
  1144.                             MPFROM2SHORT (MIA_DISABLED, MIA_DISABLED));
  1145.             }
  1146.  
  1147.             if (WinQueryClipbrdFmtInfo (hab, CF_TEXT, &usInfo))
  1148.                 WinSendMsg (hwndMenu, MM_SETITEMATTR,
  1149.                             MPFROM2SHORT (IDM_PASTE, TRUE),
  1150.                             MPFROM2SHORT (MIA_DISABLED, 0));
  1151.             else
  1152.                 WinSendMsg (hwndMenu, MM_SETITEMATTR,
  1153.                             MPFROM2SHORT (IDM_PASTE, TRUE),
  1154.                             MPFROM2SHORT (MIA_DISABLED, MIA_DISABLED));
  1155.  
  1156.             WinSendMsg (hwndMenu, MM_SETITEMATTR,
  1157.                         MPFROM2SHORT (IDM_UNDODELETE, TRUE),
  1158.                         MPFROM2SHORT (MIA_DISABLED, 
  1159.                             fCardInBuffer ? 0 : MIA_DISABLED));
  1160.  
  1161.             return (0);
  1162.  
  1163.         case IDM_OPTIONS:
  1164.             WinSendMsg (hwndMenu, MM_SETITEMATTR,
  1165.                         MPFROM2SHORT (IDM_FINDPREV, TRUE),
  1166.                         MPFROM2SHORT (MIA_DISABLED,
  1167.                             (strlen (szSearchText) != 0) ? 0 : MIA_DISABLED));
  1168.  
  1169.             WinSendMsg (hwndMenu, MM_SETITEMATTR,
  1170.                         MPFROM2SHORT (IDM_FINDNEXT, TRUE),
  1171.                         MPFROM2SHORT (MIA_DISABLED,
  1172.                             (strlen (szSearchText) != 0) ? 0 : MIA_DISABLED));
  1173.  
  1174.             return (0);
  1175.         }
  1176.         break;
  1177.  
  1178.     case WM_CHAR:
  1179.         if (CHARMSG (&msg) -> fs & KC_KEYUP)
  1180.             return (0);
  1181.  
  1182.         if (CHARMSG (&msg) -> fs & KC_VIRTUALKEY)
  1183.  
  1184.             switch (CHARMSG (&msg) -> vkey) {
  1185.  
  1186.             case VK_PAGEUP:
  1187.                 if (fEditing)
  1188.                     if (ProcessCard (hwndButton[2]))
  1189.                         break;
  1190.                 CardNo = (CardNo == 0) ? CardCount-1 : CardNo-1;
  1191.                 UpdateMLE ();
  1192.                 break;
  1193.  
  1194.             case VK_PAGEDOWN:
  1195.                 if (fEditing)
  1196.                     if (ProcessCard (hwndButton[3]))
  1197.                         break;
  1198.                 CardNo = (CardNo == CardCount-1) ? 0 : CardNo+1;
  1199.                 UpdateMLE ();
  1200.                 break;
  1201.             }
  1202.  
  1203.         return (0);
  1204.  
  1205.     case WM_COMMAND:
  1206.  
  1207.         switch (COMMANDMSG(&msg)->cmd) {
  1208.  
  1209.         case SRCH_BUTTON:
  1210.             if (fEditing)
  1211.                 if (ProcessCard (hwndButton[0]))
  1212.                     return (0);
  1213.  
  1214.             if (WinDlgBox (HWND_DESKTOP, hwnd, SearchDlgProc, NULL,
  1215.                            IDD_SEARCH, NULL)) {
  1216.  
  1217.                 if (strlen (szSearchText) != 0) {
  1218.                     if (FindNextCard() != 0)
  1219.                         UpdateMLE ();
  1220.                     else {
  1221.                         strcpy (szTextBuffer, "\"");
  1222.                         strcat (szTextBuffer, szSearchText);
  1223.                         strcat (szTextBuffer, "\"");
  1224.                         strcat (szTextBuffer, szErrMsg4);
  1225.                         WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  1226.                             NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1227.                     }
  1228.                 }
  1229.             }
  1230.  
  1231.             return (0);
  1232.  
  1233.         case DIAL_BUTTON:
  1234.             if (fEditing)
  1235.                 if (ProcessCard (hwndButton[1]))
  1236.                     return (0);
  1237.  
  1238.             ulTextLength = (ULONG) WinSendMsg (hwndMLE, MLM_QUERYSEL,
  1239.                                     (MPARAM) MLFQS_MINMAXSEL, 0L);
  1240.  
  1241.             if ((ulTextLength >> 16) - (ulTextLength & 0xFFFF) >
  1242.                 sizeof (achBuffer)) {
  1243.                 WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg15,
  1244.                                NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1245.                 WinSetFocus (HWND_DESKTOP, hwndMLE);
  1246.                 return (0);
  1247.             }
  1248.  
  1249.             ulBytesCopied = (ULONG) WinSendMsg (hwndMLE, MLM_QUERYSELTEXT,
  1250.                                         MPFROMP (achBuffer), 0L);
  1251.  
  1252.             if (ulBytesCopied > 1) {
  1253.                 CopyToList (strlen (achBuffer), szPhoneNumber, achBuffer);
  1254.                 DialPhone (szPhoneNumber);
  1255.                 WinSetFocus (HWND_DESKTOP, hwndMLE);
  1256.             }
  1257.             else {
  1258.                 usPhoneCount = BuildPhoneList (szPhoneList);
  1259.                 if (WinDlgBox (HWND_DESKTOP, hwnd, DialDlgProc, NULL, IDD_DIAL, NULL))
  1260.                     DialPhone (szPhoneNumber);
  1261.             }
  1262.  
  1263.             return (0);
  1264.  
  1265.         case PREV_BUTTON:
  1266.             if (fEditing)
  1267.                 if (ProcessCard (hwndButton[2]))
  1268.                     return (0);
  1269.             CardNo = (CardNo == 0) ? CardCount-1 : CardNo-1;
  1270.             UpdateMLE ();
  1271.             return (0);
  1272.  
  1273.         case NEXT_BUTTON:
  1274.             if (fEditing)
  1275.                 if (ProcessCard (hwndButton[3]))
  1276.                     return (0);
  1277.             CardNo = (CardNo == CardCount-1) ? 0 : CardNo+1;
  1278.             UpdateMLE ();
  1279.             return (0);
  1280.  
  1281.         case IDM_NEW:
  1282.             if (fEditing)
  1283.                 if (ProcessCard (hwndButton[3]))
  1284.                     return (0);
  1285.  
  1286.             if (SaveBeforeExit (szCurrentFile) > 1)
  1287.                 return (0);
  1288.  
  1289.             CardCount = 1;
  1290.             CardNo = usCardLength[0] = usCardOffset[0] = usTopOffset = 0;
  1291.             szCurrentFile[0] = 0;
  1292.             UpdateMLE ();
  1293.             return (0);
  1294.  
  1295.         case IDM_OPEN:
  1296.             if (fEditing)
  1297.                 if (ProcessCard (hwndButton[3]))
  1298.                     return (0);
  1299.  
  1300.             if ((CardCount > 1) || (usCardLength[0] > 0))
  1301.                 if (SaveBeforeExit (szCurrentFile) > 1)
  1302.                     return (0);
  1303.  
  1304.             if (WinDlgBox (HWND_DESKTOP, hwnd, OpenDlgProc, NULL,
  1305.                            IDD_OPEN, NULL)) {
  1306.  
  1307.                 if ((usResult = ReadFile (szCurrentFile)) == 0) {
  1308.                     CardNo = 0;
  1309.                     UpdateMLE ();
  1310.                 }
  1311.                 else
  1312.                     switch (usResult) {
  1313.  
  1314.                     case (1):
  1315.                     strcpy (szTextBuffer, szCurrentFile);
  1316.                     strcat (szTextBuffer, szErrMsg1);
  1317.                         WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  1318.                             NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1319.                         break;
  1320.  
  1321.                     case (2):
  1322.                     strcpy (szTextBuffer, szCurrentFile);
  1323.                     strcat (szTextBuffer, szErrMsg6);
  1324.                         WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  1325.                             NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1326.                         break;
  1327.                     }
  1328.             }
  1329.  
  1330.             return (0);
  1331.  
  1332.         case IDM_SAVE:
  1333.             if (fEditing)
  1334.                 if (ProcessCard (hwndButton[3]))
  1335.                     return (0);
  1336.  
  1337.             if (szCurrentFile[0] == 0x00)
  1338.                 if (!WinDlgBox (HWND_DESKTOP, hwnd, SaveAsDlgProc, NULL,
  1339.                                IDD_SAVEAS, NULL))
  1340.                     return (0);
  1341.  
  1342.             if ((usResult = SaveFile (szCurrentFile)) != 0)
  1343.  
  1344.                 switch (usResult) {
  1345.  
  1346.                 case (1):
  1347.                     strcpy (szTextBuffer, szCurrentFile);
  1348.                     strcat (szTextBuffer, szErrMsg8);
  1349.                     WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  1350.                                    NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1351.                     break;
  1352.  
  1353.                 case (2):
  1354.                     DosDelete (szCurrentFile, 0L);
  1355.                     WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg7,
  1356.                                    NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1357.                 }
  1358.  
  1359.             PackBuffer ();
  1360.             return (0);
  1361.  
  1362.         case IDM_SAVEAS:
  1363.             if (fEditing)
  1364.                 if (ProcessCard (hwndButton[3]))
  1365.                     return (0);
  1366.  
  1367.             if (!WinDlgBox (HWND_DESKTOP, hwnd, SaveAsDlgProc, NULL,
  1368.                            IDD_SAVEAS, NULL))
  1369.                 return (0);
  1370.  
  1371.             if ((usResult = SaveFile (szCurrentFile)) != 0)
  1372.  
  1373.                 switch (usResult) {
  1374.  
  1375.                 case (1):
  1376.                     strcpy (szTextBuffer, szCurrentFile);
  1377.                     strcat (szTextBuffer, szErrMsg8);
  1378.                     WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  1379.                                    NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1380.                     break;
  1381.  
  1382.                 case (2):
  1383.                     DosDelete (szCurrentFile, 0L);
  1384.                     WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg7,
  1385.                                    NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1386.                     break;
  1387.                 }
  1388.  
  1389.             PackBuffer ();
  1390.             return (0);
  1391.  
  1392.         case IDM_EXIT:
  1393.             WinSendMsg (hwnd, WM_CLOSE, 0L, 0L);
  1394.             return (0);
  1395.  
  1396.         case IDM_CUT:
  1397.             WinSendMsg (hwndMLE, MLM_CUT, 0L, 0L);
  1398.             return (0);
  1399.  
  1400.         case IDM_COPY:
  1401.             WinSendMsg (hwndMLE, MLM_COPY, 0L, 0L);
  1402.             return (0);
  1403.  
  1404.         case IDM_PASTE:
  1405.             if (fEditing)
  1406.                 WinSendMsg (hwndMLE, MLM_PASTE, 0L, 0L);
  1407.             else
  1408.                 WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg10,
  1409.                                NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1410.             return (0);
  1411.  
  1412.         case IDM_CLEAR:
  1413.             WinSendMsg (hwndMLE, MLM_CLEAR, 0L, 0L);
  1414.             return (0);
  1415.  
  1416.         case IDM_DELCARD:
  1417.             if (fEditing)
  1418.                 if (ProcessCard (hwndButton[3]))
  1419.                     return (0);
  1420.  
  1421.             fCardInBuffer = TRUE;
  1422.             usDeletedTextLength = usCardLength[CardNo];
  1423.  
  1424.             if (usCardLength[CardNo] != 0)
  1425.                 for (i=0; i<usDeletedTextLength; i++)
  1426.                     chDeleteBuffer[i] = *(chBufferPtr + usCardOffset[CardNo] + i);
  1427.  
  1428.             if (CardCount == 1)
  1429.                 usCardLength[0] = usCardOffset[0] = 0;
  1430.             else
  1431.                 if (CardNo == --CardCount)
  1432.                     CardNo = 0;
  1433.                 else
  1434.                     for (i=CardNo; i<CardCount; i++) {
  1435.                         usCardOffset[i] = usCardOffset[i+1];
  1436.                         usCardLength[i] = usCardLength[i+1];
  1437.                     }
  1438.  
  1439.             UpdateMLE ();
  1440.             return (0);            
  1441.  
  1442.         case IDM_UNDODELETE:
  1443.             if (CardCount == 999) {
  1444.                 WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg3,
  1445.                                NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1446.                 return (0);
  1447.             }
  1448.  
  1449.             if (fEditing)
  1450.                 if (ProcessCard (hwndButton[3]))
  1451.                     return (0);
  1452.  
  1453.             if (usDeletedTextLength > (0xFFFE - usTopOffset)) {
  1454.                 WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg11,
  1455.                                NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1456.                 return (0);
  1457.             }
  1458.  
  1459.             for (j=CardCount-1; j>=CardNo; j--) {
  1460.                 usCardOffset[j+1] = usCardOffset[j];
  1461.                 usCardLength[j+1] = usCardLength[j];
  1462.             }
  1463.  
  1464.             usCardOffset[CardNo] = usTopOffset;
  1465.             usCardLength[CardNo] = usDeletedTextLength;
  1466.             usTopOffset += usDeletedTextLength;
  1467.             CardCount++;
  1468.  
  1469.             if (usCardLength[CardNo] != 0)
  1470.                 for (i=0; i<usDeletedTextLength; i++)
  1471.                     *(chBufferPtr + usCardOffset[CardNo] + i) = chDeleteBuffer[i];
  1472.  
  1473.             UpdateMLE ();
  1474.             return (0);
  1475.  
  1476.         case IDM_INSERTCARD:
  1477.             if (CardCount == 999) {
  1478.                 WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg3,
  1479.                                NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1480.                 return (0);
  1481.             }
  1482.  
  1483.             if (fEditing)
  1484.                 if (ProcessCard (hwndButton[3]))
  1485.                     return (0);
  1486.  
  1487.             for (j=CardCount-1; j>=CardNo; j--) {
  1488.                 usCardOffset[j+1] = usCardOffset[j];
  1489.                 usCardLength[j+1] = usCardLength[j];
  1490.             }
  1491.  
  1492.             usCardOffset[CardNo] = 0;
  1493.             usCardLength[CardNo] = 0;
  1494.             CardCount++;
  1495.             UpdateMLE ();
  1496.             return (0);
  1497.  
  1498.         case IDM_SEARCH:
  1499.             if (fEditing)
  1500.                 if (ProcessCard (hwndButton[0]))
  1501.                     return (0);
  1502.  
  1503.             if (WinDlgBox (HWND_DESKTOP, hwnd, SearchDlgProc, NULL,
  1504.                            IDD_SEARCH, NULL)) {
  1505.  
  1506.                 if (strlen (szSearchText) != 0) {
  1507.                     if (FindNextCard() != 0) {
  1508.                         UpdateMLE ();
  1509.                         WinSetFocus (HWND_DESKTOP, hwndButton[1]);
  1510.                     }
  1511.                     else {
  1512.                         strcpy (szTextBuffer, "\"");
  1513.                         strcat (szTextBuffer, szSearchText);
  1514.                         strcat (szTextBuffer, "\"");
  1515.                         strcat (szTextBuffer, szErrMsg4);
  1516.                         WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  1517.                             NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1518.                     }
  1519.                 }
  1520.             }
  1521.  
  1522.             return (0);
  1523.  
  1524.         case IDM_FINDPREV:
  1525.             if (fEditing)
  1526.                 if (ProcessCard (hwndButton[0]))
  1527.                     return (0);
  1528.  
  1529.             if (FindPrevCard() != 0)
  1530.                 UpdateMLE ();
  1531.             else {
  1532.                 strcpy (szTextBuffer, "\"");
  1533.                 strcat (szTextBuffer, szSearchText);
  1534.                 strcat (szTextBuffer, "\"");
  1535.                 strcat (szTextBuffer, szErrMsg4);
  1536.                 WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  1537.                                NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1538.             }
  1539.  
  1540.             return (0);
  1541.  
  1542.         case IDM_FINDNEXT:
  1543.             if (fEditing)
  1544.                 if (ProcessCard (hwndButton[0]))
  1545.                     return (0);
  1546.  
  1547.             if (FindNextCard() != 0)
  1548.                 UpdateMLE ();
  1549.             else {
  1550.                 strcpy (szTextBuffer, "\"");
  1551.                 strcat (szTextBuffer, szSearchText);
  1552.                 strcat (szTextBuffer, "\"");
  1553.                 strcat (szTextBuffer, szErrMsg4);
  1554.                 WinMessageBox (HWND_DESKTOP, hwndClient, szTextBuffer,
  1555.                                NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1556.             }
  1557.  
  1558.             return (0);
  1559.  
  1560.         case IDM_GOTO:
  1561.             if (fEditing)
  1562.                 if (ProcessCard (hwndButton[3]))
  1563.                     return (0);
  1564.  
  1565.             if (WinDlgBox (HWND_DESKTOP, hwnd, GotoDlgProc,
  1566.                 NULL, IDD_GOTO, NULL))
  1567.                 UpdateMLE ();
  1568.  
  1569.             return (0);
  1570.  
  1571.         case IDM_DIAL:
  1572.             if (fEditing)
  1573.                 if (ProcessCard (hwndButton[1]))
  1574.                     return (0);
  1575.  
  1576.             ulTextLength = (ULONG) WinSendMsg (hwndMLE, MLM_QUERYSEL,
  1577.                                     (MPARAM) MLFQS_MINMAXSEL, 0L);
  1578.  
  1579.             if ((ulTextLength >> 16) - (ulTextLength & 0xFFFF) >
  1580.                 sizeof (achBuffer)) {
  1581.                 WinMessageBox (HWND_DESKTOP, hwndClient, szErrMsg15,
  1582.                                NULL, NULL, MB_ICONEXCLAMATION | MB_OK);
  1583.                 WinSetFocus (HWND_DESKTOP, hwndMLE);
  1584.                 return (0);
  1585.             }
  1586.  
  1587.             ulBytesCopied = (ULONG) WinSendMsg (hwndMLE, MLM_QUERYSELTEXT,
  1588.                                         MPFROMP (achBuffer), 0L);
  1589.  
  1590.             if (ulBytesCopied > 1) {
  1591.                 CopyToList (strlen (achBuffer), szPhoneNumber, achBuffer);
  1592.                 DialPhone (szPhoneNumber);
  1593.                 WinSetFocus (HWND_DESKTOP, hwndMLE);
  1594.             }
  1595.             else {
  1596.                 usPhoneCount = BuildPhoneList (szPhoneList);
  1597.                 if (WinDlgBox (HWND_DESKTOP, hwnd, DialDlgProc, NULL, IDD_DIAL, NULL))
  1598.                     DialPhone (szPhoneNumber);
  1599.             }
  1600.  
  1601.             return (0);
  1602.  
  1603.         case IDM_MEMORY:
  1604.             WinDlgBox (HWND_DESKTOP, hwnd, StatusDlgProc,
  1605.                        NULL, IDD_MEMORY, NULL);
  1606.             return (0);
  1607.  
  1608.         case IDM_SETTINGS:
  1609.             WinDlgBox (HWND_DESKTOP, hwnd, ConfigDlgProc,
  1610.                        NULL, IDD_SETTINGS, NULL);
  1611.             return (0);
  1612.  
  1613.         case IDM_ABOUT:
  1614.             WinDlgBox (HWND_DESKTOP, hwnd, AboutDlgProc,
  1615.                        NULL, IDD_ABOUT, NULL);
  1616.             return (0);
  1617.         }
  1618.         break;
  1619.  
  1620.     case WM_CONTROL:
  1621.  
  1622.         switch (SHORT2FROMMP (mp1)) {
  1623.  
  1624.         case MLN_SETFOCUS:
  1625.             fEditing = TRUE;
  1626.             return (0);
  1627.         }
  1628.         break;
  1629.     }
  1630.  
  1631.     return (WinDefWindowProc (hwnd, msg, mp1, mp2));
  1632. }
  1633.  
  1634. /*---------------------------------------------------------------------------
  1635.     AboutDlgProc processes messages sent to the About dialog box.
  1636. ---------------------------------------------------------------------------*/
  1637.  
  1638. MRESULT EXPENTRY AboutDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1639. {
  1640.     switch (msg) {
  1641.  
  1642.     case WM_COMMAND:
  1643.  
  1644.         switch (COMMANDMSG(&msg)->cmd) {
  1645.  
  1646.         case DID_OK:
  1647.         case DID_CANCEL:
  1648.             WinDismissDlg (hwnd, TRUE);
  1649.             return (0);
  1650.         }
  1651.         break;
  1652.     }
  1653.     return (WinDefDlgProc (hwnd, msg, mp1, mp2));
  1654. }
  1655.  
  1656. /*---------------------------------------------------------------------------
  1657.     SearchDlgProc processes messages sent to the Search dialog box.
  1658. ---------------------------------------------------------------------------*/
  1659.  
  1660. MRESULT EXPENTRY SearchDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1661. {
  1662.     switch (msg) {
  1663.  
  1664.     case WM_INITDLG:
  1665.         WinSendDlgItemMsg (hwnd, IDD_SEARCHTEXT, EM_SETTEXTLIMIT,
  1666.                         MPFROM2SHORT (40, 0), NULL);
  1667.         WinSetDlgItemText (hwnd, IDD_SEARCHTEXT, szSearchText);
  1668.         WinSendDlgItemMsg (hwnd, IDD_CHECKCASE, BM_SETCHECK,
  1669.                            MPFROM2SHORT (fCaseSensitive, 0), NULL);
  1670.  
  1671.         return (0);
  1672.  
  1673.     case WM_CONTROL:
  1674.         if (SHORT1FROMMP (mp1) == IDD_CHECKCASE)
  1675.             fCaseSensitive = fCaseSensitive ? FALSE : TRUE;
  1676.         return (0);
  1677.  
  1678.     case WM_COMMAND:
  1679.  
  1680.         switch (COMMANDMSG(&msg)->cmd) {
  1681.  
  1682.         case DID_OK:
  1683.             WinQueryDlgItemText (hwnd, IDD_SEARCHTEXT, 40, szSearchText);
  1684.             WinDismissDlg (hwnd, TRUE);
  1685.             return (0);
  1686.  
  1687.         case DID_CANCEL:
  1688.             WinDismissDlg (hwnd, FALSE);
  1689.             return (0);
  1690.         }
  1691.         break;
  1692.     }
  1693.     return (WinDefDlgProc (hwnd, msg, mp1, mp2));
  1694. }
  1695.  
  1696. /*---------------------------------------------------------------------------
  1697.     SaveAsDlgProc processes messages sent to the Save As dialog box.
  1698. ---------------------------------------------------------------------------*/
  1699.  
  1700. MRESULT EXPENTRY SaveAsDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1701. {
  1702.     SHORT        Index;
  1703.     static CHAR    szPath[255];
  1704.  
  1705.     switch (msg) {
  1706.  
  1707.     case WM_INITDLG:
  1708.         FillDriveListBox (hwnd, IDD_DRIVELIST2);
  1709.         FillDirListBox (hwnd, IDD_DIRLIST2);
  1710.         WinSendDlgItemMsg (hwnd, IDD_NEWFILENAME, EM_SETTEXTLIMIT,
  1711.                            MPFROM2SHORT (254, 0), NULL);
  1712.         ExtractFileName (szCurrentFile, szPath);
  1713.         WinSetDlgItemText (hwnd, IDD_NEWFILENAME, szPath);
  1714.         WinSendMsg (WinWindowFromID (hwnd, IDD_NEWFILENAME),
  1715.                     EM_SETSEL, MPFROM2SHORT (0, 255), 0L);
  1716.         MakePath (szPath, sizeof szPath);
  1717.         WinSetDlgItemText (hwnd, IDD_DIRECTORY2, szPath);
  1718.         return (0);
  1719.  
  1720.     case WM_CONTROL:
  1721.         switch (SHORT1FROMMP (mp1)) {
  1722.  
  1723.         case IDD_DRIVELIST2:
  1724.             switch (SHORT2FROMMP (mp1)) {
  1725.  
  1726.             case LN_ENTER:
  1727.                 Index = (SHORT) WinSendDlgItemMsg (hwnd, IDD_DRIVELIST2,
  1728.                                                     LM_QUERYSELECTION, 0L, 0L);
  1729.  
  1730.                 WinSendDlgItemMsg (hwnd, IDD_DRIVELIST2, LM_QUERYITEMTEXT,
  1731.                                    MPFROM2SHORT (Index, sizeof (szPath)),
  1732.                                    MPFROMP (szPath));
  1733.  
  1734.                 DosSelectDisk ((USHORT) szPath[1] - 0x40);
  1735.                 MakePath (szPath, sizeof szPath);
  1736.                 WinSetDlgItemText (hwnd, IDD_DIRECTORY2, szPath);
  1737.                 FillDirListBox (hwnd, IDD_DIRLIST2);
  1738.                 return (0);
  1739.             }
  1740.             break;
  1741.  
  1742.         case IDD_DIRLIST2:
  1743.             switch (SHORT2FROMMP (mp1)) {
  1744.  
  1745.             case LN_ENTER:
  1746.                 Index = (SHORT) WinSendDlgItemMsg (hwnd, IDD_DIRLIST2,
  1747.                                                    LM_QUERYSELECTION, 0L, 0L);
  1748.  
  1749.                 WinSendDlgItemMsg (hwnd, IDD_DIRLIST2, LM_QUERYITEMTEXT,
  1750.                                    MPFROM2SHORT (Index, sizeof (szPath)),
  1751.                                    MPFROMP (szPath));
  1752.  
  1753.                 DosChDir (szPath, 0L);
  1754.                 MakePath (szPath, sizeof szPath);
  1755.                 WinSetDlgItemText (hwnd, IDD_DIRECTORY2, szPath);
  1756.                 FillDirListBox (hwnd, IDD_DIRLIST2);
  1757.                 return (0);
  1758.             }
  1759.             break;
  1760.         }
  1761.         break;
  1762.  
  1763.     case WM_COMMAND:
  1764.         switch (COMMANDMSG (&msg) -> cmd) {
  1765.  
  1766.         case DID_OK:
  1767.             WinQueryDlgItemText (hwnd, IDD_NEWFILENAME,
  1768.                                  sizeof (szPath), szPath);
  1769.             MakeQFN (szPath, szCurrentFile, sizeof szCurrentFile);
  1770.             WinDismissDlg (hwnd, TRUE);
  1771.             return (0);
  1772.  
  1773.         case DID_CANCEL:
  1774.             WinDismissDlg (hwnd, FALSE);
  1775.             return (0);
  1776.         }
  1777.         break;
  1778.     }
  1779.     return (WinDefDlgProc (hwnd, msg, mp1, mp2));
  1780. }
  1781.  
  1782. /*---------------------------------------------------------------------------
  1783.     OpenDlgProc processes messages sent to the File Open dialog box.
  1784. ---------------------------------------------------------------------------*/
  1785.  
  1786. MRESULT EXPENTRY OpenDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1787. {
  1788.     SHORT        Index;
  1789.     static CHAR szPath[255];
  1790.     static CHAR    szFileName[255];
  1791.  
  1792.     switch (msg) {
  1793.  
  1794.     case WM_INITDLG:
  1795.         FillDriveListBox (hwnd, IDD_DRIVELIST);
  1796.         FillDirListBox (hwnd, IDD_DIRLIST);
  1797.         FillFileListBox (hwnd, IDD_FILELIST);
  1798.         WinSendDlgItemMsg (hwnd, IDD_FILENAME, EM_SETTEXTLIMIT,
  1799.                            MPFROM2SHORT (254, 0), NULL);
  1800.         MakePath (szPath, sizeof szPath);
  1801.         WinSetDlgItemText (hwnd, IDD_DIRECTORY, szPath);
  1802.         return (0);
  1803.  
  1804.     case WM_CONTROL:
  1805.         switch (SHORT1FROMMP (mp1)) {
  1806.  
  1807.         case IDD_DRIVELIST:
  1808.             switch (SHORT2FROMMP (mp1)) {
  1809.  
  1810.             case LN_ENTER:
  1811.                 Index = (SHORT) WinSendDlgItemMsg (hwnd, IDD_DRIVELIST,
  1812.                                                    LM_QUERYSELECTION, 0L, 0L);
  1813.  
  1814.                 WinSendDlgItemMsg (hwnd, IDD_DRIVELIST, LM_QUERYITEMTEXT,
  1815.                                    MPFROM2SHORT (Index, sizeof (szPath)),
  1816.                                    MPFROMP (szPath));
  1817.  
  1818.                 DosSelectDisk ((USHORT) szPath[1] - 0x40);
  1819.                 MakePath (szPath, sizeof szPath);
  1820.                 WinSetDlgItemText (hwnd, IDD_DIRECTORY, szPath);
  1821.                 FillDirListBox (hwnd, IDD_DIRLIST);
  1822.                 FillFileListBox (hwnd, IDD_FILELIST);
  1823.                 return (0);
  1824.             }
  1825.             break;
  1826.  
  1827.         case IDD_DIRLIST:
  1828.             switch (SHORT2FROMMP (mp1)) {
  1829.  
  1830.             case LN_ENTER:
  1831.                 Index = (SHORT) WinSendDlgItemMsg (hwnd, IDD_DIRLIST,
  1832.                                                    LM_QUERYSELECTION, 0L, 0L);
  1833.  
  1834.                 WinSendDlgItemMsg (hwnd, IDD_DIRLIST, LM_QUERYITEMTEXT,
  1835.                                    MPFROM2SHORT (Index, sizeof (szPath)),
  1836.                                    MPFROMP (szPath));
  1837.  
  1838.                 DosChDir (szPath, 0L);
  1839.                 MakePath (szPath, sizeof szPath);
  1840.                 WinSetDlgItemText (hwnd, IDD_DIRECTORY, szPath);
  1841.                 FillDirListBox (hwnd, IDD_DIRLIST);
  1842.                 FillFileListBox (hwnd, IDD_FILELIST);
  1843.                 return (0);
  1844.             }
  1845.             break;
  1846.  
  1847.         case IDD_FILELIST:
  1848.             switch (SHORT2FROMMP (mp1)) {
  1849.  
  1850.             case LN_SELECT:
  1851.                 Index = (SHORT) WinSendDlgItemMsg (hwnd, IDD_FILELIST,
  1852.                                                    LM_QUERYSELECTION, 0L, 0L);
  1853.  
  1854.                 WinSendDlgItemMsg (hwnd, IDD_FILELIST, LM_QUERYITEMTEXT,
  1855.                                    MPFROM2SHORT (Index, sizeof (szFileName)),
  1856.                                    MPFROMP (szFileName));
  1857.  
  1858.                 WinSetDlgItemText (hwnd, IDD_FILENAME, szFileName);
  1859.                 return (0);
  1860.  
  1861.             case LN_ENTER:
  1862.                 MakeQFN (szFileName, szCurrentFile, sizeof szCurrentFile);
  1863.                 WinDismissDlg (hwnd, TRUE);
  1864.                 return (0);
  1865.             }
  1866.             break;
  1867.         }
  1868.         break;
  1869.  
  1870.     case WM_COMMAND:
  1871.         switch (COMMANDMSG(&msg)->cmd) {
  1872.  
  1873.         case DID_OK:
  1874.             WinQueryDlgItemText (hwnd, IDD_FILENAME, sizeof (szFileName),
  1875.                                  szFileName);
  1876.             MakeQFN (szFileName, szCurrentFile, sizeof szCurrentFile);
  1877.             WinDismissDlg (hwnd, TRUE);
  1878.             return (0);
  1879.  
  1880.         case DID_CANCEL:
  1881.             WinDismissDlg (hwnd, FALSE);
  1882.             return (0);
  1883.         }
  1884.         break;
  1885.     }
  1886.     return (WinDefDlgProc (hwnd, msg, mp1, mp2));
  1887. }
  1888.  
  1889. /*---------------------------------------------------------------------------
  1890.     ConfigDlgProc processes messages sent to the Settings dialog box.
  1891. ---------------------------------------------------------------------------*/
  1892.  
  1893. MRESULT EXPENTRY ConfigDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1894. {
  1895.     static struct CommParms LclParms;
  1896.     static BOOL fSaveSettings = TRUE;
  1897.  
  1898.     switch (msg) {
  1899.  
  1900.     case WM_INITDLG:
  1901.         LclParms.BaudRate = GblParms.BaudRate;
  1902.         LclParms.COMPort = GblParms.COMPort;
  1903.         LclParms.Parity = GblParms.Parity;
  1904.         LclParms.DataBits = GblParms.DataBits;
  1905.         LclParms.StopBits = GblParms.StopBits;
  1906.  
  1907.         WinSendDlgItemMsg (hwnd, LclParms.BaudRate + IDD_BAUDRATE, BM_SETCHECK,
  1908.                            MPFROM2SHORT (TRUE, 0), NULL);
  1909.         WinSendDlgItemMsg (hwnd, LclParms.COMPort + IDD_COMPORT, BM_SETCHECK,
  1910.                            MPFROM2SHORT (TRUE, 0), NULL);
  1911.         WinSendDlgItemMsg (hwnd, LclParms.Parity + IDD_PARITY, BM_SETCHECK,
  1912.                            MPFROM2SHORT (TRUE, 0), NULL);
  1913.         WinSendDlgItemMsg (hwnd, LclParms.DataBits + IDD_DATABITS, BM_SETCHECK,
  1914.                            MPFROM2SHORT (TRUE, 0), NULL);
  1915.         WinSendDlgItemMsg (hwnd, LclParms.StopBits + IDD_STOPBITS, BM_SETCHECK,
  1916.                            MPFROM2SHORT (TRUE, 0), NULL);
  1917.  
  1918.         WinSendDlgItemMsg (hwnd, IDD_DIALTEXT, EM_SETTEXTLIMIT,
  1919.                            MPFROM2SHORT (16, 0), NULL);
  1920.         WinSetDlgItemText (hwnd, IDD_DIALTEXT, szDialCmd);
  1921.  
  1922.         WinSendDlgItemMsg (hwnd, IDD_HANGUPTEXT, EM_SETTEXTLIMIT,
  1923.                            MPFROM2SHORT (16, 0), NULL);
  1924.         WinSetDlgItemText (hwnd, IDD_HANGUPTEXT, szHangUpCmd);
  1925.  
  1926.         WinSendDlgItemMsg (hwnd, IDD_DEFDATAFILE, EM_SETTEXTLIMIT,
  1927.                            MPFROM2SHORT (128, 0), NULL);
  1928.         WinSetDlgItemText (hwnd, IDD_DEFDATAFILE, szDefDataFile);
  1929.  
  1930.         WinSendDlgItemMsg (hwnd, IDD_DIALPREFIX, EM_SETTEXTLIMIT,
  1931.                            MPFROM2SHORT (6, 0), NULL);
  1932.         WinSetDlgItemText (hwnd, IDD_DIALPREFIX, szDialPrefix);
  1933.  
  1934.         WinSendDlgItemMsg (hwnd, IDD_CHECKSAVE, BM_SETCHECK,
  1935.                            MPFROM2SHORT (fSaveSettings, 0), NULL);
  1936.  
  1937.         WinSetFocus (HWND_DESKTOP, WinWindowFromID (hwnd, LclParms.BaudRate + IDD_BAUDRATE));
  1938.         return (1);
  1939.  
  1940.     case WM_CONTROL:
  1941.         if ((SHORT1FROMMP (mp1) >= IDD_BAUDRATE) &&
  1942.             (SHORT1FROMMP (mp1) < IDD_COMPORT))
  1943.             LclParms.BaudRate = SHORT1FROMMP (mp1) - IDD_BAUDRATE;
  1944.  
  1945.         else if ((SHORT1FROMMP (mp1) >= IDD_COMPORT) &&
  1946.             (SHORT1FROMMP (mp1) < IDD_PARITY))
  1947.             LclParms.COMPort = SHORT1FROMMP (mp1) - IDD_COMPORT;
  1948.  
  1949.         else if ((SHORT1FROMMP (mp1) >= IDD_PARITY) &&
  1950.             (SHORT1FROMMP (mp1) < IDD_DATABITS))
  1951.             LclParms.Parity = SHORT1FROMMP (mp1) - IDD_PARITY;
  1952.  
  1953.         else if ((SHORT1FROMMP (mp1) >= IDD_DATABITS) &&
  1954.             (SHORT1FROMMP (mp1) < IDD_STOPBITS))
  1955.             LclParms.DataBits = SHORT1FROMMP (mp1) - IDD_DATABITS;
  1956.  
  1957.         else if ((SHORT1FROMMP (mp1) >= IDD_STOPBITS) &&
  1958.             (SHORT1FROMMP (mp1) < IDD_STOPBITS + 2))
  1959.             LclParms.StopBits = SHORT1FROMMP (mp1) - IDD_STOPBITS;
  1960.  
  1961.         else if (SHORT1FROMMP (mp1) == IDD_CHECKSAVE)
  1962.             fSaveSettings = fSaveSettings ? FALSE : TRUE;
  1963.  
  1964.         return (0);
  1965.  
  1966.     case WM_COMMAND:
  1967.  
  1968.         switch (COMMANDMSG(&msg)->cmd) {
  1969.  
  1970.         case DID_OK:
  1971.             WinQueryDlgItemText (hwnd, IDD_DIALTEXT, 40, szDialCmd);
  1972.             WinQueryDlgItemText (hwnd, IDD_HANGUPTEXT, 40, szHangUpCmd);
  1973.             WinQueryDlgItemText (hwnd, IDD_DEFDATAFILE, 128, szDefDataFile);
  1974.             WinQueryDlgItemText (hwnd, IDD_DIALPREFIX, 40, szDialPrefix);
  1975.  
  1976.             strupr (szDefDataFile);
  1977.  
  1978.             GblParms.BaudRate = LclParms.BaudRate;
  1979.             GblParms.COMPort = LclParms.COMPort;
  1980.             GblParms.Parity = LclParms.Parity;
  1981.             GblParms.DataBits = LclParms.DataBits;
  1982.             GblParms.StopBits = LclParms.StopBits;
  1983.  
  1984.             if (fSaveSettings) {
  1985.                 WinWriteProfileData (hab, szAppName, szKeyName1,
  1986.                                      &GblParms, sizeof (GblParms));
  1987.                 WinWriteProfileString (hab, szAppName, szKeyName2, szDialCmd);
  1988.                 WinWriteProfileString (hab, szAppName, szKeyName3, szHangUpCmd);
  1989.                 WinWriteProfileString (hab, szAppName, szKeyName4, szDefDataFile);
  1990.                 WinWriteProfileString (hab, szAppName, szKeyName5, szDialPrefix);
  1991.             }
  1992.  
  1993.             WinDismissDlg (hwnd, TRUE);
  1994.             return (0);
  1995.  
  1996.         case DID_CANCEL:
  1997.             WinDismissDlg (hwnd, FALSE);
  1998.             return (0);
  1999.         }
  2000.         break;
  2001.     }
  2002.     return (WinDefDlgProc (hwnd, msg, mp1, mp2));
  2003. }
  2004.  
  2005. /*---------------------------------------------------------------------------
  2006.     StatusDlgProc processes messages sent to the Memory dialog box.
  2007. ---------------------------------------------------------------------------*/
  2008.  
  2009. MRESULT EXPENTRY StatusDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  2010. {
  2011.     CHAR    szBuffer[10];
  2012.     ULONG    ulBytesFree, ulBytesAvail, ulBytesUsed = 0;
  2013.     USHORT    i;
  2014.  
  2015.     switch (msg) {
  2016.  
  2017.     case WM_INITDLG:
  2018.         for (i=0; i<CardCount; i++)
  2019.             ulBytesUsed += (ULONG) usCardLength[i];
  2020.         ulBytesFree = 0xFFFE - ulBytesUsed;
  2021.         ulBytesAvail = 0xFFFE - (ULONG) usTopOffset;
  2022.  
  2023.         ultoa (ulBytesUsed, szBuffer, 10);
  2024.         WinSetDlgItemText (hwnd, IDD_BYTESUSED, szBuffer);
  2025.         ultoa (ulBytesFree, szBuffer, 10);
  2026.         WinSetDlgItemText (hwnd, IDD_BYTESFREE, szBuffer);
  2027.         ultoa (ulBytesAvail, szBuffer, 10);
  2028.         WinSetDlgItemText (hwnd, IDD_BYTESAVAIL, szBuffer);
  2029.         return (0);
  2030.  
  2031.     case WM_COMMAND:
  2032.  
  2033.         switch (COMMANDMSG (&msg) -> cmd) {
  2034.             case DID_OK:
  2035.             case DID_CANCEL:
  2036.                 WinDismissDlg (hwnd, TRUE);
  2037.                 return (0);
  2038.         }
  2039.         break;
  2040.     }
  2041.     return (WinDefDlgProc (hwnd, msg, mp1, mp2));
  2042. }
  2043.  
  2044. /*---------------------------------------------------------------------------
  2045.     GotoDlgProc processes messages sent to the Go To dialog box.
  2046. ---------------------------------------------------------------------------*/
  2047.  
  2048. MRESULT EXPENTRY GotoDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  2049. {
  2050.     CHAR    szBuffer[5];
  2051.     LONG    lNewCard;
  2052.  
  2053.     switch (msg) {
  2054.  
  2055.     case WM_INITDLG:
  2056.         WinSendDlgItemMsg (hwnd, IDD_CARDNO, EM_SETTEXTLIMIT,
  2057.                            MPFROM2SHORT (sizeof (szBuffer) - 1, 0), NULL);
  2058.         return (0);
  2059.  
  2060.     case WM_COMMAND:
  2061.  
  2062.         switch (COMMANDMSG(&msg)->cmd) {
  2063.  
  2064.         case DID_OK:
  2065.             WinQueryDlgItemText (hwnd, IDD_CARDNO, sizeof szBuffer, szBuffer);
  2066.  
  2067.             lNewCard = atol (szBuffer);
  2068.             if ((lNewCard > 0) && (lNewCard <= CardCount)) {
  2069.                 CardNo = (SHORT) lNewCard - 1;
  2070.                 WinDismissDlg (hwnd, TRUE);
  2071.             }
  2072.             else
  2073.                 WinDismissDlg (hwnd, FALSE);
  2074.  
  2075.             return (0);
  2076.  
  2077.         case DID_CANCEL:
  2078.             WinDismissDlg (hwnd, FALSE);
  2079.             return (0);
  2080.         }
  2081.         break;
  2082.     }
  2083.     return (WinDefDlgProc (hwnd, msg, mp1, mp2));
  2084. }
  2085.  
  2086. /*---------------------------------------------------------------------------
  2087.     DialDlgProc processes messages sent to the Dial dialog box.
  2088. ---------------------------------------------------------------------------*/
  2089.  
  2090. MRESULT EXPENTRY DialDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  2091. {
  2092.     static USHORT usIndex;
  2093.  
  2094.     switch (msg) {
  2095.  
  2096.     case WM_INITDLG:
  2097.         WinSendDlgItemMsg (hwnd, IDD_PHONENO, EM_SETTEXTLIMIT,
  2098.                         MPFROM2SHORT (16, 0), NULL);
  2099.  
  2100.         if (usPhoneCount != 0) {
  2101.             WinSetDlgItemText (hwnd, IDD_PHONENO, szPhoneList);
  2102.             WinSendMsg (WinWindowFromID (hwnd, IDD_PHONENO),
  2103.                         EM_SETSEL, MPFROM2SHORT (0, 99), 0L);
  2104.         }
  2105.  
  2106.         WinEnableWindow (WinWindowFromID (hwnd, DID_NEXT),
  2107.                          (usPhoneCount > 1) ? TRUE : FALSE);
  2108.  
  2109.         usIndex = 0;
  2110.         return (0);
  2111.  
  2112.     case WM_COMMAND:
  2113.  
  2114.         switch (COMMANDMSG(&msg)->cmd) {
  2115.  
  2116.         case DID_OK:
  2117.             WinQueryDlgItemText (hwnd, IDD_PHONENO, 17, szPhoneNumber);
  2118.             WinDismissDlg (hwnd, TRUE);
  2119.             return (0);
  2120.  
  2121.         case DID_CANCEL:
  2122.             WinDismissDlg (hwnd, FALSE);
  2123.             return (0);
  2124.  
  2125.         case DID_NEXT:
  2126.             usIndex = (usIndex == usPhoneCount-1) ? 0 : usIndex + 1;
  2127.             WinSetDlgItemText (hwnd, IDD_PHONENO, &szPhoneList[usIndex*20]);
  2128.             WinSendMsg (WinWindowFromID (hwnd, IDD_PHONENO),
  2129.                         EM_SETSEL, MPFROM2SHORT (0, 20), 0L);
  2130.             WinSetFocus (HWND_DESKTOP, WinWindowFromID (hwnd, IDD_PHONENO));
  2131.             return (0);
  2132.         }
  2133.         break;
  2134.     }
  2135.     return (WinDefDlgProc (hwnd, msg, mp1, mp2));
  2136. }
  2137.