home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / EDITFILE / EDITFILE.C_ / EDITFILE.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  19.2 KB  |  626 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.         SaveFile() - Save current file
  15.         QuerySaveFile() - Called when some action might lose current contents
  16.         SetNewBuffer() - Set new buffer for edit window
  17.  
  18. ****************************************************************************/
  19.  
  20. #include "windows.h"
  21. #include "editfile.h"
  22. #include "stdio.h"
  23. #include "io.h"
  24. #include "string.h"
  25. #include <commdlg.h>
  26.  
  27. HANDLE hInst;
  28.  
  29. HANDLE hAccTable;                                /* handle to accelerator table */
  30. HWND hEditWnd;                                      /* handle to edit window */
  31. /* Additional includes needed for the fstat() function */
  32.  
  33. #include <sys\types.h>
  34. #include <sys\stat.h>
  35.  
  36. /* new variables for common dialogs */
  37. static char szFilterSpec [128]
  38.           = "All Files(*.*)\0*.*\0";  /* filter string for dir. listings   */
  39. char szCustFilterSpec[MAXCUSTFILTER];      /* custom filter buffer           */
  40. char szOpenDlgTitle[] = "Open File";      /* title of File open dialog           */
  41. char szSaveDlgTitle[] = "Save File";      /* title of File saveas dialog       */
  42. OPENFILENAME ofn;              /* struct. passed to GetOpenFileName */
  43.  
  44. static char PathName[128] = "\0";
  45. static char FileName[128] = "\0";
  46. char str[255];
  47.  
  48. HANDLE hEditBuffer;                       /* handle to editing buffer      */
  49. HANDLE hOldBuffer;                        /* old buffer handle        */
  50. HANDLE hHourGlass;                        /* handle to hourglass cursor      */
  51. HANDLE hSaveCursor;                       /* current cursor handle      */
  52. int hFile;                                /* file handle              */
  53. int count;                                /* number of chars read or written */
  54. PSTR pBuffer;                             /* address of read/write buffer    */
  55. OFSTRUCT OfStruct;                        /* information from OpenFile()     */
  56. struct stat FileStatus;                   /* information from fstat()      */
  57. BOOL bChanges = FALSE;                    /* TRUE if the file is changed     */
  58. BOOL bSaveEnabled = FALSE;                /* TRUE if text in the edit buffer */
  59. PSTR pEditBuffer;                         /* address of the edit buffer      */
  60. RECT Rect;                                /* dimension of the client window  */
  61. HWND hwnd;                                /* handle to main window           */
  62.  
  63.  
  64. char Untitled[] =                         /* default window title      */
  65.      "Edit File - (untitled)";
  66.  
  67. /****************************************************************************
  68.  
  69.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  70.  
  71.     PURPOSE: calls initialization function, processes message loop
  72.  
  73. ****************************************************************************/
  74.  
  75. int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  76. HANDLE hInstance;
  77. HANDLE hPrevInstance;
  78. LPSTR lpCmdLine;
  79. int nCmdShow;
  80. {
  81.     MSG msg;
  82.  
  83.     if (!hPrevInstance)
  84.         if (!InitApplication(hInstance))
  85.             return (FALSE);
  86.  
  87.     if (!InitInstance(hInstance, nCmdShow))
  88.         return (FALSE);
  89.  
  90.     while (GetMessage(&msg, NULL, NULL, NULL)) {
  91.  
  92.     /* Only translate message if it is not an accelerator message */
  93.  
  94.         if (!TranslateAccelerator(hwnd, hAccTable, &msg)) {
  95.             TranslateMessage(&msg);
  96.             DispatchMessage(&msg);
  97.         }
  98.     }
  99.     return (msg.wParam);
  100. }
  101.  
  102.  
  103. /****************************************************************************
  104.  
  105.     FUNCTION: InitApplication(HANDLE)
  106.  
  107.     PURPOSE: Initializes window data and registers window class
  108.  
  109. ****************************************************************************/
  110.  
  111. BOOL InitApplication(hInstance)
  112. HANDLE hInstance;
  113. {
  114.     WNDCLASS  wc;
  115.  
  116.     wc.style = NULL;
  117.     wc.lpfnWndProc = MainWndProc;
  118.     wc.cbClsExtra = 0;
  119.     wc.cbWndExtra = 0;
  120.     wc.hInstance = hInstance;
  121.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  122.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  123.     wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  124.     wc.lpszMenuName =  "EditFileMenu";
  125.     wc.lpszClassName = "EditFileWClass";
  126.  
  127.     return (RegisterClass(&wc));
  128. }
  129.  
  130.  
  131. /****************************************************************************
  132.  
  133.     FUNCTION:  InitInstance(HANDLE, int)
  134.  
  135.     PURPOSE:  Saves instance handle and creates main window
  136.  
  137. ****************************************************************************/
  138.  
  139. BOOL InitInstance(hInstance, nCmdShow)
  140.     HANDLE          hInstance;
  141.     int             nCmdShow;
  142. {
  143.     RECT            Rect;
  144.  
  145.     hInst = hInstance;
  146.  
  147.     hAccTable = LoadAccelerators(hInst, "EditFileAcc");
  148.  
  149.     hwnd = CreateWindow(
  150.         "EditFileWClass",
  151.         "EditFile Sample Application",
  152.         WS_OVERLAPPEDWINDOW,
  153.         CW_USEDEFAULT,
  154.         CW_USEDEFAULT,
  155.         CW_USEDEFAULT,
  156.         CW_USEDEFAULT,
  157.         NULL,
  158.         NULL,
  159.         hInstance,
  160.         NULL
  161.     );
  162.  
  163.     if (!hwnd)
  164.         return (FALSE);
  165.  
  166.     GetClientRect(hwnd, (LPRECT) &Rect);
  167.  
  168.     /* Create a child window */
  169.  
  170.     hEditWnd = CreateWindow("Edit",
  171.         NULL,
  172.         WS_CHILD | WS_VISIBLE |
  173.         ES_MULTILINE |
  174.         WS_VSCROLL | WS_HSCROLL |
  175.         ES_AUTOHSCROLL | ES_AUTOVSCROLL,
  176.         0,
  177.         0,
  178.         (Rect.right-Rect.left),
  179.         (Rect.bottom-Rect.top),
  180.         hwnd,
  181.         IDC_EDIT,                          /* Child control i.d. */
  182.         hInst,
  183.         NULL);
  184.  
  185.     if (!hEditWnd) {
  186.         DestroyWindow(hwnd);
  187.         return (NULL);
  188.     }
  189.  
  190.     /* Get an hourglass cursor to use during file transfers */
  191.  
  192.     hHourGlass = LoadCursor(NULL, IDC_WAIT);
  193.  
  194.     /* fill in non-variant fields of OPENFILENAME struct. */
  195.     ofn.lStructSize      = sizeof(OPENFILENAME);
  196.     ofn.hwndOwner      = hwnd;
  197.     ofn.lpstrFilter      = szFilterSpec;
  198.     ofn.lpstrCustomFilter = szCustFilterSpec;
  199.     ofn.nMaxCustFilter      = MAXCUSTFILTER;
  200.     ofn.nFilterIndex      = 1;
  201.     ofn.lpstrFile      = FileName;
  202.     ofn.nMaxFile      = MAXFILENAME;
  203.     ofn.lpstrInitialDir   = PathName;
  204.     ofn.Flags          = 0L;
  205.     ofn.lpfnHook      = NULL;
  206.  
  207.     ShowWindow(hwnd, nCmdShow);
  208.     UpdateWindow(hwnd);
  209.     return (TRUE);
  210.  
  211. }
  212.  
  213. /****************************************************************************
  214.  
  215.     FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)
  216.  
  217.     PURPOSE:  Processes messages
  218.  
  219.     MESSAGES:
  220.  
  221.         WM_COMMAND    - application menu (About dialog box)
  222.         WM_DESTROY    - destroy window
  223.         WM_SIZE       - window size has changed
  224.         WM_QUERYENDSESSION - willing to end session?
  225.         WM_ENDSESSION - end Windows session
  226.         WM_CLOSE      - close the window
  227.         WM_SIZE       - window resized
  228.  
  229.     COMMENTS:
  230.  
  231.         WM_COMMAND processing:
  232.  
  233.             IDM_NEW - query to save current file if there is one and it has
  234.                       been changed, clear buffer and start new file.
  235.  
  236.             IDM_OPEN - query to save current file if there is one and it
  237.                        has been changed, open a new file.
  238.  
  239.             IDM_SAVE - save current file, prompt for name if none exists.
  240.  
  241.             IDM_SAVEAS - prompt for new filename to save to, save file.
  242.  
  243.             IDC_EDIT - change "bChanges" flag to indicate if edit buffer has
  244.                       been modified.  Affects actions of IDM_NEW and
  245.                       IDM_OPEN.  Reset when file is saved.
  246.  
  247.             IDM_EXIT - query to save current file if there is one and it
  248.                        has been changed, then exit.
  249.  
  250.             IDM_ABOUT - display "About" box.
  251.  
  252.         When more then one string needs to be sent to a message box,
  253.         sprintf() is used to combine the strings into str[], and then str[]
  254.         is passed to the MessageBox() function.  A message box string cannot
  255.         exceed 255 characters, but may contain \n to generate separate
  256.         lines.
  257.  
  258.         After the size of the file is determined, only enough memory to store
  259.         the file is allocated for the Edit buffer.  The edit control will
  260.         automatically expand this memory as needed.  Once the file has been
  261.         read into the edit buffer, unlock the memory.  Use whatever was
  262.         obtained from the read() function, even if an error occured.  This
  263.         allows partial salvage of a file with a bad sector.
  264.  
  265. ****************************************************************************/
  266.  
  267. long FAR PASCAL __export MainWndProc(hWnd, message, wParam, lParam)
  268. HWND hWnd;
  269. UINT message;
  270. WPARAM wParam;
  271. LPARAM lParam;
  272. {
  273.     FARPROC lpProcAbout;
  274.  
  275.     int IOStatus;                /* result of file i/o      */
  276.  
  277.     switch (message) {
  278.         case WM_COMMAND:
  279.             switch (wParam) {
  280.                 case IDM_ABOUT:
  281.                     lpProcAbout = MakeProcInstance(About, hInst);
  282.                     DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
  283.                     FreeProcInstance(lpProcAbout);
  284.                     break;
  285.  
  286.                 case IDM_NEW:
  287.  
  288.                     /* If current file has been modified, query user about
  289.                      * saving it.
  290.                      */
  291.  
  292.                     if (!QuerySaveFile(hWnd))
  293.                         return (NULL);
  294.  
  295.                     /* bChanges is set to FALSE to indicate there have been
  296.                      * no changes since the last file save.
  297.                      */
  298.  
  299.                     bChanges = FALSE;
  300.             FileName[0] = 0;
  301.  
  302.                     /* Update the edit buffer */
  303.  
  304.                     SetNewBuffer(hWnd, NULL, Untitled);
  305.                     break;
  306.  
  307.                 case IDM_OPEN:
  308.                     if (!QuerySaveFile(hWnd))
  309.                         return (NULL);
  310.  
  311.             /* fill in title field of OPENFILENAME struct. and show
  312.              * dialog box
  313.              */
  314.             ofn.lpstrTitle      = (LPSTR)szOpenDlgTitle;
  315.             if (!GetOpenFileName ((LPOPENFILENAME)&ofn))
  316.             return NULL;
  317.  
  318.             /* Open the file and get its handle */
  319.             hFile = OpenFile (FileName, (LPOFSTRUCT)&OfStruct,
  320.                           OF_READ);
  321.                     if (!hFile)
  322.                         return (NULL);
  323.  
  324.                     /* Allocate edit buffer to the size of the file + 1 */
  325.             fstat(hFile, &FileStatus);
  326.                     hEditBuffer =
  327.                         LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,
  328.                 (WORD)(FileStatus.st_size+1));
  329.  
  330.                     if (!hEditBuffer) {
  331.                         MessageBox(hWnd, "Not enough memory.",
  332.                             NULL, MB_OK | MB_ICONHAND);
  333.                         return (NULL);
  334.                     }
  335.                     hSaveCursor = SetCursor(hHourGlass);
  336.                     pEditBuffer = LocalLock(hEditBuffer);
  337.  
  338.             IOStatus = read(hFile, pEditBuffer, (unsigned int)FileStatus.st_size);
  339.                     close(hFile);
  340.  
  341.                     /* # bytes read must equal file size */
  342.  
  343.             if (IOStatus != (int)FileStatus.st_size) {
  344.  
  345.             sprintf(str, "Error reading %s.", FileName);
  346.                         SetCursor(hSaveCursor);      /* Remove the hourglass */
  347.                         MessageBox(hWnd, str, NULL, MB_OK | MB_ICONEXCLAMATION);
  348.                     }
  349.                     LocalUnlock(hEditBuffer);
  350.  
  351.                     /* Set up a new buffer and window title */
  352.  
  353.             sprintf(str, "EditFile - %s", FileName);
  354.                     SetNewBuffer(hWnd, hEditBuffer, str);
  355.                     SetCursor(hSaveCursor);            /* restore the cursor */
  356.                     break;
  357.  
  358.                 case IDM_SAVE:
  359.                     /* If there is no filename, use the saveas command to get
  360.                      * one.  Otherwise, save the file using the current
  361.                      * filename.
  362.                      */
  363.             if (FileName[0]){
  364.             if (bChanges)
  365.                 SaveFile(hWnd);
  366.             break;
  367.             }
  368.             /* else fall thro' for Saveas processing */
  369.  
  370.                 case IDM_SAVEAS:
  371.  
  372.             /* fill in title field of OPENFILENAME struct. and show
  373.              * dialog box
  374.              */
  375.             ofn.lpstrTitle      = (LPSTR)szSaveDlgTitle;
  376.             if (!GetSaveFileName ((LPOPENFILENAME)&ofn))
  377.             return FALSE;        /* User canceled */
  378.  
  379.                     /* If successful, update the window title, save the file */
  380.             sprintf(str, "EditFile - %s", FileName);
  381.             SetWindowText(hWnd, str);
  382.             SaveFile(hWnd);
  383.             break;
  384.  
  385.                 case IDM_PRINT:
  386.                 /* edit menu commands */
  387.  
  388.                 case IDM_UNDO:
  389.                 case IDM_CUT:
  390.                 case IDM_COPY:
  391.                 case IDM_PASTE:
  392.                 case IDM_CLEAR:
  393.                     MessageBox (
  394.                           GetFocus(),
  395.                           "Command not implemented",
  396.                           "EditFile Sample Application",
  397.                           MB_ICONASTERISK | MB_OK);
  398.                     break;
  399.  
  400.                 case IDM_EXIT:
  401.                     QuerySaveFile(hWnd);
  402.                     DestroyWindow(hWnd);
  403.                     break;
  404.  
  405.                 case IDC_EDIT:
  406.             switch (HIWORD (lParam)){
  407.             case EN_ERRSPACE:
  408.                 MessageBox (
  409.                   GetFocus ()
  410.                 , "Out of memory."
  411.                 , "EditFile Sample Application"
  412.                 , MB_ICONHAND | MB_OK
  413.                 );
  414.                 break;
  415.  
  416.             case EN_CHANGE:
  417.                 /* contents of edit control buffer have changed */
  418.                 if (!bChanges)
  419.                 bChanges = TRUE;
  420.                 break;
  421.  
  422.             default:
  423.                 break;
  424.                     }
  425.                     break;
  426.  
  427.             }
  428.             break;
  429.  
  430.         case WM_SETFOCUS:
  431.             SetFocus (hEditWnd);
  432.             break;
  433.  
  434.         case WM_SIZE:
  435.             MoveWindow(hEditWnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
  436.             break;
  437.  
  438.         case WM_QUERYENDSESSION:             /* message: to end the session? */
  439.             return (QuerySaveFile(hWnd));
  440.  
  441.         case WM_CLOSE:                       /* message: close the window    */
  442.             if (QuerySaveFile(hWnd))
  443.                 DestroyWindow(hWnd);
  444.             break;
  445.  
  446.         case WM_DESTROY:
  447.             PostQuitMessage(0);
  448.             break;
  449.  
  450.         default:
  451.             return (DefWindowProc(hWnd, message, wParam, lParam));
  452.     }
  453.     return (NULL);
  454. }
  455.  
  456. /****************************************************************************
  457.  
  458.     FUNCTION: SaveFile(HWND)
  459.  
  460.     PURPOSE: Save current file
  461.  
  462.     COMMENTS:
  463.  
  464.         This saves the current contents of the Edit buffer, and changes
  465.         bChanges to indicate that the buffer has not been changed since the
  466.         last save.
  467.  
  468.         Before the edit buffer is sent, you must get its handle and lock it
  469.         to get its address.  Once the file is written, you must unlock the
  470.         buffer.  This allows Windows to move the buffer when not in immediate
  471.         use.
  472.  
  473. ****************************************************************************/
  474. BOOL SaveFile(hWnd)
  475. HWND hWnd;
  476. {
  477.     BOOL bSuccess;
  478.     int IOStatus;                                  /* result of a file write */
  479.  
  480.     if ((hFile = OpenFile(FileName, &OfStruct,
  481.         OF_PROMPT | OF_CANCEL | OF_CREATE)) < 0) {
  482.  
  483.         /* If the file can't be saved */
  484.  
  485.         sprintf(str, "Cannot write to %s.", FileName);
  486.         MessageBox(hWnd, str, NULL, MB_OK | MB_ICONEXCLAMATION);
  487.         return (FALSE);
  488.     }
  489.  
  490.     hEditBuffer = (HANDLE)SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
  491.     pEditBuffer = LocalLock(hEditBuffer);
  492.  
  493.     /* Set the cursor to an hourglass during the file transfer */
  494.  
  495.     hSaveCursor = SetCursor(hHourGlass);
  496.     IOStatus = write(hFile, pEditBuffer, strlen(pEditBuffer));
  497.     close(hFile);
  498.     SetCursor(hSaveCursor);
  499.     if (IOStatus != (int)strlen(pEditBuffer)) {
  500.         sprintf(str, "Error writing to %s.", FileName);
  501.         MessageBox(hWnd, str,
  502.             NULL, MB_OK | MB_ICONHAND);
  503.         bSuccess = FALSE;
  504.     }
  505.     else {
  506.         bSuccess = TRUE;                /* Indicates the file was saved      */
  507.         bChanges = FALSE;               /* Indicates changes have been saved */
  508.     }
  509.  
  510.     LocalUnlock(hEditBuffer);
  511.     return (bSuccess);
  512. }
  513.  
  514. /****************************************************************************
  515.  
  516.     FUNCTION: QuerySaveFile(HWND);
  517.  
  518.     PURPOSE: Called when some action might lose current contents
  519.  
  520.     COMMENTS:
  521.  
  522.         This function is called whenever we are about to take an action that
  523.         would lose the current contents of the edit buffer.
  524.  
  525. ****************************************************************************/
  526.  
  527. BOOL QuerySaveFile(hWnd)
  528. HWND hWnd;
  529. {
  530.     int Response;
  531.  
  532.     if (bChanges) {
  533.  
  534.     ofn.lpstrTitle          = (LPSTR)szSaveDlgTitle;
  535.         sprintf(str, "Save current changes? %s", FileName);
  536.         Response = MessageBox(hWnd, str,
  537.             "EditFile",  MB_YESNOCANCEL | MB_ICONEXCLAMATION);
  538.         if (Response == IDYES) {
  539.  
  540.             /* Make sure there is a filename to save to */
  541.         while (!FileName[0]) {
  542.  
  543.         /* fill in pertinent field of OPENFILENAME struct. and show
  544.          * dialog box
  545.          */
  546.         if (!GetSaveFileName ((LPOPENFILENAME)&ofn))
  547.             return FALSE;        /* User canceled */
  548.             }
  549.             SaveFile(hWnd);
  550.         }
  551.         else if (Response == IDCANCEL)
  552.             return (FALSE);
  553.     }
  554.     else
  555.         return (TRUE);
  556. }
  557.  
  558. /****************************************************************************
  559.  
  560.     FUNCTION: SetNewBuffer(HWND, HANDLE, PSTR)
  561.  
  562.     PURPOSE: Set new buffer for edit window
  563.  
  564.     COMMENTS:
  565.  
  566.         Point the edit window to the new buffer, update the window title, and
  567.         redraw the edit window.  If hNewBuffer is NULL, then create an empty
  568.         1K buffer, and return its handle.
  569.  
  570. ****************************************************************************/
  571.  
  572. void SetNewBuffer(hWnd, hNewBuffer, Title)
  573. HWND hWnd;
  574. HANDLE hNewBuffer;
  575. PSTR Title;
  576. {
  577.     HANDLE hOldBuffer;
  578.  
  579.     hOldBuffer = (HANDLE)SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
  580.     LocalFree(hOldBuffer);
  581.     if (!hNewBuffer)                    /* Allocates a buffer if none exists */
  582.         hNewBuffer = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, 1);
  583.  
  584.     /* Updates the buffer and displays new buffer */
  585.     SendMessage(hEditWnd, EM_SETHANDLE, hNewBuffer, 0L);
  586.  
  587.     SetWindowText(hWnd, Title);
  588.     SetFocus(hEditWnd);
  589.     bChanges = FALSE;
  590. }
  591.  
  592.  
  593. /****************************************************************************
  594.  
  595.     FUNCTION: About(HWND, unsigned, WORD, LONG)
  596.  
  597.     PURPOSE:  Processes messages for "About" dialog box
  598.  
  599.     MESSAGES:
  600.  
  601.         WM_INITDIALOG - initialize dialog box
  602.         WM_COMMAND    - Input received
  603.  
  604. ****************************************************************************/
  605.  
  606. BOOL FAR PASCAL __export About(hDlg, message, wParam, lParam)
  607. HWND hDlg;
  608. unsigned message;
  609. WORD wParam;
  610. LONG lParam;
  611. {
  612.     switch (message) {
  613.         case WM_INITDIALOG:
  614.             return (TRUE);
  615.  
  616.         case WM_COMMAND:
  617.         if (wParam == IDOK
  618.                 || wParam == IDCANCEL) {
  619.                 EndDialog(hDlg, TRUE);
  620.                 return (TRUE);
  621.             }
  622.             break;
  623.     }
  624.     return (FALSE);
  625. }
  626.