Annotation of pmsdk/samples/linefrac/lffile.c, revision 1.1.1.1

1.1       root        1: /************************************************************************
                      2: *
                      3: *   lffile.c -- File handling subroutines for LineFrac.
                      4: *
                      5: *   Created by Microsoft Corporation, 1989
                      6: *
                      7: ************************************************************************/
                      8: 
                      9: #define INCL_WIN
                     10: #define INCL_GPI
                     11: #define INCL_DOSMEMMGR
                     12: #define INCL_DOSFILEMGR
                     13: #define INCL_BITMAPFILEFORMAT
                     14: #include <os2.h>
                     15: 
                     16: #include <stdio.h>
                     17: 
                     18: #include "opendlg.h"
                     19: 
                     20: #define INCL_GLOBALS
                     21: #define INCL_THREADS
                     22: #include "linefrac.h"
                     23: 
                     24: #define INCL_LFFILE
                     25: #define INCL_LFPS
                     26: #define INCL_LFUTIL
                     27: #include "lffuncs.h"
                     28: 
                     29: 
                     30: 
                     31: 
                     32: /*
                     33:  * this is the bitmap resource file format structure
                     34:  */
                     35: typedef struct {
                     36:     USHORT    wType;
                     37:     ULONG     dwSize;
                     38:     int       xHotspot;
                     39:     int       yHotspot;
                     40:     ULONG     dwBitsOffset;
                     41:     USHORT    bmWidth;       /* from here this is a BitmapInfo table */
                     42:     USHORT    bmHeight;
                     43:     USHORT    bmPlanes;
                     44:     USHORT    bmBitcount;
                     45: } RCBITMAP;
                     46: typedef RCBITMAP FAR *PRCBITMAP;
                     47: 
                     48: 
                     49: 
                     50: 
                     51: /************************************************************************
                     52: *
                     53: *   Global Variables
                     54: *
                     55: ************************************************************************/
                     56: 
                     57: extern GLOBALDATA global;
                     58: 
                     59: 
                     60: 
                     61: 
                     62: /************************************************************************
                     63: *
                     64: *   LfReadFile
                     65: *
                     66: *   Calls the OpenDlg function to ask the user what file name to
                     67: *   read from.
                     68: *
                     69: ************************************************************************/
                     70: 
                     71: VOID
                     72: LfReadFile(hwnd, pthr)
                     73: HWND hwnd;
                     74: PTHR pthr;
                     75: {
                     76:     HFILE hFile;
                     77:     DLF dlf;
                     78: 
                     79:     dlf.rgbAction      = DLG_OPENDLG;
                     80:     dlf.rgbFlags       = ATTRDIRLIST;
                     81:     dlf.phFile         = &hFile;
                     82:     dlf.pszExt         = (PSZ)"\\*.bmp";
                     83:     dlf.pszAppName     = "LineFrac";
                     84:     dlf.pszTitle       = "Load Bitmap";
                     85:     dlf.pszInstructions = NULL;
                     86:     dlf.szFileName[0]  = '\0';
                     87:     dlf.szOpenFile[0]  = '\0';
                     88: 
                     89:     switch (DlgFile(hwnd,&dlf))
                     90:     {
                     91:     case TDF_ERRMEM:
                     92:     case TDF_INVALID:
                     93:        MyMessageBox(hwnd, "Error reading file.");
                     94:        break;
                     95: 
                     96:     case TDF_NOOPEN:
                     97:        break;
                     98: 
                     99:     default:
                    100:        if (!LfReadBMP(pthr, &dlf))
                    101:            MyMessageBox(hwnd, "Error reading file.\nIs AutoResize enabled?");
                    102:     }
                    103: }
                    104: 
                    105: 
                    106: 
                    107: 
                    108: /************************************************************************
                    109: *
                    110: *   LfReadBMP
                    111: *
                    112: *   Read a bitmap in from a BMP format file.  Prepare the DC for the
                    113: *   given thread to accept it. The user can have the DC resized to
                    114: *   fit exactly the bitmap, or fit the bits in as best as we can.
                    115: *   If we're not resizing and the bitmap is larger than the thread's
                    116: *   DC, then load the bits flush with the lower left.
                    117: *
                    118: *   Both old-style (PRCBITMAP) and new-style (PBITMAPFILEHEADER)
                    119: *   bitmaps can be read.
                    120: *
                    121: *   Free up memory and close the file before leaving.  The file
                    122: *   will have been opened by the time this function is called,
                    123: *   and the file handle will be in the *pdlf structure.
                    124: *
                    125: ************************************************************************/
                    126: 
                    127: BOOL
                    128: LfReadBMP(pthr, pdlf)
                    129: PTHR pthr;
                    130: PDLF pdlf;             /* File information filled by DlgFile. */
                    131: {
                    132:     HFILE hfile;
                    133:     ULONG cScans;
                    134:     ULONG ulSize;       /* Number of bytes occupied by bitmap bits.         */
                    135:     USHORT cSegs;       /* Number of 64K segments in ulSize.                */
                    136:     USHORT cbExtra;     /* Bytes in last segment of ulSize.                 */
                    137:     SEL sel;            /* Base selector to file data.                      */
                    138:     USHORT hugeshift;   /* Segment index shift value.                       */
                    139:     USHORT cbRead1;     /* Number of bytes to read first call to DosRead    */
                    140:     USHORT cbRead2;     /* Number of bytes to read second call to DosRead   */
                    141:     USHORT cbRead;      /* Number of bytes read by DosRead.                 */
                    142:     BOOL fRet = FALSE;  /* Function return code.                            */
                    143:     int i;              /* Generic loop index.                              */
                    144:     FILESTATUS fsts;
                    145:     PBITMAPFILEHEADER pbfh;
                    146:     PRCBITMAP  rb;
                    147:     PBYTE pImage;
                    148: 
                    149: 
                    150:     /*******************************************************************
                    151:     * Find out how big the file is so we can read the whole thing in.
                    152:     *******************************************************************/
                    153: 
                    154:     hfile = *(pdlf->phFile);
                    155:     if( DosQFileInfo( hfile, 1, &fsts, sizeof(FILESTATUS)) != 0)
                    156:        goto lfread_error_close_file;
                    157: 
                    158:     ulSize  = fsts.cbFile;
                    159:     cSegs   = (USHORT)(ulSize/0x10000L);
                    160:     cbExtra = (USHORT)(ulSize%0x10000L);
                    161:     if (DosAllocHuge(cSegs, cbExtra, (PSEL)&sel, 0, 0))
                    162:        goto lfread_error_close_file;
                    163:     if (DosGetHugeShift(&hugeshift))
                    164:        goto lfread_error_free_bits;
                    165: 
                    166:     pImage = (PBYTE)MAKEP(sel, 0);
                    167:     rb    = (PRCBITMAP)pImage;
                    168:     pbfh   = (PBITMAPFILEHEADER)pImage;
                    169: 
                    170: 
                    171:     /*******************************************************************
                    172:     * Read the bits in from the file. The DosRead function allows a
                    173:     * maximum of 64K-1 bytes read at a time.  We get around this
                    174:     * by reading two 32K chunks for each 64K segment, and reading the
                    175:     * last segment in one piece.
                    176:     *******************************************************************/
                    177: 
                    178:     for (i = 0; i <= cSegs; ++i)
                    179:     {
                    180:        if (i < cSegs)
                    181:        {
                    182:            /* This segment is 64K bytes long, so split it up. */
                    183:            cbRead1 = 0x8000;
                    184:            cbRead2 = 0x8000;
                    185:        }
                    186:        else
                    187:        {
                    188:            /* This segment is less than 64K bytes long, so read it all. */
                    189:            cbRead1 = cbExtra;
                    190:            cbRead2 = 0;
                    191:        }
                    192: 
                    193:        /* There's a possibility that cbExtra will be 0, so check
                    194:         * to avoid an unnecessary system call.
                    195:         */
                    196:        if (cbRead1 > 0)
                    197:        {
                    198:            if (DosRead( hfile
                    199:                       , (PVOID)MAKEP(sel+(i<<hugeshift), 0)
                    200:                       , cbRead1
                    201:                       , &cbRead))
                    202:                goto lfread_error_free_bits;
                    203:            if (cbRead1 != cbRead)
                    204:                goto lfread_error_free_bits;
                    205:        }
                    206: 
                    207:        /* This will always be skipped on the last partial segment. */
                    208:        if (cbRead2 > 0)
                    209:        {
                    210:            if (DosRead( hfile
                    211:                       , (PVOID)MAKEP(sel+(i<<hugeshift), cbRead1)
                    212:                       , cbRead2
                    213:                       , &cbRead))
                    214:                goto lfread_error_free_bits;
                    215:            if (cbRead2 != cbRead)
                    216:                goto lfread_error_free_bits;
                    217:        }
                    218:     }
                    219: 
                    220: 
                    221:     /*******************************************************************
                    222:     * At this point we have the bitmap completely in memory.  Now we
                    223:     * look at how the user wants them set into the thread's PS.  If
                    224:     * the thread has fAutoResizePS set, then make the PS fit the size
                    225:     * of the bitmap (the easy case).  If the flag is not set, then
                    226:     * figure out how to place it.
                    227:     *******************************************************************/
                    228: 
                    229:     if (pthr->fAutoSizePS)
                    230:     {
                    231:        if (pbfh->bmp.cbFix != sizeof(BITMAPINFOHEADER))
                    232:        {
                    233:            global.bm.cx        = rb->bmWidth;
                    234:            global.bm.cy        = rb->bmHeight;
                    235:            global.bm.cPlanes   = rb->bmPlanes;
                    236:            global.bm.cBitCount = rb->bmBitcount;
                    237:        }
                    238:        else
                    239:        {
                    240:            global.bm.cx        = pbfh->bmp.cx;
                    241:            global.bm.cy        = pbfh->bmp.cy;
                    242:            global.bm.cPlanes   = pbfh->bmp.cPlanes;
                    243:            global.bm.cBitCount = pbfh->bmp.cBitCount;
                    244:        }
                    245: 
                    246:        LfResizePS(pthr);
                    247:     }
                    248:     else
                    249:        goto lfread_error_free_bits;
                    250: 
                    251: 
                    252:     /*******************************************************************
                    253:     * Tell GPI to put the bits into the thread's PS. The function returns
                    254:     * the number of scan lines of the bitmap that were copied. We want
                    255:     * all of them at once.
                    256:     *******************************************************************/
                    257: 
                    258:     if (pbfh->bmp.cbFix != sizeof(BITMAPINFOHEADER))
                    259:     {
                    260:         pImage += rb->dwBitsOffset;
                    261:         rb->dwBitsOffset = sizeof(BITMAPINFOHEADER);
                    262:        cScans = GpiSetBitmapBits( pthr->hps
                    263:                                 , 0L
                    264:                                 , (LONG)rb->bmHeight
                    265:                                 , pImage
                    266:                                 , (PBITMAPINFO)&(rb->dwBitsOffset));
                    267:        if (cScans != (LONG)rb->bmHeight)  /* compare with original number of scans */
                    268:            goto lfread_error_free_bits;
                    269:     }
                    270:     else
                    271:     {
                    272:        cScans = GpiSetBitmapBits( pthr->hps
                    273:                                 , 0L
                    274:                                 , (LONG)pbfh->bmp.cy
                    275:                                 , pImage + pbfh->offBits
                    276:                                 , (PBITMAPINFO)&(pbfh->bmp));
                    277:        if (cScans != (LONG)pbfh->bmp.cy)  /* compare with original number of scans */
                    278:            goto lfread_error_free_bits;
                    279:     }
                    280:     fRet = TRUE;     /* We made it!  The bits are in the thread's PS. */
                    281: 
                    282: 
                    283:     /*******************************************************************
                    284:     * Close the file, free the buffer space and leave. This is a
                    285:     * common exit point from the function.  Since the same cleanup
                    286:     * operations need to be performed for such a large number of
                    287:     * possible error conditions, this is a concise way to do the right
                    288:     * thing.
                    289:     *******************************************************************/
                    290: 
                    291: lfread_error_free_bits:
                    292:     DosFreeSeg(sel);
                    293: lfread_error_close_file:
                    294:     DosClose(hfile);
                    295:     return fRet;
                    296: }
                    297: 
                    298: 
                    299: 
                    300: 
                    301: /************************************************************************
                    302: *
                    303: *   LfWriteFile
                    304: *
                    305: *   Calls the OpenDlg function to ask the user what file name to
                    306: *   save under.
                    307: *
                    308: ************************************************************************/
                    309: 
                    310: VOID
                    311: LfWriteFile(hwnd, pthr)
                    312: HWND hwnd;
                    313: PTHR pthr;
                    314: {
                    315:     HFILE hFile;
                    316:     DLF dlf;
                    317:     BITMAPINFOHEADER bmih;
                    318: 
                    319: 
                    320:     SetUpDLF( &dlf
                    321:            , DLG_SAVEDLG
                    322:            , &hFile
                    323:            , (PSZ)"\\*.BMP"
                    324:            , (PSZ)"LineFrac"
                    325:            , (PSZ)"Save Bitmap"
                    326:            , NULL );
                    327:     dlf.szFileName[0] = '\0';
                    328:     dlf.szOpenFile[0] = '\0';
                    329: 
                    330:     switch (DlgFile(hwnd,&dlf))
                    331:     {
                    332:     case TDF_ERRMEM:
                    333:     case TDF_INVALID:
                    334:        MyMessageBox(hwnd, "Error opening file.");
                    335:        break;
                    336: 
                    337:     case TDF_NOSAVE:
                    338:        break;
                    339: 
                    340:     default:
                    341:        bmih.cbFix     = sizeof(BITMAPINFOHEADER);
                    342:        bmih.cx        = (USHORT) pthr->rcl.xRight;
                    343:        bmih.cy        = (USHORT) pthr->rcl.yTop;
                    344:        bmih.cPlanes   = pthr->cPlanes;
                    345:        bmih.cBitCount = pthr->cBitCount;
                    346: 
                    347:        if (!LfWriteBMP(pthr->hps, &bmih, &dlf))
                    348:            MyMessageBox(hwnd, "Error writing file.");
                    349:     }
                    350: }
                    351: 
                    352: 
                    353: 
                    354: 
                    355: /************************************************************************
                    356: *
                    357: *   LfWriteBMP
                    358: *
                    359: *   Write the bitmap out to a BMP format file. Write the file
                    360: *   header first, then the bitmap bits.  Space for the header
                    361: *   and the bits is allocated. Huge bitmaps are supported.
                    362: *   Free up memory and close the file before leaving.  The file
                    363: *   will have been opened by the time this function is called,
                    364: *   and the file handle will be in the *pdlf structure.
                    365: *
                    366: ************************************************************************/
                    367: 
                    368: BOOL
                    369: LfWriteBMP(hPS, pbmih, pdlf)
                    370: HPS hPS;               /* hPS from which to get bitmap bits.     */
                    371: PBITMAPINFOHEADER pbmih;/* Bitmap information.                   */
                    372: PDLF pdlf;             /* File information filled by DlgFile. */
                    373: {
                    374:     HFILE hfile;
                    375:     ULONG cScans;
                    376:     ULONG ulSize;       /* Number of bytes occupied by bitmap bits.         */
                    377:     USHORT cSegs;       /* Number of 64K segments in ulSize.                */
                    378:     USHORT cbExtra;     /* Bytes in last segment of ulSize.                 */
                    379:     SEL selBits;        /* Base selector to bitmap bits.                    */
                    380:     USHORT hugeshift;   /* Segment index shift value.                       */
                    381:     USHORT cbBMHdr;     /* Size of bitmap header.                           */
                    382:     PBITMAPFILEHEADER pbfh; /* Pointer to private copy of bitmap info data.    */
                    383:     USHORT cbWrite1;    /* Number of bytes to write first call to DosWrite  */
                    384:     USHORT cbWrite2;    /* Number of bytes to write second call to DosWrite */
                    385:     USHORT cbWritten;   /* Number of bytes written by DosWrite.             */
                    386:     BOOL fRet = FALSE;  /* Function return code.                            */
                    387:     int i;              /* Generic loop index.                              */
                    388:     struct
                    389:     {
                    390:        LONG cPlanes;
                    391:        LONG cBitCount;
                    392:     } bmFmt;
                    393: 
                    394: 
                    395:     hfile = *(pdlf->phFile);
                    396: 
                    397:     /*******************************************************************
                    398:     * If the bitmap was created with either 0 planes or 0 bits per
                    399:     * pixel, then query the format to write with.  By asking for just
                    400:     * one format (two LONGs, or one instance of structure of bmFmt),
                    401:     * we'll get the device's favored format.
                    402:     *******************************************************************/
                    403: 
                    404:     if ((pbmih->cPlanes == 0) || (pbmih->cBitCount))
                    405:     {
                    406:        if (!GpiQueryDeviceBitmapFormats(hPS, 2L, (PLONG)&bmFmt))
                    407:            goto lfwrite_error_close_file;
                    408:     }
                    409:     else
                    410:     {
                    411:        bmFmt.cPlanes   = pbmih->cPlanes;
                    412:        bmFmt.cBitCount = pbmih->cBitCount;
                    413:     }
                    414: 
                    415: 
                    416:     /*******************************************************************
                    417:     * Determine size of bitmap header. The header consists of a
                    418:     * a fixed-size part and a variable-length color table.  The
                    419:     * latter has  2^cBitCount  entries, each of which is sizeof(RGB)
                    420:     * bytes long.  The exception is when cBitCount is 24, in which
                    421:     * case the color table is omitted because the pixels are direct
                    422:     * rgb values.
                    423:     *******************************************************************/
                    424: 
                    425:     i = (int) bmFmt.cBitCount;
                    426:     if (i == 24)
                    427:        cbBMHdr = 0;
                    428:     else
                    429:        for (cbBMHdr = sizeof(RGB); i > 0; --i)
                    430:            cbBMHdr *= 2;
                    431:     cbBMHdr += sizeof(BITMAPFILEHEADER);
                    432: 
                    433: 
                    434:     /*******************************************************************
                    435:     * Copy structure from input to work buffer.  The call to
                    436:     * GpiQueryBitmapBits will have write-access to this, so we won't
                    437:     * let it have the user's data.
                    438:     *******************************************************************/
                    439: 
                    440:     pbfh = 0;
                    441:     if (DosAllocSeg(cbBMHdr, ((PUSHORT)&pbfh)+1, 0))
                    442:        goto lfwrite_error_close_file;
                    443:     pbfh->bmp = *pbmih;
                    444:     if ((pbmih->cPlanes == 0) || (pbmih->cBitCount))
                    445:     {
                    446:        pbfh->bmp.cPlanes   = (USHORT) bmFmt.cPlanes;
                    447:        pbfh->bmp.cBitCount = (USHORT) bmFmt.cBitCount;
                    448:     }
                    449: 
                    450: 
                    451:     /*******************************************************************
                    452:     * Allocate space for the bitmap bits -- all of them at once.
                    453:     * The extra ULONG casts are there to force all the arithmetic
                    454:     * to be done in 32 bits.
                    455:     *******************************************************************/
                    456: 
                    457:     ulSize = (
                    458:               (
                    459:                 (
                    460:                   (ULONG)pbfh->bmp.cBitCount
                    461:                   * (ULONG)pbfh->bmp.cx
                    462:                   + 31L
                    463:                 ) / 32L
                    464:               ) * (ULONG)pbfh->bmp.cPlanes * 4L
                    465:             ) * (ULONG)pbfh->bmp.cy;
                    466: 
                    467:     cSegs   = (USHORT)(ulSize/0x10000L);
                    468:     cbExtra = (USHORT)(ulSize%0x10000L);
                    469:     if (DosAllocHuge(cSegs, cbExtra, (PSEL)&selBits, 0, 0))
                    470:        goto lfwrite_error_free_header;
                    471:     if (DosGetHugeShift(&hugeshift))
                    472:        goto lfwrite_error_free_bits;
                    473: 
                    474: 
                    475:     /*******************************************************************
                    476:     * Tell GPI to give us the bits. The function returns the number
                    477:     * of scan lines of the bitmap that were copied.  We want all of
                    478:     * them at once.
                    479:     *******************************************************************/
                    480: 
                    481:     cScans = GpiQueryBitmapBits( hPS
                    482:                               , 0L
                    483:                               , (ULONG)pbfh->bmp.cy
                    484:                               , (PBYTE)MAKEP(selBits, 0)
                    485:                               , (PBITMAPINFO)&pbfh->bmp);
                    486:     if (cScans != pbfh->bmp.cy)  /* compare with original number of scans */
                    487:        goto lfwrite_error_free_bits;
                    488: 
                    489: 
                    490:     /*******************************************************************
                    491:     * Fill in the extra header fields and write the header out to
                    492:     * the file.
                    493:     *******************************************************************/
                    494: 
                    495:     pbfh->usType    = 0x4D42;            /* 'MB' */
                    496:     pbfh->cbSize    = ulSize + cbBMHdr;
                    497:     pbfh->xHotspot  = pbfh->bmp.cx / 2;    /* why bother ? */
                    498:     pbfh->yHotspot  = pbfh->bmp.cy / 2;
                    499:     pbfh->offBits   = cbBMHdr;
                    500: 
                    501:     if (DosWrite( hfile
                    502:                , (PVOID)pbfh
                    503:                , cbBMHdr
                    504:                , &cbWritten))
                    505:        goto lfwrite_error_free_bits;
                    506:     if (cbWritten != cbBMHdr)
                    507:        goto lfwrite_error_free_bits;
                    508: 
                    509: 
                    510:     /*******************************************************************
                    511:     * Write the bits out to the file. The DosWrite function allows a
                    512:     * maximum of 64K-1 bytes written at a time.  We get around this
                    513:     * by writing two 32K chunks for each 64K segment, and writing the
                    514:     * last segment in one piece.
                    515:     *******************************************************************/
                    516: 
                    517:     for (i = 0; i <= cSegs; ++i)
                    518:     {
                    519:        if (i < cSegs)
                    520:        {
                    521:            /* This segment is 64K bytes long, so split it up. */
                    522:            cbWrite1 = 0x8000;
                    523:            cbWrite2 = 0x8000;
                    524:        }
                    525:        else
                    526:        {
                    527:            /* This segment is less than 64K bytes long, so write it all. */
                    528:            cbWrite1 = cbExtra;
                    529:            cbWrite2 = 0;
                    530:        }
                    531: 
                    532:        /* There's a possibility that cbExtra will be 0, so check
                    533:         * to avoid an unnecessary system call.
                    534:         */
                    535:        if (cbWrite1 > 0)
                    536:        {
                    537:            if (DosWrite( hfile
                    538:                        , (PVOID)MAKEP(selBits+(i<<hugeshift), 0)
                    539:                        , cbWrite1
                    540:                        , &cbWritten))
                    541:                goto lfwrite_error_free_bits;
                    542:            if (cbWrite1 != cbWritten)
                    543:                goto lfwrite_error_free_bits;
                    544:        }
                    545: 
                    546:        /* This will always be skipped on the last partial segment. */
                    547:        if (cbWrite2 > 0)
                    548:        {
                    549:            if (DosWrite( hfile
                    550:                        , (PVOID)MAKEP(selBits+(i<<hugeshift), cbWrite1)
                    551:                        , cbWrite2
                    552:                        , &cbWritten))
                    553:                goto lfwrite_error_free_bits;
                    554:            if (cbWrite2 != cbWritten)
                    555:                goto lfwrite_error_free_bits;
                    556:        }
                    557:     }
                    558: 
                    559:     fRet = TRUE;     /* We made it!  The bits are on the disk. */
                    560: 
                    561: 
                    562:     /*******************************************************************
                    563:     * Close the file, free the buffer space and leave. This is a
                    564:     * common exit point from the function.  Since the same cleanup
                    565:     * operations need to be performed for such a large number of
                    566:     * possible error conditions, this is concise way to do the right
                    567:     * thing.
                    568:     *******************************************************************/
                    569: 
                    570: lfwrite_error_free_bits:
                    571:     DosFreeSeg(selBits);
                    572: lfwrite_error_free_header:
                    573:     DosFreeSeg(*((PUSHORT)&pbfh+1));
                    574: lfwrite_error_close_file:
                    575:     DosClose(hfile);
                    576:     return fRet;
                    577: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.