home *** CD-ROM | disk | FTP | other *** search
/ Total C++ 2 / TOTALCTWO.iso / borland / 32addres.pak / ADR_MAIN.C < prev    next >
C/C++ Source or Header  |  1997-05-06  |  76KB  |  2,314 lines

  1. // BDE32 3.x - (C) Copyright 1996 by Borland International
  2.  
  3. #include "address.h"
  4.  
  5. static bReset = FALSE;
  6.  
  7. //=================================================================
  8. //  Name:   WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  9. //
  10. //  Input:  hInstance - The handle that represents the applications
  11. //                      unique instance ID.
  12. //          hPrevInstance - Indicates if this is the first instance
  13. //                          of the app.
  14. //          lpCmdLine - Command line parameters (up to the app to parse).
  15. //          nCmdShow - TRUE = Show as non-icon application
  16. //
  17. //  Return: ???
  18. //
  19. //  Description:    This is the application entry point for the
  20. //                   Windows driver. It will set up the app, init
  21. //                  the Windows instance, process all event driven
  22. //                  messages, and clean up the suite prior to
  23. //                  returning to Windows.
  24. //=================================================================
  25. #ifdef __BORLANDC__
  26. #pragma argsused
  27. #endif
  28. int PASCAL
  29. WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
  30.          int nCmdShow)
  31. {
  32.     MSG     msg;
  33.  
  34. #ifndef WIN32
  35.     lpCmdLine = lpCmdLine;
  36.     nCmdShow = nCmdShow;
  37. #endif
  38.  
  39.     // Make this a single instance program
  40.     if (hPrevInstance)
  41.     {
  42.         MessageBox(GetFocus(), "This application is already running!",
  43.                    "AddressBook Manager", MB_OK | MB_ICONHAND);
  44.         return(FALSE);
  45.     }
  46.  
  47.     // Register CTL3D
  48.     Ctl3dRegister(hInstance);
  49.     Ctl3dAutoSubclass(hInstance);
  50.     Ctl3dColorChange();
  51.  
  52.     // Start the application, and set the main dialog to no show until
  53.     // everything is setup.
  54.     hInst = hInstance;
  55.     if (InitApp(SW_HIDE) == FALSE)
  56.     {
  57.         return(FALSE);
  58.     }
  59.  
  60.     // Process all event driven messages...
  61.     while (GetMessage(&msg, NULL, NULL, NULL))
  62.     {
  63.         if (!IsDialogMessage(hMainWnd, &msg))
  64.         {
  65.             TranslateMessage(&msg);
  66.             DispatchMessage(&msg);
  67.         }
  68.     }
  69.  
  70.     // Unregister CTL3D
  71.     Ctl3dUnregister(hInstance);
  72.     
  73.     return msg.wParam;
  74. }
  75.  
  76. //====================================================================
  77. //  Name:   InitApp();
  78. //
  79. //  Input:  None.
  80. //
  81. //  Return: TRUE - Init worked
  82. //          FALSE - Init failed
  83. //
  84. //  Description:    Create the application window & init any default
  85. //  of the main window.
  86. //====================================================================
  87. BOOL
  88. InitApp (int nCmdShow)
  89. {
  90.     WNDCLASS    wc;
  91.     unsigned    uCount;
  92.  
  93.     // Make certain to allocate enough space for the message.
  94.     char        szMessage[(DBIMAXMSGLEN * 2) + 1];
  95.     char        szRelativeTblDirectory[DBIMAXPATHLEN+1];
  96.  
  97.     // Init the application & create the needed windows
  98.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  99.     wc.lpfnWndProc   = MainWndProc;
  100.     wc.cbClsExtra    = 0;
  101.     wc.cbWndExtra    = DLGWINDOWEXTRA;
  102.     wc.hInstance     = hInst;
  103.     wc.hIcon         = LoadIcon(hInst, MAKEINTRESOURCE(9999));
  104.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  105.     wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  106.     wc.lpszMenuName  = NULL;
  107.     wc.lpszClassName = "MainWindowClass";
  108.  
  109.     // Register the class
  110.     if(!RegisterClass(&wc))
  111.     {
  112.         MessageBox(NULL, "RegisterClass failed!",  "System Error",
  113.                    MB_OK | MB_ICONHAND);
  114.         return(FALSE);
  115.     }
  116.  
  117.     // Increase the number of file handles that are available to the
  118.     // system.  
  119.     uCount = SetHandleCount(FILEHANDLESNEEDED);
  120.     if (uCount < FILEHANDLESNEEDED)
  121.     {
  122.         MessageBox(NULL, "Not enough file handles available. 'Set files=40'"
  123.                    " in CONFIG.SYS.",  "System Error", MB_OK | MB_ICONHAND);
  124.         return FALSE;
  125.     }
  126.  
  127.     // Get the directory which contains the tables. 
  128.     GetPrivateProfileString("ADDRESS", "TblDir",
  129.                             "..\\..\\TABLES",
  130.                             (LPSTR)szRelativeTblDirectory,
  131.                             sizeof(szRelativeTblDirectory),
  132.                             "bde.ini");
  133.  
  134.     // Create a fully qualified pathname for the table directory
  135.     if (MakeFullPath(szTblDirectory, szRelativeTblDirectory))
  136.     {
  137.         sprintf(szMessage,"Table Directory does not exist: %s",
  138.                 szTblDirectory);
  139.         MessageBox(NULL, szMessage,  "System Error", MB_OK | MB_ICONHAND);
  140.         return FALSE;
  141.     }
  142.  
  143.     // Get the private directory. Needed in case example is run off a
  144.     // CD-ROM.
  145.     GetPrivateProfileString("ADDRESS", "PrivateDir",
  146.                             ".", (LPSTR)szRelativeTblDirectory,
  147.                             sizeof(szRelativeTblDirectory),
  148.                             "bde.ini");
  149.  
  150.     // Create a fully qualified path for the table private.
  151.     if (MakeFullPath(szPrivDirectory, szRelativeTblDirectory))
  152.     {
  153.         sprintf(szMessage,"Private Directory does not exist: %s",
  154.                 szPrivDirectory);
  155.         MessageBox(NULL, szMessage,  "System Error", MB_OK | MB_ICONHAND);
  156.         return FALSE;
  157.     }
  158.  
  159.     // Create the dialog that serves as the main window
  160.     hMainWnd = CreateDialog(hInst, "MainDlg", 0, NULL);
  161.     if (hMainWnd == NULL)
  162.     {
  163.         MessageBox(NULL, "CreateDialog failed!",  "System Error",
  164.                    MB_OK | MB_ICONHAND);
  165.         return(FALSE);
  166.     }
  167.  
  168.     _wpOrigWndProc = SubClassWindow(GetDlgItem(hMainWnd, IDE_COMMENTS),
  169.                                     EditSubClassProc);
  170.  
  171.     ShowWindow(hMainWnd, nCmdShow);
  172.     return(TRUE);
  173. }
  174.  
  175. // ===============================================================
  176. //  Name:   MainWndProc(hWnd, msg, wParam, lParam);
  177. //
  178. //  Desc:   This routine will process all messaged for the primary
  179. //          application window. Included in this are all menu
  180. //          commands.
  181. // ===============================================================
  182. LRESULT CALLBACK
  183. MainWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  184. {
  185.     UINT32      lRet = FALSE;
  186.     pCHAR       pszTableInfo;
  187.     CHAR        szInitIndex[]="FullName";
  188.     CHAR        szMdxName[DBIMAXPATHLEN];
  189.     UINT        iRangeVal;
  190.     UINT16      i;
  191.     CHAR        szABType[DBIMAXPATHLEN];
  192.     CHAR        szTable[DBIMAXPATHLEN];
  193.     CHAR        szMsg[150];
  194.     UINT        iType;
  195.     BOOL        bFlag;
  196.     ABHANDLES   AbHandle;
  197.     pCS         pCreate;
  198. #ifndef WIN32
  199.     DLGPROC     lpProc;
  200. #endif
  201.     HWND        hwnd;
  202.     HBRUSH      hBrush;
  203.  
  204.     // The following variables are static so that the original state that
  205.     // is passed into the window proc is kept after we fall through it.
  206.     static  hDBIDb      hDb;
  207.     static  hDBICur     hCur;
  208.     static  hDBIDb      hTempDb;
  209.     static  hDBICur     hTempCur;
  210.     static  CHAR        szTempName[DBIMAXPATHLEN];
  211.     static  CHAR        szTempDir[DBIMAXPATHLEN];
  212.  
  213.     // These variables are used for the FileOpen/FileSave dialogs
  214.     LPFOCHUNK   lpFOChunk;
  215.     hErrorWnd = hWnd;
  216.  
  217.     switch (msg)
  218.     {
  219.         case WM_CREATE:
  220. #ifndef WIN32
  221.             if((lpfnFileHook = (FARHOOK)MakeProcInstance(
  222.                                     (FARPROC)FileHook, hInst))==NULL)
  223.             {
  224.                  WinMsg("Could not create Common Dialog Hook",
  225.                         MB_ICONHAND, MB_OK);
  226.             }
  227. #endif
  228.             PostMessage(hWnd, WM_DBIINIT, 0, 0);
  229.             break;
  230.  
  231.         case WM_DBIINIT:
  232.             hwnd = GetWindow(hWnd, GW_CHILD);
  233.             while (hwnd != NULL)
  234.             {
  235.                 Ctl3dSubclassCtl(hwnd);
  236.                 hwnd = GetWindow(hwnd, GW_HWNDNEXT);
  237.             }
  238.             // Check to see if the engine could not initialize.
  239.             if(DbInit()!=DBIERR_NONE)
  240.             {
  241.                 // There was an error so shut down.
  242.                 PostQuitMessage(0);
  243.                 break;
  244.             }
  245.  
  246.             // Get memory to hold the full table name with path.
  247.             pszTableInfo = (pCHAR)malloc((DBIMAXPATHLEN + 1) * sizeof(CHAR));
  248.             if (pszTableInfo == NULL)
  249.             {
  250.                 WinMsg("You have run out of memory!", MB_ICONHAND,
  251.                        MB_OK);
  252.                 PostMessage(hWnd, WM_DESTROY, 0, 0L);
  253.                 return 0;
  254.             }
  255.  
  256.             OpenDB(&hDb, NULL, NULL, NULL);
  257.  
  258.             // Create the two tables - the Paradox Business table and the
  259.             // dBASE personal table.
  260.             for(i=0; i<2; i++)
  261.             {
  262.                 if(i==1)
  263.                 {
  264.                     strcpy((pCHAR)szTblName, szPERSONAL);
  265.                     strcpy((pCHAR)szTblType, szDBASE);
  266.                     strcpy(szABType, szPERSONAL);
  267.                 }
  268.                 else
  269.                 {
  270.                     strcpy((pCHAR)szTblName, szBUSINESS);
  271.                     strcpy((pCHAR)szTblType, szPARADOX);
  272.                     strcpy(szABType, szBUSINESS);
  273.                 }
  274.  
  275.                 // Check if the table exists or empty.
  276.                 if(!TableExist(pszTableInfo))
  277.                 {
  278.                     if(CreateTable(hDb, &hCur, szABType)==DBIERR_NONE)
  279.                     {
  280.                         // Fill it with the data that is inside the resource
  281.                         // file.
  282.                         if(FillTable(hCur, szABType))
  283.                         {
  284.                             CloseTable(&hCur);
  285.                         }
  286.                     }
  287.                 }
  288.                 pszTableInfo[0] = 0;
  289.             }
  290.  
  291.             free(pszTableInfo);
  292.  
  293.             if(!GetTable(hDb, &hCur))
  294.             {
  295.                 // Get the Production index's name.
  296.                 GetMdxName(hCur, szMdxName);
  297.  
  298.                 // Switch to the an index.  This is done because we are
  299.                 // using a dBASE table which defaults to no index upon being
  300.                 // opened.  You can choose any index by changing the
  301.                 // szInitIndex variable.
  302.                 SetIndex(&hCur, szInitIndex);
  303.  
  304.                 // Goto the top of the table and move forward one record.
  305.                 GoTop(hCur, TRUE);
  306.             }
  307.             else
  308.             {
  309.                 wsprintf(szMsg, "The following table: %s is corrupt - please"
  310.                          " delete it and rerun the program.", szTblName);
  311.                 WinMsg(szMsg, MB_ICONHAND, MB_OK);
  312.                 PostMessage(hWnd, WM_DESTROY, 0, 0L);
  313.                 return FALSE;
  314.             }
  315.  
  316.             if(hCur==NULL)
  317.             {
  318.                 WinMsg("Error opening tables!", MB_ICONHAND, MB_OK);
  319.                 PostMessage(hWnd, WM_DESTROY, 0, 0L);
  320.             }
  321.             else
  322.             {
  323.                 ShowWindow(hWnd, SW_SHOW);
  324.  
  325.                 // Display the field names for this table in the main
  326.                 // window.
  327.                 SetFieldNames(hCur);
  328.  
  329.                 // Get the message number for the common dialog hook.
  330.                 iMSGFileOK = RegisterWindowMessage(FILEOKSTRING);
  331.  
  332.                 // Display the first record.
  333.                 PostMessage(hWnd, WM_DISPLAY, 0, 0L);
  334.             }
  335.             break;
  336.  
  337. #ifdef WIN32
  338.         case WM_CTLCOLORSCROLLBAR:
  339.         case WM_CTLCOLORBTN:
  340.         case WM_CTLCOLORDLG:
  341.         case WM_CTLCOLOREDIT:
  342.         case WM_CTLCOLORLISTBOX:
  343.         case WM_CTLCOLORMSGBOX:
  344.         case WM_CTLCOLORSTATIC:
  345. #else
  346.         case WM_CTLCOLOR:
  347. #endif        
  348.             hBrush = Ctl3dCtlColorEx(msg, wParam, lParam);
  349.             if (hBrush != (HBRUSH)0)
  350.             {
  351.                 return (long)(WORD)hBrush;
  352.             }
  353.             else
  354.             {
  355.                 return DefWindowProc(hWnd, msg, wParam, lParam);
  356.             }
  357.  
  358.         case WM_SYSCOLORCHANGE:
  359.             Ctl3dColorChange();
  360.             return TRUE;
  361.  
  362.         case WM_NCPAINT:
  363.         case WM_NCACTIVATE:
  364.         case WM_SETTEXT:
  365.             return Ctl3dDlgFramePaint(hWnd, msg, wParam, lParam);
  366.  
  367.         case WM_SETFOCUS:
  368.             SetFNameFocus();
  369.             break;
  370.  
  371.         case WM_DISPLAY:
  372.             // Check the navigational buttons.
  373.             CheckButtons(hCur);
  374.  
  375.             // Display the current record.
  376.             DisplayTable(hCur);
  377.  
  378.             // Setup the edit controls so that the user can only
  379.             // enter the correct amount of information.
  380.             SetupEdits();
  381.             break;
  382.  
  383.         case WM_ABFILECREATE:
  384.             iType = wParam;
  385.             if(iType == 1)
  386.             {
  387.                 strcpy((pCHAR)szABType, szBUSINESS);
  388.             }
  389.             else
  390.             {
  391.                 strcpy((pCHAR)szABType, szPERSONAL);
  392.             }
  393.  
  394.             if(bIsServer)
  395.             {
  396.                 strcpy((pCHAR)szTable, (pCHAR)lParam);
  397.  
  398.                 // Strip out any periods.
  399.                 StripChar((pCHAR)szTblName, szTable, 46);
  400.             }
  401.  
  402.             if(CreateTable(hTempDb, &hTempCur, szABType)==DBIERR_NONE)
  403.             {
  404.                 if(FillTable(hTempCur, szABType))
  405.                 {
  406.                     if(CloseTable(&hTempCur)==DBIERR_NONE)
  407.                     {
  408.                         SendMessage(hWnd, WM_ABFILEOPEN, 0, lParam);
  409.                     }
  410.                 }
  411.             }
  412.             else
  413.             {
  414.                 strcpy((pCHAR)szTblName, szTempName);
  415.                 strcpy((pCHAR)szTblDirectory, szTempDir);
  416.                 if(hTempDb)
  417.                 {
  418.                     CloseDb(&hTempDb);
  419.                 }
  420.                 hTempCur = 0;
  421.                 hTempDb = 0;
  422.                 if(hCur)
  423.                 {
  424.                     GetTblType(hCur, (pCHAR)szTblType);
  425.                 }
  426.             }
  427.             break;
  428.  
  429.         case WM_ABFILEOPEN:
  430.             if(!CanContinue("Do you wish to save your changes"
  431.                             " before opening the new table", ID_UNDO_REC))
  432.             {
  433.                 SaveRec(hCur, FALSE);
  434.             }
  435.  
  436.             if(bIsServer)
  437.             {
  438.                 strcpy((pCHAR)szTable, (pCHAR)lParam);
  439.             }
  440.             else
  441.             {
  442.                 strcpy((pCHAR)szTblName, (pCHAR)lParam);
  443.             }
  444.  
  445.             if(GetTable(hTempDb, &hTempCur) == DBIERR_NONE)
  446.             {
  447.                 CheckTable(hTempCur, &bFlag);
  448.                 if(bFlag)
  449.                 {
  450.                     EnableMenuItem(GetMenu(hMainWnd),ID_CLEAR_RANGE,
  451.                                    MF_GRAYED);
  452.                     if(hDb)
  453.                     {
  454.                         CloseDb(&hDb);
  455.                     }
  456.                     hDb = hTempDb;
  457.                     hCur = hTempCur;
  458.                     hTempCur = 0;
  459.                     hTempDb = 0;
  460.                     if(AtBOF(hCur) && AtEOF(hCur))
  461.                     {
  462.                         WinMsg("Filling the empty table with the default "
  463.                                "data.", MB_ICONHAND, MB_OK);
  464.                         FillTable(hCur, szBUSINESS);
  465.                     }
  466.                     GoTop(hCur, TRUE);
  467.                     InitIndex1(&hCur);
  468.                     SetAll(TRUE);
  469.  
  470.                     // Display the field names for this table in the
  471.                     // main window.
  472.                     SetFieldNames(hCur);
  473.  
  474.                     // Display the current record.
  475.                     PostMessage(hWnd, WM_DISPLAY, 0, 0L);
  476.                 }
  477.                 else
  478.                 {
  479.                     wsprintf(szMsg, "The Table named: %s is not a valid "
  480.                              "AddressBook table.  Please try again",
  481.                              szTblName);
  482.  
  483.                     WinMsg(szMsg, MB_ICONHAND, MB_OK);
  484.                     strcpy((pCHAR)szTblName, szTempName);
  485.                     strcpy((pCHAR)szTblDirectory, szTempDir);
  486.                     if(hTempDb)
  487.                     {
  488.                         CloseDb(&hTempDb);
  489.                     }
  490.                     hTempCur = 0;
  491.                     hTempDb = 0;
  492.                     if(hCur!=NULL)
  493.                     {
  494.                         GetTblType(hCur, (pCHAR)szTblType);
  495.                     }    
  496.                 }
  497.             }
  498.             else
  499.             {
  500.                 strcpy((pCHAR)szTblName, szTempName);
  501.                 strcpy((pCHAR)szTblDirectory, szTempDir);
  502.                 if(hTempDb)
  503.                 {
  504.                     CloseDb(&hTempDb);
  505.                 }
  506.                 if(hCur)
  507.                 {
  508.                     GetTblType(hCur, (pCHAR)szTblType);
  509.                 }
  510.                 hTempDb = 0;
  511.             }
  512.             break;
  513.  
  514.         case WM_COMMAND:
  515.             switch (GET_WM_COMMAND_ID(wParam,lParam))
  516.             {
  517.                 // These messages are two buttons that are not visible
  518.                 // until the user sends an ID_ADD_REC message by pressing
  519.                 // the add button or choosing the add menu option.  Once
  520.                 // that is done the OK button will stay dimmed until the
  521.                 // user has input valid data.  Which consists of some first
  522.                 // and last name and a valid date.
  523.                 case IDOK:
  524.  
  525.                     // Insert the record.
  526.                     HourGlassCursor(TRUE);
  527.                     SaveRec(hCur, TRUE);
  528.                     HourGlassCursor(FALSE);
  529.  
  530.                     // Reset the controls back to normal. 
  531.                     EndNewRec(hCur);
  532.                     SetFNameFocus();
  533.                     break;
  534.  
  535.                 case IDCANCEL:
  536.                      // Confirm if the data will be lost.
  537.                     if(CanContinue("Data not saved cancel anyway?", IDOK))
  538.                     {
  539.                         // Reset the controls and cancel any data.
  540.                         EndNewRec(hCur);
  541.                     }
  542.                     break;
  543.  
  544.                 // Check all the edits at once for any changes.  Then
  545.                 // check if the data is valid.
  546.                 case IDE_FIRST_NAME:
  547.                 case IDE_LAST_NAME:
  548.                 case IDE_LAST_DATE:
  549.                 case IDE_ADDRESS1:
  550.                 case IDE_ADDRESS2:
  551.                 case IDE_CITY:
  552.                 case IDE_STATE:
  553.                 case IDE_ZIP:
  554.                 case IDE_PHONE1:
  555.                 case IDE_PHONE2:
  556.                 case IDE_COMMENTS:
  557.                     if ((GET_WM_COMMAND_CMD(wParam,lParam) == EN_UPDATE)
  558.                          && !bReset)
  559.                     {
  560.                         if(Varified())
  561.                         {
  562.                             // If in add mode enable the OK button.
  563.                             if(NewRecMode)
  564.                             {
  565.                                 EnableWindow(GetDlgItem(hMainWnd, IDOK),
  566.                                              TRUE);
  567.                             }
  568.                             else
  569.                             {
  570.                                 SetControl(ID_MOD_REC, TRUE);
  571.                                 SetControl(ID_UNDO_REC, TRUE);
  572.                             }
  573.                         }
  574.                         else
  575.                         {
  576.                             if(NewRecMode)
  577.                             {
  578.                                 // Disable the OK button, so that the
  579.                                 // user cannot save the invalid data.
  580.                                 EnableWindow(GetDlgItem(hMainWnd, IDOK),
  581.                                              FALSE);
  582.                             }
  583.                             else
  584.                             {
  585.                                 // Disable the save button but do not
  586.                                 // disable the Undo button.
  587.                                 SetControl(ID_MOD_REC, FALSE);
  588.                                 SetControl(ID_UNDO_REC, TRUE);
  589.                             }
  590.                         }
  591.                     }
  592.                     break;
  593.  
  594.                 case ID_DELETETABLE:
  595.                     if(WinMsg("Delete This table?", MB_ICONHAND,
  596.                               MB_YESNO)==IDYES)
  597.                     {
  598.                         HourGlassCursor(TRUE);
  599.                         if((DeleteTable(&hCur, hDb, (pCHAR)szTblName,
  600.                                         (pCHAR)szTblType)) == DBIERR_NONE)
  601.                         {
  602.                             ClearDlg();
  603.                             SetAll(FALSE);
  604.                         }
  605.                         HourGlassCursor(FALSE);
  606.                     }
  607.                     break;
  608.  
  609.                 case ID_NEW:
  610.                     if((lpFOChunk = (LPFOCHUNK) malloc(sizeof(FOCHUNK)))
  611.                                                 == NULL)
  612.                     {
  613.                         return 0;
  614.                     }
  615.  
  616.                     if((pCreate = (pCS) malloc(sizeof(ABCREATESTRUCT)))
  617.                                                 == NULL)
  618.                     {
  619.                         return 0;
  620.                     }
  621.  
  622.                     pCreate->phDb = &hTempDb;
  623.                     pCreate->uType = 1;
  624.  
  625.                     // Clear the variable before re-using the variable.
  626.                     memset(szTempName, '\0', DBIMAXNAMELEN);
  627.                     memset(szTempDir, '\0', DBIMAXPATHLEN);
  628.                     memset(szTable, '\0', DBIMAXNAMELEN);
  629.  
  630.                     OpenDB(&hTempDb, NULL, NULL, NULL);
  631.  
  632.                     InitializeStruct((LPSTR)lpFOChunk, pCreate);
  633.  
  634.                     strcpy((pCHAR)szTable, szTblName);
  635.  
  636.                     if ( GetSaveFileName( &(lpFOChunk->ofn) ) )
  637.                     {
  638.                         strcpy(szTempDir, szTblDirectory);
  639.                         memset((pCHAR)szTblDirectory, '\0', DBIMAXPATHLEN);
  640.                         if(bIsServer)
  641.                         {
  642.                             strcpy((pCHAR)szTempName, szTable);
  643.                             strcpy((pCHAR)szTblType, "");
  644.                         }
  645.                         else
  646.                         {
  647.                             strcpy((pCHAR)szTempName, szTblName);
  648.                             memset((pCHAR)szTblName, '\0', DBIMAXNAMELEN);
  649.                             GetFileTitle(lpFOChunk->ofn.lpstrFile,
  650.                                     (pCHAR)szTblName, DBIMAXTBLNAMELEN - 1);
  651.                             strncpy((pCHAR)szTblDirectory,
  652.                                         lpFOChunk->ofn.lpstrFile,
  653.                                         (lpFOChunk->ofn.nFileOffset)-1);
  654.  
  655.                             strlwr((pCHAR)szTblName);
  656.                             if(strstr(szTblName, ".dbf")==NULL)
  657.                             {
  658.                                 strcpy((pCHAR)szTblType, szPARADOX);
  659.                             }
  660.                             else
  661.                             {
  662.                                 strcpy((pCHAR)szTblType, szDBASE);
  663.                             }
  664.                         }
  665.                         iType = pCreate->uType;
  666.                         SendMessage(hWnd, WM_ABFILECREATE, iType,
  667.                                     (LPARAM)szTblName);
  668.                     }
  669.                     else
  670.                     {
  671.                         ProcessCDError(CommDlgExtendedError());
  672.  
  673.                         // The user pressed cancel so we must close the
  674.                         // temporary database handle.
  675.                         if(hTempDb)
  676.                         {
  677.                             CloseDb(&hTempDb);
  678.                         }
  679.                         strcpy((pCHAR)szTblName, szTable);
  680.                     }
  681.  
  682.                     free(lpFOChunk);
  683.                     free(pCreate);
  684.                     break;
  685.  
  686.                 case ID_OPEN:
  687.  
  688.                     if((lpFOChunk = (LPFOCHUNK) malloc(sizeof(FOCHUNK)))
  689.                                                 == NULL)
  690.                     {
  691.                         return 0;
  692.                     }
  693.  
  694.                     if((pCreate = (pCS) malloc(sizeof(ABCREATESTRUCT)))
  695.                                                 == NULL)
  696.                     {
  697.                         return 0;
  698.                     }
  699.  
  700.                     pCreate->phDb = &hTempDb;
  701.                     pCreate->uType = 0;
  702.  
  703.                     // Clear the variable before re-using the variable.
  704.                     memset(szTempName, '\0', DBIMAXNAMELEN);
  705.                     memset(szTempDir, '\0', DBIMAXPATHLEN);
  706.                     memset(szTable, '\0', DBIMAXNAMELEN);
  707.  
  708.                     OpenDB(&hTempDb, NULL, NULL, NULL);
  709.  
  710.                     InitializeStruct((LPSTR)lpFOChunk, pCreate);
  711.  
  712.                     strcpy((pCHAR)szTable, szTblName);
  713. #ifndef WIN32
  714.                     if((lpfnFileHook = (FARHOOK)MakeProcInstance(
  715.                                     (FARPROC)FileHook, hInst))==NULL)
  716.                     {
  717.                             WinMsg("Could not create Common Dialog Hook",
  718.                             MB_ICONHAND, MB_OK);
  719.                     }
  720. #endif
  721.  
  722.                     if ( GetOpenFileName( &(lpFOChunk->ofn) ) )
  723.                     {
  724.                         strcpy(szTempDir, szTblDirectory);
  725.                         memset((pCHAR)szTblDirectory, '\0', DBIMAXPATHLEN);
  726.                         if(bIsServer)
  727.                         {
  728.                             strcpy((pCHAR)szTempName, szTable);
  729.                         }
  730.                         else
  731.                         {
  732.                             strcpy((pCHAR)szTempName, szTblName);
  733.                             memset((pCHAR)szTblName, '\0', DBIMAXNAMELEN);
  734.                             GetFileTitle(lpFOChunk->ofn.lpstrFile,
  735.                                     (pCHAR)szTblName, DBIMAXTBLNAMELEN - 1);
  736.                             strncpy((pCHAR)szTblDirectory,
  737.                                         lpFOChunk->ofn.lpstrFile,
  738.                                         (lpFOChunk->ofn.nFileOffset)-1);
  739.                         }
  740.                         SendMessage(hWnd, WM_ABFILEOPEN, 0,
  741.                                     (LPARAM)szTblName);
  742.                     }
  743.                     else
  744.                     {
  745.                         // The user pressed cancel so we must close the
  746.                         // temporary database handle.
  747.                         if(hTempDb != NULL)
  748.                         {
  749.                             CloseDb(&hTempDb);
  750.                         }
  751.                         strcpy((pCHAR)szTblName, szTable);
  752.                     }
  753.  
  754.                     free(lpFOChunk);
  755.                     free(pCreate);
  756.                     break;
  757.  
  758.  
  759.                 // Display the About dialog box.
  760.                 case ID_ABOUT:
  761. #ifndef WIN32
  762.                     lpProc = (DLGPROC)MakeProcInstance((FARPROC) AboutDlg,
  763.                                                        hInst);
  764.                     DialogBox(hInst, "AboutDlg", hMainWnd, lpProc);
  765.                     FreeProcInstance((FARPROC) lpProc);
  766. #else
  767.                     DialogBox(hInst, "AboutDlg", hMainWnd, AboutDlg);
  768. #endif
  769.                     SetFNameFocus();
  770.                     break;
  771.  
  772.                 // Display the Order dialog box.
  773.                 case ID_ORDER:
  774. #ifndef WIN32
  775.                     lpProc = (DLGPROC)MakeProcInstance((FARPROC) OrderDlg,
  776.                                                        hInst);
  777. #endif
  778.  
  779.                     AbHandle.phCur = &hCur;
  780.                     AbHandle.hDb = hDb;
  781.  
  782. #ifndef WIN32
  783.                     // Pass the pointer to the ABHandle structure so it
  784.                     // can be modified inside the dialogbox.
  785.                     if(DialogBoxParam(hInst, "OrderDlg", hMainWnd, lpProc,
  786.                                    (LONG)(void far*)&AbHandle)==IDOK)
  787. #else
  788.                     if(DialogBoxParam(hInst, "OrderDlg", hMainWnd, OrderDlg,
  789.                                    (LONG)(void far*)&AbHandle)==IDOK)
  790. #endif
  791.                     {
  792.                         // Display the current record.
  793.                         DisplayTable(hCur);
  794.                         CheckButtons(hCur);
  795.                     }
  796. #ifndef WIN32
  797.                     FreeProcInstance((FARPROC) lpProc);
  798. #endif
  799.                     SetFNameFocus();
  800.                     break;
  801.  
  802.                 // Display the Range dialog box.
  803.                 case ID_RANGE:
  804. #ifndef WIN32
  805.                     lpProc = (DLGPROC)MakeProcInstance((FARPROC)RangeDlg,
  806.                                                        hInst);
  807. #endif                    
  808.  
  809.                     AbHandle.phCur = &hCur;
  810.                     AbHandle.hDb = hDb;
  811.  
  812.                     // Pass the pointer to the ABHandle structure so it
  813.                     // can be modified inside the dialogbox.
  814. #ifndef WIN32
  815.                     iRangeVal = DialogBoxParam(hInst, "RangeDlg", hMainWnd,
  816.                                               lpProc,
  817.                                               (LONG)(void far*)&AbHandle);
  818. #else
  819.                     iRangeVal = DialogBoxParam(hInst, "RangeDlg", hMainWnd,
  820.                                               RangeDlg,
  821.                                               (LONG)(void far*)&AbHandle);
  822. #endif                    
  823.                     if(iRangeVal == IDOK)
  824.                     {
  825.                         // Set the global variable RangeSet to TRUE as
  826.                         // we did set a range for the present cursor.
  827.                         RangeSet = TRUE;
  828.  
  829.                         // Display the current record.
  830.                         DisplayTable(hCur);
  831.                         CheckButtons(hCur);
  832.  
  833.                         // Enable the Clear Range menu option.
  834.                         EnableMenuItem(GetMenu(hMainWnd), ID_CLEAR_RANGE,
  835.                                        MF_ENABLED);
  836.                     }
  837.                     else
  838.                     {
  839.                         SetFNameFocus();
  840.                     }
  841. #ifndef WIN32
  842.                     FreeProcInstance((FARPROC) lpProc);
  843. #endif
  844.                     break;
  845.  
  846.                 // This menu option is enabled ONLY after a range has
  847.                 // been set.
  848.                 case ID_CLEAR_RANGE:
  849.  
  850.                     ResetRange(hCur);
  851.  
  852.                     // Go to the first record in the table.
  853.                     GoTop(hCur, TRUE);
  854.  
  855.                     // Disable the Reset Range menu option.
  856.                     EnableMenuItem(GetMenu(hMainWnd), ID_CLEAR_RANGE,
  857.                                    MF_GRAYED);
  858.  
  859.                     // Set the global variable to FALSE.
  860.                     RangeSet = FALSE;
  861.  
  862.                     // Display the current record.
  863.                     DisplayTable(hCur);
  864.                     CheckButtons(hCur);
  865.                     break;
  866.  
  867.                 // Display the Search dialog box.
  868.                 case ID_SEARCH:
  869. #ifndef WIN32
  870.                     lpProc = (DLGPROC)MakeProcInstance((FARPROC) SearchDlg,
  871.                                                        hInst);
  872. #endif
  873.                     AbHandle.phCur = &hCur;
  874.                     AbHandle.hDb = hDb;
  875.  
  876.                     // Pass the pointer to the ABHandle structure so it
  877.                     // can be modified inside the dialogbox.
  878. #ifndef WIN32
  879.                     if(DialogBoxParam(hInst, "SearchDlg", hMainWnd, lpProc,
  880.                                       (LONG)(void far*)&AbHandle)==IDOK)
  881. #else
  882.                     if(DialogBoxParam(hInst, "SearchDlg", hMainWnd, SearchDlg,
  883.                                       (LONG)(void far*)&AbHandle)==IDOK)
  884. #endif
  885.                     {
  886.                         // Move one record past the crack that the Search
  887.                         // function leaves you at.
  888.                         CHKERR(GetNextRec(hCur));
  889.                     }
  890. #ifndef WIN32
  891.                     FreeProcInstance((FARPROC) lpProc);
  892. #endif
  893.  
  894.                     // Display the current record.
  895.                     DisplayTable(hCur);
  896.                     CheckButtons(hCur);
  897.                     break;
  898.  
  899.                 case ID_ADD_REC:
  900.                     // Change the "mode" of the main window so as to allow
  901.                     // for a new name to be entered. This "mode" will not
  902.                     // be deactivated until the IDOK and IDCANCEL messages
  903.                     // are processed in this message switch!
  904.                     ChangeEntryMode(hCur);
  905.  
  906.                     // Clear the edit controls to allow the user to input
  907.                     // the new data easily.
  908.                     ClearDlg();
  909.  
  910.                     // Enable the Cancel button.
  911.                     EnableWindow(GetDlgItem(hMainWnd, IDCANCEL), TRUE);
  912.  
  913.                     // Disable the OK button until valid data has been
  914.                     // input.
  915.                     EnableWindow(GetDlgItem(hMainWnd, IDOK), FALSE);
  916.  
  917.                     // Put the current date into the Date Edit control.
  918.                     SetDefaultDate();
  919.                     SetFNameFocus();
  920.                     break;
  921.  
  922.                 case ID_NEXT_REC:
  923.                     // Move one record forward.
  924.                     MoveRec(hCur, NEXT_REC);
  925.                     break;
  926.  
  927.                 case ID_PREV_REC:
  928.                     // Move back one record.
  929.                     MoveRec(hCur, PREV_REC);
  930.                     break;
  931.  
  932.                 case ID_FIRST_REC:
  933.                     // Move to the first record in the table.
  934.                     MoveRec(hCur, TOP);
  935.                     break;
  936.  
  937.                 case ID_LAST_REC:
  938.                     // Move to the last record in the table.
  939.                     MoveRec(hCur, BOTTOM);
  940.                     break;
  941.  
  942.                 case ID_MOD_REC:
  943.                     if(CanContinue("Do you want to modify this record?",
  944.                                    ID_UNDO_REC))
  945.                     {
  946.                         // Modify record.
  947.                         SaveRec(hCur, FALSE);
  948.  
  949.                         // Set the navigational controls.
  950.                         CheckButtons(hCur);
  951.                         SetControl(ID_MOD_REC, FALSE);
  952.                         SetControl(ID_UNDO_REC, FALSE);
  953.                     }
  954.                     break;
  955.  
  956.                 case ID_DEL_REC:
  957.                     if(WinMsg("Do you want to delete this record?",
  958.                               MB_ICONHAND, MB_YESNO)== IDYES)
  959.                     {
  960.                         // Delete the record.
  961.                         DeleteRecord(hCur);
  962.                         CheckButtons(hCur);
  963.                     }
  964.                     break;
  965.  
  966.                 case ID_UNDO_REC:
  967.                     if(CanContinue("All changes will be lost - Undo "
  968.                                    "anyway?", ID_UNDO_REC))
  969.                     {
  970.                         // Redisplay the original data from the table.
  971.                         PostMessage(hWnd, WM_DISPLAY, 0, 0L);
  972.                     }
  973.                     break;
  974.  
  975.                 case ID_EXIT:
  976.                     PostMessage(hWnd, WM_CLOSE, 0, 0L);
  977.                     break;
  978.  
  979.                 default:
  980.                     lRet = DefWindowProc(hWnd, msg, wParam, lParam);
  981.                     break;
  982.  
  983.             }
  984.             break;
  985.  
  986.         case WM_CLOSE:
  987.             if(CanContinue("Data not saved quit anyway?", IDOK))
  988.             {
  989.                 DestroyWindow(hWnd);
  990.             }
  991.             else
  992.             {
  993.                 SetFNameFocus();
  994.             }
  995.             break;
  996.  
  997.         case WM_DESTROY:
  998.             if(hCur)
  999.             {
  1000.                 CloseTable(&hCur);
  1001.             }
  1002.             if(hDb)
  1003.             {
  1004.                 CloseDb(&hDb);
  1005.             } 
  1006.             DbExit();
  1007.  
  1008.             // Quit the application.
  1009.             PostQuitMessage(0);
  1010.             break;
  1011.  
  1012.         default:
  1013.             // Otherwise default to the DefWindowProc.
  1014.             lRet = DefWindowProc(hWnd, msg, wParam, lParam);
  1015.             break;
  1016.     }
  1017.     return(lRet);
  1018. }
  1019.  
  1020. //======================================================================
  1021. //  Name:   FillStruct()
  1022. //
  1023. //  Input:  Record structure pointer (RecordType *), Starting Resource ID
  1024. //          (UINT16), AddressBook type (pCHAR).
  1025. //
  1026. //  Return: TRUE -  The structure is filled.
  1027. //
  1028. //  Desc:   This routine will fill the structure with the strings that start
  1029. //          at Offset and are found in the resource file.
  1030. //======================================================================
  1031. BOOL
  1032. FillStruct (RecordType *pRec, UINT16 iOffSet, pCHAR pszABType)
  1033. {
  1034.     // Used to keep count of the resource ID.  We add one to the uNumFields
  1035.     // to take into account the extra #define for the Bussiness/Spouse pair.
  1036.     UINT      j=IDS_FIRST_NAME_1 + (iOffSet*(uNumFields + 1));
  1037.  
  1038.     memset(pRec, 0, sizeof(RecordType));
  1039.  
  1040.     // Get the string into the structure
  1041.     LoadString(hInst, j++, (pCHAR)pRec->FName, sizeof(pRec->FName));
  1042.     LoadString(hInst, j++, (pCHAR)pRec->LName, sizeof(pRec->LName));
  1043.  
  1044.     // Check if this is a personal addressbook.
  1045.     if(strcmpi(pszABType, szPERSONAL) == 0)
  1046.     {
  1047.         LoadString(hInst, j++, (pCHAR)pRec->Spouse, sizeof(pRec->Spouse));
  1048.  
  1049.         // Increment j to get past the Business data.
  1050.         j++;
  1051.     }
  1052.     else
  1053.     {
  1054.         j++;
  1055.         LoadString(hInst, j++, (pCHAR)pRec->Spouse, sizeof(pRec->Spouse));
  1056.     }
  1057.         
  1058.     LoadString(hInst, j++, (pCHAR)pRec->Addrs1, sizeof(pRec->Addrs1));
  1059.     LoadString(hInst, j++, (pCHAR)pRec->Addrs2, sizeof(pRec->Addrs2));
  1060.     LoadString(hInst, j++, (pCHAR)pRec->City, sizeof(pRec->City));
  1061.     LoadString(hInst, j++, (pCHAR)pRec->State, sizeof(pRec->State));
  1062.     LoadString(hInst, j++, (pCHAR)pRec->Zip, sizeof(pRec->Zip));
  1063.     LoadString(hInst, j++, (pCHAR)pRec->Phone1, sizeof(pRec->Phone1));
  1064.     LoadString(hInst, j++, (pCHAR)pRec->Phone2, sizeof(pRec->Phone2));
  1065.     LoadString(hInst, j++, (pCHAR)pRec->Date1, sizeof(pRec->Date1));
  1066.     LoadString(hInst, j++, (pCHAR)pRec->Comment, sizeof(pRec->Comment));
  1067.  
  1068.     return TRUE;
  1069. }
  1070.  
  1071. //======================================================================
  1072. //  Name:   DisplayTable()
  1073. //
  1074. //  Input:  Cursor handle (hDBICur).
  1075. //
  1076. //  Return: TRUE -  The record is displayed.
  1077. //          FALSE - The record Structure allocation failed.
  1078. //
  1079. //  Desc:   This routine will fill a structure with the record pointed
  1080. //          to by the cursor and then display the record in the main Window.
  1081. //======================================================================
  1082. BOOL
  1083. DisplayTable (hDBICur hCur)
  1084. {                                                                       
  1085.     RecordType *pRecord;
  1086.  
  1087.     // Allocate a temporary buffer to read information that is pointed
  1088.     // to by the cursor.
  1089.     if((pRecord = (RecordType *) malloc(1 * sizeof(RecordType))) == NULL)
  1090.     {
  1091.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1092.         return FALSE;
  1093.     }
  1094.  
  1095.     memset(pRecord, 0, sizeof(RecordType));
  1096.  
  1097.     // Set the Reset Variable to TRUE.
  1098.     bReset = TRUE;
  1099.  
  1100.     // Fill the structure with the record.
  1101.     GetData(hCur, pRecord);
  1102.  
  1103.     // Display the record.
  1104.     DispRec(pRecord);
  1105.  
  1106.     // Set the Reset Variable to FALSE.
  1107.     bReset = FALSE;
  1108.     SetControl(ID_MOD_REC, FALSE);
  1109.     SetControl(ID_UNDO_REC, FALSE);
  1110.     SetFNameFocus();
  1111.     free(pRecord);
  1112.     return TRUE;
  1113. }
  1114.  
  1115. //======================================================================
  1116. //  Name:   TableExist()
  1117. //
  1118. //  Input:  Char string that holds the table's FULL name and path (pCHAR).
  1119. //
  1120. //  Return: TRUE -  The table exists and IS NOT empty.
  1121. //          FALSE - The table is empty or does not exist.
  1122. //
  1123. //  Desc:   This routine takes in a table name and checks if the table
  1124. //          exists.  If it exists it checks if the table is empty.
  1125. //======================================================================
  1126. BOOL
  1127. TableExist (pCHAR pszTableInfo)
  1128. {
  1129.     BOOL    bRetVal;
  1130.     int     iExist ;
  1131.     hDBIDb  hDb;
  1132.     hDBICur hCur;
  1133.  
  1134.     // Create the full path string of the table.
  1135.     strcpy(pszTableInfo, szTblDirectory);
  1136.     strcat(pszTableInfo, "\\");
  1137.     strcat(pszTableInfo, szTblName);
  1138.  
  1139.     if(strcmpi(szTblType, szDBASE)==0)
  1140.     {
  1141.         strcat(pszTableInfo, ".dbf");
  1142.         strcat((pCHAR)szTblName, ".dbf");
  1143.     }
  1144.     else
  1145.     {
  1146.         strcat(pszTableInfo, ".db");
  1147.         strcat((pCHAR)szTblName, ".db");        
  1148.     }
  1149.     iExist = access(pszTableInfo, 00); // Check if the table exists
  1150.     if(iExist == -1)
  1151.     {
  1152.         bRetVal = FALSE;
  1153.     }
  1154.     else
  1155.     {
  1156.         OpenDB(&hDb, NULL, NULL, NULL);
  1157.         GetTable(hDb, &hCur);
  1158.  
  1159.         // Go to the top of the table and stay at the BOF crack.
  1160.         GoTop(hCur, FALSE);
  1161.  
  1162.         // If we are at the EOF as well we have an empty table.
  1163.         if(AtEOF(hCur))
  1164.         {
  1165.             bRetVal = FALSE;
  1166.         }
  1167.         else
  1168.         {
  1169.             bRetVal = TRUE;
  1170.         }
  1171.         
  1172.         // Close up and return the bool RetVal.
  1173.         CloseTable(&hCur);
  1174.         CloseDb(&hDb);
  1175.     }
  1176.  
  1177.     return bRetVal;
  1178. }
  1179.  
  1180. //======================================================================
  1181. //  Name:   FillTable()
  1182. //
  1183. //  Input:  Cursor handle (hDBICur), and AddressBook Type (pCHAR).
  1184. //
  1185. //  Return: TRUE -  The record was added to the table.
  1186. //          FALSE - The record Structure allocation failed.
  1187. //
  1188. //  Desc:   This function fills the table with all the strings that are
  1189. //          in the resource file.
  1190. //======================================================================
  1191. BOOL
  1192. FillTable (hDBICur hCur, pCHAR pszABType)
  1193. {
  1194.     RecordType  *pRecord;
  1195.     UINT16      i;
  1196.     BOOL        bRet = FALSE;
  1197.  
  1198.     // Allocate a temporary buffer to read information sitting in
  1199.     // the resource file.
  1200.     if((pRecord = (RecordType *) malloc(1 * sizeof(RecordType))) == NULL)
  1201.     {
  1202.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1203.         return FALSE;
  1204.     }
  1205.  
  1206.     for(i=0; i<uNumRecs; i++)
  1207.     {
  1208.         memset(pRecord, 0, sizeof(RecordType));
  1209.  
  1210.         // Fill a structure with the data sitting in the resource file.
  1211.         if(FillStruct(pRecord, i, pszABType))
  1212.         {
  1213.             // Add the record to the table and insert it rather than
  1214.             // overwriting an old record (TRUE parameter).
  1215.             if(AddRecord(hCur, pRecord, TRUE)==DBIERR_NONE)
  1216.             {
  1217.                 bRet = TRUE;
  1218.             }
  1219.         }
  1220.     }
  1221.     free(pRecord);
  1222.     return bRet;
  1223. }
  1224.  
  1225. //======================================================================
  1226. //  Name:   DispRec()
  1227. //
  1228. //  Input:  Record structure pointer (RecordType *).
  1229. //
  1230. //  Return: TRUE -  The record was displayed.
  1231. //
  1232. //  Desc:   This function displays the data in the record structure
  1233. //          into the main Window.
  1234. //======================================================================
  1235. BOOL DispRec(RecordType *pRecord)
  1236. {
  1237.     SetDlgItemText(hMainWnd, IDE_FIRST_NAME, pRecord->FName);
  1238.     SetDlgItemText(hMainWnd, IDE_LAST_NAME, pRecord->LName);
  1239.     SetDlgItemText(hMainWnd, IDE_SP_COMP, pRecord->Spouse);    
  1240.     SetDlgItemText(hMainWnd, IDE_ADDRESS1, pRecord->Addrs1);
  1241.     SetDlgItemText(hMainWnd, IDE_ADDRESS2, pRecord->Addrs2);
  1242.     SetDlgItemText(hMainWnd, IDE_CITY, pRecord->City);
  1243.     SetDlgItemText(hMainWnd, IDE_STATE, pRecord->State);
  1244.     SetDlgItemText(hMainWnd, IDE_ZIP, pRecord->Zip);
  1245.     SetDlgItemText(hMainWnd, IDE_PHONE1, pRecord->Phone1);
  1246.     SetDlgItemText(hMainWnd, IDE_PHONE2, pRecord->Phone2);
  1247.     SetDlgItemText(hMainWnd, IDE_LAST_DATE, pRecord->Date1);
  1248.     SetDlgItemText(hMainWnd, IDE_COMMENTS, pRecord->Comment);
  1249.     return TRUE;
  1250. }
  1251.  
  1252. //======================================================================
  1253. //  Name:   MoveRec()
  1254. //
  1255. //  Input:  Cursor handle (hDBICur) and Movement (INT16).
  1256. //
  1257. //  Return: None.
  1258. //
  1259. //  Desc:   This function moves the cursor to the bottom or the top
  1260. //          of the table.  Or it moves it a record forward or backwards.
  1261. //======================================================================
  1262. DBIResult
  1263. MoveRec (hDBICur hCur, INT16 iMovement)
  1264. {                                                                       
  1265.     // Check if data has been changed by looking at the status of the Undo
  1266.     // button.  Then ask if the user wishes to lose the data by moving.
  1267.     if(CanContinue("Data not saved move to next record anyway?",
  1268.                    ID_UNDO_REC))
  1269.     {
  1270.  
  1271.         HourGlassCursor(TRUE);
  1272.         switch(iMovement)
  1273.         {
  1274.             // These macros are defined in the header file.
  1275.             case TOP:
  1276.                 GoTop(hCur, TRUE);
  1277.                 break;
  1278.             case BOTTOM:
  1279.                 GoBottom(hCur, TRUE);
  1280.                 break;
  1281.             case NEXT_REC:
  1282.                 if(!AtEOF(hCur))
  1283.                 {
  1284.                     CHKERR(GetNextRec(hCur));
  1285.                 }
  1286.                 break;
  1287.             case PREV_REC:
  1288.                 if(!AtBOF(hCur))
  1289.                 {
  1290.                     GetPrevRec(hCur);
  1291.                 }
  1292.                 break;
  1293.             default:
  1294.                 return DBIERR_NOTSUPPORTED;
  1295.         }
  1296.  
  1297.         // Check the navigational controls and display the current record.
  1298.         CheckButtons(hCur);
  1299.         DisplayTable(hCur);
  1300.     }
  1301.     else
  1302.     {
  1303.         SetFNameFocus();
  1304.     }
  1305.  
  1306.     HourGlassCursor(FALSE);
  1307.  
  1308.     return DBIERR_NONE;
  1309. }
  1310.  
  1311. //======================================================================
  1312. //  Name:   CheckButtons()
  1313. //
  1314. //  Input:  Cursor handle (hDBICur).
  1315. //
  1316. //  Return: None.
  1317. //
  1318. //  Desc:   This function checks the position of the cursor and then
  1319. //          enables or disables the naviagtional buttons AND menu options.
  1320. //======================================================================
  1321. void
  1322. CheckButtons (hDBICur hCur)
  1323. {
  1324.     if(AtEOF(hCur))
  1325.     {
  1326.         // If at EOF disable the Next and Last record buttons and
  1327.         // menu options.
  1328.         SetControl(ID_NEXT_REC, FALSE);
  1329.         SetControl(ID_LAST_REC, FALSE);
  1330.     }
  1331.     else
  1332.     {
  1333.         // Else enable them.
  1334.         SetControl(ID_NEXT_REC, TRUE);
  1335.         SetControl(ID_LAST_REC, TRUE);
  1336.     }
  1337.  
  1338.     if(AtBOF(hCur))
  1339.     {
  1340.         // If at BOF disable the Prev and First record buttons
  1341.         // and menu options.
  1342.         SetControl(ID_PREV_REC, FALSE);
  1343.         SetControl(ID_FIRST_REC, FALSE);
  1344.     }
  1345.     else
  1346.     {
  1347.         // Else enable them.
  1348.         SetControl(ID_PREV_REC, TRUE);
  1349.         SetControl(ID_FIRST_REC, TRUE);
  1350.     }
  1351.  
  1352.     // If the table is empty.
  1353.     if(AtBOF(hCur) && AtEOF(hCur))
  1354.     {
  1355.         if(GetPrevRec(hCur)==DBIERR_BOF && GetNextRec(hCur)==DBIERR_EOF)
  1356.         {
  1357.             SetControl(ID_DEL_REC, FALSE);
  1358.             SetControl(ID_ORDER, FALSE);
  1359.             SetControl(ID_RANGE, FALSE);
  1360.             SetControl(ID_SEARCH, FALSE);
  1361.         }
  1362.         else
  1363.         {
  1364.             SetControl(ID_DEL_REC, TRUE);
  1365.             SetControl(ID_ORDER, TRUE);
  1366.             SetControl(ID_RANGE, TRUE);
  1367.             SetControl(ID_SEARCH, TRUE);
  1368.         }
  1369.     }
  1370.     else
  1371.     {
  1372.         SetControl(ID_DEL_REC, TRUE);
  1373.         SetControl(ID_ORDER, TRUE);
  1374.         SetControl(ID_RANGE, TRUE);
  1375.         SetControl(ID_SEARCH, TRUE);
  1376.     }
  1377.  
  1378.     SetFNameFocus();
  1379. }
  1380.  
  1381. //======================================================================
  1382. //  Name:   SetupEdits()
  1383. //
  1384. //  Input:  None.
  1385. //
  1386. //  Return: None.
  1387. //
  1388. //  Desc:   This function sets the text input limit of each of the edit
  1389. //          controls that are in the main window.
  1390. //======================================================================
  1391. void
  1392. SetupEdits (void)
  1393. {
  1394.     // Use the constants -1 to allow room for the NULL terminator.
  1395.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_FIRST_NAME), NAMELEN-1);
  1396.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_LAST_NAME), NAMELEN-1);
  1397.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_SP_COMP), ADDRESSLEN-1);
  1398.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_COMMENTS), COMMENTLEN-1);
  1399.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_ADDRESS1), ADDRESSLEN-1);
  1400.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_ADDRESS2), ADDRESSLEN-1);
  1401.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_CITY), CITYLEN-1);
  1402.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_STATE), STATELEN-1);
  1403.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_ZIP), ZIPLEN-1);
  1404.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_PHONE1), PHONELEN-1);
  1405.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_PHONE2), PHONELEN-1);
  1406.     Edit_LimitText(GetDlgItem(hMainWnd, IDE_LAST_DATE), DATELEN-1);
  1407.  
  1408.     // Disable the Cancel and OK buttons that are hidden.
  1409.     EnableWindow(GetDlgItem(hMainWnd, IDCANCEL), FALSE);
  1410.     EnableWindow(GetDlgItem(hMainWnd, IDOK), FALSE);
  1411. }
  1412.  
  1413. //======================================================================
  1414. //  Name:   SaveRec()
  1415. //
  1416. //  Input:  Cursor handle (hDBICur), Add or Overwrite bool (BOOL).
  1417. //
  1418. //  Return: TRUE:   If the memory is allocated.
  1419. //          FALSE:  If the memory allocation fails.
  1420. //
  1421. //  Desc:   This function takes the data from off the main window and
  1422. //          puts it in a record structure.  Then based upon the bAdd Bool
  1423. //          it inserts the record or overwrites the old record.
  1424. //======================================================================
  1425. BOOL
  1426. SaveRec (hDBICur hCur, BOOL bAdd)
  1427. {
  1428.     RecordType *pRecord;
  1429.  
  1430.     // Allocate a temporary buffer to store data that is inside the
  1431.     // main Window.
  1432.     if((pRecord = (RecordType *) malloc(1 * sizeof(RecordType))) == NULL)
  1433.     {
  1434.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1435.         return FALSE;
  1436.     }
  1437.  
  1438.     // Clear the record structure.
  1439.     memset(pRecord, 0, sizeof(RecordType));
  1440.  
  1441.     // Get the data from the main Window and put it into the record
  1442.     // structure.
  1443.     GetRec(pRecord);
  1444.  
  1445.     // Add the record or insert the record based upon the bAdd value.
  1446.     AddRecord(hCur, pRecord, bAdd);
  1447.     free(pRecord);
  1448.     CheckButtons(hCur);
  1449.     return TRUE;
  1450. }
  1451.  
  1452. //======================================================================
  1453. //  Name:   GetRec()
  1454. //
  1455. //  Input:  Record structure pointer (RecordType *).
  1456. //
  1457. //  Return: TRUE.
  1458. //
  1459. //  Desc:   This function fills the record structure with the data that
  1460. //          is in the main Window.
  1461. //======================================================================
  1462. BOOL
  1463. GetRec (RecordType *pRecord)
  1464. {
  1465.     GetDlgItemText(hMainWnd, IDE_FIRST_NAME, pRecord->FName, NAMELEN);
  1466.     GetDlgItemText(hMainWnd, IDE_LAST_NAME, pRecord->LName, NAMELEN);
  1467.     GetDlgItemText(hMainWnd, IDE_SP_COMP, pRecord->Spouse, ADDRESSLEN);
  1468.     GetDlgItemText(hMainWnd, IDE_ADDRESS1, pRecord->Addrs1, ADDRESSLEN);
  1469.     GetDlgItemText(hMainWnd, IDE_ADDRESS2, pRecord->Addrs2, ADDRESSLEN);
  1470.     GetDlgItemText(hMainWnd, IDE_CITY, pRecord->City, CITYLEN);
  1471.     GetDlgItemText(hMainWnd, IDE_STATE, pRecord->State, STATELEN);
  1472.     GetDlgItemText(hMainWnd, IDE_ZIP, pRecord->Zip, ZIPLEN);
  1473.     GetDlgItemText(hMainWnd, IDE_PHONE1, pRecord->Phone1, PHONELEN);
  1474.     GetDlgItemText(hMainWnd, IDE_PHONE2, pRecord->Phone2, PHONELEN);
  1475.     GetDlgItemText(hMainWnd, IDE_LAST_DATE, pRecord->Date1, DATELEN);
  1476.     GetDlgItemText(hMainWnd, IDE_COMMENTS, pRecord->Comment, COMMENTLEN);
  1477.     return TRUE;
  1478. }
  1479.  
  1480. //======================================================================
  1481. //  Name:   FillDropList()
  1482. //
  1483. //  Input:  Window Handle (HWND), Cursor handle(hDBICur), Database Handle
  1484. //          (hDBIDb), Resource ID (UINT16), and Active Index name (pCHAR).
  1485. //
  1486. //  Return: The name of presently active index on the AddressBook table.
  1487. //
  1488. //  Desc:   This function fills the combobox represented by Id with the all
  1489. //          names that are open on the table.  It also returns the name
  1490. //          of the currently active index inside of the pszActiveIndex
  1491. //          string.
  1492. //======================================================================
  1493. UINT16
  1494. FillDropList (HWND hWnd, UINT16 iId, UINT16 iNumIdxs, pABIDXDESC pABIdxDesc,
  1495.               pCHAR pszIndex)
  1496. {
  1497.     UINT16  i;      // used for loop counter
  1498.     UINT32  lOff;
  1499.     UINT32  lIndex;
  1500.  
  1501.     // Fill the combobox with all the index names that are listed in the
  1502.     // pABIdxDesc structure.
  1503.     for(i=0; i<iNumIdxs ; i++)
  1504.     {
  1505.         lOff = ComboBox_AddString(GetDlgItem(hWnd, iId),
  1506.                                   pABIdxDesc[i].szTagName);
  1507.  
  1508.         // Send the listbox item its data.  The data is the offset of the
  1509.         // index name inside of the index structure.
  1510.         (void)ComboBox_SetItemData(GetDlgItem(hWnd, iId), lOff, i);
  1511.     }
  1512.  
  1513.     // Select the currently active index from the ComboBox.
  1514.     lOff = ComboBox_SelectString(GetDlgItem(hWnd, iId), -1, pszIndex);
  1515.  
  1516.     lIndex = ComboBox_GetItemData(GetDlgItem(hWnd, iId), lOff);
  1517.  
  1518.     // Set the description text into the static text box based upon
  1519.     // the active index's item data.
  1520.     if(iId == IDE_ORDER_COMBOBOX)
  1521.     {
  1522.          SetWindowText(GetDlgItem(hWnd, IDE_ORDER_INFO),
  1523.                        pABIdxDesc[(UINT16)lIndex].szKeyExp);
  1524.     }
  1525.  
  1526.     // Return the current index's order inside the index structure array.
  1527.     return (UINT16)lIndex;
  1528.  
  1529. }
  1530.  
  1531. //======================================================================
  1532. //  Name:   SetFNameFocus()
  1533. //
  1534. //  Input:  None.
  1535. //
  1536. //  Return: None.
  1537. //
  1538. //  Desc:   This function sets focus to the First Name edit control of
  1539. //          the main Window.
  1540. //======================================================================
  1541. void
  1542. SetFNameFocus (void)
  1543. {
  1544.     SetFocus(GetDlgItem(hMainWnd, IDE_FIRST_NAME));
  1545. }
  1546.  
  1547. //======================================================================
  1548. //  Name:   DeleteRecord()
  1549. //
  1550. //  Input:  Cursor handle (hDBICur).
  1551. //
  1552. //  Return: TRUE:   If the record is deleted.
  1553. //          FALSE:  If the record is not deleted.
  1554. //
  1555. //  Desc:   This function simply deletes the record that the cursor is
  1556. //          pointing to.  It then moves forward one record to get off the
  1557. //          crack that the deleted record created.
  1558. //======================================================================
  1559. BOOL
  1560. DeleteRecord (hDBICur hCur)
  1561. {
  1562.     BOOL bFlag = TRUE;
  1563.  
  1564.     if(DeleteRec(hCur)!=DBIERR_NONE)
  1565.     {
  1566.         bFlag = FALSE;
  1567.     }
  1568.  
  1569.     if(!AtEOF(hCur))
  1570.     {
  1571.         GetNextRec(hCur);
  1572.     }
  1573.     else
  1574.     {
  1575.         if(!AtBOF(hCur))
  1576.         {
  1577.             GetPrevRec(hCur);
  1578.         }
  1579.     }
  1580.  
  1581.     // Display the current record.
  1582.     DisplayTable(hCur);
  1583.     CheckButtons(hCur);
  1584.     return bFlag;
  1585. }
  1586.  
  1587. //======================================================================
  1588. //  Name:   SetControl()
  1589. //
  1590. //  Input:  Id resource(UINT16), and Set bool(BOOL).
  1591. //
  1592. //  Return: None.
  1593. //
  1594. //  Desc:   This function sets the button and menu option of the Id to the
  1595. //          bool value.
  1596. //======================================================================
  1597. void
  1598. SetControl (UINT16 iId, BOOL bSetMod)
  1599. {
  1600.     if(bSetMod)
  1601.     {
  1602.         if(!IsWindowEnabled(GetDlgItem(hMainWnd, iId)))
  1603.         {
  1604.             EnableWindow(GetDlgItem(hMainWnd, iId), bSetMod);
  1605.             EnableMenuItem(GetMenu(hMainWnd), iId, MF_ENABLED);
  1606.         }
  1607.     }
  1608.     else
  1609.     {
  1610.         if(IsWindowEnabled(GetDlgItem(hMainWnd, iId)))
  1611.         {
  1612.             EnableWindow(GetDlgItem(hMainWnd, iId), bSetMod);
  1613.             EnableMenuItem(GetMenu(hMainWnd), iId, MF_GRAYED);
  1614.         }    
  1615.     }
  1616. }
  1617.  
  1618. //======================================================================
  1619. //  Name:   ClearDlg()
  1620. //
  1621. //  Input:  None.
  1622. //
  1623. //  Return: TRUE:   If the memory allocation was successful.
  1624. //          FALSE:  If the memory allocation was unsuccessful.
  1625. //
  1626. //  Desc:   This function clears all the edit controls in the main Window.
  1627. //======================================================================
  1628. BOOL
  1629. ClearDlg (void)
  1630. {
  1631.     RecordType *pRecord;
  1632.  
  1633.     // Allocate a temporary record structure to use in clearing the
  1634.     // main Window.
  1635.     if((pRecord = (RecordType *) malloc(1 * sizeof(RecordType))) == NULL)
  1636.     {
  1637.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1638.         return FALSE;
  1639.     }
  1640.  
  1641.     // Clear the record structure so that we display an empty structure.
  1642.     memset(pRecord, 0, sizeof(RecordType));
  1643.  
  1644.     // Display the empty structure so that we clear the main Window.
  1645.     DispRec(pRecord);
  1646.     SetFNameFocus();
  1647.     free(pRecord);
  1648.     return TRUE;
  1649. }
  1650.  
  1651. //======================================================================
  1652. //  Name:   Varified()
  1653. //
  1654. //  Input:  None.
  1655. //
  1656. //  Return: TRUE:   If the memory allocation was successful and if the
  1657. //                  data is valid.
  1658. //
  1659. //          FALSE:  If the memory allocation was unsuccessful, or if
  1660. //                  the data is not valid.
  1661. //
  1662. //  Desc:   This function varifies if the data in the edit controls
  1663. //          are valid.
  1664. //======================================================================
  1665. BOOL
  1666. Varified (void)
  1667. {
  1668.     struct      dosdate_t d;
  1669.     pCHAR       pszFName;
  1670.     pCHAR       pszLName;
  1671.     pCHAR       pDate;
  1672.     pCHAR       pVal;
  1673.     BOOL        bRetVal;
  1674.     UINT        iFName;
  1675.     UINT        iLName;
  1676.     DBIDATE     TempDate;
  1677.     pFMTDate    pFmtDate;
  1678.     DBIResult   rslt;
  1679.  
  1680.     if((pszFName = (pCHAR) malloc(NAMELEN * sizeof(CHAR))) == NULL)
  1681.     {
  1682.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1683.         return FALSE;
  1684.     }
  1685.  
  1686.     if((pszLName = (pCHAR) malloc(NAMELEN * sizeof(CHAR))) == NULL)
  1687.     {
  1688.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1689.         free(pszFName);
  1690.         return FALSE;
  1691.     }
  1692.  
  1693.     if((pDate = (pCHAR) malloc(DATELEN * sizeof(CHAR))) == NULL)
  1694.     {
  1695.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1696.         free(pszFName);
  1697.         free(pszLName);
  1698.         return FALSE;
  1699.     }
  1700.  
  1701.     if((pFmtDate = (pFMTDate) malloc(sizeof(FMTDate))) == NULL)
  1702.     {
  1703.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1704.         free(pszFName);
  1705.         free(pszLName);
  1706.         free(pDate);
  1707.         return FALSE;
  1708.     }
  1709.  
  1710.     rslt = AdrGetDateFormat(pFmtDate);
  1711.     if(rslt!=DBIERR_NONE)
  1712.     {
  1713.         free(pszFName);
  1714.         free(pszLName);
  1715.         free(pDate);
  1716.         free(pFmtDate);
  1717.         return FALSE;
  1718.     }
  1719.  
  1720.     iFName = GetDlgItemText(hMainWnd, IDE_FIRST_NAME, pszFName, NAMELEN);
  1721.     iLName = GetDlgItemText(hMainWnd, IDE_LAST_NAME, pszLName, NAMELEN);
  1722.  
  1723.     // Check if there is data in the First and Last Name edit controls.
  1724.     if((iFName > 0) && (iLName >0))
  1725.     {
  1726.         bRetVal = TRUE;
  1727.     }
  1728.     else
  1729.     {
  1730.         bRetVal = FALSE;
  1731.     }
  1732.  
  1733.     GetDlgItemText(hMainWnd, IDE_LAST_DATE, pDate, DATELEN);
  1734.  
  1735.     // Need to convert the string to a Date structure
  1736.     pVal = strtok(pDate, pFmtDate->szDateSeparator);
  1737.     if(pVal && bRetVal)
  1738.     {
  1739.         d.month = (INT16)atoi(pVal);
  1740.         pVal = strtok(NULL, pFmtDate->szDateSeparator);
  1741.         if(pVal && bRetVal)
  1742.         {
  1743.             d.day = (INT16)atoi(pVal);
  1744.             pVal = strtok(NULL, pFmtDate->szDateSeparator);
  1745.             if(pVal && bRetVal)
  1746.             {
  1747.                 d.year = atoi(pVal);
  1748.             }
  1749.             else
  1750.             {
  1751.                 bRetVal = FALSE;
  1752.             }
  1753.         }
  1754.         else
  1755.         {
  1756.             bRetVal = FALSE;
  1757.         }
  1758.  
  1759.     }
  1760.     else
  1761.     {
  1762.         bRetVal = FALSE;
  1763.     }
  1764.  
  1765.     if(bRetVal)
  1766.     {
  1767.         // Check if the date is legal.
  1768.         rslt = DateEncode(d.month, d.day, d.year, &TempDate);
  1769.         if(rslt == DBIERR_NONE)
  1770.         {
  1771.             bRetVal = TRUE;
  1772.         }
  1773.         else
  1774.         {
  1775.             bRetVal = FALSE;
  1776.         }
  1777.     }
  1778.  
  1779.     free(pszFName);
  1780.     free(pszLName);
  1781.     free(pDate);
  1782.     free(pFmtDate);
  1783.  
  1784.     return bRetVal;
  1785. }
  1786.  
  1787. //======================================================================
  1788. //  Name:   SetDefaultDate()
  1789. //
  1790. //  Input:  None.
  1791. //
  1792. //  Return: None.
  1793. //
  1794. //  Desc:   This function puts the current date into the Last Date edit
  1795. //          control so that we have a valid date to start.
  1796. //======================================================================
  1797. DBIResult
  1798. SetDefaultDate (void)
  1799. {
  1800. #ifndef WIN32
  1801.     struct      dosdate_t d;
  1802. #else
  1803.     SYSTEMTIME  ST;
  1804. #endif
  1805.     pFMTDate    pFmtDate;
  1806.     CHAR        szDateString[DATELEN];
  1807.  
  1808.     if((pFmtDate = (pFMTDate) malloc(sizeof(FMTDate))) == NULL)
  1809.     {
  1810.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  1811.         return DBIERR_NOMEMORY;
  1812.     }
  1813.  
  1814.     CHKERR(AdrGetDateFormat(pFmtDate));
  1815. #ifndef WIN32
  1816.     _dos_getdate(&d);
  1817. #else
  1818.     GetLocalTime(&ST);
  1819. #endif
  1820.  
  1821.     if(pFmtDate->iDateMode==0)
  1822.     {
  1823. #ifndef WIN32
  1824.         wsprintf(szDateString, "%02d%s%02d%s%02d", d.month,
  1825.             pFmtDate->szDateSeparator, d.day, pFmtDate->szDateSeparator,
  1826.             d.year);
  1827. #else
  1828.         wsprintf(szDateString, "%02d%s%02d%s%02d", ST.wMonth,
  1829.             pFmtDate->szDateSeparator, ST.wDay, pFmtDate->szDateSeparator,
  1830.             ST.wYear);
  1831. #endif
  1832.     }
  1833.  
  1834.     if(pFmtDate->iDateMode==1)
  1835.     {
  1836. #ifndef WIN32
  1837.         wsprintf(szDateString, "%02d%s%02d%s%02d", d.day,
  1838.             pFmtDate->szDateSeparator, d.month, pFmtDate->szDateSeparator,
  1839.             d.year);
  1840. #else
  1841.         wsprintf(szDateString, "%02d%s%02d%s%02d", ST.wDay,
  1842.             pFmtDate->szDateSeparator, ST.wMonth, pFmtDate->szDateSeparator,
  1843.             ST.wYear);
  1844. #endif
  1845.     }
  1846.  
  1847.     if(pFmtDate->iDateMode==2)
  1848.     {
  1849. #ifndef WIN32
  1850.         wsprintf(szDateString, "%02d%s%02d%s%02d", d.year,
  1851.             pFmtDate->szDateSeparator, d.month, pFmtDate->szDateSeparator,
  1852.             d.day);
  1853. #else
  1854.         wsprintf(szDateString, "%02d%s%02d%s%02d", ST.wYear,
  1855.             pFmtDate->szDateSeparator, ST.wMonth, pFmtDate->szDateSeparator,
  1856.             ST.wDay);
  1857. #endif
  1858.     }
  1859.  
  1860.     SetDlgItemText(hMainWnd, IDE_LAST_DATE, szDateString);
  1861.     free(pFmtDate);
  1862.     return DBIERR_NONE;
  1863. }
  1864.  
  1865. //======================================================================
  1866. //  Name:   EndNewRec()
  1867. //
  1868. //  Input:  Cursor handle (hDBICur).
  1869. //
  1870. //  Return: None.
  1871. //
  1872. //  Desc:   This function is called during the end of the Add new person
  1873. //          function.  It changes the current state of the NewRecMode
  1874. //          global variable.  Then it checks the navigational controls
  1875. //          and sets focus unto the First Name edit control.
  1876. //======================================================================
  1877. void
  1878. EndNewRec (hDBICur hCur)
  1879. {
  1880.     ChangeEntryMode(hCur);
  1881.     DisplayTable(hCur);
  1882.     CheckButtons(hCur);
  1883.     SetFNameFocus();
  1884. }
  1885.  
  1886. //======================================================================
  1887. //  Name:   PutField()
  1888. //
  1889. //  Input:  Record structure pointer (RecordType *), pointer to the input
  1890. //          text (pCHAR), and Array element number (UINT16).
  1891. //
  1892. //  Return: None.
  1893. //
  1894. //  Desc:   This function puts input text into the correct field of the
  1895. //          record structure pointer based upon MemberNum.
  1896. //======================================================================
  1897. void
  1898. PutField (RecordType *pRec, pCHAR pszText, UINT iMemberNum)
  1899. {
  1900.     switch(iMemberNum)
  1901.     {
  1902.         case 0:
  1903.             strcpy(pRec->FName, pszText);
  1904.             break;
  1905.         case 1:
  1906.             strcpy(pRec->LName, pszText);
  1907.             break;
  1908.         case 2:
  1909.             strcpy(pRec->Spouse, pszText);
  1910.             break;
  1911.         case 3:
  1912.             strcpy(pRec->Addrs1, pszText);
  1913.             break;
  1914.         case 4:
  1915.             strcpy(pRec->Addrs2, pszText);
  1916.             break;
  1917.         case 5:
  1918.             strcpy(pRec->City, pszText);
  1919.             break;
  1920.         case 6:
  1921.             strcpy(pRec->State, pszText);
  1922.             break;
  1923.         case 7:
  1924.             strcpy(pRec->Zip, pszText);
  1925.             break;
  1926.         case 8:
  1927.             strcpy(pRec->Phone1, pszText);
  1928.             break;
  1929.         case 9:
  1930.             strcpy(pRec->Phone2, pszText);
  1931.             break;
  1932.         case 10:
  1933.             strcpy(pRec->Date1, pszText);
  1934.             break;
  1935.     }
  1936. }
  1937.  
  1938. //======================================================================
  1939. //  Name:   GetField()
  1940. //
  1941. //  Input:  Record structure pointer (RecordType *), pointer to the input
  1942. //          text (pCHAR), and Array element number (UINT16).
  1943. //
  1944. //  Return: None.
  1945. //
  1946. //  Desc:   This function gets data from the field in the record structure,
  1947. //          based upon the input variable - MemberNum.
  1948. //======================================================================
  1949. void
  1950. GetField (RecordType *pRec, pCHAR pszText, UINT16 iMemberNum)
  1951. {
  1952.     switch(iMemberNum)
  1953.     {
  1954.         case 0:
  1955.             strcpy(pszText, pRec->FName);
  1956.             break;
  1957.         case 1:
  1958.             strcpy(pszText, pRec->LName);
  1959.             break;
  1960.         case 2:
  1961.             strcpy(pszText, pRec->Spouse);
  1962.             break;
  1963.         case 3:
  1964.             strcpy(pszText, pRec->Addrs1);
  1965.             break;
  1966.         case 4:
  1967.             strcpy(pszText, pRec->Addrs2);
  1968.             break;
  1969.         case 5:
  1970.             strcpy(pszText, pRec->City);
  1971.             break;
  1972.         case 6:
  1973.             strcpy(pszText, pRec->State);
  1974.             break;
  1975.         case 7:
  1976.             strcpy(pszText, pRec->Zip);
  1977.             break;
  1978.         case 8:
  1979.             strcpy(pszText, pRec->Phone1);
  1980.             break;
  1981.         case 9:
  1982.             strcpy(pszText, pRec->Phone2);
  1983.             break;
  1984.         case 10:
  1985.             strcpy(pszText, pRec->Date1);
  1986.             break;
  1987.     }
  1988. }
  1989.  
  1990. //======================================================================
  1991. //  Name:   GetCond()
  1992. //
  1993. //  Input:  Handle to the window that has the check boxes.
  1994. //
  1995. //  Return: Which check box is checked.
  1996. //
  1997. //  Desc:   This function simply returns a number based upon which check
  1998. //          box is checked.
  1999. //======================================================================
  2000. DBISearchCond
  2001. GetCond (HWND hWnd)
  2002. {
  2003.     DBISearchCond   eRet;
  2004.     UINT32          iCond=0;
  2005.     UINT16          i=IDC_GREATEREQ;
  2006.  
  2007.     while(iCond!=1)
  2008.     {
  2009.         iCond = Button_GetCheck(GetDlgItem(hWnd, i));
  2010.         i++;
  2011.     }
  2012.  
  2013.     // Subtract 1 to counteract the last i++
  2014.     i--;
  2015.  
  2016.     switch(i)
  2017.     {
  2018.         case IDC_EQUAL:
  2019.             eRet = keySEARCHEQ;
  2020.             break;
  2021.         case IDC_GREATER:
  2022.             eRet = keySEARCHGT;
  2023.             break;
  2024.         case IDC_GREATEREQ:
  2025.             eRet = keySEARCHGEQ;
  2026.             break;
  2027.     }
  2028.  
  2029.     return eRet;
  2030. }
  2031.  
  2032. //======================================================================
  2033. //  Name:   CanContinue()
  2034. //
  2035. //  Input:  Pointer to the string that is to be displayed (pCHAR), and
  2036. //          a resource ID (UINT16).
  2037. //
  2038. //  Return: If the resource is enabled, then it returns the user's response.
  2039. //          Otherwise, it returns a TRUE.
  2040. //
  2041. //  Desc:   This function checks if the Id is enabled.  If it is then it
  2042. //          prompts the user with the pString and returns the response.
  2043. //          Otherwise it returns a TRUE.
  2044. //======================================================================
  2045. BOOL
  2046. CanContinue (pCHAR pszString, UINT16 iId)
  2047. {
  2048.     BOOL bRetVal = TRUE;
  2049.  
  2050.     // Check to see if the button is enabled.
  2051.     if(IsWindowEnabled(GetDlgItem(hMainWnd, iId)))
  2052.     {
  2053.         if(WinMsg(pszString, MB_ICONHAND, MB_YESNO) == IDNO)
  2054.         {
  2055.             bRetVal = FALSE;
  2056.         }
  2057.     }
  2058.     return bRetVal;
  2059. }
  2060.  
  2061. //=========================================================================
  2062. //  Function:   FillAliasCBBox()
  2063. //
  2064. //  Input:      Pointer to the Alias Structures(pDBDesc), Number of aliases
  2065. //              (UINT32), and the Combo Box's ID to fill (UINT16)
  2066. //
  2067. //  Returns:    None
  2068. //
  2069. //  Desc:       This function is used to fill the CB whose ID is CBId.  The
  2070. //              CB is filled with the Aliases that are available to the
  2071. //              client.
  2072. //=========================================================================
  2073. void
  2074. FillAliasCBBox (pDBDesc pAliases, UINT32 lNumAliases, UINT16 iCBId,
  2075.                 HWND hWnd)
  2076. {
  2077.     UINT16  i;
  2078.     UINT32  lSel;
  2079.     CHAR    szString[]="NULL - Std Tables";
  2080.  
  2081.     // First put all the aliases into the CB.
  2082.     for(i=0; i<(UINT16)lNumAliases; i++)
  2083.     {
  2084.         (void)ComboBox_AddString(GetDlgItem(hWnd, iCBId), pAliases[i].szName);
  2085.     }
  2086.  
  2087.     // Now add the NULL alias which is the local tables.
  2088.     (void)ComboBox_AddString(GetDlgItem(hWnd, iCBId), szString);
  2089.  
  2090.     // Now get the Paradox item number and display Paradox in the Alias CB.
  2091.     lSel = ComboBox_FindString(GetDlgItem(hWnd, iCBId), -1, szString);
  2092.     (void)ComboBox_SetCurSel(GetDlgItem(hWnd, iCBId), lSel);
  2093. }
  2094.  
  2095. //=========================================================================
  2096. //  Function:   FillFileList()
  2097. //
  2098. //  Input:      Window handle(HWND), Number of tables to display (UINT32),
  2099. //              Handle of the database (hDBIDb).
  2100. //
  2101. //  Returns:    TRUE if the names of the table are uppercase on the server.
  2102. //              FALSE if the names of the table are lowercase on the server.
  2103. //
  2104. //  Desc:       This function is used to fill the listbox whose ID is LBId
  2105. //              with all the table names who are available to the database
  2106. //              (hDb).  We use this to fill the list box in the common
  2107. //              dialogbox with all the table names in the remote database.
  2108. //=========================================================================
  2109. BOOL
  2110. FillFileList (HWND hWnd, UINT16 iLBId, hDBIDb hDb)
  2111. {
  2112.     hDBICur     hTblCur;
  2113.     BOOL        bRet = TRUE;
  2114.     TBLBaseDesc baseDesc;
  2115.  
  2116.     HourGlassCursor(TRUE);
  2117.  
  2118.     GetTableList(hDb, &hTblCur);
  2119.  
  2120.     // Go to the top of the table.
  2121.     GoTop(hTblCur, FALSE);
  2122.  
  2123.     // Put all the Tablenames into the Filelist.
  2124.     while((GetNextTblRec(hTblCur, &baseDesc))!=DBIERR_EOF)
  2125.     {
  2126.         (void)ListBox_AddString(GetDlgItem(hWnd, iLBId), baseDesc.szName);
  2127.     }
  2128.  
  2129.     if(islower(baseDesc.szName[0]))
  2130.     {
  2131.         bRet = FALSE;
  2132.     }
  2133.  
  2134.     CloseTable(&hTblCur);
  2135.  
  2136.     HourGlassCursor(FALSE);
  2137.  
  2138.     return bRet;
  2139. }
  2140.  
  2141. //=========================================================================
  2142. //  Function:   SetFieldNames()
  2143. //
  2144. //  Input:      Cursor handle (hDBICur).
  2145. //
  2146. //  Returns:    None
  2147. //
  2148. //  Desc:       This function is used to set the field names into the dialog
  2149. //              box.  It gets the field names and displays them in proper
  2150. //              format with a trailing :.
  2151. //=========================================================================
  2152. void
  2153. SetFieldNames (hDBICur hCur)
  2154. {
  2155.     UINT16          i;
  2156.     pFIELDName      pFieldNames;
  2157.     CHAR            szName[DBIMAXTBLNAMELEN];
  2158.  
  2159.     if((pFieldNames = (pFIELDName) malloc(sizeof(FIELDNAME) * uNumFields))
  2160.                     == NULL)
  2161.     {
  2162.         WinMsg("You have run out of memory!", MB_ICONHAND, MB_OK);
  2163.         return;
  2164.     }
  2165.  
  2166.     // Get the field names and the amount of fields.
  2167.     GetFldNames(hCur, pFieldNames);
  2168.  
  2169.     for(i=0; i<uNumFields; i++)
  2170.     {
  2171.         strcat(pFieldNames[i].FieldName, ":");
  2172.     }
  2173.  
  2174.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD1),
  2175.                   Proper(pFieldNames[0].FieldName));
  2176.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD2),
  2177.                   Proper(pFieldNames[1].FieldName));
  2178.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD3),
  2179.                   Proper(pFieldNames[2].FieldName));
  2180.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD4),
  2181.                   Proper(pFieldNames[3].FieldName));
  2182.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD5),
  2183.                   Proper(pFieldNames[4].FieldName));
  2184.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD6),
  2185.                   Proper(pFieldNames[5].FieldName));
  2186.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD7),
  2187.                   Proper(pFieldNames[6].FieldName));
  2188.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD8),
  2189.                   Proper(pFieldNames[7].FieldName));
  2190.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD9),
  2191.                   Proper(pFieldNames[8].FieldName));
  2192.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD10),
  2193.                   Proper(pFieldNames[9].FieldName));
  2194.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD11),
  2195.                   Proper(pFieldNames[10].FieldName));
  2196.     SetWindowText(GetDlgItem(hMainWnd, IDS_FIELD12),
  2197.                   Proper(pFieldNames[11].FieldName));
  2198.  
  2199.     memset(szName, 0, DBIMAXTBLNAMELEN);
  2200.     strcpy(szName, szTblName);
  2201.     SetWindowText(GetDlgItem(hMainWnd, IDS_TABLENAME),
  2202.                   Proper((pCHAR)szName));
  2203.     SetWindowText(GetDlgItem(hMainWnd, IDS_DBTYPE), (pCHAR)szTblType);
  2204.  
  2205.     free(pFieldNames);
  2206. }
  2207.  
  2208. //=========================================================================
  2209. //  Function:   Proper()
  2210. //
  2211. //  Input:      String to properize (pCHAR).
  2212. //
  2213. //  Returns:    Properized string (pCHAR).
  2214. //
  2215. //  Desc:       This function is used to change the case of a string.  When
  2216. //              the function returns the string - the string will have its
  2217. //              first letter put into uppercase while the rest of the
  2218. //              letters will be in lowercase.
  2219. //=========================================================================
  2220. pCHAR
  2221. Proper (pCHAR pszString)
  2222. {
  2223.     CHAR    szFirst[3];
  2224.  
  2225.     // First set all the letters lowercase.
  2226.     strlwr(pszString);
  2227.  
  2228.     // Next clear the temporary string.
  2229.     memset(szFirst, '\0', 3);
  2230.  
  2231.     // Next get first letter in the string to convert into uppercase.
  2232.     szFirst[0] = pszString[0];
  2233.  
  2234.     strcat(szFirst, " \0");
  2235.  
  2236.     // Uppercase the temporary string.
  2237.     strupr(szFirst);
  2238.  
  2239.     // Copy the first letter of the temporary string into the first letter
  2240.     // of the string to convert.
  2241.     pszString[0] = szFirst[0];
  2242.  
  2243.     return pszString;
  2244. }
  2245.  
  2246.  
  2247. //=========================================================================
  2248. //  Function:   SetAll()
  2249. //
  2250. //  Input:      Action to take (BOOL).
  2251. //
  2252. //  Returns:    None.
  2253. //
  2254. //  Desc:       This function is used to set the various controls off or on,
  2255. //              based upon the the value sent in.
  2256. //=========================================================================
  2257. void
  2258. SetAll (BOOL bAction)
  2259. {
  2260.     SetControl(ID_FIRST_REC, bAction);
  2261.     SetControl(ID_PREV_REC, bAction);
  2262.     SetControl(ID_NEXT_REC, bAction);
  2263.     SetControl(ID_LAST_REC, bAction);
  2264.     SetControl(ID_ADD_REC, bAction);
  2265.     SetControl(ID_DEL_REC, bAction);
  2266.     SetControl(ID_MOD_REC, bAction);
  2267.     SetControl(ID_ORDER, bAction);
  2268.     SetControl(ID_RANGE, bAction);
  2269.     EnableMenuItem(GetMenu(hMainWnd), ID_CLEAR_RANGE, MF_GRAYED);
  2270.     if(bAction)
  2271.     {
  2272.         EnableMenuItem(GetMenu(hMainWnd), ID_DELETETABLE, MF_ENABLED);
  2273.     }
  2274.     else
  2275.     {
  2276.         EnableMenuItem(GetMenu(hMainWnd), ID_DELETETABLE, MF_GRAYED);
  2277.         SetWindowText(GetDlgItem(hMainWnd, IDS_TABLENAME), (pCHAR)"");
  2278.         SetWindowText(GetDlgItem(hMainWnd, IDS_DBTYPE), (pCHAR)"");
  2279.     }
  2280.     SetControl(ID_SEARCH, bAction);
  2281.     SetControl(ID_UNDO_REC, bAction);
  2282. }
  2283.  
  2284. //======================================================================
  2285. //  Name:   HourGlassCursor()
  2286. //
  2287. //  Input:  turnOn  - Turn on or off the Hourglass cursor
  2288. //
  2289. //  Return: TRUE
  2290. //
  2291. //  Description:
  2292. //          Turns the hourglass cursor on or off according to value
  2293. //          specified in turnOn.
  2294. //======================================================================
  2295. BOOL 
  2296. HourGlassCursor (BOOL bTurnOn)
  2297. {
  2298.     if (bTurnOn)
  2299.     {
  2300.        if (SetCursor(LoadCursor(NULL, IDC_WAIT)))
  2301.        {
  2302.            ShowCursor(TRUE);
  2303.        }
  2304.     }
  2305.     else
  2306.     {
  2307.         if (SetCursor(LoadCursor(NULL, IDC_ARROW)))
  2308.         {
  2309.             ShowCursor(TRUE);
  2310.         }
  2311.     }
  2312.     return TRUE;
  2313. }
  2314.