home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / dbcs.zip / FILEPRN.C < prev    next >
C/C++ Source or Header  |  1996-01-21  |  44KB  |  1,281 lines

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