home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / prnt3.zip / FilePrn.C < prev    next >
C/C++ Source or Header  |  1995-05-09  |  44KB  |  1,288 lines

  1. #pragma    title("Printer Driver  --  Version 3  --  (PrnWnd.C)")
  2. #pragma    subtitle("   Application Window - Interface Definitions")
  3.  
  4. #define    INCL_DEV           /* Include OS/2 Device Interface    */
  5. #define    INCL_DOS           /* Include OS/2 DOS Kernal        */
  6. #define    INCL_DOSERRORS           /* Include OS/2 DOS Errors        */
  7. #define    INCL_GPI           /* Include OS/2 PM GPI Interface    */
  8. #define    INCL_WIN           /* Include OS/2 PM Windows Interface    */
  9.  
  10. #pragma    info(noext)
  11.  
  12. #include <malloc.h>
  13. #include <os2.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17.  
  18. #include "appdefs.h"
  19. #include "prnsetup.h"
  20.  
  21. /* This    module contains    the routines to    handle the font    selection,    */
  22. /* file    selection and printing.                        */
  23.  
  24. /* Filename:   FilePrn.C                        */
  25.  
  26. /*  Version:   2                            */
  27. /*  Created:   1995-03-07                        */
  28. /*  Revised:   1995-04-02                        */
  29.  
  30. /* Routines:   MRESULT EXPENTRY    FilePrintDlgProc(HWND hWnd,        */
  31. /*                         ULONG msg,        */
  32. /*                         MPARAM    mp1,        */
  33. /*                         MPARAM    mp2);        */
  34. /*           static VOID ShowDirInfo(HWND hWnd, ULONG    idPath,        */
  35. /*                       ULONG idVol, ULONG idRoom);    */
  36. /*           static VOID DiskVolDrive(ULONG ulDrive,            */
  37. /*                    CHAR *pszDiskName);        */
  38. /*           static VOID QueryDriveList( );                */
  39. /*           static ULONG ulGetDirList(HWND hwndDrives, HWND hwndDirs,*/
  40. /*                     HWND hwndFiles);        */
  41. /*           static BOOL fPrnLine(HPS    hpsPrinter, HDC    hdcPrinter,    */
  42. /*                    PSZ    pszStr,    PPOINTL    pptl,        */
  43. /*                    PPOINTL pptlFooter,            */
  44. /*                    PSIZEL psizlPage, LONG yShift,    */
  45. /*                    BOOL fDateFooter, PSZ pszFooter,    */
  46. /*                    PULONG pcPages);            */
  47. /*           VOID _System PrnFile(PPRNDATA pprni);            */
  48.  
  49. /************************************************************************/
  50. /************************************************************************/
  51. /************************************************************************/
  52. /* DISCLAIMER OF WARRANTIES:                        */
  53. /* -------------------------                        */
  54. /* The following [enclosed] code is sample code    created    by IBM        */
  55. /* Corporation and Prominare Inc.  This    sample code is not part    of any    */
  56. /* standard IBM    product    and is provided    to you solely for the purpose    */
  57. /* of assisting    you in the development of your applications.  The code    */
  58. /* is provided "AS IS",    without    warranty of any    kind.  Neither IBM nor    */
  59. /* Prominare shall be liable for any damages arising out of your    */
  60. /* use of the sample code, even    if they    have been advised of the    */
  61. /* possibility of such damages.                        */
  62. /************************************************************************/
  63. /************************************************************************/
  64. /************************************************************************/
  65. /*               D I S C L A I M E R                */
  66. /* This    code is    provided on an as is basis with    no implied support.    */
  67. /* It should be    considered freeware that cannot    be rebundled as        */
  68. /* part    of a larger "*ware" offering without our consent.        */
  69. /************************************************************************/
  70. /************************************************************************/
  71. /************************************************************************/
  72.  
  73. /* Copyright ╕ International Business Machines Corp., 1995.        */
  74. /* Copyright ╕ 1995  Prominare Inc.  All Rights    Reserved.        */
  75.  
  76. /* --------------------------------------------------------------------    */
  77.  
  78. /************************************************************************/
  79. /*                                    */
  80. /*     Module Prototype    Definitions                    */
  81. /*                                    */
  82. /************************************************************************/
  83.  
  84. static VOID  QueryDriveList(VOID);
  85. static ULONG ulGetDirList(HWND hwndDrives, HWND    hwndDirs, HWND hwndFiles);
  86. static VOID  DiskVolDrive(ULONG    ulDrive, CHAR *pszDiskName);
  87. static VOID  ShowDirInfo(HWND hWnd, ULONG idPath, ULONG    idVol, ULONG idRoom);
  88. static BOOL  fPrnLine(HPS hpsPrinter, HDC hdcPrinter, PSZ pszStr,
  89.            PPOINTL pptl, PPOINTL pptlFooter, PSIZEL    psizlPage, LONG    yShift,
  90.            BOOL fDateFooter, PSZ pszFooter,    PULONG pcPages);
  91. VOID _System PrnFile(PPRNDATA pprni);
  92.  
  93. /************************************************************************/
  94. /*                                    */
  95. /*     Module Data Definitions                        */
  96. /*                                    */
  97. /************************************************************************/
  98.  
  99. BOOL  fLineNumbers = FALSE;       /* Line Numbers Flag            */
  100. INT   iFileSel = LIT_NONE;       /* File Selected            */
  101. BOOL  fDrivesFilled;           /* Drives Filled Flag        */
  102. ULONG ulDriveMap;           /* Drive Bit    Map Holder        */
  103. LONG  cDrives;
  104. CHAR  aszDrives[26][20];
  105. BOOL  afRemoveable[26] = { FALSE, FALSE, FALSE,    FALSE, FALSE, FALSE, FALSE, FALSE,
  106.                FALSE, FALSE, FALSE,    FALSE, FALSE, FALSE, FALSE, FALSE,
  107.                FALSE, FALSE, FALSE,    FALSE, FALSE, FALSE, FALSE, FALSE,
  108.                FALSE, FALSE    };
  109.  
  110. CHAR szDayNames[ ]   = { "SunMonTueWedThuFriSat" };
  111. CHAR szMonthNames[ ] = { "JanFebMarAprMayJunJulAugSepOctNovDec"    };
  112.  
  113. #pragma    subtitle("   File Print -  File Print Dialogue Procedure")
  114. #pragma    page( )
  115.  
  116. /* --- FilePrintDlgProc    -------------------------------- [ Public ] ---    */
  117. /*                                    */
  118. /*     This function is    used to    process    the messages for the file    */
  119. /*     print dialogue procedure.                    */
  120. /*                                    */
  121. /*     Upon Entry:                            */
  122. /*                                    */
  123. /*     HWND   hWnd; = Dialog Window Handle                */
  124. /*     ULONG  msg;  = PM Message                    */
  125. /*     MPARAM mp1;  = Message Parameter    1                */
  126. /*     MPARAM mp2;  = Message Parameter    2                */
  127. /*                                    */
  128. /*     Upon Exit:                            */
  129. /*                                    */
  130. /*     FilePrintDlgProc    = Message Handling Result            */
  131. /*                                    */
  132. /* --------------------------------------------------------------------    */
  133.  
  134. MRESULT    EXPENTRY FilePrintDlgProc(HWND hWnd, ULONG msg,    MPARAM mp1, MPARAM mp2)
  135.  
  136. {
  137. CHAR     szFileName[CCHMAXPATH];   /* Filename Holder            */
  138. CHAR     szStrBuf[CCHMAXPATH];       /* String Buffer            */
  139. PPRNDATA pprni;               /* Print Data Pointer        */
  140. TID     tid;               /* Thread ID                */
  141. register INT i;               /* Loop Counters            */
  142.  
  143. switch ( msg )
  144.    {
  145.                /* Perform dialog initialization            */
  146.    case    WM_INITDLG :
  147.        WinSetPointer(HWND_DESKTOP, hptrWait);
  148.  
  149.                /* Clear    the drives filled flag            */
  150.  
  151.        fDrivesFilled = FALSE;
  152.  
  153.                /* Show the selected print name            */
  154.  
  155.        WinSetDlgItemText(hWnd, IT_PRINTER, PrnQueryPrinterName(&prn));
  156.  
  157.                /* Set the fonts    for the    printer    selected    */
  158.  
  159.        switch (    lSetFonts(WinWindowFromID(hWnd,    CBX_FONT)) )
  160.        {
  161.                /* Error    return:    bad HDC    for printer        */
  162.        case    1L :
  163.            WinMessageBox(HWND_DESKTOP, hWnd, "Printer Device Context could not be opened.",
  164.                  "Print Font Example", 0UL,    MB_OK |    MB_ICONHAND | MB_MOVEABLE);
  165.            WinDismissDlg(hWnd, FALSE);
  166.            return(0L);
  167.  
  168.                /* Error    return:    bad HPS    for printer        */
  169.        case    2L :
  170.            WinMessageBox(HWND_DESKTOP, hWnd, "Printer Presentation Space could not be created.",
  171.                  "Print Font Example", 0UL,    MB_OK |    MB_ICONHAND | MB_MOVEABLE);
  172.            WinDismissDlg(hWnd, FALSE);
  173.            return(0L);
  174.  
  175.                /* Error    return:    no error, fonts    set in combo    */
  176.        default :
  177.            break;
  178.        }
  179.                /* Set the check    box for    the inclusion of the    */
  180.                /* line numbers                    */
  181.  
  182.        WinSendDlgItemMsg(hWnd, CB_INCLUDELINENUMS, BM_SETCHECK,
  183.              MPFROMSHORT(fLineNumbers), 0L);
  184.  
  185.                /* Get directory/file list and display in list    */
  186.                /* boxes                        */
  187.  
  188.        ShowDirInfo(hWnd, IT_DIRECTORY, IT_VOLUMELABEL, IT_DISKFREE);
  189.  
  190.                /* Get a    list of    the drives, directories    and    */
  191.                /* files    for the    list boxes and show the    number    */
  192.                /* of files within the directory            */
  193.  
  194.        sprintf(szStrBuf, "%d", ulGetDirList(WinWindowFromID(hWnd, CBX_DRIVES),
  195.                         WinWindowFromID(hWnd, LB_DIRECTORIES),
  196.                         WinWindowFromID(hWnd, LB_FILES)));
  197.        WinSetDlgItemText(hWnd, IT_FILECOUNT, szStrBuf);
  198.  
  199.                /* Select the last file printed            */
  200.  
  201.        if ( iFileSel !=    LIT_NONE )
  202.        WinSendDlgItemMsg(hWnd, LB_DIRECTORIES, LM_SELECTITEM, MPFROMSHORT(iFileSel),
  203.                  MPFROMSHORT(TRUE));
  204.        WinSetPointer(HWND_DESKTOP, hptrArrow);
  205.        break;
  206.             /* Process control selections            */
  207.    case    WM_CONTROL :
  208.        switch (    SHORT2FROMMP(mp1) )
  209.        {
  210.                /* Enter    or selection made within error combo    */
  211.                /* box                        */
  212.        case    CBN_ENTER :
  213.            switch (    SHORT1FROMMP(mp1) )
  214.            {
  215.            case    CBX_DRIVES :
  216.  
  217.                /* Get item selected from the list box        */
  218.  
  219.                WinSendDlgItemMsg(hWnd, CBX_DRIVES, LM_QUERYITEMTEXT,
  220.                   MPFROM2SHORT(LONGFROMMR(WinSendDlgItemMsg(hWnd, CBX_DRIVES,
  221.                                         LM_QUERYSELECTION,
  222.                                         0L,    0L)),
  223.                            CCHMAXPATH),
  224.                   MPFROMP(szFileName));
  225.  
  226.                /* Change drives                    */
  227.  
  228.                DosSetDefaultDisk((ULONG)((szFileName[0]    & 223) - '@'));
  229.  
  230.                /* Refresh the directory    files list and show the    */
  231.                /* number of files within the directory        */
  232.  
  233.                sprintf(szStrBuf, "%d", ulGetDirList(WinWindowFromID(hWnd, CBX_DRIVES),
  234.                     WinWindowFromID(hWnd, LB_DIRECTORIES),
  235.                     WinWindowFromID(hWnd, LB_FILES)));
  236.                WinSetDlgItemText(hWnd, IT_FILECOUNT, szStrBuf);
  237.  
  238.                /* Display the directory    path, volume label and    */
  239.                /* total    disk space free                */
  240.  
  241.                ShowDirInfo(hWnd, IT_DIRECTORY, IT_VOLUMELABEL, IT_DISKFREE);
  242.                break;
  243.  
  244.            default :
  245.                break;
  246.            }
  247.            break;
  248.                /* Process message combo    box entry selections    */
  249.  
  250.        case    CBN_LBSELECT :
  251.            switch (    SHORT1FROMMP(mp1) )
  252.            {
  253.            case    CBX_FONT :
  254.                SetFontSize(WinWindowFromID(hWnd, CBX_FONT),
  255.                    WinWindowFromID(hWnd, CBX_FONTSIZE));
  256.                break;
  257.            }
  258.            break;
  259.                /* Drive/directory selected, get    entry selected    */
  260.                /* and change to    drive or directory selected    */
  261.  
  262.        case    LN_ENTER :
  263.            switch (    SHORT1FROMMP(mp1) )
  264.            {
  265.            case    LB_DIRECTORIES :
  266.  
  267.                /* Get item selected from the directories list    */
  268.                /* box                        */
  269.  
  270.                WinSendDlgItemMsg(hWnd, LB_DIRECTORIES, LM_QUERYITEMTEXT,
  271.                   MPFROM2SHORT(LONGFROMMR(WinSendDlgItemMsg(hWnd, LB_DIRECTORIES,
  272.                                         LM_QUERYSELECTION, 0L, 0L)),
  273.                            sizeof(szFileName)),
  274.                   MPFROMP(szFileName));
  275.  
  276.                /* Change to the    selected directory        */
  277.  
  278.                DosSetCurrentDir(szFileName);
  279.  
  280.                /* Refresh the directory    files list and show the    */
  281.                /* number of files within the directory        */
  282.  
  283.                sprintf(szStrBuf, "%d", ulGetDirList(WinWindowFromID(hWnd, CBX_DRIVES),
  284.                     WinWindowFromID(hWnd, LB_DIRECTORIES),
  285.                     WinWindowFromID(hWnd, LB_FILES)));
  286.                WinSetDlgItemText(hWnd, IT_FILECOUNT, szStrBuf);
  287.  
  288.                /* Display the directory    path, volume label and    */
  289.                /* total    disk space free                */
  290.  
  291.                ShowDirInfo(hWnd, IT_DIRECTORY, IT_VOLUMELABEL, IT_DISKFREE);
  292.                break;
  293.  
  294.            case    LB_FILES :
  295.  
  296.                /* Item within the files    list box double    clicked    */
  297.                /* on, user indicating that the file selected    */
  298.                /* should be printed, therefore,    force the    */
  299.                /* simulation of    the Print push button        */
  300.  
  301.                WinSendMsg(hWnd,    WM_COMMAND, MPFROMSHORT(DID_OK), 0L);
  302.                break;
  303.            }
  304.            break;
  305.        }
  306.        break;
  307.             /* Process push    button selections        */
  308.    case    WM_COMMAND :
  309.     switch ( SHORT1FROMMP(mp1) )
  310.         {
  311.                /* Print    push button clicked            */
  312.        case    DID_OK :
  313.                /* Get the file selected                */
  314.  
  315.            if ( (iFileSel =    (i = (INT)LONGFROMMR(WinSendDlgItemMsg(hWnd, LB_FILES,
  316.                                        LM_QUERYSELECTION,
  317.                                        0L, 0L)))) == LIT_NONE )
  318.            break;
  319.            else
  320.                /* Get item selected from the list box and    */
  321.                /* determine which file selected            */
  322.  
  323.            WinSendDlgItemMsg(hWnd, LB_FILES, LM_QUERYITEMTEXT,
  324.                      MPFROM2SHORT(i, sizeof(szFileName)),
  325.                      MPFROMP(szFileName));
  326.  
  327.                /* Get the font selected                */
  328.  
  329.            if ( !fQuerySelectedFont(WinWindowFromID(hWnd, CBX_FONT),
  330.                     WinWindowFromID(hWnd, CBX_FONTSIZE),
  331.                     &fsel) )
  332.            break;
  333.  
  334.                /* Get the line number include option        */
  335.  
  336.            fLineNumbers = (BOOL)SHORT1FROMMR(WinSendDlgItemMsg(hWnd,
  337.                                    CB_INCLUDELINENUMS,
  338.                                    BM_QUERYCHECK,
  339.                                    0L, 0L));
  340.  
  341.                /* Allocate memory for the printer information    */
  342.                /* and save the printer information from    the    */
  343.                /* dialogue in the memory            */
  344.  
  345.            DosAllocMem((PPVOID)(PVOID)&pprni, PRNDATASIZE +    CCHMAXPATH,
  346.                PAG_READ | PAG_WRITE    | PAG_COMMIT);
  347.  
  348.            pprni->prn       = prn;
  349.            pprni->fsel       = fsel;
  350.            pprni->pags       = pags;
  351.            pprni->cPrnFiles       = 1;
  352.            pprni->fLineNumbers = fLineNumbers;
  353.            pprni->fDateFooter  = TRUE;
  354.            memcpy(pprni->szTitle, "Print Font Example - ", 22);
  355.            strcat(pprni->szTitle, strcpy(pprni->aszFiles[0], szFileName));
  356.  
  357.                /* Create a separate thread from    which the    */
  358.                /* printing is performed                */
  359.  
  360.            DosCreateThread(&tid, (PFNTHREAD)PrnFile, (ULONG)pprni,
  361.                    STACK_COMMITTED,    16384UL);
  362.  
  363.            WinDismissDlg(hWnd, TRUE);
  364.            break;
  365.                /* Cancel push button selected            */
  366.        case    DID_CANCEL :
  367.            WinDismissDlg(hWnd, FALSE);
  368.            break;
  369.                /* Setup    push button selected            */
  370.  
  371.        case    DID_SETUP :
  372.            if ( WinDlgBox(HWND_DESKTOP, hwndPrnSetupFrame, (PFNWP)PrnSetupDlgProc,
  373.                   (HMODULE)NULL, DLG_PRNSETUP, (PVOID)&prn)    )
  374.            {
  375.                /* Set the fonts    for the    printer    selected    */
  376.  
  377.            switch ( lSetFonts(WinWindowFromID(hWnd, CBX_FONT)) )
  378.                {
  379.                /* Error    return:    bad HDC    for printer        */
  380.  
  381.                case 1L :
  382.                WinMessageBox(HWND_DESKTOP, hWnd, "Printer Device Context could not be opened.",
  383.                      "Print Font Example", 0UL, MB_OK | MB_ICONHAND    | MB_MOVEABLE);
  384.                WinDismissDlg(hWnd, FALSE);
  385.                return(0L);
  386.  
  387.                /* Error    return:    bad HPS    for printer        */
  388.  
  389.                case 2L :
  390.                WinMessageBox(HWND_DESKTOP, hWnd, "Printer Presentation Space could not be created.",
  391.                      "Print Font Example", 0UL, MB_OK | MB_ICONHAND    | MB_MOVEABLE);
  392.                WinDismissDlg(hWnd, FALSE);
  393.                return(0L);
  394.  
  395.                /* Error    return:    no error, fonts    set in combo    */
  396.  
  397.                default :
  398.                WinSetDlgItemText(hWnd, IT_PRINTER, PrnQueryPrinterName(&prn));
  399.                break;
  400.                }
  401.  
  402.            switch ( lSetFonts(WinWindowFromID(hwndToolBar, CBX_FONT)) )
  403.                {
  404.                /* Error    return:    bad HDC    for printer        */
  405.  
  406.                case 1L :
  407.                WinMessageBox(HWND_DESKTOP, hWnd, "Printer Device Context could not be opened.",
  408.                      "Print Font Example", 0UL, MB_OK | MB_ICONHAND    | MB_MOVEABLE);
  409.                return(MRFROMLONG(TRUE));
  410.  
  411.                /* Error    return:    bad HPS    for printer        */
  412.  
  413.                case 2L :
  414.                WinMessageBox(HWND_DESKTOP, hWnd, "Printer Presentation Space could not be created.",
  415.                      "Print Font Example", 0UL, MB_OK | MB_ICONHAND    | MB_MOVEABLE);
  416.                return(MRFROMLONG(TRUE));
  417.  
  418.                /* Error    return:    no error, fonts    set in combo    */
  419.  
  420.                default :
  421.                break;
  422.                }
  423.            }
  424.            break;
  425.         }
  426.     break;
  427.             /* Close requested, exit dialogue        */
  428.    case    WM_CLOSE :
  429.     WinDismissDlg(hWnd, FALSE);
  430.     break;
  431.             /* Pass    through    unhandled messages        */
  432.    default :
  433.        return(WinDefDlgProc(hWnd, msg, mp1, mp2));
  434.    }
  435. return(0L);
  436. }
  437. #pragma    subtitle("   File Print - Directory Information Display Function")
  438. #pragma    page( )
  439.  
  440. /* --- ShowDirInfo ------------------------------------    [ Private ] ---    */
  441. /*                                    */
  442. /*     This function is    used to    display    information regarding the    */
  443. /*     path, volume label and room remaining.                */
  444. /*                                    */
  445. /*     Upon Entry:                            */
  446. /*                                    */
  447. /*     HWND  hWnd;   = Dialog Dialogue Window Handle            */
  448. /*     ULONG idPath; = Path ID                        */
  449. /*     ULONG idVol;  = Volume Label ID                    */
  450. /*     ULONG idRoom; = Room Remaining ID                */
  451. /*                                    */
  452. /*     Upon Exit:                            */
  453. /*                                    */
  454. /*     Nothing                                */
  455. /*                                    */
  456. /* --------------------------------------------------------------------    */
  457.  
  458. static VOID ShowDirInfo(HWND hWnd, ULONG idPath, ULONG idVol, ULONG idRoom)
  459.  
  460. {
  461. CHAR       szStrBuf[CCHMAXPATH];   /* String Buffer            */
  462. FSALLOCATE diskinfo;           /* Disk Information Structure    */
  463. FSINFO       fsinf;           /* Disk Volume Information Structure    */
  464. ULONG       cbBuf;           /* Directory    Buffer Size Count    */
  465. ULONG       ulCurDrive;           /* Current Drive Designation        */
  466. ULONG       ulDrives;           /* Drive Map                */
  467.  
  468.                /* Form the current drive/path and display    */
  469.                /* within the Path display field            */
  470.  
  471. DosQueryCurrentDisk(&ulCurDrive, &ulDriveMap);
  472.  
  473.                /* Get the current drive    and path being used and    */
  474.                /* display with Path display field        */
  475.  
  476. DosQueryCurrentDisk(&ulCurDrive, &ulDrives);
  477. memcpy(&szStrBuf[1], ":\\", 3);
  478. szStrBuf[0] = (CHAR)(ulCurDrive    + '@');
  479. cbBuf =    CCHMAXPATH - 3;
  480.                /* Get information on the current directory    */
  481.  
  482. if ( !DosQueryCurrentDir(ulCurDrive, &szStrBuf[3], &cbBuf) )
  483.    {
  484.                /* Show the full    path information        */
  485.  
  486.    WinSetDlgItemText(hWnd, idPath, szStrBuf);
  487.  
  488.                /* Get the volume information and display it    */
  489.  
  490.    if (    !DosQueryFSInfo(0UL, FSIL_VOLSER, (PBYTE)(&fsinf), sizeof(FSINFO)) )
  491.        if ( fsinf.vol.szVolLabel[0] )
  492.        WinSetDlgItemText(hWnd, idVol, fsinf.vol.szVolLabel);
  493.        else
  494.        WinSetDlgItemText(hWnd, idVol, "");
  495.  
  496.                /* Get the remaining space of the drive and    */
  497.                /* display                    */
  498.  
  499.    if (    !DosQueryFSInfo(ulCurDrive, FSIL_ALLOC,    (PVOID)&diskinfo,
  500.             sizeof(FSALLOCATE)) )
  501.        WinSetDlgItemText(hWnd, idRoom,
  502.              strcat(_ltoa((LONG)(diskinfo.cbSector * diskinfo.cSectorUnit *    diskinfo.cUnitAvail),
  503.                 szStrBuf, 10), " Bytes"));
  504.    }
  505. }
  506. #pragma    subtitle("   File Print - Get Disk Volume Label Function")
  507. #pragma    page( )
  508.  
  509. /* --- DiskVolDrive -----------------------------------    [ Private ] ---    */
  510. /*                                    */
  511. /*     This function is    used to    retrieve the volume label of the    */
  512. /*     default disk drive.                        */
  513. /*                                    */
  514. /*     Upon Entry:                            */
  515. /*                                    */
  516. /*     ULONG ulDrive;       = Drive Number                */
  517. /*     CHAR  *pszDiskName; = Holder for    Volume Label            */
  518. /*                                    */
  519. /*     Upon Exit:                            */
  520. /*                                    */
  521. /*     Nothing                                */
  522. /*                                    */
  523. /* --------------------------------------------------------------------    */
  524.  
  525. static VOID DiskVolDrive(ULONG ulDrive,    CHAR *pszDiskName)
  526.  
  527. {
  528. FSINFO fsinf;              /* Disk Volume Information Structure */
  529.  
  530.                /* Get the disk volume label            */
  531.  
  532. if ( !DosQueryFSInfo(ulDrive, FSIL_VOLSER, (PBYTE)(&fsinf), sizeof(FSINFO)) )
  533.    if (    fsinf.vol.szVolLabel[0]    )
  534.        strcat(strcat(memcpy(pszDiskName, "[ ", 3), fsinf.vol.szVolLabel), " ]");
  535.    else
  536.        pszDiskName[0] =    0;
  537. }
  538. #pragma    subtitle("   File Print - Drive List Query Procedure")
  539. #pragma    page( )
  540.  
  541. /* --- QueryDriveList ---------------------------------- [ Public ] ---    */
  542. /*                                    */
  543. /*     This function is    used to    build a    list of    valid drives.        */
  544. /*                                    */
  545. /*     Upon Entry:                            */
  546. /*                                    */
  547. /*     Nothing                                */
  548. /*                                    */
  549. /*     Upon Exit:                            */
  550. /*                                    */
  551. /*     Nothing                                */
  552. /*                                    */
  553. /* --------------------------------------------------------------------    */
  554.  
  555. static VOID QueryDriveList( )
  556.  
  557. {
  558. CHAR        szDrive[4];           /* Drive Designation    Holder        */
  559. PFSQBUFFER2 psqbf;           /* File System Query    Buffer Pointer    */
  560. ULONG        cbDrvi;           /* Buffer Count            */
  561. ULONG        ulError;           /* OS/2 Error            */
  562. ULONG        ulCurDrive;           /* Current Drive Designation        */
  563. ULONG        ulDriveMask    = 1;       /* Drive Bit    Map Mask        */
  564. register INT i;               /* Loop Counter            */
  565.  
  566.                /* Perform general initialization        */
  567.  
  568. DosQueryCurrentDisk(&ulCurDrive, &ulDriveMap);
  569.  
  570.                /* Allocate space for the file system query    */
  571.                /* buffer                    */
  572.  
  573. psqbf =    (PFSQBUFFER2)malloc(1024UL);
  574. memcpy(&szDrive[1], ":", 2);
  575. DosError(FERR_DISABLEHARDERR);
  576.  
  577. for ( i    = cDrives = 0; i < 26; i++ )
  578.    {
  579.                /* Determine if a disk drive present by masking    */
  580.                /* out the drive    present    bit            */
  581.  
  582.    if (    ulDriveMap & ulDriveMask )
  583.        {
  584.                /* Save the drive designation for the drive    */
  585.                /* that is present                */
  586.  
  587.        aszDrives[cDrives][0] = szDrive[0] = (CHAR)(i + 'A');
  588.        memcpy(&aszDrives[cDrives][1], ":\\ ", 4);
  589.  
  590.                /* Start    with hard disk drives, check to    see if    */
  591.                /* the drive is local or    remote.     Remote    drives    */
  592.                /* are generally    networked drives.  Prominare    */
  593.                /* Builder denotes diskette, local and remote    */
  594.                /* drives within    the Drives/Directories window.    */
  595.        if ( i >    1 )
  596.        {
  597.                /* Initialize the buffer    count before the file    */
  598.                /* system is queried otherwise the call may fail    */
  599.  
  600.        cbDrvi = 1024UL;
  601.  
  602.        if (    (ulError = DosQueryFSAttach(szDrive, 1UL, FSAIL_QUERYNAME,
  603.                         (PFSQBUFFER2)psqbf,
  604.                         &cbDrvi)) == ERROR_NOT_READY )
  605.            afRemoveable[cDrives++] = TRUE;
  606.        else
  607.            if ( !ulError )
  608.            if (    !memcmp(&psqbf->rgFSAData[1], "CDFS", 5) )
  609.                afRemoveable[cDrives++] = TRUE;
  610.            else
  611.                ++cDrives;
  612.        }
  613.        else
  614.        afRemoveable[cDrives++] = TRUE;
  615.        }
  616.                /* Shift    the drive designation bitmap mask    */
  617.    ulDriveMask <<= 1;
  618.    }
  619. DosError(FERR_ENABLEHARDERR);
  620.  
  621.                /* Release the memory allocated for the query    */
  622.                /* buffer                    */
  623. free(psqbf);
  624. }
  625. #pragma    subtitle("   File Print - Directory Retrieval/Display Function")
  626. #pragma    page( )
  627.  
  628. /* --- ulGetDirList -----------------------------------    [ Private ] ---    */
  629. /*                                    */
  630. /*     This function is    used to    search for sub-directories and files    */
  631. /*     within the current sub-directory/drive and place    the entries    */
  632. /*     within two list boxes.                        */
  633. /*                                    */
  634. /*     Upon Entry:                            */
  635. /*                                    */
  636. /*     HWND hwndDrives;    = Drives Combo Box Handle            */
  637. /*     HWND hwndDirs;    = Directories List Box Handle            */
  638. /*     HWND hwndFiles;    = Files    List Box Handle                */
  639. /*                                    */
  640. /*     Upon Exit:                            */
  641. /*                                    */
  642. /*     ulGetDirList = Number of    Files in Files List Box            */
  643. /*                                    */
  644. /* --------------------------------------------------------------------    */
  645.  
  646. static ULONG ulGetDirList(HWND hwndDrives, HWND    hwndDirs, HWND hwndFiles)
  647.  
  648. {
  649. HDIR          hDir = (HDIR)HDIR_CREATE;/* Directory Handle        */
  650. HPOINTER      hptr;           /* Mouse Pointer Handle        */
  651. PFILEFINDBUF3 pfindbuf3;       /* File Find    Buffer            */
  652. PFILEFINDBUF3 pfindbuf;           /* File Find    Buffer            */
  653. ULONG          cFiles = 0UL;       /* Files Count            */
  654. ULONG          ulCurDrive;       /* Current Drive Designation        */
  655. ULONG          ulDrives;           /* Drive Bit    Map Holder        */
  656. ULONG          ulErr;           /* OS/2 Error Value            */
  657. ULONG          ulFileCnt    = 71UL;       /* File Counter Holder        */
  658. register INT i,    n;           /* Loop Counters            */
  659.  
  660. hptr = WinQueryPointer(HWND_DESKTOP);
  661.  
  662.                /* Set the mouse    pointer    to hourglass shape    */
  663.                /* while    directory search taking    place        */
  664.  
  665. WinSetPointer(HWND_DESKTOP,
  666.           WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE));
  667.  
  668.                /* Allocate memory for a    large directory    search    */
  669.                /* buffer                    */
  670.  
  671. pfindbuf3 = (PFILEFINDBUF3)malloc(71UL * sizeof(FILEFINDBUF3));
  672.  
  673.                /* Get the handles of the list boxes and    disable    */
  674.                /* updating of them while inserting the data    */
  675.                /* into them and    delete the contents within them    */
  676.  
  677. WinEnableWindowUpdate(hwndDirs,     FALSE);
  678. WinEnableWindowUpdate(hwndFiles, FALSE);
  679. WinSendMsg(hwndDirs,  LM_DELETEALL, 0L,    0L);
  680. WinSendMsg(hwndFiles, LM_DELETEALL, 0L,    0L);
  681.  
  682.                /* Start    directory search            */
  683.  
  684. if ( !(ulErr = DosFindFirst("*.*", &hDir, MUST_HAVE_DIRECTORY |    FILE_DIRECTORY,
  685.                 (PVOID)pfindbuf3, 71UL * sizeof(FILEFINDBUF3),
  686.                 &ulFileCnt,    FIL_STANDARD)) )
  687.    {
  688.    do
  689.        for ( i = 0, pfindbuf = pfindbuf3; i < ulFileCnt; i++ )
  690.        {
  691.                /* If file found    a sub-directory, place into the    */
  692.                /* Directories list box                */
  693.  
  694.        if (    (pfindbuf->attrFile & FILE_DIRECTORY) && memcmp(pfindbuf->achName, ".",    2) )
  695.            WinSendMsg(hwndDirs, LM_INSERTITEM,
  696.               MPFROMSHORT(LIT_SORTASCENDING),
  697.               MPFROMP(pfindbuf->achName));
  698.        pfindbuf = (PFILEFINDBUF3)((PBYTE)pfindbuf +    pfindbuf->oNextEntryOffset);
  699.        }
  700.        while ( (ulFileCnt == 71UL) &&
  701.            !DosFindNext(hDir, pfindbuf3, 71UL * sizeof(FILEFINDBUF3), &ulFileCnt) );
  702.  
  703.                /* Close    directory search handle            */
  704.    DosFindClose(hDir);
  705.    }
  706. else
  707.    if (    ulErr != ERROR_NO_MORE_FILES )
  708.        {
  709.                /* Release the memory allocated for the search    */
  710.                /* buffer                    */
  711.  
  712.        free((PVOID)pfindbuf3);
  713.        return(0);
  714.        }
  715.  
  716. if ( !fDrivesFilled )
  717.    {
  718.                /* Form the current drive/path and display    */
  719.                /* within the Path display field            */
  720.  
  721.    DosQueryCurrentDisk(&ulCurDrive, &ulDrives);
  722.    if (    ulDriveMap != ulDrives )
  723.        QueryDriveList( );
  724.    for ( i = 0;    i < cDrives; i++ )
  725.        {
  726.        if ( !afRemoveable[i] )
  727.        DiskVolDrive((ULONG)(i + 1),    &aszDrives[i][4]);
  728.        else
  729.        aszDrives[i][4] = 0;
  730.        n = (INT)LONGFROMMR(WinSendMsg(hwndDrives, LM_INSERTITEM, MPFROMSHORT(LIT_END),
  731.                 MPFROMP(aszDrives[i])));
  732.        if ( i == (ulCurDrive - 1) )
  733.        WinSendMsg(hwndDrives, LM_SELECTITEM,
  734.               MPFROMLONG(n), MPFROMLONG(TRUE));
  735.        }
  736.    fDrivesFilled = TRUE;
  737.    }
  738.                /* Reset    directory handle and file counter    */
  739. hDir = (HDIR)HDIR_CREATE;
  740. ulFileCnt = 71UL;
  741.                /* Start    file search                */
  742.  
  743. if ( !(ulErr = DosFindFirst("*.*", &hDir, FILE_NORMAL,
  744.                 (PVOID)pfindbuf3, 71UL * sizeof(FILEFINDBUF3),
  745.                 &ulFileCnt,    FIL_STANDARD)) )
  746.    {
  747.    do
  748.        for ( i = 0, pfindbuf = pfindbuf3; i < ulFileCnt; i++ )
  749.        {
  750.                /* If file found    not a sub-directory, place    */
  751.                /* filename in list box                */
  752.  
  753.        if (    (pfindbuf->attrFile & FILE_DIRECTORY) != FILE_DIRECTORY    )
  754.            {
  755.            ++cFiles;
  756.            WinSendMsg(hwndFiles, LM_INSERTITEM,
  757.               MPFROMSHORT(LIT_SORTASCENDING),
  758.               MPFROMP(pfindbuf->achName));
  759.            }
  760.        pfindbuf = (PFILEFINDBUF3)((PBYTE)pfindbuf +    pfindbuf->oNextEntryOffset);
  761.        }
  762.                /* Search for remaining entries and place valid    */
  763.                /* entries in list box                */
  764.  
  765.        while ( (ulFileCnt == 71UL) &&
  766.         !DosFindNext(hDir, pfindbuf3, 71UL * sizeof(FILEFINDBUF3), &ulFileCnt) );
  767.  
  768.                /* Close    directory search handle            */
  769.    DosFindClose(hDir);
  770.    }
  771. else
  772.    if (    ulErr != ERROR_NO_MORE_FILES )
  773.        {
  774.                /* Release the memory allocated for the search    */
  775.                /* buffer                    */
  776.  
  777.        free((PVOID)pfindbuf3);
  778.        return(0);
  779.        }
  780.                /* Release the memory allocated for the search    */
  781.                /* buffer                    */
  782. free((PVOID)pfindbuf3);
  783.                /* Re-enable updating to    the list boxes and    */
  784.                /* force    the displaying of the new contents    */
  785.  
  786. WinShowWindow(hwndDirs,    TRUE);
  787. WinShowWindow(hwndFiles, TRUE);
  788.  
  789.                /* Reset    edit field text    in case    invalid    search    */
  790.                /* spec entered and reset mouse pointer back to    */
  791.                /* arrow    shape                    */
  792.  
  793. WinSetPointer(HWND_DESKTOP, hptr);
  794. return(cFiles);
  795. }
  796. #pragma    subtitle("   File Print - File Line Printing Routine")
  797. #pragma    page( )
  798.  
  799. /* --- PrnLine ----------------------------------------    [ Private ] ---    */
  800. /*                                    */
  801. /*     This function is    used to    print a    multiple line entry such that    */
  802. /*     when the    string is wider    than the printable area    it is properly    */
  803. /*     truncated and the remainder printed on the next line or lines.    */
  804. /*                                    */
  805. /*     This routine is recursive.                    */
  806. /*                                    */
  807. /*     Upon Entry:                            */
  808. /*                                    */
  809. /*     HPS     hpsPrinter;  = Presentation Space Handle            */
  810. /*     HDC     hdcPrinter;  = Device Context Handle            */
  811. /*     PSZ     pszStr;        = String to    Print                */
  812. /*     PPOINTL pptl;        = Display Point                */
  813. /*     PPOINTL pptlFooter;  = Footer Display Point            */
  814. /*     PSIZEL  psizlPage;   = Page Size                    */
  815. /*     LONG    yShift;        = Vertical Line Shift            */
  816. /*     BOOL    fDateFooter; = Print Footer Flag                */
  817. /*     PSZ     pszFooter;   = Footer String                */
  818. /*     PULONG  pcPages;        = Page Counter Pointer            */
  819. /*                                    */
  820. /*     Upon Exit:                            */
  821. /*                                    */
  822. /*     fPrnLine    =  TRUE    : New Page Started                */
  823. /*        = FALSE    : Normal Line Printed                */
  824. /*                                    */
  825. /* --------------------------------------------------------------------    */
  826.  
  827. static BOOL fPrnLine(HPS hpsPrinter, HDC hdcPrinter, PSZ pszStr,
  828.              PPOINTL pptl, PPOINTL pptlFooter, PSIZEL psizlPage, LONG yShift,
  829.              BOOL fDateFooter, PSZ pszFooter, PULONG pcPages)
  830.  
  831. {
  832. PPOINTL    aptlLimits;           /* Limits Point Array Pointer    */
  833. POINTL    aptl[TXTBOX_COUNT];       /* Character    Text Box Array        */
  834. register INT i,    n;           /* Index                */
  835.  
  836.                /* Check    to see if the length of    the string is    */
  837.                /* greater than 512 characters.    Present    GPI    */
  838.                /* functions cannot handle greater than 512    */
  839.                /* characters.                    */
  840.  
  841. if ( (n    = (INT)strlen(pszStr)) > 512 )
  842.    n = 512;
  843.                /* Determine the    width of the line        */
  844.  
  845. GpiQueryTextBox(hpsPrinter, n, pszStr, TXTBOX_COUNT, aptl);
  846.  
  847.                /* Check    to see if the width is less than the    */
  848.                /* width    of the page                */
  849.  
  850. if ( aptl[TXTBOX_CONCAT].x < (psizlPage->cx - 720L) )
  851.    GpiCharStringAt(hpsPrinter, pptl, n,    pszStr);
  852. else
  853.    {
  854.                /* Allocate memory for the point    array to allow    */
  855.                /* the proper break to be found            */
  856.  
  857.    DosAllocMem((PPVOID)(PVOID)&aptlLimits, (ULONG)(n * sizeof(POINTL)),
  858.            PAG_READ    | PAG_WRITE | PAG_COMMIT);
  859.  
  860.                /* Get the point    position of each character    */
  861.                /* within the string                */
  862.  
  863.    GpiQueryCharStringPosAt(hpsPrinter, pptl, 0UL, n, pszStr, (PLONG)NULL, aptlLimits);
  864.  
  865.                /* Search for a break character            */
  866.  
  867.    if (    strchr(pszStr, ' ') )
  868.        {
  869.        for ( i = n - 1;    i > 0; i-- )
  870.        if (    aptlLimits[i].x    < (pptl->x + (psizlPage->cx - 720L)) )
  871.            {
  872.            while ( pszStr[i] && (pszStr[i] != ' ') )
  873.            --i;
  874.            ++i;
  875.            break;
  876.            }
  877.        }
  878.    else
  879.                /* No break character found, look for a clean    */
  880.                /* location where the forced break can occur    */
  881.  
  882.        for ( i = 0; i <    n; i++ )
  883.        if (    aptlLimits[i].x    > (pptl->x + (psizlPage->cx - 720L)) )
  884.            break;
  885.                /* Release the memory allocated for the point    */
  886.                /* array                        */
  887.  
  888.    DosFreeMem((PVOID)aptlLimits);
  889.  
  890.                /* Display the string                */
  891.  
  892.    GpiCharStringAt(hpsPrinter, pptl, i,    pszStr);
  893.  
  894.                /* Update the string pointer and    check to see    */
  895.                /* if any more characters should    be displayed    */
  896.    pszStr += i;
  897.    if (    *pszStr    )
  898.        {
  899.                /* Update the position on the page        */
  900.  
  901.        if ( (pptl->y -=    yShift)    < 720L )
  902.        {
  903.                /* Have reached the bottom of the page, display    */
  904.                /* the footer for the page            */
  905.  
  906.        if (    fDateFooter )
  907.            GpiCharStringAt(hpsPrinter, pptlFooter, 37L, pszFooter);
  908.  
  909.                /* Force    the ejection of    the page        */
  910.  
  911.        DevEscape(hdcPrinter, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL);
  912.  
  913.                /* Reset    the pointer to the top of the page    */
  914.  
  915.        pptl->y = psizlPage->cy - yShift * TOP_MARGIN;
  916.        ++(*pcPages);
  917.        }
  918.                /* Print    the remaining portion of the string    */
  919.  
  920.        return(fPrnLine(hpsPrinter, hdcPrinter, pszStr,
  921.                pptl, pptlFooter, psizlPage, yShift,
  922.                fDateFooter, pszFooter, pcPages));
  923.        }
  924.    }
  925.                /* Update the position on the page        */
  926.  
  927. if ( (pptl->y -= yShift) < 720L    )
  928.    {
  929.                /* Have reached the bottom of the page, display    */
  930.                /* the footer for the page            */
  931.  
  932.    if (    fDateFooter )
  933.        GpiCharStringAt(hpsPrinter, pptlFooter, 37L, pszFooter);
  934.  
  935.                /* Force    the ejection of    the page        */
  936.  
  937.    DevEscape(hdcPrinter, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL);
  938.  
  939.                /* Reset    the pointer to the top of the page    */
  940.  
  941.    pptl->y = psizlPage->cy - yShift * TOP_MARGIN;
  942.    ++(*pcPages);
  943.    return(TRUE);
  944.    }
  945. else
  946.    return(FALSE);
  947. }
  948. #pragma    subtitle("   File Print - File Printing Routine")
  949. #pragma    page( )
  950.  
  951. /* --- PrnFile ----------------------------------------    [ Private ] ---    */
  952. /*                                    */
  953. /*     This function is    used to    read in    the file selected and        */
  954. /*     provide the appropriate decoding    for printing the file.        */
  955. /*     The function constructs a line from the file and    then        */
  956. /*     determines if further decoding is required or to    print        */
  957. /*     constructed line.                        */
  958. /*                                    */
  959. /*     Upon Entry:                            */
  960. /*                                    */
  961. /*     PPRNDATA    pprni; = Print Information Pointer            */
  962. /*                                    */
  963. /*     Upon Exit:                            */
  964. /*                                    */
  965. /*     Nothing                                */
  966. /*                                    */
  967. /* --------------------------------------------------------------------    */
  968.  
  969. VOID _System PrnFile(PPRNDATA pprni)
  970.  
  971. {
  972. BOOL        fEndOfFile;           /* End of File Flag            */
  973. BOOL        fNewPage;           /* New Page Flag            */
  974. BYTE        bCh;           /* Input Character            */
  975. BYTE        szLineBuf[8];       /* Line Number Buffer        */
  976. BYTE        szFooter[48];       /* Footer Buffer            */
  977. DATETIME    dt;               /* Date and Time Holder        */
  978. FILESTATUS3 fs;               /* File Status            */
  979. FONTMETRICS fmPrn;           /* Font Metrics Info            */
  980. HAB        habThread;           /* Thread Anchor Block Handle    */
  981. HCINFO        hci;           /* Hard Copy    Information Structure    */
  982. HDC        hdcPrinter;           /* Printer Device Context Handle    */
  983. HFILE        hFile;           /* Input File Handle            */
  984. HPS        hpsPrinter;           /* Printer Presentation Space Handle    */
  985. INT        cLineNum;           /* Line Number Character Counter    */
  986. INT        cLines;           /* Line Number Counter        */
  987. LONG        lOut;           /* Output Count            */
  988. LONG        lcid;           /* Logical Font ID            */
  989. LONG        sPos;           /* Current Buffer Position        */
  990. PBYTE        pbInputBuffer;       /* File Input Buffer            */
  991. PBYTE        pszOutPutLine;       /* Formatted    Output Buffer        */
  992. POINTL        ptl;           /* Display Point            */
  993. POINTL        ptlFooter;           /* Display Point            */
  994. SIZEL        sizlPage;           /* Page Size    Holder            */
  995. ULONG        cPages;           /* Page Count            */
  996. ULONG        cbRead;           /* Bytes Read            */
  997. ULONG        ulAction;           /* Action Taken            */
  998. USHORT        usJobID;           /* Spooler Job ID            */
  999. register INT i;               /* Loop Counter            */
  1000. register UINT sPointer;           /* Input Buffer Pointer        */
  1001.  
  1002.                /* Get an anchor    block handle to    allow proper    */
  1003.                /* thread initialization    of stack space and    */
  1004.                /* usage    of some    PM calls.  Create a message    */
  1005.                /* queue    as well    to make    sure that everything    */
  1006.                /* works    properly in terms of error message    */
  1007.                /* display.                    */
  1008.  
  1009. habThread = WinInitialize(0UL);
  1010.  
  1011.                /* Open a device    context    for the    printer        */
  1012.                /* selected                    */
  1013.  
  1014. if ( (hdcPrinter = PrnOpenDC(&pprni->prn, "PM_Q_STD")) != (HDC)NULL )
  1015.    {
  1016.                /* Create a presentation    space into which the    */
  1017.                /* printing will    occur using TWIPS as the unit    */
  1018.                /* of measure                    */
  1019.  
  1020.    sizlPage.cx = sizlPage.cy = 0L;
  1021.    hpsPrinter =    GpiCreatePS(habThread, hdcPrinter, &sizlPage, PU_TWIPS |
  1022.                 GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC);
  1023.  
  1024.                /* Start    the printing of    the selected file by    */
  1025.                /* indicating the start of the document within    */
  1026.                /* device context                */
  1027.  
  1028.    if (    DevEscape(hdcPrinter, DEVESC_STARTDOC, (LONG)strlen(pprni->szTitle),
  1029.           pprni->szTitle, NULL,    NULL) != DEVESC_ERROR )
  1030.        {
  1031.                /* Determine the    size of    the output area        */
  1032.  
  1033.        GpiQueryPS(hpsPrinter, &sizlPage);
  1034.  
  1035.                /* Select and scale the font for    the printer    */
  1036.  
  1037.        lcid = ScaleFont(hpsPrinter, pprni->fsel.szFacename,
  1038.             pprni->fsel.lNominalPointSize);
  1039.  
  1040.                /* Get the new font metrics for the scaled font    */
  1041.                /* and determine    the number of lines that can be    */
  1042.                /* contained within the page            */
  1043.  
  1044.        GpiQueryFontMetrics(hpsPrinter, sizeof(FONTMETRICS), &fmPrn);
  1045.  
  1046.                /* Determine the    hard copy capabilities for the    */
  1047.                /* form selected.  Note that all    values returned    */
  1048.                /* are in millimetres except for    the xPels and    */
  1049.                /* yPels    elements.                */
  1050.  
  1051.        DevQueryHardcopyCaps(hdcPrinter,    0L, 1L,    &hci);
  1052.  
  1053.        DosAllocMem((PPVOID)(PVOID)&pszOutPutLine, 4096UL, PAG_READ | PAG_WRITE | PAG_COMMIT);
  1054.  
  1055.                /* Provide a 1/2    inch left margin including any    */
  1056.                /* device provided margin.  There are 57    twips    */
  1057.                /* per millimetre.                */
  1058.  
  1059.        ptl.x = 1080L - hci.xLeftClip * 57L;
  1060.  
  1061.        if ( pprni->fDateFooter )
  1062.        {
  1063.        DosGetDateTime(&dt);
  1064.  
  1065.                /* Copy the masking string into the buffer and    */
  1066.                /* copy the day and month strings into the    */
  1067.                /* buffer                    */
  1068.  
  1069.        memcpy(szFooter, "Printed:  Tue Jan 01 00:00:00.00 1970", 38);
  1070.        memcpy(&szFooter[10], (PCHAR)(szDayNames + (dt.weekday * 3)), 3);
  1071.        memcpy(&szFooter[14], (PCHAR)(szMonthNames +    ((dt.month - 1)    * 3)), 3);
  1072.  
  1073.                /* Point    to the day of the month    within the    */
  1074.                /* buffer and store the day of the month    within    */
  1075.                /* the buffer (1    - 31)                */
  1076.  
  1077.        szFooter[18]    = (CHAR)('0' + (dt.day / 10));
  1078.        szFooter[19]    = (CHAR)('0' + (dt.day % 10));
  1079.  
  1080.                /* Store    the hours within the buffer (0 - 23)    */
  1081.  
  1082.        szFooter[21]    = (CHAR)('0' + (dt.hours / 10));
  1083.        szFooter[22]    = (CHAR)('0' + (dt.hours % 10));
  1084.  
  1085.                /* Store    the minutes within the buffer (0 - 59)    */
  1086.         
  1087.        szFooter[24]    = (CHAR)('0' + (dt.minutes / 10));
  1088.        szFooter[25]    = (CHAR)('0' + (dt.minutes % 10));
  1089.  
  1090.                /* Store    the seconds within the buffer (0 - 59)    */
  1091.  
  1092.        szFooter[27]    = (CHAR)('0' + (dt.seconds / 10));
  1093.        szFooter[28]    = (CHAR)('0' + (dt.seconds % 10));
  1094.  
  1095.                /* Store    the hundredths within the buffer    */
  1096.                /* (0 - 100)                    */
  1097.  
  1098.        szFooter[30]    = (CHAR)('0' + (dt.hundredths /    10));
  1099.        szFooter[31]    = (CHAR)('0' + (dt.hundredths %    10));
  1100.  
  1101.                /* Store    the year within    the buffer        */
  1102.  
  1103.        szFooter[33]    = (CHAR)('0' + ((dt.year / 100)    / 10));
  1104.        szFooter[34]    = (CHAR)('0' + ((dt.year / 100)    % 10));
  1105.        szFooter[35]    = (CHAR)('0' + ((dt.year % 100)    / 10));
  1106.        szFooter[36]    = (CHAR)('0' + ((dt.year % 100)    % 10));
  1107.        ptlFooter.x = 1080L - hci.xLeftClip * 57L;
  1108.        ptlFooter.y = TOP_MARGIN / 2L;
  1109.        }
  1110.  
  1111.                /* Open the requested file for printing        */
  1112.  
  1113.        for ( i = 0; i <    pprni->cPrnFiles; i++ )
  1114.        {
  1115.        if (    DosOpen(pprni->aszFiles[i], &hFile, &ulAction, 0UL, FILE_NORMAL,
  1116.             OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
  1117.             OPEN_ACCESS_READONLY | OPEN_SHARE_DENYWRITE, NULL) )
  1118.            continue;
  1119.        else
  1120.            {
  1121.                /* Get the file information for the file    which    */
  1122.                /* will allow the size of the file to be        */
  1123.                /* determined and allow the entire file to be    */
  1124.                /* read in in one read                */
  1125.  
  1126.            DosQueryFileInfo(hFile, FIL_STANDARD, (PVOID)&fs, sizeof(FILESTATUS3));
  1127.            DosAllocMem((PPVOID)(PVOID)&pbInputBuffer, fs.cbFile + 1UL, PAG_READ | PAG_WRITE    | PAG_COMMIT);
  1128.            DosRead(hFile, (PVOID)pbInputBuffer, fs.cbFile, &cbRead);
  1129.  
  1130.                /* Close    the file opened    for printing and clear    */
  1131.                /* the printing active flag            */
  1132.  
  1133.            DosClose(hFile);
  1134.  
  1135.            cLines     = 1;
  1136.            cPages     = 1;
  1137.            fNewPage     = TRUE;
  1138.            sPointer    = 0;
  1139.            fEndOfFile = FALSE;
  1140.  
  1141.                /* Check    to see if line numbers requested and if    */
  1142.                /* required form    the start of the line        */
  1143.  
  1144.            if ( pprni->fLineNumbers    )
  1145.            {
  1146.            memcpy(pszOutPutLine, " 00000: ", 9);
  1147.            sPos    = 8;
  1148.            }
  1149.            else
  1150.            {
  1151.            pszOutPutLine[0] = 0;
  1152.            sPos    = 0;
  1153.            }
  1154.                /* Enter    the loop that reads in the requested    */
  1155.                /* file,    and sends it to    the printing context    */
  1156.            do
  1157.            {
  1158.            if (    sPointer >= cbRead )
  1159.  
  1160.                /* Logical End-of-File encountered, set        */
  1161.                /* character to End-of-File value        */
  1162.  
  1163.                bCh = 26;
  1164.            else
  1165.                /* Get a    character from the file    input buffer    */
  1166.  
  1167.                bCh = pbInputBuffer[sPointer++];
  1168.  
  1169.                /* Decode character to line demarcation values    */
  1170.            switch ( bCh    )
  1171.                {
  1172.                case CR :
  1173.                continue;
  1174.  
  1175.                case TAB    :
  1176.                do pszOutPutLine[sPos] = ' ';
  1177.                    while ( ++sPos %    8 );
  1178.                break;
  1179.  
  1180.                case TOF    :
  1181.  
  1182.                /* Complete the printing    of the page and    set    */
  1183.                /* new page flag    before returning        */
  1184.  
  1185.                if (    pprni->fDateFooter )
  1186.                    GpiCharStringAt(hpsPrinter, &ptlFooter, 37L, szFooter);
  1187.                DevEscape(hdcPrinter, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL);
  1188.                fNewPage = TRUE;
  1189.                break;
  1190.  
  1191.                case LF :
  1192.  
  1193.                /* Line feed signifying end-of-line encountered    */
  1194.                /* complete the line and    send for processing    */
  1195.                /* and printing                    */
  1196.  
  1197.                pszOutPutLine[sPos] = 0;
  1198.                if (    fNewPage )
  1199.                    {
  1200.                /* Form top margin co-ordinates            */
  1201.  
  1202.                    ptl.y = sizlPage.cy - fmPrn.lMaxBaselineExt * TOP_MARGIN;
  1203.  
  1204.                /* Reset    new page flag                */
  1205.  
  1206.                    fNewPage    = FALSE;
  1207.                    }
  1208.                if (    pprni->fLineNumbers )
  1209.                    {
  1210.                    cLineNum    = (INT)strlen(itoa(cLines++, szLineBuf,    10));
  1211.  
  1212.                    memcpy(&pszOutPutLine[6 - cLineNum], szLineBuf, (UINT)cLineNum);
  1213.                    }
  1214.  
  1215.                /* Print    out formatted line            */
  1216.  
  1217.                fNewPage = fPrnLine(hpsPrinter, hdcPrinter, pszOutPutLine,
  1218.                            &ptl, &ptlFooter, &sizlPage, fmPrn.lMaxBaselineExt,
  1219.                            pprni->fDateFooter, szFooter, &cPages);
  1220.                if (    pprni->fLineNumbers )
  1221.                    sPos = 8;
  1222.                else
  1223.                    sPos = 0;
  1224.                break;
  1225.  
  1226.                case 26 :
  1227.  
  1228.                /* End-of-File mark encounted, set end-of-file    */
  1229.                /* file to stop input processing            */
  1230.  
  1231.                fEndOfFile =    TRUE;
  1232.                break;
  1233.  
  1234.                /* Normal character, save in output buffer    */
  1235.  
  1236.                default :
  1237.                pszOutPutLine[sPos++] = bCh;
  1238.                }
  1239.            } while ( !fEndOfFile );
  1240.  
  1241.            if ( !fNewPage && ((i + 1) != pprni->cPrnFiles) )
  1242.            {
  1243.            if (    pprni->fDateFooter )
  1244.                GpiCharStringAt(hpsPrinter, &ptlFooter, 37L, szFooter);
  1245.            DevEscape(hdcPrinter, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL);
  1246.            if (    cPages % 2 )
  1247.                {
  1248.                if ( pprni->fDateFooter )
  1249.                GpiCharStringAt(hpsPrinter, &ptlFooter, 37L,    szFooter);
  1250.                DevEscape(hdcPrinter, DEVESC_NEWFRAME, 0L, NULL,    NULL, NULL);
  1251.                }
  1252.            }
  1253.            }
  1254.        DosFreeMem((PVOID)pbInputBuffer);
  1255.        }
  1256.        if ( pprni->fDateFooter )
  1257.        GpiCharStringAt(hpsPrinter, &ptlFooter, 37L,    szFooter);
  1258.        DosFreeMem((PVOID)pszOutPutLine);
  1259.  
  1260.                /* Reset    the character set back to the default    */
  1261.  
  1262.        GpiSetCharSet(hpsPrinter, 0L);
  1263.        GpiDeleteSetId(hpsPrinter, lcid);
  1264.  
  1265.                /* Inform the device context printing complete    */
  1266.                /* to allow the correct spooling    and final    */
  1267.                /* printing to occur                */
  1268.        lOut = 2L;
  1269.        DevEscape(hdcPrinter, DEVESC_ENDDOC, 0L,    NULL, &lOut, (PBYTE)&usJobID);
  1270.  
  1271.                /* Release and destroy both the printing        */
  1272.                /* presentation space and device    context    handles    */
  1273.  
  1274.        GpiAssociate(hpsPrinter,    (HDC)NULL);
  1275.        GpiDestroyPS(hpsPrinter);
  1276.        DevCloseDC(hdcPrinter);
  1277.        }
  1278.    }
  1279. DosFreeMem((PVOID)pprni);
  1280.  
  1281.                /* Destroy the message queue used by the    thread    */
  1282.                /* and destroy the anchor block before exiting    */
  1283.                /* the thread                    */
  1284. WinTerminate(habThread);
  1285.  
  1286. DosExit(EXIT_THREAD, 0UL);
  1287. }
  1288.