home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c045 / 5.ddi / PRNTFILE / PRNTFILE.C$ / PRNTFILE.bin
Encoding:
Text File  |  1992-01-01  |  32.2 KB  |  1,206 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.         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 "prntfile.h"
  29. #include "string.h"
  30. #include "io.h"
  31.  
  32. #include <stdio.h>
  33.  
  34. HANDLE hInst;
  35.  
  36. HANDLE hAccTable;                                /* handle to accelerator table */
  37. HWND hEditWnd;                                      /* handle to edit window */
  38. HWND hwnd;                                       /* handle to main window */
  39.  
  40. /* Additional includes needed for the fstat() function */
  41.  
  42. #include <sys\types.h>
  43. #include <sys\stat.h>
  44.  
  45. char FileName[128];
  46. char PathName[128];
  47. char OpenName[128];
  48. char DefPath[128];
  49. char DefSpec[13] = "*.*";
  50. char DefExt[] = ".txt";
  51. char str[255];
  52.  
  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. DWORD dwLines;                      /* number of lines to print       */
  78. DWORD dwIndex;                      /* index into lines to print      */
  79. char pLine[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. /****************************************************************************
  86.  
  87.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  88.  
  89.     PURPOSE: calls initialization function, processes message loop
  90.  
  91. ****************************************************************************/
  92.  
  93. int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  94. HANDLE hInstance;
  95. HANDLE hPrevInstance;
  96. LPSTR lpCmdLine;
  97. int nCmdShow;
  98. {
  99.     MSG msg;
  100.  
  101.     if (!hPrevInstance)
  102.         if (!InitApplication(hInstance))
  103.             return (FALSE);
  104.  
  105.     if (!InitInstance(hInstance, nCmdShow))
  106.         return (FALSE);
  107.  
  108.     while (GetMessage(&msg, NULL, NULL, NULL))
  109.     {
  110.     /* Only translate message if it is not an accelerator message */
  111.         if (!TranslateAccelerator(hwnd, hAccTable, &msg))
  112.         {
  113.             TranslateMessage(&msg);
  114.             DispatchMessage(&msg);
  115.         }
  116.     }
  117.     return (msg.wParam);
  118. }
  119.  
  120.  
  121. /****************************************************************************
  122.  
  123.     FUNCTION: InitApplication(HANDLE)
  124.  
  125.     PURPOSE: Initializes window data and registers window class
  126.  
  127. ****************************************************************************/
  128.  
  129. BOOL InitApplication(HANDLE hInstance)
  130. {
  131.     WNDCLASS  wc;
  132.  
  133.     wc.style = NULL;
  134.     wc.lpfnWndProc = MainWndProc;
  135.     wc.cbClsExtra = 0;
  136.     wc.cbWndExtra = 0;
  137.     wc.hInstance = hInstance;
  138.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  139.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  140.     wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  141.     wc.lpszMenuName =  "PrntFileMenu";
  142.     wc.lpszClassName = "PrntFileWClass";
  143.  
  144.     return (RegisterClass(&wc));
  145. }
  146.  
  147.  
  148. /****************************************************************************
  149.  
  150.     FUNCTION:  InitInstance(HANDLE, int)
  151.  
  152.     PURPOSE:  Saves instance handle and creates main window
  153.  
  154. ****************************************************************************/
  155.  
  156. BOOL InitInstance(HANDLE hInstance, int nCmdShow)
  157. {
  158.     RECT            Rect;
  159.  
  160.     hInst = hInstance;
  161.  
  162.     hAccTable = LoadAccelerators(hInst, "PrntFileAcc");
  163.  
  164.     hwnd = CreateWindow(
  165.         "PrntFileWClass",
  166.         "PrntFile Sample Application",
  167.         WS_OVERLAPPEDWINDOW,
  168.         CW_USEDEFAULT,
  169.         CW_USEDEFAULT,
  170.         CW_USEDEFAULT,
  171.         CW_USEDEFAULT,
  172.         NULL,
  173.         NULL,
  174.         hInstance,
  175.         NULL
  176.     );
  177.  
  178.     if (!hwnd)
  179.         return (FALSE);
  180.  
  181.     GetClientRect(hwnd, (LPRECT) &Rect);
  182.  
  183.     /* Create a child window */
  184.  
  185.     hEditWnd = CreateWindow("Edit",
  186.         NULL,
  187.         WS_CHILD | WS_VISIBLE |
  188.         ES_MULTILINE |
  189.         WS_VSCROLL | WS_HSCROLL |
  190.         ES_AUTOHSCROLL | ES_AUTOVSCROLL,
  191.         0,
  192.         0,
  193.         (Rect.right-Rect.left),
  194.         (Rect.bottom-Rect.top),
  195.         hwnd,
  196.         IDC_EDIT,                          /* Child control i.d. */
  197.         hInst,
  198.         NULL);
  199.  
  200.     if (!hEditWnd) {
  201.         DestroyWindow(hwnd);
  202.         return (NULL);
  203.     }
  204.  
  205.     /* Get an hourglass cursor to use during file transfers */
  206.  
  207.     hHourGlass = LoadCursor(NULL, IDC_WAIT);
  208.  
  209.     ShowWindow(hwnd, nCmdShow);
  210.     UpdateWindow(hwnd);
  211.     return (TRUE);
  212.  
  213. }
  214.  
  215. /****************************************************************************
  216.  
  217.     FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
  218.  
  219.     PURPOSE:  Processes messages
  220.  
  221.     MESSAGES:
  222.  
  223.         WM_COMMAND    - application menu (About dialog box)
  224.         WM_DESTROY    - destroy window
  225.         WM_SIZE       - window size has changed
  226.         WM_QUERYENDSESSION - willing to end session?
  227.         WM_ENDSESSION - end Windows session
  228.         WM_CLOSE      - close the window
  229.         WM_SIZE       - window resized
  230.  
  231.     COMMENTS:
  232.  
  233.         Adds printing capability to the EDITFILE program.  Printing request
  234.         is sent as an IDM_PRINT message.
  235.  
  236.         Before the printing operation begins, a modeless dialog box is
  237.         created to allow the user to abort the printing operation.  This
  238.         dialog box remains active until the print job is completed, or the
  239.         user cancels the print operation.
  240.  
  241. ****************************************************************************/
  242.  
  243. long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
  244. HWND hWnd;
  245. unsigned message;
  246. WORD wParam;
  247. LONG lParam;
  248. {
  249.     FARPROC lpProcAbout, lpOpenDlg, lpSaveAsDlg;
  250.  
  251.     int Success;                            /* return value from SaveAsDlg() */
  252.     int IOStatus;               /* result of file i/o      */
  253.     int nPageSize;              /* vert. resolution of printer device */
  254.  
  255.  
  256.     switch (message)
  257.     {
  258.         case WM_COMMAND:
  259.             switch (wParam)
  260.             {
  261.                 case IDM_ABOUT:
  262.                     lpProcAbout = MakeProcInstance(About, hInst);
  263.                     DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
  264.                     FreeProcInstance(lpProcAbout);
  265.                     break;
  266.  
  267.                 case IDM_NEW:
  268.  
  269.                     /* If current file has been modified, query user about
  270.                      * saving it.
  271.                      */
  272.  
  273.                     if (!QuerySaveFile(hWnd))
  274.                         return (NULL);
  275.  
  276.                     /* bChanges is set to FALSE to indicate there have been
  277.                      * no changes since the last file save.
  278.                      */
  279.  
  280.                     bChanges = FALSE;
  281.                     FileName[0] = 0;
  282.  
  283.                     /* Update the edit buffer */
  284.  
  285.                     SetNewBuffer(hWnd, NULL, Untitled);
  286.                     break;
  287.  
  288.                 case IDM_OPEN:
  289.                     if (!QuerySaveFile(hWnd))
  290.                         return (NULL);
  291.  
  292.                     lpOpenDlg = MakeProcInstance((FARPROC) OpenDlg, hInst);
  293.  
  294.                     /* Open the file and get its handle */
  295.  
  296.                     hFile = DialogBox(hInst, "Open", hWnd, lpOpenDlg);
  297.                     FreeProcInstance(lpOpenDlg);
  298.                     if (!hFile)
  299.                         return (NULL);
  300.  
  301.                     /* Allocate edit buffer to the size of the file + 1 */
  302.  
  303.                     hEditBuffer =  LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,
  304.                         (WORD)FileStatus.st_size+1);
  305.  
  306.                     if (!hEditBuffer)
  307.                     {
  308.                         MessageBox(hWnd, "Not enough memory.",NULL, MB_OK | MB_ICONHAND);
  309.                         return (NULL);
  310.                     }
  311.                     hSaveCursor = SetCursor(hHourGlass);
  312.                     pEditBuffer = LocalLock(hEditBuffer);
  313.  
  314.                     IOStatus = read(hFile, pEditBuffer, (WORD) FileStatus.st_size);
  315.                     close(hFile);
  316.  
  317.                     /* # bytes read must equal file size */
  318.  
  319.                     if (IOStatus != (int)FileStatus.st_size)
  320.                     {
  321.                         sprintf(str, "Error reading %s.", FileName);
  322.                         SetCursor(hSaveCursor);      /* Remove the hourglass */
  323.                         MessageBox(hWnd, str, NULL, MB_OK | MB_ICONEXCLAMATION);
  324.                     }
  325.  
  326.                     LocalUnlock(hEditBuffer);
  327.  
  328.                     /* Set up a new buffer and window title */
  329.  
  330.                     sprintf(str, "PrntFile - %s", FileName);
  331.                     SetNewBuffer(hWnd, hEditBuffer, str);
  332.                     SetCursor(hSaveCursor);            /* restore the cursor */
  333.                     break;
  334.  
  335.                 case IDM_SAVE:
  336.  
  337.                     /* If there is no filename, use the saveas command to get
  338.                      * one.  Otherwise, save the file using the current
  339.                      * filename.
  340.                      */
  341.  
  342.                     if (!FileName[0])
  343.                         goto saveas;
  344.                     if (bChanges)
  345.                         SaveFile(hWnd);
  346.                     break;
  347.  
  348.                 case IDM_SAVEAS:
  349. saveas:
  350.                     lpSaveAsDlg = MakeProcInstance(SaveAsDlg, hInst);
  351.  
  352.                     /* Call the SaveAsDlg() function to get the new filename */
  353.  
  354.                     Success = DialogBox(hInst, "SaveAs", hWnd, lpSaveAsDlg);
  355.                     FreeProcInstance(lpSaveAsDlg);
  356.  
  357.                     /* If successful, update the window title, save the file */
  358.  
  359.                     if (Success == IDOK)
  360.                     {
  361.                         sprintf(str, "PrntFile - %s", FileName);
  362.                         SetWindowText(hWnd, str);
  363.                         SaveFile(hWnd);
  364.                     }
  365.                     break;                                  /* User canceled */
  366.                 case IDM_PRINT:
  367.                     hSaveCursor = SetCursor(hHourGlass);
  368.                     hPr = GetPrinterDC();
  369.                     if (!hPr)
  370.                     {
  371.                         sprintf(str, "Cannot print %s", FileName);
  372.                         MessageBox(hWnd, str, NULL, MB_OK | MB_ICONHAND);
  373.                         return (NULL);
  374.                     }
  375.  
  376.                     lpAbortDlg =  MakeProcInstance(AbortDlg, hInst);
  377.                     lpAbortProc = MakeProcInstance(AbortProc, hInst);
  378.  
  379.                     /* Define the abort function */
  380.  
  381.                     Escape(hPr, SETABORTPROC, NULL,
  382.                         (LPSTR) (long) lpAbortProc,
  383.                         (LPSTR) NULL);
  384.  
  385.                     if (Escape(hPr, STARTDOC, 4, "PrntFile text",(LPSTR) NULL) < 0)
  386.                     {
  387.                         MessageBox(hWnd, "Unable to start print job",
  388.                             NULL, MB_OK | MB_ICONHAND);
  389.                         FreeProcInstance(lpAbortDlg);
  390.                         FreeProcInstance(lpAbortProc);
  391.                         DeleteDC(hPr);
  392.                     }
  393.  
  394.                     bAbort = FALSE; /* Clears the abort flag  */
  395.  
  396.                     /* Create the Abort dialog box (modeless) */
  397.  
  398.                     hAbortDlgWnd = CreateDialog(hInst, "AbortDlg",hWnd, lpAbortDlg);
  399.  
  400.                     if (!hAbortDlgWnd)
  401.                     {
  402.                         SetCursor(hSaveCursor);      /* Remove the hourglass */
  403.                         MessageBox(hWnd, "NULL Abort window handle",NULL, MB_OK | MB_ICONHAND);
  404.                         return (FALSE);
  405.                     }
  406.  
  407.                     /* Now show Abort dialog */
  408.  
  409.                     ShowWindow (hAbortDlgWnd, SW_NORMAL);
  410.  
  411.                     /* Disable the main window to avoid reentrancy problems */
  412.  
  413.                     EnableWindow(hWnd, FALSE);
  414.                     SetCursor(hSaveCursor);      /* Remove the hourglass */
  415.  
  416.                     /* Since you may have more than one line, you need to
  417.                      * compute the spacing between lines.  You can do that by
  418.                      * retrieving the height of the characters you are printing
  419.                      * and advancing their height plus the recommended external
  420.                      * leading height.
  421.                      */
  422.  
  423.                     GetTextMetrics(hPr, &TextMetric);
  424.                     LineSpace = TextMetric.tmHeight + TextMetric.tmExternalLeading;
  425.  
  426.                     /* Since you may have more lines than can fit on one
  427.                      * page, you need to compute the number of lines you can
  428.                      * print per page.  You can do that by retrieving the
  429.                      * dimensions of the page and dividing the height
  430.                      * by the line spacing.
  431.                      */
  432.  
  433.                     nPageSize = GetDeviceCaps (hPr, VERTRES);
  434.                     LinesPerPage = nPageSize / LineSpace - 1;
  435.  
  436.  
  437.                     /* You can output only one line at a time, so you need a
  438.                      * count of the number of lines to print.  You can retrieve
  439.                      * the count sending the EM_GETLINECOUNT message to the edit
  440.                      * control.
  441.                      */
  442.  
  443.                     dwLines = SendMessage(hEditWnd, EM_GETLINECOUNT, 0, 0L);
  444.  
  445.                     /* Keep track of the current line on the current page */
  446.  
  447.                     CurrentLine = 1;
  448.  
  449.                     /* One way to output one line at a time is to retrieve
  450.                      * one line at a time from the edit control and write it
  451.                      * using the TextOut function.  For each line you need to
  452.                      * advance one line space.  Also, you need to check for the
  453.                      * end of the page and start a new page if necessary.
  454.                      */
  455.  
  456.                     for (dwIndex = IOStatus = 0; dwIndex < dwLines; dwIndex++)
  457.                     {
  458.                         pLine[0] = 128;               /* Maximum buffer size */
  459.                         pLine[1] = 0;
  460.                         LineLength = (int) SendMessage(hEditWnd, EM_GETLINE,
  461.                             (WORD)dwIndex, (LONG)((LPSTR)pLine));
  462.                         TextOut(hPr, 0, CurrentLine*LineSpace,
  463.                             (LPSTR)pLine, LineLength);
  464.                         if (++CurrentLine > LinesPerPage )
  465.                         {
  466.                             CurrentLine = 1;
  467.                             IOStatus = Escape(hPr, NEWFRAME, 0, 0L, 0L);
  468.                             if (IOStatus<0 || bAbort)
  469.                                 break;
  470.                         }
  471.                     }
  472.  
  473.                     if (IOStatus >= 0 && !bAbort)
  474.                     {
  475.                         Escape(hPr, NEWFRAME, 0, 0L, 0L);
  476.                         Escape(hPr, ENDDOC, 0, 0L, 0L);
  477.                     }
  478.                     EnableWindow(hWnd, TRUE);
  479.  
  480.                     /* Destroy the Abort dialog box */
  481.  
  482.                     DestroyWindow(hAbortDlgWnd);
  483.                     FreeProcInstance(lpAbortDlg);
  484.                     FreeProcInstance(lpAbortProc);
  485.                     DeleteDC(hPr);
  486.                     break;
  487.  
  488.  
  489.                 /* edit menu commands */
  490.  
  491.                 case IDM_UNDO:
  492.                 case IDM_CUT:
  493.                 case IDM_COPY:
  494.                 case IDM_PASTE:
  495.                 case IDM_CLEAR:
  496.                     MessageBox (
  497.                           GetFocus(),
  498.                           "Command not implemented",
  499.                           "PrntFile Sample Application",
  500.                           MB_ICONASTERISK | MB_OK);
  501.                     break;
  502.  
  503.                 case IDM_EXIT:
  504.                     QuerySaveFile(hWnd);
  505.                     DestroyWindow(hWnd);
  506.                     break;
  507.  
  508.                 case IDC_EDIT:
  509.                     if (HIWORD (lParam) == EN_ERRSPACE)
  510.                         MessageBox (GetFocus (), "Out of memory.",
  511.                             "PrntFile Sample Application", MB_ICONHAND | MB_OK);
  512.                     break;
  513.  
  514.             }
  515.             break;
  516.  
  517.         case WM_SETFOCUS:
  518.             SetFocus (hEditWnd);
  519.             break;
  520.  
  521.         case WM_SIZE:
  522.             MoveWindow(hEditWnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
  523.             break;
  524.  
  525.         case WM_QUERYENDSESSION:             /* message: to end the session? */
  526.             return (QuerySaveFile(hWnd));
  527.  
  528.         case WM_CLOSE:                       /* message: close the window    */
  529.             if (QuerySaveFile(hWnd))
  530.                 DestroyWindow(hWnd);
  531.             break;
  532.  
  533.         case WM_DESTROY:
  534.             PostQuitMessage(0);
  535.             break;
  536.  
  537.         default:
  538.             return (DefWindowProc(hWnd, message, wParam, lParam));
  539.     }
  540.     return (NULL);
  541. }
  542.  
  543. /****************************************************************************
  544.  
  545.     FUNCTION: SaveAsDlg(HWND, unsigned, WORD, LONG)
  546.  
  547.     PURPOSE: Allows user to change name to save file to
  548.  
  549.     COMMENTS:
  550.  
  551.         This will initialize the window class if it is the first time this
  552.         application is run.  It then creates the window, and processes the
  553.         message loop until a PostQuitMessage is received.  It exits the
  554.         application by returning the value passed by the PostQuitMessage.
  555.  
  556. ****************************************************************************/
  557.  
  558. int FAR PASCAL SaveAsDlg(hDlg, message, wParam, lParam)
  559. HWND hDlg;
  560. unsigned message;
  561. WORD wParam;
  562. LONG lParam;
  563. {
  564.     char TempName[128];
  565.  
  566.     switch (message)
  567.     {
  568.         case WM_INITDIALOG:
  569.  
  570.             /* If no filename is entered, don't allow the user to save to it */
  571.  
  572.             if (!FileName[0])
  573.                 bSaveEnabled = FALSE;
  574.             else
  575.             {
  576.                 bSaveEnabled = TRUE;
  577.  
  578.                 /* Process the path to fit within the IDC_PATH field */
  579.  
  580.                 DlgDirList(hDlg, DefPath, NULL, IDC_PATH, 0x4010);
  581.  
  582.                 /* Send the current filename to the edit control */
  583.  
  584.                 SetDlgItemText(hDlg, IDC_EDIT, FileName);
  585.  
  586.                 /* Accept all characters in the edit control */
  587.  
  588.                 SendDlgItemMessage(hDlg, IDC_EDIT, EM_SETSEL, 0,
  589.                     MAKELONG(0, 0x7fff));
  590.             }
  591.  
  592.             /* Enable or disable the save control depending on whether the
  593.              * filename exists.
  594.              */
  595.  
  596.             EnableWindow(GetDlgItem(hDlg, IDOK), bSaveEnabled);
  597.  
  598.             /* Set the focus to the edit control within the dialog box */
  599.  
  600.             SetFocus(GetDlgItem(hDlg, IDC_EDIT));
  601.             return (FALSE);                 /* FALSE since Focus was changed */
  602.  
  603.         case WM_COMMAND:
  604.             switch (wParam)
  605.             {
  606.                 case IDC_EDIT:
  607.  
  608.                     /* If there was previously no filename in the edit
  609.                      * control, then the save control must be enabled as soon as
  610.                      * a character is entered.
  611.                      */
  612.  
  613.                     if (HIWORD(lParam) == EN_CHANGE && !bSaveEnabled)
  614.                     EnableWindow(GetDlgItem(hDlg, IDOK), bSaveEnabled = TRUE);
  615.                     return (TRUE);
  616.  
  617.                 case IDOK:
  618.  
  619.                     /* Get the filename from the edit control */
  620.  
  621.                     GetDlgItemText(hDlg, IDC_EDIT, TempName, 128);
  622.  
  623.                     /* If there are no wildcards, then separate the name into
  624.                      * path and name.  If a path was specified, replace the
  625.                      * default path with the new path.
  626.                      */
  627.  
  628.                     if (CheckFileName(hDlg, FileName, TempName)) {
  629.                         SeparateFile(hDlg, (LPSTR) str, (LPSTR) DefSpec,
  630.                             (LPSTR) FileName);
  631.                         if (str[0])
  632.                             strcpy(DefPath, str);
  633.  
  634.                         /* Tell the caller a filename was selected */
  635.  
  636.                         EndDialog(hDlg, IDOK);
  637.                     }
  638.                     return (TRUE);
  639.  
  640.                 case IDCANCEL:
  641.  
  642.                     /* Tell the caller the user canceled the SaveAs function */
  643.  
  644.                     EndDialog(hDlg, IDCANCEL);
  645.                     return (TRUE);
  646.             }
  647.             break;
  648.  
  649.     }
  650.     return (FALSE);
  651. }
  652.  
  653. /****************************************************************************
  654.  
  655.     FUNCTION: OpenDlg(HWND, unsigned, WORD, LONG)
  656.  
  657.     PURPOSE: Let user select a file, and open it.
  658.  
  659. ****************************************************************************/
  660.  
  661. HANDLE FAR PASCAL OpenDlg(hDlg, message, wParam, lParam)
  662. HWND hDlg;
  663. unsigned message;
  664. WORD wParam;
  665. LONG lParam;
  666. {
  667.     WORD index;
  668.     PSTR pTptr;
  669.     HANDLE hFile;
  670.  
  671.     switch (message)
  672.     {
  673.         case WM_COMMAND:
  674.             switch (wParam)
  675.             {
  676.                 case IDC_LISTBOX:
  677.                     switch (HIWORD(lParam))
  678.                     {
  679.                         case LBN_SELCHANGE:
  680.                             /* If item is a directory name, append "*.*" */
  681.                             if (DlgDirSelect(hDlg, str, IDC_LISTBOX))
  682.                                 strcat(str, DefSpec);
  683.                             SetDlgItemText(hDlg, IDC_EDIT, str);
  684.                             SendDlgItemMessage(hDlg,IDC_EDIT,EM_SETSEL,NULL,MAKELONG(0, 0x7fff));
  685.                             break;
  686.  
  687.                         case LBN_DBLCLK:
  688.                             goto openfile;
  689.                     }
  690.                     return (TRUE);
  691.  
  692.                 case IDOK:
  693. openfile:
  694.                     GetDlgItemText(hDlg, IDC_EDIT, OpenName, 128);
  695.                     if (strchr(OpenName, '*') || strchr(OpenName, '?'))
  696.                     {
  697.                         SeparateFile(hDlg, (LPSTR) str, (LPSTR) DefSpec,
  698.                             (LPSTR) OpenName);
  699.                         if (str[0])
  700.                             strcpy(DefPath, str);
  701.                         ChangeDefExt(DefExt, DefSpec);
  702.                         UpdateListBox(hDlg);
  703.                         return (TRUE);
  704.                     }
  705.  
  706.                     if (!OpenName[0])
  707.                     {
  708.                         MessageBox(hDlg, "No filename specified.",NULL, MB_OK | MB_ICONHAND);
  709.                         return (TRUE);
  710.                     }
  711.                     AddExt(OpenName, DefExt);
  712.  
  713.                     /* Open the file */
  714.  
  715.                     if ((hFile = OpenFile(OpenName, (LPOFSTRUCT) &OfStruct,
  716.                             OF_READ)) == -1)
  717.                     {
  718.                         sprintf(str, "Error %d opening %s.",OfStruct.nErrCode, OpenName);
  719.                         MessageBox(hDlg, str, NULL,MB_OK | MB_ICONHAND);
  720.                     }
  721.                     else
  722.                     {
  723.                         /* Make sure there's enough room for the file */
  724.                         fstat(hFile, &FileStatus);
  725.                         if (FileStatus.st_size > MAXFILESIZE)
  726.                         {
  727.                             sprintf(str,
  728.                                 "Not enough memory to load %s.\n%s exceeds %ld bytes.",
  729.                                 OpenName, OpenName, MAXFILESIZE);
  730.                             MessageBox(hDlg, str, NULL,MB_OK | MB_ICONHAND);
  731.                             return (TRUE);
  732.                         }
  733.  
  734.                         /* File is opened and there is enough room so return
  735.                          * the handle to the caller.
  736.                          */
  737.  
  738.                         strcpy(FileName, OpenName);
  739.                         EndDialog(hDlg, hFile);
  740.                         return (TRUE);
  741.                     }
  742.                     return (TRUE);
  743.  
  744.                 case IDCANCEL:
  745.                     /* strcpy(DefPath, str);
  746.                         ChangeDefExt(DefExt, DefSpec);*/
  747.                     EndDialog(hDlg, NULL);
  748.                     return (TRUE);
  749.             }
  750.             break;
  751.  
  752.         case WM_INITDIALOG:                        /* message: initialize    */
  753.             UpdateListBox(hDlg);
  754.             SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
  755.             SendDlgItemMessage(hDlg,               /* dialog handle      */
  756.                 IDC_EDIT,                          /* where to send message  */
  757.                 EM_SETSEL,                         /* select characters      */
  758.                 NULL,                              /* additional information */
  759.                 MAKELONG(0, 0x7fff));              /* entire contents      */
  760.             SetFocus(GetDlgItem(hDlg, IDC_EDIT));
  761.             return (FALSE); /* Indicates the focus is set to a control */
  762.     }
  763.     return FALSE;
  764. }
  765.  
  766. /****************************************************************************
  767.  
  768.     FUNCTION: UpdateListBox(HWND);
  769.  
  770.     PURPOSE: Update the list box of OpenDlg
  771.  
  772. ****************************************************************************/
  773.  
  774. void UpdateListBox(hDlg)
  775. HWND hDlg;
  776. {
  777.     strcpy(str, DefPath);
  778.     strcat(str, DefSpec);
  779.     DlgDirList(hDlg, str, IDC_LISTBOX, IDC_PATH, 0x4010);
  780.  
  781.     /* To ensure that the listing is made for a subdir. of
  782.      * current drive dir...
  783.      */
  784.     if (!strchr (DefPath, ':'))
  785.         DlgDirList(hDlg, DefSpec, IDC_LISTBOX, IDC_PATH, 0x4010);
  786.  
  787.     /* Remove the '..' character from path if it exists, since this
  788.      * will make DlgDirList move us up an additional level in the tree
  789.      * when UpdateListBox() is called again.
  790.      */
  791.     if (strstr (DefPath, ".."))
  792.         DefPath[0] = '\0';
  793.     SetDlgItemText(hDlg, IDC_EDIT, DefSpec);
  794. }
  795.  
  796. /****************************************************************************
  797.  
  798.     FUNCTION: ChangeDefExt(PSTR, PSTR);
  799.  
  800.     PURPOSE: Change the default extension
  801.  
  802. ****************************************************************************/
  803.  
  804. void ChangeDefExt(Ext, Name)
  805. PSTR Ext, Name;
  806. {
  807.     PSTR pTptr;
  808.  
  809.     pTptr = Name;
  810.     while (*pTptr && *pTptr != '.')
  811.         pTptr++;
  812.     if (*pTptr)
  813.         if (!strchr(pTptr, '*') && !strchr(pTptr, '?'))
  814.             strcpy(Ext, pTptr);
  815. }
  816.  
  817. /****************************************************************************
  818.  
  819.     FUNCTION: SeparateFile(HWND, LPSTR, LPSTR, LPSTR)
  820.  
  821.     PURPOSE: Separate filename and pathname
  822.  
  823. ****************************************************************************/
  824.  
  825. void SeparateFile(hDlg, lpDestPath, lpDestFileName, lpSrcFileName)
  826. HWND hDlg;
  827. LPSTR lpDestPath, lpDestFileName, lpSrcFileName;
  828. {
  829.     LPSTR lpTmp;
  830.     char  cTmp;
  831.  
  832.     lpTmp = lpSrcFileName + (long) lstrlen(lpSrcFileName);
  833.     while (*lpTmp != ':' && *lpTmp != '\\' && lpTmp > lpSrcFileName)
  834.         lpTmp = AnsiPrev(lpSrcFileName, lpTmp);
  835.     if (*lpTmp != ':' && *lpTmp != '\\')
  836.     {
  837.         lstrcpy(lpDestFileName, lpSrcFileName);
  838.         lpDestPath[0] = 0;
  839.         return;
  840.     }
  841.     lstrcpy(lpDestFileName, lpTmp + 1);
  842.     cTmp = *(lpTmp + 1);
  843.     lstrcpy(lpDestPath, lpSrcFileName);
  844.     *(lpTmp + 1) = cTmp;
  845.     lpDestPath[(lpTmp - lpSrcFileName) + 1] = 0;
  846. }
  847.  
  848. /****************************************************************************
  849.  
  850.     FUNCTION: AddExt(PSTR, PSTR);
  851.  
  852.     PURPOSE: Add default extension
  853.  
  854. /***************************************************************************/
  855.  
  856. void AddExt(Name, Ext)
  857. PSTR Name, Ext;
  858. {
  859.     PSTR pTptr;
  860.  
  861.     pTptr = Name;
  862.     while (*pTptr && *pTptr != '.')
  863.         pTptr++;
  864.     if (*pTptr != '.')
  865.         strcat(Name, Ext);
  866. }
  867.  
  868. /****************************************************************************
  869.  
  870.     FUNCTION: CheckFileName(HWND, PSTR, PSTR)
  871.  
  872.     PURPOSE: Check for wildcards, add extension if needed
  873.  
  874.     COMMENTS:
  875.  
  876.         Make sure you have a filename and that it does not contain any
  877.         wildcards.  If needed, add the default extension.  This function is
  878.         called whenever your application wants to save a file.
  879.  
  880. ****************************************************************************/
  881.  
  882. BOOL CheckFileName(hWnd, pDest, pSrc)
  883. HWND hWnd;
  884. PSTR pDest, pSrc;
  885. {
  886.     PSTR pTmp;
  887.  
  888.     if (!pSrc[0])
  889.         return (FALSE);               /* Indicates no filename was specified */
  890.  
  891.     pTmp = pSrc;
  892.     while (*pTmp)                    /* Searches the string for wildcards */
  893.     {
  894.         switch (*pTmp++)
  895.         {
  896.             case '*':
  897.             case '?':
  898.                 MessageBox(hWnd, "Wildcards not allowed.",NULL, MB_OK | MB_ICONEXCLAMATION);
  899.                 return (FALSE);
  900.         }
  901.     }
  902.  
  903.     AddExt(pSrc, DefExt);            /* Adds the default extension if needed */
  904.  
  905.     if (OpenFile(pSrc, (LPOFSTRUCT) &OfStruct, OF_EXIST) >= 0)
  906.     {
  907.         sprintf(str, "Replace existing %s?", pSrc);
  908.         if (MessageBox(hWnd, str, "PrntFile",
  909.                 MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
  910.             return (FALSE);
  911.     }
  912.     strcpy(pDest, pSrc);
  913.     return (TRUE);
  914. }
  915.  
  916. /****************************************************************************
  917.  
  918.     FUNCTION: SaveFile(HWND)
  919.  
  920.     PURPOSE: Save current file
  921.  
  922.     COMMENTS:
  923.  
  924.         This saves the current contents of the Edit buffer, and changes
  925.         bChanges to indicate that the buffer has not been changed since the
  926.         last save.
  927.  
  928.         Before the edit buffer is sent, you must get its handle and lock it
  929.         to get its address.  Once the file is written, you must unlock the
  930.         buffer.  This allows Windows to move the buffer when not in immediate
  931.         use.
  932.  
  933. ****************************************************************************/
  934.  
  935. BOOL SaveFile(hWnd)
  936. HWND hWnd;
  937. {
  938.     BOOL bSuccess;
  939.     int IOStatus;                                  /* result of a file write */
  940.  
  941.     if ((hFile = OpenFile(FileName, &OfStruct,OF_PROMPT | OF_CANCEL | OF_CREATE)) < 0)
  942.     {
  943.         /* If the file can't be saved */
  944.         sprintf(str, "Cannot write to %s.", FileName);
  945.         MessageBox(hWnd, str, NULL, MB_OK | MB_ICONHAND);
  946.         return (FALSE);
  947.     }
  948.  
  949.     hEditBuffer = (HANDLE) SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
  950.     pEditBuffer = LocalLock(hEditBuffer);
  951.  
  952.     /* Set the cursor to an hourglass during the file transfer */
  953.  
  954.     hSaveCursor = SetCursor(hHourGlass);
  955.     IOStatus = write(hFile, pEditBuffer, strlen(pEditBuffer));
  956.     close(hFile);
  957.     SetCursor(hSaveCursor);
  958.     if (IOStatus != (int) strlen(pEditBuffer))
  959.     {
  960.         sprintf(str, "Error writing to %s.", FileName);
  961.         MessageBox(hWnd, str,NULL, MB_OK | MB_ICONHAND);
  962.         bSuccess = FALSE;
  963.     }
  964.     else
  965.     {
  966.         bSuccess = TRUE;                /* Indicates the file was saved      */
  967.         bChanges = FALSE;               /* Indicates changes have been saved */
  968.     }
  969.  
  970.     LocalUnlock(hEditBuffer);
  971.     return (bSuccess);
  972. }
  973.  
  974. /****************************************************************************
  975.  
  976.     FUNCTION: QuerySaveFile(HWND);
  977.  
  978.     PURPOSE: Called when some action might lose current contents
  979.  
  980.     COMMENTS:
  981.  
  982.         This function is called whenever we are about to take an action that
  983.         would lose the current contents of the edit buffer.
  984.  
  985. ****************************************************************************/
  986.  
  987. BOOL QuerySaveFile(hWnd)
  988. HWND hWnd;
  989. {
  990.     int Response;
  991.     FARPROC lpSaveAsDlg;
  992.  
  993.     if (bChanges)
  994.     {
  995.         sprintf(str, "Save current changes: %s", FileName);
  996.         Response = MessageBox(hWnd, str,"PrntFile",  MB_YESNOCANCEL | MB_ICONHAND);
  997.         if (Response == IDYES)
  998.         {
  999. check_name:
  1000.  
  1001.             /* Make sure there is a filename to save to */
  1002.             if (!FileName[0])
  1003.             {
  1004.                 lpSaveAsDlg = MakeProcInstance(SaveAsDlg, hInst);
  1005.                 Response = DialogBox(hInst, "SaveAs",hWnd, lpSaveAsDlg);
  1006.                 FreeProcInstance(lpSaveAsDlg);
  1007.                 if (Response == IDOK)
  1008.                     goto check_name;
  1009.                 else
  1010.                     return (FALSE);
  1011.             }
  1012.             SaveFile(hWnd);
  1013.         }
  1014.         else if (Response == IDCANCEL)
  1015.             return (FALSE);
  1016.     }
  1017.     else
  1018.         return (TRUE);
  1019. }
  1020.  
  1021. /****************************************************************************
  1022.  
  1023.     FUNCTION: SetNewBuffer(HWND, HANDLE, PSTR)
  1024.  
  1025.     PURPOSE: Set new buffer for edit window
  1026.  
  1027.     COMMENTS:
  1028.  
  1029.         Point the edit window to the new buffer, update the window title, and
  1030.         redraw the edit window.  If hNewBuffer is NULL, then create an empty
  1031.         1K buffer, and return its handle.
  1032.  
  1033. ****************************************************************************/
  1034.  
  1035. void SetNewBuffer(hWnd, hNewBuffer, Title)
  1036. HWND hWnd;
  1037. HANDLE hNewBuffer;
  1038. PSTR Title;
  1039. {
  1040.     HANDLE hOldBuffer;
  1041.  
  1042.     hOldBuffer = (HANDLE) SendMessage(hEditWnd, EM_GETHANDLE, 0, 0L);
  1043.     LocalFree(hOldBuffer);
  1044.     if (!hNewBuffer)                    /* Allocates a buffer if none exists */
  1045.         hNewBuffer = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, 1);
  1046.  
  1047.     SendMessage(hEditWnd, EM_SETHANDLE, hNewBuffer, 0L); /* Updates the buffer
  1048.                                 and displays new buffer */
  1049.     SetWindowText(hWnd, Title);
  1050.     SetFocus(hEditWnd);
  1051.     bChanges = FALSE;
  1052. }
  1053.  
  1054.  
  1055. /****************************************************************************
  1056.  
  1057.     FUNCTION: GetPrinterDC()
  1058.  
  1059.     PURPOSE:  Get hDc for current device on current output port according to
  1060.               info in WIN.INI.
  1061.  
  1062.     COMMENTS:
  1063.  
  1064.         Searches WIN.INI for information about what printer is connected, and
  1065.         if found, creates a DC for the printer.
  1066.  
  1067.         returns
  1068.             hDC > 0 if success
  1069.             hDC = 0 if failure
  1070.  
  1071. ****************************************************************************/
  1072.  
  1073. HANDLE GetPrinterDC()
  1074. {
  1075.     char pPrintInfo[80];
  1076.     LPSTR lpTemp;
  1077.     LPSTR lpPrintType;
  1078.     LPSTR lpPrintDriver;
  1079.     LPSTR lpPrintPort;
  1080.  
  1081.     if (!GetProfileString("windows", "Device", (LPSTR)"", pPrintInfo, 80))
  1082.         return (NULL);
  1083.     lpTemp = lpPrintType = pPrintInfo;
  1084.     lpPrintDriver = lpPrintPort = 0;
  1085.     while (*lpTemp) {
  1086.         if (*lpTemp == ',') {
  1087.             *lpTemp++ = 0;
  1088.             while (*lpTemp == ' ')
  1089.                 lpTemp = AnsiNext(lpTemp);
  1090.             if (!lpPrintDriver)
  1091.                 lpPrintDriver = lpTemp;
  1092.             else {
  1093.                 lpPrintPort = lpTemp;
  1094.                 break;
  1095.             }
  1096.         }
  1097.         else
  1098.             lpTemp = AnsiNext(lpTemp);
  1099.     }
  1100.  
  1101.     return (CreateDC(lpPrintDriver, lpPrintType, lpPrintPort, (LPSTR) NULL));
  1102. }
  1103.  
  1104. /****************************************************************************
  1105.  
  1106.     FUNCTION: AbortProc()
  1107.  
  1108.     PURPOSE:  Processes messages for the Abort Dialog box
  1109.  
  1110. ****************************************************************************/
  1111.  
  1112. int FAR PASCAL AbortProc(hPr, Code)
  1113. HDC hPr;                            /* for multiple printer display contexts */
  1114. int Code;                           /* printing status                */
  1115. {
  1116.     MSG msg;
  1117.  
  1118.     /* Process messages intended for the abort dialog box */
  1119.  
  1120.     while (!bAbort && PeekMessage(&msg, NULL, NULL, NULL, TRUE))
  1121.         if (!IsDialogMessage(hAbortDlgWnd, &msg))
  1122.         {
  1123.             TranslateMessage(&msg);
  1124.             DispatchMessage(&msg);
  1125.         }
  1126.  
  1127.     /* bAbort is TRUE (return is FALSE) if the user has aborted */
  1128.  
  1129.     return (!bAbort);
  1130. }
  1131.  
  1132. /****************************************************************************
  1133.  
  1134.     FUNCTION: AbortDlg(HWND, unsigned, WORD, LONG)
  1135.  
  1136.     PURPOSE:  Processes messages for printer abort dialog box
  1137.  
  1138.     MESSAGES:
  1139.  
  1140.         WM_INITDIALOG - initialize dialog box
  1141.         WM_COMMAND    - Input received
  1142.  
  1143.     COMMENTS
  1144.  
  1145.         This dialog box is created while the program is printing, and allows
  1146.         the user to cancel the printing process.
  1147.  
  1148. ****************************************************************************/
  1149.  
  1150. int FAR PASCAL AbortDlg(hDlg, msg, wParam, lParam)
  1151. HWND hDlg;
  1152. unsigned msg;
  1153. WORD wParam;
  1154. LONG lParam;
  1155. {
  1156.     switch(msg)
  1157.     {
  1158.         /* Watch for Cancel button, RETURN key, ESCAPE key, or SPACE BAR */
  1159.         case WM_COMMAND:
  1160.             return (bAbort = TRUE);
  1161.  
  1162.         case WM_INITDIALOG:
  1163.             /* Set the focus to the Cancel box of the dialog */
  1164.             SetFocus(GetDlgItem(hDlg, IDCANCEL));
  1165.             SetDlgItemText(hDlg, IDC_FILENAME, FileName);
  1166.             return (TRUE);
  1167.     }
  1168.     return (FALSE);
  1169. }
  1170.  
  1171.  
  1172. /****************************************************************************
  1173.  
  1174.     FUNCTION: About(HWND, unsigned, WORD, LONG)
  1175.  
  1176.     PURPOSE:  Processes messages for "About" dialog box
  1177.  
  1178.     MESSAGES:
  1179.  
  1180.         WM_INITDIALOG - initialize dialog box
  1181.         WM_COMMAND    - Input received
  1182.  
  1183. ****************************************************************************/
  1184.  
  1185. BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
  1186. HWND hDlg;
  1187. unsigned message;
  1188. WORD wParam;
  1189. LONG lParam;
  1190. {
  1191.     switch (message)
  1192.     {
  1193.         case WM_INITDIALOG:
  1194.             return (TRUE);
  1195.  
  1196.         case WM_COMMAND:
  1197.             if (wParam == IDOK || wParam == IDCANCEL)
  1198.             {
  1199.                 EndDialog(hDlg, TRUE);
  1200.                 return (TRUE);
  1201.             }
  1202.             return (TRUE);
  1203.     }
  1204.     return (FALSE);
  1205. }
  1206.