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

  1. /****************************************************************************
  2.  
  3.     PROGRAM: PrntFile.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 "print.h"
  22. #include "prntfile.h"
  23. #include "commdlg.h"
  24. #include "io.h"
  25. #include "stdio.h"
  26. #include "string.h"
  27.  
  28. HANDLE hInst;
  29.  
  30. HANDLE hAccTable;                                /* handle to accelerator table */
  31. HWND hEditWnd;                                      /* handle to edit window */
  32. HWND hwnd;                                       /* handle to main window */
  33.  
  34. /* Additional includes needed for the fstat() function */
  35.  
  36. #include <sys\types.h>
  37. #include <sys\stat.h>
  38.  
  39. /* new variables for common dialogs */
  40. OPENFILENAME ofn;
  41. char szFilterSpec [128] =                       /* file type filters */
  42.              "Text Files (*.TXT)\0*.TXT\0All Files (*.*)\0*.*\0";
  43.  
  44. char szFileName[MAXFILENAME];
  45. char szFileTitle[MAXFILENAME];
  46.  
  47. char szBaseWindowTitle[] = "PrntOpen Sample Application";
  48. char szWindowTitle[80];
  49.  
  50. PRINTDLG pd;                              /* Common print dialog structure */
  51.  
  52. char szTemp[128];
  53. HANDLE hEditBuffer;                       /* handle to editing buffer      */
  54. HANDLE hOldBuffer;                        /* old buffer handle        */
  55. HANDLE hHourGlass;                        /* handle to hourglass cursor      */
  56. HANDLE hSaveCursor;                       /* current cursor handle      */
  57. int hFile;                                /* file handle              */
  58. int count;                                /* number of chars read or written */
  59. PSTR pBuffer;                             /* address of read/write buffer    */
  60. OFSTRUCT OfStruct;                        /* information from OpenFile()     */
  61. struct stat FileStatus;                   /* information from fstat()      */
  62. BOOL bChanges = FALSE;                    /* TRUE if the file is changed     */
  63. BOOL bSaveEnabled = FALSE;                /* TRUE if text in the edit buffer */
  64. PSTR pEditBuffer;                         /* address of the edit buffer      */
  65. RECT Rect;                                /* dimension of the client window  */
  66.  
  67. char Untitled[] =                         /* default window title      */
  68.      "Edit File - (untitled)";
  69.  
  70. /* Printer variables  */
  71.  
  72. HDC hPr;                            /* handle for printer device context     */
  73. int LineSpace;                      /* spacing between lines          */
  74. int LinesPerPage;                   /* lines per page                 */
  75. int CurrentLine;                    /* current line                   */
  76. int LineLength;                     /* line length                    */
  77. WORD wLines;                        /* number of lines to print       */
  78. WORD wIndex;                        /* index into lines to print      */
  79. char szLine[128];                   /* buffer to store lines before printing */
  80. TEXTMETRIC TextMetric;              /* information about character size      */
  81. BOOL bAbort;                        /* FALSE if user cancels printing      */
  82. HWND hAbortDlgWnd;
  83. FARPROC lpAbortDlg, lpAbortProc;
  84.  
  85. HDC GetPrinterDC(void);
  86.  
  87. /****************************************************************************
  88.  
  89.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  90.  
  91.     PURPOSE: calls initialization function, processes message loop
  92.  
  93. ****************************************************************************/
  94.  
  95. int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  96. HANDLE hInstance;
  97. HANDLE hPrevInstance;
  98. LPSTR lpCmdLine;
  99. int nCmdShow;
  100. {
  101.     MSG msg;
  102.  
  103.     if (!hPrevInstance)
  104.         if (!InitApplication(hInstance))
  105.             return (FALSE);
  106.  
  107.     if (!InitInstance(hInstance, nCmdShow))
  108.         return (FALSE);
  109.  
  110.     while (GetMessage(&msg, NULL, NULL, NULL)) {
  111.  
  112.     /* Only translate message if it is not an accelerator message */
  113.  
  114.         if (!TranslateAccelerator(hwnd, hAccTable, &msg)) {
  115.             TranslateMessage(&msg);
  116.             DispatchMessage(&msg);
  117.         }
  118.     }
  119.     return (msg.wParam);
  120. }
  121.  
  122.  
  123. /****************************************************************************
  124.  
  125.     FUNCTION: InitApplication(HANDLE)
  126.  
  127.     PURPOSE: Initializes window data and registers window class
  128.  
  129. ****************************************************************************/
  130.  
  131. BOOL InitApplication(hInstance)
  132. HANDLE hInstance;
  133. {
  134.     WNDCLASS  wc;
  135.  
  136.     wc.style = NULL;
  137.     wc.lpfnWndProc = MainWndProc;
  138.     wc.cbClsExtra = 0;
  139.     wc.cbWndExtra = 0;
  140.     wc.hInstance = hInstance;
  141.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  142.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  143.     wc.hbrBackground = COLOR_WINDOW+1;
  144.     wc.lpszMenuName =  "PrntFileMenu";
  145.     wc.lpszClassName = "PrntFileWClass";
  146.  
  147.     return (RegisterClass(&wc));
  148. }
  149.  
  150.  
  151. /****************************************************************************
  152.  
  153.     FUNCTION:  InitInstance(HANDLE, int)
  154.  
  155.     PURPOSE:  Saves instance handle and creates main window
  156.  
  157. ****************************************************************************/
  158.  
  159. BOOL InitInstance(hInstance, nCmdShow)
  160.     HANDLE          hInstance;
  161.     int             nCmdShow;
  162. {
  163.     RECT            Rect;
  164.  
  165.     hInst = hInstance;
  166.  
  167.     hAccTable = LoadAccelerators(hInst, "PrntFileAcc");
  168.  
  169.     hwnd = CreateWindow(
  170.         "PrntFileWClass",
  171.         szBaseWindowTitle,
  172.         WS_OVERLAPPEDWINDOW,
  173.         CW_USEDEFAULT,
  174.         CW_USEDEFAULT,
  175.         CW_USEDEFAULT,
  176.         CW_USEDEFAULT,
  177.         NULL,
  178.         NULL,
  179.         hInstance,
  180.         NULL
  181.     );
  182.  
  183.     if (!hwnd)
  184.         return (FALSE);
  185.  
  186.     GetClientRect(hwnd, (LPRECT) &Rect);
  187.  
  188.     /* Create a child window */
  189.  
  190.     hEditWnd = CreateWindow("Edit",
  191.         NULL,
  192.         WS_CHILD | WS_VISIBLE |
  193.         ES_MULTILINE |
  194.         WS_VSCROLL | WS_HSCROLL |
  195.         ES_AUTOHSCROLL | ES_AUTOVSCROLL,
  196.         0,
  197.         0,
  198.         (Rect.right-Rect.left),
  199.         (Rect.bottom-Rect.top),
  200.         hwnd,
  201.         IDC_EDIT,                          /* Child control i.d. */
  202.         hInst,
  203.         NULL);
  204.  
  205.     if (!hEditWnd) {
  206.         DestroyWindow(hwnd);
  207.         return (NULL);
  208.     }
  209.  
  210.     /* Get an hourglass cursor to use during file transfers */
  211.  
  212.     hHourGlass = LoadCursor(NULL, IDC_WAIT);
  213.  
  214.     /* fill in non-variant fields of OPENFILENAME struct. */
  215.     ofn.lStructSize       = sizeof(OPENFILENAME);
  216.     ofn.hwndOwner      = hwnd;
  217.     ofn.lpstrFilter      = szFilterSpec;
  218.     ofn.lpstrCustomFilter = NULL;
  219.     ofn.nMaxCustFilter      = 0;
  220.     ofn.nFilterIndex      = 1;
  221.     ofn.lpstrFile         = szFileName;
  222.     ofn.nMaxFile      = MAXFILENAME;
  223.     ofn.lpstrInitialDir   = NULL;
  224.     ofn.lpstrFileTitle    = szFileTitle;
  225.     ofn.nMaxFileTitle     = MAXFILENAME;
  226.     ofn.lpstrTitle        = NULL;
  227.     ofn.lpstrDefExt       = "TXT";
  228.     ofn.Flags             = 0;
  229.  
  230.     /* fill in non-variant fields of PRINTDLG struct. */
  231.  
  232.     pd.lStructSize    = sizeof(PRINTDLG);
  233.     pd.hwndOwner      = hwnd;
  234.     pd.hDevMode       = NULL;
  235.     pd.hDevNames      = NULL;
  236.     pd.Flags          = PD_RETURNDC | PD_NOSELECTION | PD_NOPAGENUMS;
  237.     pd.nCopies        = 1;
  238.  
  239.     ShowWindow(hwnd, nCmdShow);
  240.     UpdateWindow(hwnd);
  241.     return (TRUE);
  242.  
  243. }
  244.  
  245. /****************************************************************************
  246.  
  247.     FUNCTION: MainWndProc(HWND, UINT, WPARAM, LPARAM)
  248.  
  249.     PURPOSE:  Processes messages
  250.  
  251.     MESSAGES:
  252.  
  253.         WM_COMMAND    - application menu (About dialog box)
  254.         WM_DESTROY    - destroy window
  255.         WM_SIZE       - window size has changed
  256.         WM_QUERYENDSESSION - willing to end session?
  257.         WM_ENDSESSION - end Windows session
  258.         WM_CLOSE      - close the window
  259.         WM_SIZE       - window resized
  260.  
  261.     COMMENTS:
  262.  
  263.         Adds printing capability to the EDITFILE program.  Printing request
  264.         is sent as an IDM_PRINT message.
  265.  
  266.         Before the printing operation begins, a modeless dialog box is
  267.         created to allow the user to abort the printing operation.  This
  268.         dialog box remains active until the print job is completed, or the
  269.         user cancels the print operation.
  270.  
  271. ****************************************************************************/
  272.  
  273. long FAR PASCAL _export MainWndProc(hWnd, message, wParam, lParam)
  274. HWND hWnd;
  275. UINT message;
  276. WPARAM wParam;
  277. LPARAM lParam;
  278. {
  279.     FARPROC lpProcAbout;
  280.  
  281.     WORD IOStatus;                           /* result of file i/o      */
  282.     int Status;
  283.     int nPageSize;                /* vert. resolution of printer device */
  284.     DWORD FlagSave;
  285.  
  286.  
  287.     switch (message) {
  288.         case WM_COMMAND:
  289.             switch (wParam) {
  290.                 case IDM_ABOUT:
  291.                     lpProcAbout = MakeProcInstance(About, hInst);
  292.                     DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
  293.                     FreeProcInstance(lpProcAbout);
  294.                     break;
  295.  
  296.                 case IDM_NEW:
  297.  
  298.                     /* If current file has been modified, query user about
  299.                      * saving it.
  300.                      */
  301.  
  302.                     if (!QuerySaveFile(hWnd))
  303.                         return (NULL);
  304.  
  305.                     /* bChanges is set to FALSE to indicate there have been
  306.                      * no changes since the last file save.
  307.                      */
  308.  
  309.                     bChanges = FALSE;
  310.                     szFileName[0] = 0;
  311.  
  312.                     /* Update the edit buffer */
  313.  
  314.                     SetNewBuffer(hWnd, NULL, Untitled);
  315.                     break;
  316.  
  317.                 case IDM_OPEN:
  318.                     if (!QuerySaveFile(hWnd))
  319.                         return (NULL);
  320.  
  321.                     /* Use standard open dialog */
  322.  
  323.             if (!GetOpenFileName ((LPOPENFILENAME)&ofn))
  324.             return NULL;
  325.  
  326.             /* Open the file and get its handle */
  327.                     hFile = OpenFile ((LPSTR)szFileName, (LPOFSTRUCT)&OfStruct,
  328.                           OF_READ);
  329.                     if (!hFile)
  330.                         return (NULL);
  331.  
  332.                     /* Allocate edit buffer to the size of the file + 1 */
  333.             fstat(hFile, &FileStatus);
  334.  
  335.                     if (FileStatus.st_size > 65534) {
  336.                         MessageBox(hWnd, "Can't load files larger than 65,534 bytes long",
  337.                             NULL, MB_OK | MB_ICONEXCLAMATION);
  338.                         close(hFile);
  339.                         return (NULL);
  340.                     }
  341.  
  342.                     hEditBuffer =
  343.                         LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,
  344.                 (WORD)FileStatus.st_size+1);
  345.  
  346.                     if (!hEditBuffer) {
  347.                         MessageBox(hWnd, "Not enough memory.",
  348.                             NULL, MB_OK | MB_ICONEXCLAMATION);
  349.                         close(hFile);
  350.                         return (NULL);
  351.                     }
  352.  
  353.                     hSaveCursor = SetCursor(hHourGlass);
  354.                     pEditBuffer = LocalLock(hEditBuffer);
  355.  
  356.                     IOStatus = read(hFile, pEditBuffer, (WORD)FileStatus.st_size);
  357.                     close(hFile);
  358.  
  359.                     /* # bytes read must equal file size */
  360.  
  361.                     if (IOStatus != (WORD)FileStatus.st_size) {
  362.  
  363.                         sprintf(szTemp, "Error reading %s.", szFileName);
  364.                         SetCursor(hSaveCursor);      /* Remove the hourglass */
  365.                         MessageBox(hWnd, szTemp, NULL, MB_OK | MB_ICONEXCLAMATION);
  366.                     }
  367.  
  368.                     LocalUnlock(hEditBuffer);
  369.  
  370.                     /* Set up a new buffer and window title */
  371.  
  372.                     sprintf(szTemp, "%s - %s", szBaseWindowTitle, szFileTitle);
  373.                     SetNewBuffer(hWnd, hEditBuffer, szTemp);
  374.                     SetCursor(hSaveCursor);            /* restore the cursor */
  375.                     break;
  376.  
  377.                 case IDM_SAVE:
  378.  
  379.                     /* If there is no filename, use the saveas command to get
  380.                      * one.  Otherwise, save the file using the current
  381.                      * filename.
  382.                      */
  383.                     if (szFileName[0]){
  384.             if (bChanges)
  385.                 SaveFile(hWnd);
  386.             break;
  387.             }
  388.             /* else fall thro' for Saveas processing */
  389.  
  390.                 case IDM_SAVEAS:
  391.  
  392.                     /* Use standard save dialog */
  393.  
  394.             if (!GetSaveFileName ((LPOPENFILENAME)&ofn))
  395.             return FALSE;        /* User canceled */
  396.  
  397.                     /* Change window title to include file title */
  398.  
  399.                     lstrcpy(szWindowTitle, szBaseWindowTitle);
  400.                     lstrcat(szWindowTitle, " - ");
  401.                     lstrcat(szWindowTitle, szFileTitle);
  402.                     SetWindowText(hWnd, szWindowTitle);
  403.  
  404.             SaveFile(hWnd);
  405.             break;
  406.  
  407.                 case IDM_PRINT:
  408.                     hSaveCursor = SetCursor(hHourGlass);
  409.                     hPr = GetPrinterDC();
  410.                     if (!hPr) {
  411.                         sprintf(szTemp, "Cannot print %s", szFileName);
  412.                         MessageBox(hWnd, szTemp, NULL, MB_OK | MB_ICONHAND);
  413.                         return (NULL);
  414.                     }
  415.  
  416.                     lpAbortDlg =  MakeProcInstance(AbortDlg, hInst);
  417.                     lpAbortProc = MakeProcInstance(AbortProc, hInst);
  418.  
  419.                     /* Define the abort function */
  420.  
  421.                     Escape(hPr, SETABORTPROC, NULL,
  422.             (LPSTR)  lpAbortProc,
  423.                         (LPSTR) NULL);
  424.  
  425.                     if (Escape(hPr, STARTDOC, 14, "PrntFile text",
  426.                             (LPSTR) NULL) < 0) {
  427.                         MessageBox(hWnd, "Unable to start print job",
  428.                             NULL, MB_OK | MB_ICONHAND);
  429.                         FreeProcInstance(lpAbortDlg);
  430.                         FreeProcInstance(lpAbortProc);
  431.                         DeleteDC(hPr);
  432.                     }
  433.  
  434.                     bAbort = FALSE; /* Clears the abort flag  */
  435.  
  436.                     /* Create the Abort dialog box (modeless) */
  437.  
  438.                     hAbortDlgWnd = CreateDialog(hInst, "AbortDlg",
  439.                         hWnd, lpAbortDlg);
  440.  
  441.                     if (!hAbortDlgWnd) {
  442.                         SetCursor(hSaveCursor);      /* Remove the hourglass */
  443.                         MessageBox(hWnd, "NULL Abort window handle",
  444.                             NULL, MB_OK | MB_ICONHAND);
  445.                         return (FALSE);
  446.                     }
  447.  
  448.                     /* Now show Abort dialog */
  449.  
  450.                     ShowWindow (hAbortDlgWnd, SW_NORMAL);
  451.  
  452.                     /* Disable the main window to avoid reentrancy problems */
  453.  
  454.                     EnableWindow(hWnd, FALSE);
  455.                     SetCursor(hSaveCursor);      /* Remove the hourglass */
  456.  
  457.                     /* Since you may have more than one line, you need to
  458.                      * compute the spacing between lines.  You can do that by
  459.                      * retrieving the height of the characters you are printing
  460.                      * and advancing their height plus the recommended external
  461.                      * leading height.
  462.                      */
  463.  
  464.                     GetTextMetrics(hPr, &TextMetric);
  465.                     LineSpace = TextMetric.tmHeight +
  466.                         TextMetric.tmExternalLeading;
  467.  
  468.                     /* Since you may have more lines than can fit on one
  469.                      * page, you need to compute the number of lines you can
  470.                      * print per page.  You can do that by retrieving the
  471.              * dimensions of the page and dividing the height
  472.                      * by the line spacing.
  473.                      */
  474.  
  475.             nPageSize = GetDeviceCaps (hPr, VERTRES);
  476.             LinesPerPage = nPageSize / LineSpace - 1;
  477.  
  478.  
  479.                     /* You can output only one line at a time, so you need a
  480.                      * count of the number of lines to print.  You can retrieve
  481.                      * the count sending the EM_GETLINECOUNT message to the edit
  482.                      * control.
  483.                      */
  484.  
  485.                     wLines = (WORD)SendMessage(hEditWnd, EM_GETLINECOUNT, 0, 0L);
  486.  
  487.                     /* Keep track of the current line on the current page */
  488.  
  489.                     CurrentLine = 1;
  490.  
  491.                     /* One way to output one line at a time is to retrieve
  492.                      * one line at a time from the edit control and write it
  493.                      * using the TextOut function.  For each line you need to
  494.                      * advance one line space.  Also, you need to check for the
  495.                      * end of the page and start a new page if necessary.
  496.                      */
  497.  
  498.                     for (wIndex = Status = 0; wIndex < wLines; wIndex++) {
  499.             szLine[0] = 127;           /* Maximum buffer size */
  500.                         szLine[1] = 0;
  501.                         LineLength = (int)SendMessage(hEditWnd, EM_GETLINE,
  502.                             wIndex, (DWORD)(LPSTR)szLine);
  503.                         TextOut(hPr, 0, CurrentLine*LineSpace,
  504.                             (LPSTR)szLine, LineLength);
  505.                         if (++CurrentLine > LinesPerPage ) {
  506.                             CurrentLine = 1;
  507.                             Status = Escape(hPr, NEWFRAME, 0, 0L, 0L);
  508.                             if (Status < 0 || bAbort)
  509.                                 break;
  510.                         }
  511.                     }
  512.  
  513.                     if (Status >= 0 && !bAbort) {
  514.                         Escape(hPr, NEWFRAME, 0, 0L, 0L);
  515.                         Escape(hPr, ENDDOC, 0, 0L, 0L);
  516.                     }
  517.                     EnableWindow(hWnd, TRUE);
  518.  
  519.                     /* Destroy the Abort dialog box */
  520.  
  521.                     DestroyWindow(hAbortDlgWnd);
  522.                     FreeProcInstance(lpAbortDlg);
  523.                     FreeProcInstance(lpAbortProc);
  524.                     DeleteDC(hPr);
  525.                     break;
  526.  
  527.  
  528.                 case IDM_PRINTSETUP:
  529.                     FlagSave = pd.Flags;
  530.                     pd.Flags |= PD_PRINTSETUP;    /* Set option */
  531.                     PrintDlg((LPPRINTDLG)&pd);
  532.                     pd.Flags = FlagSave;          /* Remove option */
  533.                     break;
  534.  
  535.                 /* edit menu commands */
  536.  
  537.                 case IDM_UNDO:
  538.                 case IDM_CUT:
  539.                 case IDM_COPY:
  540.                 case IDM_PASTE:
  541.                 case IDM_CLEAR:
  542.                     MessageBox (
  543.                           GetFocus(),
  544.                           "Command not implemented",
  545.                           "PrntFile Sample Application",
  546.                           MB_ICONASTERISK | MB_OK);
  547.                     break;
  548.  
  549.                 case IDM_EXIT:
  550.                     QuerySaveFile(hWnd);
  551.                     DestroyWindow(hWnd);
  552.                     break;
  553.  
  554.                 case IDC_EDIT:
  555.                     if (HIWORD (lParam) == EN_CHANGE)
  556.                         bChanges = TRUE;
  557.                     if (HIWORD (lParam) == EN_ERRSPACE) {
  558.                         MessageBox (
  559.                               GetFocus ()
  560.                             , "Out of memory."
  561.                             , "PrntFile Sample Application"
  562.                             , MB_ICONHAND | MB_OK
  563.                         );
  564.                     }
  565.                     break;
  566.  
  567.             }
  568.             break;
  569.  
  570.         case WM_SETFOCUS:
  571.             SetFocus (hEditWnd);
  572.             break;
  573.  
  574.         case WM_SIZE:
  575.             MoveWindow(hEditWnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
  576.             break;
  577.  
  578.         case WM_QUERYENDSESSION:             /* message: to end the session? */
  579.             return (QuerySaveFile(hWnd));
  580.  
  581.         case WM_CLOSE:                       /* message: close the window    */
  582.             if (QuerySaveFile(hWnd))
  583.                 DestroyWindow(hWnd);
  584.             break;
  585.  
  586.         case WM_DESTROY:
  587.             PostQuitMessage(0);
  588.             break;
  589.  
  590.         default:
  591.             return (DefWindowProc(hWnd, message, wParam, lParam));
  592.     }
  593.     return (NULL);
  594. }
  595.  
  596. /****************************************************************************
  597.  
  598.     FUNCTION: SaveFile(HWND)
  599.  
  600.     PURPOSE: Save current file
  601.  
  602.     COMMENTS:
  603.  
  604.         This saves the current contents of the Edit buffer, and changes
  605.         bChanges to indicate that the buffer has not been changed since the
  606.         last save.
  607.  
  608.         Before the edit buffer is sent, you must get its handle and lock it
  609.         to get its address.  Once the file is written, you must unlock the
  610.         buffer.  This allows Windows to move the buffer when not in immediate
  611.         use.
  612.  
  613. ****************************************************************************/
  614.  
  615. BOOL SaveFile(hWnd)
  616. HWND hWnd;
  617. {
  618.     BOOL bSuccess;
  619.     int IOStatus;                                  /* result of a file write */
  620.  
  621.     if ((hFile = OpenFile(szFileName, &OfStruct,
  622.         OF_CANCEL | OF_CREATE)) < 0) {
  623.  
  624.         /* If the file can't be saved */
  625.  
  626.         sprintf(szTemp, "Cannot write to %s.", szFileName);
  627.         MessageBox(hWnd, szTemp, NULL, MB_OK | MB_ICONHAND);
  628.         return (FALSE);
  629.     }
  630.  
  631.  
  632.     hEditBuffer = (HANDLE)SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
  633.     pEditBuffer = LocalLock(hEditBuffer);
  634.  
  635.     /* Set the cursor to an hourglass during the file transfer */
  636.  
  637.     hSaveCursor = SetCursor(hHourGlass);
  638.     IOStatus = write(hFile, pEditBuffer, strlen(pEditBuffer));
  639.     close(hFile);
  640.     SetCursor(hSaveCursor);
  641.     if (IOStatus != (int)strlen(pEditBuffer)) {
  642.         sprintf(szTemp, "Error writing to %s.", szFileName);
  643.         MessageBox(hWnd, szTemp,
  644.             NULL, MB_OK | MB_ICONHAND);
  645.         bSuccess = FALSE;
  646.     }
  647.     else {
  648.         bSuccess = TRUE;                /* Indicates the file was saved      */
  649.         bChanges = FALSE;               /* Indicates changes have been saved */
  650.     }
  651.  
  652.     LocalUnlock(hEditBuffer);
  653.     return (bSuccess);
  654. }
  655.  
  656. /****************************************************************************
  657.  
  658.     FUNCTION: QuerySaveFile(HWND);
  659.  
  660.     PURPOSE: Called when some action might lose current contents
  661.  
  662.     COMMENTS:
  663.  
  664.         This function is called whenever we are about to take an action that
  665.         would lose the current contents of the edit buffer.
  666.  
  667. ****************************************************************************/
  668.  
  669. BOOL QuerySaveFile(hWnd)
  670. HWND hWnd;
  671. {
  672.     int Response;
  673.  
  674.     if (bChanges) {
  675.  
  676.         sprintf(szTemp, "Save current changes: %s", szFileName);
  677.         Response = MessageBox(hWnd, szTemp,
  678.             "EditFile",  MB_YESNOCANCEL | MB_ICONEXCLAMATION);
  679.         if (Response == IDYES) {
  680.  
  681.             /* Make sure there is a filename to save to */
  682.             while (!szFileName[0]) {
  683.  
  684.                 /* Use common save dialog */
  685.         if (!GetSaveFileName ((LPOPENFILENAME)&ofn))
  686.             return FALSE;        /* User canceled */
  687.             }
  688.             SaveFile(hWnd);
  689.         }
  690.         else if (Response == IDCANCEL)
  691.             return (FALSE);
  692.     }
  693.     else
  694.         return (TRUE);
  695. }
  696.  
  697. /****************************************************************************
  698.  
  699.     FUNCTION: SetNewBuffer(HWND, HANDLE, PSTR)
  700.  
  701.     PURPOSE: Set new buffer for edit window
  702.  
  703.     COMMENTS:
  704.  
  705.         Point the edit window to the new buffer, update the window title, and
  706.         redraw the edit window.  If hNewBuffer is NULL, then create an empty
  707.         1K buffer, and return its handle.
  708.  
  709. ****************************************************************************/
  710.  
  711. void SetNewBuffer(hWnd, hNewBuffer, Title)
  712. HWND hWnd;
  713. HANDLE hNewBuffer;
  714. PSTR Title;
  715. {
  716.     HANDLE hOldBuffer;
  717.  
  718.     hOldBuffer = (HANDLE)SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
  719.     LocalFree(hOldBuffer);
  720.     if (!hNewBuffer)                    /* Allocates a buffer if none exists */
  721.         hNewBuffer = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, 1);
  722.  
  723.     SendMessage(hEditWnd, EM_SETHANDLE, hNewBuffer, 0L); /* Updates the buffer
  724.                                 and displays new buffer */
  725.     SetWindowText(hWnd, Title);
  726.     SetFocus(hEditWnd);
  727.     bChanges = FALSE;
  728. }
  729.  
  730.  
  731. /****************************************************************************
  732.  
  733.     FUNCTION: GetPrinterDC()
  734.  
  735.     PURPOSE:  Get hDc for current device on current output port according to
  736.               info in WIN.INI.
  737.  
  738.     COMMENTS:
  739.  
  740.         Searches WIN.INI for information about what printer is connected, and
  741.         if found, creates a DC for the printer.
  742.  
  743.         returns
  744.             hDC > 0 if success
  745.             hDC = 0 if failure
  746.  
  747. ****************************************************************************/
  748.  
  749. HDC GetPrinterDC(void)
  750. {
  751.  
  752.     HDC         hDC;
  753.     LPDEVMODE   lpDevMode = NULL;
  754.     LPDEVNAMES  lpDevNames;
  755.     LPSTR       lpszDriverName;
  756.     LPSTR       lpszDeviceName;
  757.     LPSTR       lpszPortName;
  758.  
  759.     if (!PrintDlg((LPPRINTDLG)&pd))
  760.         return(NULL);
  761.  
  762.     if (pd.hDC)
  763.       {
  764.         hDC = pd.hDC;
  765.       }
  766.     else
  767.       {
  768.  
  769.         if (!pd.hDevNames)
  770.             return(NULL);
  771.  
  772.         lpDevNames = (LPDEVNAMES)GlobalLock(pd.hDevNames);
  773.         lpszDriverName = (LPSTR)lpDevNames + lpDevNames->wDriverOffset;
  774.         lpszDeviceName = (LPSTR)lpDevNames + lpDevNames->wDeviceOffset;
  775.         lpszPortName   = (LPSTR)lpDevNames + lpDevNames->wOutputOffset;
  776.         GlobalUnlock(pd.hDevNames);
  777.  
  778.         if (pd.hDevMode)
  779.             lpDevMode = (LPDEVMODE)GlobalLock(pd.hDevMode);
  780.  
  781.         hDC = CreateDC(lpszDriverName, lpszDeviceName, lpszPortName, (LPSTR)lpDevMode);
  782.  
  783.         if (pd.hDevMode && lpDevMode)
  784.             GlobalUnlock(pd.hDevMode);
  785.       }
  786.  
  787.     if (pd.hDevNames)
  788.     {
  789.     GlobalFree(pd.hDevNames);
  790.     pd.hDevNames=NULL;
  791.     }
  792.     if (pd.hDevMode)
  793.        {
  794.        GlobalFree(pd.hDevMode);
  795.        pd.hDevMode=NULL;
  796.        }
  797.     return(hDC);
  798. }
  799.  
  800. /****************************************************************************
  801.  
  802.     FUNCTION: AbortProc()
  803.  
  804.     PURPOSE:  Processes messages for the Abort Dialog box
  805.  
  806. ****************************************************************************/
  807.  
  808. int FAR PASCAL _export AbortProc(hPr, Code)
  809. HDC hPr;                            /* for multiple printer display contexts */
  810. int Code;                           /* printing status                */
  811. {
  812.     MSG msg;
  813.  
  814.     if (!hAbortDlgWnd)              /* If the abort dialog isn't up yet */
  815.         return(TRUE);
  816.  
  817.     /* Process messages intended for the abort dialog box */
  818.  
  819.     while (!bAbort && PeekMessage(&msg, NULL, NULL, NULL, TRUE))
  820.         if (!IsDialogMessage(hAbortDlgWnd, &msg)) {
  821.             TranslateMessage(&msg);
  822.             DispatchMessage(&msg);
  823.         }
  824.  
  825.     /* bAbort is TRUE (return is FALSE) if the user has aborted */
  826.  
  827.     return (!bAbort);
  828. }
  829.  
  830. /****************************************************************************
  831.  
  832.     FUNCTION: AbortDlg(HWND, unsigned, WORD, LONG)
  833.  
  834.     PURPOSE:  Processes messages for printer abort dialog box
  835.  
  836.     MESSAGES:
  837.  
  838.         WM_INITDIALOG - initialize dialog box
  839.         WM_COMMAND    - Input received
  840.  
  841.     COMMENTS
  842.  
  843.         This dialog box is created while the program is printing, and allows
  844.         the user to cancel the printing process.
  845.  
  846. ****************************************************************************/
  847.  
  848. int FAR PASCAL _export AbortDlg(hDlg, msg, wParam, lParam)
  849. HWND hDlg;
  850. unsigned msg;
  851. WORD wParam;
  852. LONG lParam;
  853. {
  854.     switch(msg) {
  855.  
  856.         /* Watch for Cancel button, RETURN key, ESCAPE key, or SPACE BAR */
  857.  
  858.         case WM_COMMAND:
  859.             return (bAbort = TRUE);
  860.  
  861.         case WM_INITDIALOG:
  862.  
  863.             /* Set the focus to the Cancel box of the dialog */
  864.  
  865.             SetFocus(GetDlgItem(hDlg, IDCANCEL));
  866.             SetDlgItemText(hDlg, IDC_FILENAME, szFileName);
  867.             return (TRUE);
  868.         }
  869.     return (FALSE);
  870. }
  871.  
  872.  
  873. /****************************************************************************
  874.  
  875.     FUNCTION: About(HWND, unsigned, WORD, LONG)
  876.  
  877.     PURPOSE:  Processes messages for "About" dialog box
  878.  
  879.     MESSAGES:
  880.  
  881.         WM_INITDIALOG - initialize dialog box
  882.         WM_COMMAND    - Input received
  883.  
  884. ****************************************************************************/
  885.  
  886. BOOL FAR PASCAL _export About(hDlg, message, wParam, lParam)
  887. HWND hDlg;
  888. unsigned message;
  889. WORD wParam;
  890. LONG lParam;
  891. {
  892.     switch (message) {
  893.         case WM_INITDIALOG:
  894.             return (TRUE);
  895.  
  896.         case WM_COMMAND:
  897.         if (wParam == IDOK
  898.                 || wParam == IDCANCEL) {
  899.                 EndDialog(hDlg, TRUE);
  900.                 return (TRUE);
  901.             }
  902.             return (TRUE);
  903.     }
  904.     return (FALSE);
  905. }
  906.