home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / d / d020_1_4 / 5.ddi / EDITFILE / EDITFILE.C next >
Encoding:
C/C++ Source or Header  |  1990-06-01  |  31.3 KB  |  988 lines

  1. /****************************************************************************
  2.  
  3.     PROGRAM: EditFile.c
  4.  
  5.     PURPOSE: Loads, saves, and edits text files
  6.  
  7.     FUNCTIONS:
  8.  
  9.         WinMain() - calls initialization function, processes message loop
  10.         InitApplication() - initializes window data and registers window
  11.         InitInstance() - saves instance handle and creates main window
  12.         MainWndProc() - processes messages
  13.         About() - processes messages for "About" dialog box
  14.         SaveAsDlg() - save file under different name
  15.         OpenDlg() - let user select a file, and open it.
  16.         UpdateListBox() - Update the list box of OpenDlg
  17.         ChangeDefExt() - Change the default extension
  18.         SeparateFile() - Separate filename and pathname
  19.         AddExt() - Add default extension
  20.         CheckFileName() - Check for wildcards, add extension if needed
  21.         SaveFile() - Save current file
  22.         QuerySaveFile() - Called when some action might lose current contents
  23.         SetNewBuffer() - Set new buffer for edit window
  24.  
  25. ****************************************************************************/
  26.  
  27. #include "windows.h"
  28. #include "editfile.h"
  29.  
  30. HANDLE hInst;
  31.  
  32. HANDLE hAccTable;                                /* handle to accelerator table */
  33. HWND hEditWnd;                                      /* handle to edit window */
  34. /* Additional includes needed for the fstat() function */
  35.  
  36. #include <sys\types.h>
  37. #include <sys\stat.h>
  38.  
  39. char FileName[128];
  40. char PathName[128];
  41. char OpenName[128];
  42. char DefPath[128];
  43. char DefSpec[13] = "*.*";
  44. char DefExt[] = ".txt";
  45. char str[255];
  46.  
  47. HANDLE hEditBuffer;                       /* handle to editing buffer      */
  48. HANDLE hOldBuffer;                        /* old buffer handle        */
  49. HANDLE hHourGlass;                        /* handle to hourglass cursor      */
  50. HANDLE hSaveCursor;                       /* current cursor handle      */
  51. int hFile;                                /* file handle              */
  52. int count;                                /* number of chars read or written */
  53. PSTR pBuffer;                             /* address of read/write buffer    */
  54. OFSTRUCT OfStruct;                        /* information from OpenFile()     */
  55. struct stat FileStatus;                   /* information from fstat()      */
  56. BOOL bChanges = FALSE;                    /* TRUE if the file is changed     */
  57. BOOL bSaveEnabled = FALSE;                /* TRUE if text in the edit buffer */
  58. PSTR pEditBuffer;                         /* address of the edit buffer      */
  59. RECT Rect;                                /* dimension of the client window  */
  60. HWND hwnd;                                /* handle to main window           */
  61.  
  62.  
  63. char Untitled[] =                         /* default window title      */
  64.      "Edit File - (untitled)";
  65.  
  66. /****************************************************************************
  67.  
  68.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  69.  
  70.     PURPOSE: calls initialization function, processes message loop
  71.  
  72. ****************************************************************************/
  73.  
  74. int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  75. HANDLE hInstance;
  76. HANDLE hPrevInstance;
  77. LPSTR lpCmdLine;
  78. int nCmdShow;
  79. {
  80.     MSG msg;
  81.  
  82.     if (!hPrevInstance)
  83.         if (!InitApplication(hInstance))
  84.             return (FALSE);
  85.  
  86.     if (!InitInstance(hInstance, nCmdShow))
  87.         return (FALSE);
  88.  
  89.     while (GetMessage(&msg, NULL, NULL, NULL)) {
  90.  
  91.     /* Only translate message if it is not an accelerator message */
  92.  
  93.         if (!TranslateAccelerator(hwnd, hAccTable, &msg)) {
  94.             TranslateMessage(&msg);
  95.             DispatchMessage(&msg); 
  96.         }
  97.     }
  98.     return (msg.wParam);
  99. }
  100.  
  101.  
  102. /****************************************************************************
  103.  
  104.     FUNCTION: InitApplication(HANDLE)
  105.  
  106.     PURPOSE: Initializes window data and registers window class
  107.  
  108. ****************************************************************************/
  109.  
  110. BOOL InitApplication(hInstance)
  111. HANDLE hInstance;
  112. {
  113.     WNDCLASS  wc;
  114.  
  115.     wc.style = NULL;
  116.     wc.lpfnWndProc = MainWndProc;
  117.     wc.cbClsExtra = 0;
  118.     wc.cbWndExtra = 0;
  119.     wc.hInstance = hInstance;
  120.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  121.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  122.     wc.hbrBackground = GetStockObject(WHITE_BRUSH); 
  123.     wc.lpszMenuName =  "EditFileMenu";
  124.     wc.lpszClassName = "EditFileWClass";
  125.  
  126.     return (RegisterClass(&wc));
  127. }
  128.  
  129.  
  130. /****************************************************************************
  131.  
  132.     FUNCTION:  InitInstance(HANDLE, int)
  133.  
  134.     PURPOSE:  Saves instance handle and creates main window
  135.  
  136. ****************************************************************************/
  137.  
  138. BOOL InitInstance(hInstance, nCmdShow)
  139.     HANDLE          hInstance;
  140.     int             nCmdShow;
  141. {
  142.     RECT            Rect;
  143.  
  144.     hInst = hInstance;
  145.  
  146.     hAccTable = LoadAccelerators(hInst, "EditFileAcc");
  147.  
  148.     hwnd = CreateWindow(
  149.         "EditFileWClass",
  150.         "EditFile Sample Application",
  151.         WS_OVERLAPPEDWINDOW,
  152.         CW_USEDEFAULT,
  153.         CW_USEDEFAULT,
  154.         CW_USEDEFAULT,
  155.         CW_USEDEFAULT,
  156.         NULL,
  157.         NULL,
  158.         hInstance,
  159.         NULL
  160.     );
  161.  
  162.     if (!hwnd)
  163.         return (FALSE);
  164.  
  165.     GetClientRect(hwnd, (LPRECT) &Rect);
  166.  
  167.     /* Create a child window */
  168.  
  169.     hEditWnd = CreateWindow("Edit",
  170.         NULL,
  171.         WS_CHILD | WS_VISIBLE |
  172.         ES_MULTILINE |
  173.         WS_VSCROLL | WS_HSCROLL |
  174.         ES_AUTOHSCROLL | ES_AUTOVSCROLL,
  175.         0,
  176.         0,
  177.         (Rect.right-Rect.left),
  178.         (Rect.bottom-Rect.top),
  179.         hwnd,
  180.         IDC_EDIT,                          /* Child control i.d. */
  181.         hInst,
  182.         NULL);
  183.  
  184.     if (!hEditWnd) {
  185.         DestroyWindow(hwnd);
  186.         return (NULL);
  187.     }
  188.  
  189.     /* Get an hourglass cursor to use during file transfers */
  190.  
  191.     hHourGlass = LoadCursor(NULL, IDC_WAIT);
  192.     
  193.     ShowWindow(hwnd, nCmdShow);
  194.     UpdateWindow(hwnd);
  195.     return (TRUE);
  196.  
  197. }
  198.  
  199. /****************************************************************************
  200.  
  201.     FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
  202.  
  203.     PURPOSE:  Processes messages
  204.  
  205.     MESSAGES:
  206.  
  207.         WM_COMMAND    - application menu (About dialog box)
  208.         WM_DESTROY    - destroy window
  209.         WM_SIZE       - window size has changed
  210.         WM_QUERYENDSESSION - willing to end session?
  211.         WM_ENDSESSION - end Windows session
  212.         WM_CLOSE      - close the window
  213.         WM_SIZE       - window resized
  214.  
  215.     COMMENTS:
  216.  
  217.         WM_COMMAND processing:
  218.  
  219.             IDM_NEW - query to save current file if there is one and it has
  220.                       been changed, clear buffer and start new file.
  221.  
  222.             IDM_OPEN - query to save current file if there is one and it
  223.                        has been changed, open a new file.
  224.  
  225.             IDM_SAVE - save current file, prompt for name if none exists.
  226.  
  227.             IDM_SAVEAS - prompt for new filename to save to, save file.
  228.  
  229.             IDC_EDIT - change "bChanges" flag to indicate if edit buffer has
  230.                       been modified.  Affects actions of IDM_NEW and
  231.                       IDM_OPEN.  Reset when file is saved.
  232.  
  233.             IDM_EXIT - query to save current file if there is one and it
  234.                        has been changed, then exit.
  235.  
  236.             IDM_ABOUT - display "About" box.
  237.  
  238.         When more then one string needs to be sent to a message box,
  239.         sprintf() is used to combine the strings into str[], and then str[]
  240.         is passed to the MessageBox() function.  A message box string cannot
  241.         exceed 255 characters, but may contain \n to generate separate
  242.         lines.
  243.  
  244.         After the size of the file is determined, only enough memory to store
  245.         the file is allocated for the Edit buffer.  The edit control will
  246.         automatically expand this memory as needed.  Once the file has been
  247.         read into the edit buffer, unlock the memory.  Use whatever was
  248.         obtained from the read() function, even if an error occured.  This
  249.         allows partial salvage of a file with a bad sector.
  250.  
  251. ****************************************************************************/
  252.  
  253. long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
  254. HWND hWnd;
  255. unsigned message;
  256. WORD wParam;
  257. LONG lParam;
  258. {
  259.     FARPROC lpProcAbout, lpOpenDlg, lpSaveAsDlg;
  260.  
  261.     int Success;                            /* return value from SaveAsDlg() */
  262.     int IOStatus;                           /* result of file i/o      */
  263.  
  264.  
  265.     switch (message) {
  266.         case WM_COMMAND:
  267.             switch (wParam) {
  268.                 case IDM_ABOUT:
  269.                     lpProcAbout = MakeProcInstance(About, hInst);
  270.                     DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
  271.                     FreeProcInstance(lpProcAbout);
  272.                     break;
  273.  
  274.                 case IDM_NEW:
  275.  
  276.                     /* If current file has been modified, query user about
  277.                      * saving it.
  278.                      */
  279.  
  280.                     if (!QuerySaveFile(hWnd))
  281.                         return (NULL);
  282.  
  283.                     /* bChanges is set to FALSE to indicate there have been
  284.                      * no changes since the last file save.
  285.                      */
  286.  
  287.                     bChanges = FALSE;
  288.                     FileName[0] = 0;
  289.  
  290.                     /* Update the edit buffer */
  291.  
  292.                     SetNewBuffer(hWnd, NULL, Untitled);
  293.                     break;
  294.  
  295.                 case IDM_OPEN:
  296.                     if (!QuerySaveFile(hWnd))
  297.                         return (NULL);
  298.  
  299.                     lpOpenDlg = MakeProcInstance((FARPROC) OpenDlg, hInst);
  300.  
  301.                     /* Open the file and get its handle */
  302.  
  303.                     hFile = DialogBox(hInst, "Open", hWnd, lpOpenDlg);
  304.                     FreeProcInstance(lpOpenDlg);
  305.                     if (!hFile)
  306.                         return (NULL);
  307.  
  308.                     /* Allocate edit buffer to the size of the file + 1 */
  309.  
  310.                     hEditBuffer =
  311.                         LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,
  312.                 (WORD)(FileStatus.st_size+1));
  313.  
  314.                     if (!hEditBuffer) {
  315.                         MessageBox(hWnd, "Not enough memory.",
  316.                             NULL, MB_OK | MB_ICONHAND);
  317.                         return (NULL);
  318.                     }
  319.                     hSaveCursor = SetCursor(hHourGlass);
  320.                     pEditBuffer = LocalLock(hEditBuffer);
  321.  
  322.                     IOStatus = read(hFile, pEditBuffer, FileStatus.st_size);
  323.                     close(hFile);
  324.  
  325.                     /* # bytes read must equal file size */
  326.  
  327.                     if (IOStatus != FileStatus.st_size) {
  328.  
  329.                         sprintf(str, "Error reading %s.", FileName);
  330.                         SetCursor(hSaveCursor);      /* Remove the hourglass */
  331.                         MessageBox(hWnd, str, NULL, MB_OK | MB_ICONEXCLAMATION);
  332.                     }
  333.  
  334.                     LocalUnlock(hEditBuffer);
  335.  
  336.                     /* Set up a new buffer and window title */
  337.  
  338.                     sprintf(str, "EditFile - %s", FileName);
  339.                     SetNewBuffer(hWnd, hEditBuffer, str);
  340.                     SetCursor(hSaveCursor);            /* restore the cursor */
  341.                     break;
  342.  
  343.                 case IDM_SAVE:
  344.  
  345.                     /* If there is no filename, use the saveas command to get
  346.                      * one.  Otherwise, save the file using the current
  347.                      * filename.
  348.                      */
  349.  
  350.                     if (!FileName[0])
  351.                         goto saveas;
  352.                     if (bChanges)
  353.                         SaveFile(hWnd);
  354.                     break;
  355.  
  356.                 case IDM_SAVEAS:
  357. saveas:
  358.                     lpSaveAsDlg = MakeProcInstance(SaveAsDlg, hInst);
  359.  
  360.                     /* Call the SaveAsDlg() function to get the new filename */
  361.  
  362.                     Success = DialogBox(hInst, "SaveAs", hWnd, lpSaveAsDlg);
  363.                     FreeProcInstance(lpSaveAsDlg);
  364.  
  365.                     /* If successful, update the window title, save the file */
  366.  
  367.                     if (Success == IDOK) {
  368.                         sprintf(str, "EditFile - %s", FileName);
  369.                         SetWindowText(hWnd, str);
  370.                         SaveFile(hWnd);
  371.                     }
  372.                     break;                                  /* User canceled */
  373.                 case IDM_PRINT:
  374.                     MessageBox (
  375.                           GetFocus(),
  376.                           "Command not implemented",
  377.                           "EditFile Sample Application",
  378.                           MB_ICONASTERISK | MB_OK);
  379.                     break;  
  380.  
  381.                 /* edit menu commands */
  382.  
  383.                 case IDM_UNDO:
  384.                 case IDM_CUT:
  385.                 case IDM_COPY:
  386.                 case IDM_PASTE:
  387.                 case IDM_CLEAR:
  388.                     MessageBox (
  389.                           GetFocus(),
  390.                           "Command not implemented",
  391.                           "EditFile Sample Application",
  392.                           MB_ICONASTERISK | MB_OK);
  393.                     break;  
  394.  
  395.                 case IDM_EXIT:
  396.                     QuerySaveFile(hWnd);
  397.                     DestroyWindow(hWnd);
  398.                     break;
  399.  
  400.                 case IDC_EDIT:
  401.                     if (HIWORD (lParam) == EN_ERRSPACE) {
  402.                         MessageBox (
  403.                               GetFocus ()
  404.                             , "Out of memory."
  405.                             , "EditFile Sample Application"
  406.                             , MB_ICONHAND | MB_OK
  407.                         );
  408.                     }
  409.                     break;
  410.  
  411.             } 
  412.             break;
  413.  
  414.         case WM_SETFOCUS:
  415.             SetFocus (hEditWnd);
  416.             break;
  417.  
  418.         case WM_SIZE:
  419.             MoveWindow(hEditWnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
  420.             break;
  421.  
  422.         case WM_QUERYENDSESSION:             /* message: to end the session? */
  423.             return (QuerySaveFile(hWnd));
  424.  
  425.         case WM_CLOSE:                       /* message: close the window    */
  426.             if (QuerySaveFile(hWnd))
  427.                 DestroyWindow(hWnd);
  428.             break;
  429.  
  430.         case WM_DESTROY:
  431.             PostQuitMessage(0);
  432.             break;
  433.  
  434.         default:
  435.             return (DefWindowProc(hWnd, message, wParam, lParam));
  436.     }
  437.     return (NULL);
  438. }
  439.  
  440. /****************************************************************************
  441.  
  442.     FUNCTION: SaveAsDlg(HWND, unsigned, WORD, LONG)
  443.  
  444.     PURPOSE: Allows user to change name to save file to
  445.  
  446.     COMMENTS:
  447.  
  448.         This will initialize the window class if it is the first time this
  449.         application is run.  It then creates the window, and processes the
  450.         message loop until a PostQuitMessage is received.  It exits the
  451.         application by returning the value passed by the PostQuitMessage.
  452.  
  453. ****************************************************************************/
  454.  
  455. int FAR PASCAL SaveAsDlg(hDlg, message, wParam, lParam)
  456. HWND hDlg;
  457. unsigned message;
  458. WORD wParam;
  459. LONG lParam;
  460. {
  461.     char TempName[128];
  462.  
  463.     switch (message) {
  464.         case WM_INITDIALOG:
  465.  
  466.             /* If no filename is entered, don't allow the user to save to it */
  467.  
  468.             if (!FileName[0])
  469.                 bSaveEnabled = FALSE;
  470.             else {
  471.                 bSaveEnabled = TRUE;
  472.  
  473.                 /* Process the path to fit within the IDC_PATH field */
  474.  
  475.                 DlgDirList(hDlg, DefPath, NULL, IDC_PATH, 0x4010);
  476.  
  477.                 /* Send the current filename to the edit control */
  478.  
  479.                 SetDlgItemText(hDlg, IDC_EDIT, FileName);
  480.  
  481.                 /* Accept all characters in the edit control */
  482.  
  483.                 SendDlgItemMessage(hDlg, IDC_EDIT, EM_SETSEL, 0,
  484.                     MAKELONG(0, 0x7fff));
  485.             }
  486.  
  487.             /* Enable or disable the save control depending on whether the
  488.              * filename exists.
  489.              */
  490.  
  491.             EnableWindow(GetDlgItem(hDlg, IDOK), bSaveEnabled);
  492.  
  493.             /* Set the focus to the edit control within the dialog box */
  494.  
  495.             SetFocus(GetDlgItem(hDlg, IDC_EDIT));
  496.             return (FALSE);                 /* FALSE since Focus was changed */
  497.  
  498.         case WM_COMMAND:
  499.             switch (wParam) {
  500.                 case IDC_EDIT:
  501.  
  502.                     /* If there was previously no filename in the edit
  503.                      * control, then the save control must be enabled as soon as
  504.                      * a character is entered.
  505.                      */
  506.  
  507.                     if (HIWORD(lParam) == EN_CHANGE && !bSaveEnabled)
  508.                     EnableWindow(GetDlgItem(hDlg, IDOK), bSaveEnabled = TRUE);
  509.                     return (TRUE);
  510.  
  511.                 case IDOK:
  512.  
  513.                    /* Get the filename from the edit control */
  514.  
  515.                     GetDlgItemText(hDlg, IDC_EDIT, TempName, 128);
  516.  
  517.                     /* If there are no wildcards, then separate the name into
  518.                      * path and name.  If a path was specified, replace the
  519.                      * default path with the new path.
  520.                      */
  521.  
  522.                     if (CheckFileName(hDlg, FileName, TempName)) {
  523.                         SeparateFile(hDlg, (LPSTR) str, (LPSTR) DefSpec,
  524.                             (LPSTR) FileName);
  525.                         if (str[0])
  526.                             strcpy(DefPath, str);
  527.  
  528.                         /* Tell the caller a filename was selected */
  529.  
  530.                         EndDialog(hDlg, IDOK);
  531.                     }
  532.                     return (TRUE);
  533.  
  534.                 case IDCANCEL:
  535.  
  536.                     /* Tell the caller the user canceled the SaveAs function */
  537.  
  538.                     EndDialog(hDlg, IDCANCEL);
  539.                     return (TRUE);
  540.             }
  541.             break;
  542.  
  543.     }
  544.     return (FALSE);
  545. }
  546.  
  547. /****************************************************************************
  548.  
  549.     FUNCTION: OpenDlg(HWND, unsigned, WORD, LONG)
  550.  
  551.     PURPOSE: Let user select a file, and open it.
  552.  
  553. ****************************************************************************/
  554.  
  555. HANDLE FAR PASCAL OpenDlg(hDlg, message, wParam, lParam)
  556. HWND hDlg;
  557. unsigned message;
  558. WORD wParam;
  559. LONG lParam;
  560. {
  561.     WORD index;
  562.     PSTR pTptr;
  563.     HANDLE hFile;
  564.  
  565.     switch (message) {
  566.         case WM_COMMAND:
  567.             switch (wParam) {
  568.  
  569.                 case IDC_LISTBOX:
  570.                     switch (HIWORD(lParam)) {
  571.  
  572.                         case LBN_SELCHANGE:
  573.                             /* If item is a directory name, append "*.*" */
  574.                             if (DlgDirSelect(hDlg, str, IDC_LISTBOX)) 
  575.                                 strcat(str, DefSpec);
  576.  
  577.                             SetDlgItemText(hDlg, IDC_EDIT, str);
  578.                             SendDlgItemMessage(hDlg,
  579.                                 IDC_EDIT,
  580.                                 EM_SETSEL,
  581.                                 NULL,
  582.                                 MAKELONG(0, 0x7fff));
  583.                             break;
  584.  
  585.                         case LBN_DBLCLK:
  586.                             goto openfile;
  587.                     }
  588.                     return (TRUE);
  589.  
  590.                 case IDOK:
  591. openfile:
  592.                     GetDlgItemText(hDlg, IDC_EDIT, OpenName, 128);
  593.                     if (strchr(OpenName, '*') || strchr(OpenName, '?')) {
  594.                         SeparateFile(hDlg, (LPSTR) str, (LPSTR) DefSpec,
  595.                             (LPSTR) OpenName);
  596.                         if (str[0])
  597.                             strcpy(DefPath, str);
  598.                         ChangeDefExt(DefExt, DefSpec);
  599.                         UpdateListBox(hDlg);
  600.                         return (TRUE);
  601.                     }
  602.  
  603.                     if (!OpenName[0]) {
  604.                         MessageBox(hDlg, "No filename specified.",
  605.                             NULL, MB_OK | MB_ICONHAND);
  606.                         return (TRUE);
  607.                     }
  608.  
  609.                     AddExt(OpenName, DefExt);
  610.  
  611.                     /* Open the file */
  612.  
  613.                     if ((hFile = OpenFile(OpenName, (LPOFSTRUCT) &OfStruct,
  614.                             OF_READ)) == -1) {
  615.                         sprintf(str, "Error %d opening %s.",
  616.                             OfStruct.nErrCode, OpenName);
  617.                         MessageBox(hDlg, str, NULL,
  618.                             MB_OK | MB_ICONHAND);
  619.                     }
  620.                     else {
  621.  
  622.                         /* Make sure there's enough room for the file */
  623.  
  624.                         fstat(hFile, &FileStatus);
  625.                         if (FileStatus.st_size > MAXFILESIZE) {
  626.                             sprintf(str,
  627.                     "Not enough memory to load %s.\n%s exceeds %ld bytes.",
  628.                                 OpenName, OpenName, MAXFILESIZE);
  629.                             MessageBox(hDlg, str, NULL,
  630.                                 MB_OK | MB_ICONHAND);
  631.                             return (TRUE);
  632.                         }
  633.  
  634.                         /* File is opened and there is enough room so return
  635.                          * the handle to the caller.
  636.                          */
  637.  
  638.                         strcpy(FileName, OpenName);
  639.                         EndDialog(hDlg, hFile);
  640.                         return (TRUE);
  641.                     }
  642.                     return (TRUE);
  643.  
  644.                 case IDCANCEL:
  645.                     EndDialog(hDlg, NULL);
  646.                     return (TRUE);
  647.             }
  648.             break;
  649.  
  650.         case WM_INITDIALOG:                        /* message: initialize    */
  651.             UpdateListBox(hDlg);
  652.             SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
  653.             SendDlgItemMessage(hDlg,               /* dialog handle      */
  654.                 IDC_EDIT,                          /* where to send message  */
  655.                 EM_SETSEL,                         /* select characters      */
  656.                 NULL,                              /* additional information */
  657.                 MAKELONG(0, 0x7fff));              /* entire contents      */
  658.             SetFocus(GetDlgItem(hDlg, IDC_EDIT));
  659.             return (FALSE); /* Indicates the focus is set to a control */
  660.     }
  661.     return FALSE;
  662. }
  663.  
  664. /****************************************************************************
  665.  
  666.     FUNCTION: UpdateListBox(HWND);
  667.  
  668.     PURPOSE: Update the list box of OpenDlg
  669.  
  670. ****************************************************************************/
  671.  
  672. void UpdateListBox(hDlg)
  673. HWND hDlg;
  674. {
  675.     strcpy(str, DefPath);
  676.     strcat(str, DefSpec);
  677.     DlgDirList(hDlg, str, IDC_LISTBOX, IDC_PATH, 0x4010);
  678.  
  679.     /* To ensure that the listing is made for a subdir. of
  680.      * current drive dir...
  681.      */
  682.     if (!strchr (DefPath, ':'))
  683.     DlgDirList(hDlg, DefSpec, IDC_LISTBOX, IDC_PATH, 0x4010);
  684.  
  685.     /* Remove the '..' character from path if it exists, since this
  686.      * will make DlgDirList move us up an additional level in the tree
  687.      * when UpdateListBox() is called again.
  688.      */
  689.     if (strstr (DefPath, ".."))
  690.     DefPath[0] = '\0';
  691.  
  692.     SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
  693. }
  694.  
  695. /****************************************************************************
  696.  
  697.     FUNCTION: ChangeDefExt(PSTR, PSTR);
  698.  
  699.     PURPOSE: Change the default extension
  700.  
  701. ****************************************************************************/
  702.  
  703. void ChangeDefExt(Ext, Name)
  704. PSTR Ext, Name;
  705. {
  706.     PSTR pTptr;
  707.  
  708.     pTptr = Name;
  709.     while (*pTptr && *pTptr != '.')
  710.         pTptr++;
  711.     if (*pTptr)
  712.         if (!strchr(pTptr, '*') && !strchr(pTptr, '?'))
  713.             strcpy(Ext, pTptr);
  714. }
  715.  
  716. /****************************************************************************
  717.  
  718.     FUNCTION: SeparateFile(HWND, LPSTR, LPSTR, LPSTR)
  719.  
  720.     PURPOSE: Separate filename and pathname
  721.  
  722. ****************************************************************************/
  723.  
  724. void SeparateFile(hDlg, lpDestPath, lpDestFileName, lpSrcFileName)
  725. HWND hDlg;
  726. LPSTR lpDestPath, lpDestFileName, lpSrcFileName;
  727. {
  728.     LPSTR lpTmp;
  729.     char  cTmp;
  730.  
  731.     lpTmp = lpSrcFileName + (long) lstrlen(lpSrcFileName);
  732.     while (*lpTmp != ':' && *lpTmp != '\\' && lpTmp > lpSrcFileName)
  733.         lpTmp = AnsiPrev(lpSrcFileName, lpTmp);
  734.     if (*lpTmp != ':' && *lpTmp != '\\') {
  735.         lstrcpy(lpDestFileName, lpSrcFileName);
  736.         lpDestPath[0] = 0;
  737.         return;
  738.     }
  739.     lstrcpy(lpDestFileName, lpTmp + 1);
  740.     cTmp = *(lpTmp + 1);
  741.     lstrcpy(lpDestPath, lpSrcFileName);
  742.      *(lpTmp + 1) = cTmp;
  743.     lpDestPath[(lpTmp - lpSrcFileName) + 1] = 0;
  744. }
  745.  
  746. /****************************************************************************
  747.  
  748.     FUNCTION: AddExt(PSTR, PSTR);
  749.  
  750.     PURPOSE: Add default extension
  751.  
  752. /***************************************************************************/
  753.  
  754. void AddExt(Name, Ext)
  755. PSTR Name, Ext;
  756. {
  757.     PSTR pTptr;
  758.  
  759.     pTptr = Name;
  760.     while (*pTptr && *pTptr != '.')
  761.         pTptr++;
  762.     if (*pTptr != '.')
  763.         strcat(Name, Ext);
  764. }
  765.  
  766. /****************************************************************************
  767.  
  768.     FUNCTION: CheckFileName(HWND, PSTR, PSTR)
  769.  
  770.     PURPOSE: Check for wildcards, add extension if needed
  771.  
  772.     COMMENTS:
  773.  
  774.         Make sure you have a filename and that it does not contain any
  775.         wildcards.  If needed, add the default extension.  This function is
  776.         called whenever your application wants to save a file.
  777.  
  778. ****************************************************************************/
  779.  
  780. BOOL CheckFileName(hWnd, pDest, pSrc)
  781. HWND hWnd;
  782. PSTR pDest, pSrc;
  783. {
  784.     PSTR pTmp;
  785.  
  786.     if (!pSrc[0])
  787.         return (FALSE);               /* Indicates no filename was specified */
  788.  
  789.     pTmp = pSrc;
  790.     while (*pTmp) {                     /* Searches the string for wildcards */
  791.         switch (*pTmp++) {
  792.             case '*':
  793.             case '?':
  794.                 MessageBox(hWnd, "Wildcards not allowed.",
  795.                     NULL, MB_OK | MB_ICONEXCLAMATION);
  796.                 return (FALSE);
  797.         }
  798.     }
  799.  
  800.     AddExt(pSrc, DefExt);            /* Adds the default extension if needed */
  801.  
  802.     if (OpenFile(pSrc, (LPOFSTRUCT) &OfStruct, OF_EXIST) >= 0) {
  803.         sprintf(str, "Replace existing %s?", pSrc);
  804.         if (MessageBox(hWnd, str, "EditFile",
  805.                 MB_OKCANCEL | MB_ICONHAND) == IDCANCEL)
  806.             return (FALSE);
  807.     }
  808.     strcpy(pDest, pSrc);
  809.     return (TRUE);
  810. }
  811.  
  812. /****************************************************************************
  813.  
  814.     FUNCTION: SaveFile(HWND)
  815.  
  816.     PURPOSE: Save current file
  817.  
  818.     COMMENTS:
  819.  
  820.         This saves the current contents of the Edit buffer, and changes
  821.         bChanges to indicate that the buffer has not been changed since the
  822.         last save.
  823.  
  824.         Before the edit buffer is sent, you must get its handle and lock it
  825.         to get its address.  Once the file is written, you must unlock the
  826.         buffer.  This allows Windows to move the buffer when not in immediate
  827.         use.
  828.  
  829. ****************************************************************************/
  830.  
  831. BOOL SaveFile(hWnd)
  832. HWND hWnd;
  833. {
  834.     BOOL bSuccess;
  835.     int IOStatus;                                  /* result of a file write */
  836.  
  837.     if ((hFile = OpenFile(FileName, &OfStruct,
  838.         OF_PROMPT | OF_CANCEL | OF_CREATE)) < 0) {
  839.  
  840.         /* If the file can't be saved */
  841.  
  842.         sprintf(str, "Cannot write to %s.", FileName);
  843.         MessageBox(hWnd, str, NULL, MB_OK | MB_ICONEXCLAMATION);
  844.         return (FALSE);
  845.     }
  846.  
  847.  
  848.     hEditBuffer = SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
  849.     pEditBuffer = LocalLock(hEditBuffer);
  850.  
  851.     /* Set the cursor to an hourglass during the file transfer */
  852.  
  853.     hSaveCursor = SetCursor(hHourGlass);
  854.     IOStatus = write(hFile, pEditBuffer, strlen(pEditBuffer));
  855.     close(hFile);
  856.     SetCursor(hSaveCursor);
  857.     if (IOStatus != strlen(pEditBuffer)) {
  858.         sprintf(str, "Error writing to %s.", FileName);
  859.         MessageBox(hWnd, str,
  860.             NULL, MB_OK | MB_ICONHAND);
  861.         bSuccess = FALSE;
  862.     }
  863.     else {
  864.         bSuccess = TRUE;                /* Indicates the file was saved      */
  865.         bChanges = FALSE;               /* Indicates changes have been saved */
  866.     }
  867.  
  868.     LocalUnlock(hEditBuffer);
  869.     return (bSuccess);
  870. }
  871.  
  872. /****************************************************************************
  873.  
  874.     FUNCTION: QuerySaveFile(HWND);
  875.  
  876.     PURPOSE: Called when some action might lose current contents
  877.  
  878.     COMMENTS:
  879.  
  880.         This function is called whenever we are about to take an action that
  881.         would lose the current contents of the edit buffer.
  882.  
  883. ****************************************************************************/
  884.  
  885. BOOL QuerySaveFile(hWnd)
  886. HWND hWnd;
  887. {
  888.     int Response;
  889.     FARPROC lpSaveAsDlg;
  890.  
  891.     if (bChanges) {
  892.         sprintf(str, "Save current changes: %s", FileName);
  893.         Response = MessageBox(hWnd, str,
  894.             "EditFile",  MB_YESNOCANCEL | MB_ICONEXCLAMATION);
  895.         if (Response == IDYES) {
  896. check_name:
  897.  
  898.             /* Make sure there is a filename to save to */
  899.  
  900.             if (!FileName[0]) {
  901.                 lpSaveAsDlg = MakeProcInstance(SaveAsDlg, hInst);
  902.                 Response = DialogBox(hInst, "SaveAs",
  903.                     hWnd, lpSaveAsDlg);
  904.                 FreeProcInstance(lpSaveAsDlg);
  905.                 if (Response == IDOK)
  906.                     goto check_name;
  907.                 else
  908.                     return (FALSE);
  909.             }
  910.             SaveFile(hWnd);
  911.         }
  912.         else if (Response == IDCANCEL)
  913.             return (FALSE);
  914.     }
  915.     else
  916.         return (TRUE);
  917. }
  918.  
  919. /****************************************************************************
  920.  
  921.     FUNCTION: SetNewBuffer(HWND, HANDLE, PSTR)
  922.  
  923.     PURPOSE: Set new buffer for edit window
  924.  
  925.     COMMENTS:
  926.  
  927.         Point the edit window to the new buffer, update the window title, and
  928.         redraw the edit window.  If hNewBuffer is NULL, then create an empty
  929.         1K buffer, and return its handle.
  930.  
  931. ****************************************************************************/
  932.  
  933. void SetNewBuffer(hWnd, hNewBuffer, Title)
  934. HWND hWnd;
  935. HANDLE hNewBuffer;
  936. PSTR Title;
  937. {
  938.     HANDLE hOldBuffer;
  939.  
  940.     hOldBuffer = SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
  941.     LocalFree(hOldBuffer);
  942.     if (!hNewBuffer)                    /* Allocates a buffer if none exists */
  943.         hNewBuffer = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, 1);
  944.  
  945.     /* Updates the buffer and displays new buffer */
  946.     SendMessage(hEditWnd, EM_SETHANDLE, hNewBuffer, 0L);
  947.  
  948.     SetWindowText(hWnd, Title);
  949.     SetFocus(hEditWnd);
  950.     bChanges = FALSE;
  951. }
  952.  
  953.  
  954. /****************************************************************************
  955.  
  956.     FUNCTION: About(HWND, unsigned, WORD, LONG)
  957.  
  958.     PURPOSE:  Processes messages for "About" dialog box
  959.  
  960.     MESSAGES:
  961.  
  962.         WM_INITDIALOG - initialize dialog box
  963.         WM_COMMAND    - Input received
  964.  
  965. ****************************************************************************/
  966.  
  967. BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
  968. HWND hDlg;
  969. unsigned message;
  970. WORD wParam;
  971. LONG lParam;
  972. {
  973.     switch (message) {
  974.         case WM_INITDIALOG:
  975.             return (TRUE);
  976.  
  977.         case WM_COMMAND:
  978.         if (wParam == IDOK
  979.                 || wParam == IDCANCEL) {
  980.                 EndDialog(hDlg, TRUE);
  981.                 return (TRUE);
  982.             }
  983.             break;
  984.     }
  985.     return (FALSE);
  986. }
  987. 
  988.