home *** CD-ROM | disk | FTP | other *** search
- /*
-
- DIB.C -- User Code - Post a Dib to the Display of APW
- Copyright 1987-1991 Authorware Inc.
-
- Revision History
-
- 7/25/91 - Initial version
-
- General Notes:
-
- The functions contained in this file post objects on the APW display
- manager list. Once an object is posted it can be displayed by the dll.
-
- Posting objects to APW is accomplished by sending custom messages to the
- APW presentation window.
-
- This main functions of this dll are:
-
- 1) DisplayDIB - Post an object on the APW display manager list.
- The color palette in the DIB may or may not
- be used depending on parameters passed in.
- 2) EraseDIB - Remove an object from the APW display manager list.
- 3) DibProc - Object handler for posted objects.
-
- All other functions are support functions.
-
- See the tech note on posting objects for a complete discussion on posting
- objects to APW.
-
- */
- #include <stdlib.h>
-
- #ifdef NULL
- #undef NULL
- #endif
-
- #include <windows.h>
- #include "apwpost.h"
-
- HANDLE hInst;
-
- /* Return codes for DIB functions */
- #define DIB_COOL 0
- #define DIB_BADFILE 3
- #define DIB_MEMORY 4
-
- #define COLOR_WHITE 0xff // The color white
- #define TOTAL_PALETTE_SIZE (sizeof(PALETTEENTRY)*255+sizeof(LOGPALETTE))
-
- #define VALID_WINDOW(w) ((w) && IsWindow(w)) // Make NULL an invalid window
-
- short FAR PASCAL WEP( short bSystemExit );
- short FAR PASCAL LibMain( HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine );
- static void NEAR PASCAL GetDibSize( HANDLE hDib, short FAR *width, short FAR *height );
- static short NEAR PASCAL LoadDib(short fh, HANDLE FAR *hDib );
- static HANDLE NEAR PASCAL CreateTheDIB( LPSTR file );
- static WORD NEAR PASCAL DibNumColors (LPBITMAPINFOHEADER lpbi);
- static WORD NEAR PASCAL PaletteSize (LPBITMAPINFOHEADER lpbi);
- static void NEAR PASCAL DibPaint( HANDLE hDib, HDC dc, short left, short top );
- static HANDLE NEAR PASCAL DibCopy( HANDLE hDib );
- static HPALETTE NEAR PASCAL CreateThePal( HANDLE hDib );
- static long NEAR PASCAL PostTheDib( HWND wnd, LPSTR dib, short left, short top, BOOL colorpal );
-
-
- /* Temporary globals */
- static char dll[_MAX_PATH];
- static char *function_ptr = "DibProc";
-
-
- short FAR PASCAL LibMain( HANDLE hModule, WORD wDataSeg, WORD cbHeapSize,
- LPSTR lpszCmdLine )
-
- /*
- Is called by LibEntry. LibEntry is called by Windows when the DLL is
- loaded. The LibEntry routine is provided in the LIBENTRY.OBJ in the SDK
- Link Libraries disk. (The source LIBENTRY.ASM is also provided.)
-
- LibEntry initializes the DLL's heap, if a HEAPSIZE value is specified
- in the DLL's DEF file. Then LibEntry calls LibMain. The LibMain function
- below satisfies that call.
-
- The LibMain function should perform additional initialization tasks
- required by the DLL. In this example, no initialization tasks are
- required. LibMain should return a value of 1 if the initialization is
- successful.
- */
- {
- hInst = hModule;
- return 1;
- }
-
-
- short FAR PASCAL WEP( short bSystemExit )
- /*
- Performs cleanup tasks when the DLL is unloaded. WEP() is called
- automatically by Windows when the DLL is unloaded (no remaining tasks
- still have the DLL loaded). It is strongly recommended that a DLL have a
- WEP() function, even if it does nothing but returns success (1), as in
- this example.
- */
- {
- return 1;
- }
-
-
- long FAR PASCAL DisplayDIB( HWND wnd, LPSTR dib, short left, short top, BOOL colorpal )
- /*
- This function posts the file based DIB pointed to by dib to the APW
- presentation window at left, top.
-
- The palette of the DIB will be used by APW if colorpal is TRUE.
-
- Returns:
-
- a unique id to the DIB if it posted
- 0 if an error occurs
- */
- {
- APWC_POSTPB post;
- long id=0;
- HANDLE hDib;
- HPALETTE hpal;
-
-
- if (!VALID_WINDOW(wnd))
- return 0;
-
- // Who am I
- GetModuleFileName(hInst, dll, sizeof(dll));
-
- /*
- post.size - size of this structure.
- post.function_ptr - pointer to the exported name of the procedure which
- will handle all messages for the posted object.
-
- post.dll_ptr - name of the dll - including directory.
- post.rect.left - upper left corner of the object in APW screen
- coordinates.
- post.rect.top - upper top corner of the object in APW screen
- coordinates.
- post.data_ptr - the address of a block of memory to be stored in
- the display managers list which will be passed
- to the objects procedure (post.function_ptr).
- post.data_size - size of whats pointed to by post.data_ptr.
- post.port - which port the object is to be posted to.
- */
- post.size = sizeof(APWC_POSTPB);
- post.function_ptr = function_ptr;
- post.dll_ptr = dll;
- post.rect.left = left;
- post.rect.top = top;
- post.data_ptr = &hDib;
- post.data_size = sizeof(hDib);
- post.port = STATIC_PORT;
-
- // Load the DIB from the file and return a handle to the DIB.
- if ((hDib = CreateTheDIB(dib)))
- {
-
- if (colorpal)
- {
- // create a palette from the DIB
- hpal = CreateThePal(hDib);
-
- // Set the palette in APW
- if (hpal)
- {
- // Give palette to APW
- if (SendMessage(wnd, APWC_SETPAL, hpal, 0L) == 0)
- {
- // Cleanup the palette if an error occured in APW and this
- // palette was not set. Else the palette belongs to APW.
- DeleteObject(hpal);
- }
- }
- }
-
- // Get the width and height
- GetDibSize(hDib, &post.rect.right, &post.rect.bottom);
-
- // Complete the rectangle of the object.
- post.rect.right += left;
- post.rect.bottom += top;
-
- // Post the DIB to APW. id is the unique id value.
- id = SendMessage(wnd, APWC_POST, 0, (long)(APWC_POSTPB_PTR)&post);
- }
-
- return id;
- }
-
-
- BOOL FAR PASCAL EraseDIB( HWND wnd, long id )
- /*
- This function unposts the posted object id from the APW display manager
- list. id must have been previously set by a call to either ShowDib or
- PostDib.
-
- Returns:
-
- TRUE if successfull
- FALSE if wnd if invalid.
- */
- {
- if (VALID_WINDOW(wnd))
- {
- SendMessage(wnd, APWC_UNPOST, 0, id);
- return TRUE;
- }
-
- return FALSE;
- }
-
-
- long FAR PASCAL DibProc( APWN_AB_PTR args, unsigned msg )
- /*
- This function is the message handler for posted objects in APW. When an
- object is posted this function is loaded by APW and starts receiving messages
- from APW.
-
- The data_ptr field in args is the handle to the DIB.
-
- Returns:
-
- 0 always.
-
- */
- {
- switch (msg)
- {
-
- case APWN_INIT: // We will ignore this message for dib.ucd
-
- break;
-
- case APWN_DESTROY: // Free the DIB found at args->data_ptr
-
- if (*((WORD FAR *)args->data_ptr))
- {
- GlobalFree(*((WORD FAR *)args->data_ptr));
- *((WORD FAR *)args->data_ptr) = 0;
- }
- break;
-
- case APWN_PAINT: // Blt the DIB to the passed dc - palette already set.
-
- if (*((WORD FAR *)args->data_ptr))
- DibPaint(*((WORD FAR *)args->data_ptr), args->wparam, args->rect.left, args->rect.top);
- break;
-
- case APWN_SAVE: // Make a copy of the DIB to be stored by APW.
-
- if (*((WORD FAR *)args->data_ptr))
- return DibCopy(*((WORD FAR *)args->data_ptr));
-
- case APWN_RESTORE: // Recreate myself.
-
- // Restore Myself. Since I saved myself as a DIB - I can use the same
- // handle as whats passed to me.
-
- *((WORD FAR *)args->data_ptr) = args->wparam;
- break;
-
- default:
-
- break;
-
- }
-
- return 0L;
- }
-
-
- static HANDLE NEAR PASCAL CreateTheDIB( LPSTR file )
- /*
- This function opens the file pointed to by "file" reads it and create a
- Windows DIB from it.
-
- Returns:
-
- HANDLE to a DIB
- or 0 for error.
- */
- {
- OFSTRUCT of;
- HANDLE hDib=0;
- HANDLE fh = -1;
-
- if ((fh = OpenFile(file, &of, OF_READ)) != -1)
- {
- if (LoadDib(fh, &hDib) != DIB_COOL)
- hDib = 0;
-
- _lclose(fh);
- }
-
- return hDib;
- }
-
-
-
- static short NEAR PASCAL LoadDib(short fh, HANDLE FAR *hDib )
- /*
- This function reads the file identified by fh into a GlobalHandle as a
- Windows DIB.
-
- Returns:
-
- DIB_COOL - Everything is OK.
- DIB_BADFILE - This is not a legal DIB file.
- DIB_MEMORY - No memory.
- */
- {
- unsigned char huge *hpWrkPtr;
- long biSize, fsize;
- WORD wrksz;
- BITMAPFILEHEADER fhead;
-
- // seek to the end of the file
- fsize = _llseek(fh,0L,2);
- if (fsize < sizeof(BITMAPFILEHEADER))
- return DIB_BADFILE;
-
- // go back to the start
- if (_llseek(fh,0L,0) == -1)
- return DIB_BADFILE;
-
- // Read in the file header
- if (_lread(fh,(LPSTR)&fhead,sizeof(BITMAPFILEHEADER)) < sizeof(BITMAPFILEHEADER))
- return DIB_BADFILE;
- fsize -= sizeof(BITMAPFILEHEADER);
-
- // check header type
- if (fhead.bfType != 0x4d42)
- return DIB_BADFILE;
-
- // Allocate enough for the DIB
- // add 256 in case it's an 8-bit, BITMAPCOREINFO DIB (the palette table
- // must be converted from RGBTRIPLE to RGBQUAD)
- // add an additional 28 bytes for the difference between the two header sizes
- //
- *hDib = GlobalAlloc(GMEM_MOVEABLE, fsize + 256 + 28);
- if (!(*hDib))
- return DIB_MEMORY;
-
- hpWrkPtr = GlobalLock(*hDib);
-
- // modifications to deal with the possibility of BITMAPCOREHEADER-style DIB's
- // 12/1/92 JPK
- {
- BITMAPINFOHEADER bihHeader;
- BITMAPCOREHEADER bchHeader;
- short numColors, i;
- DWORD dwBits, dwBytes;
- WORD wPaletteTableSize;
- RGBTRIPLE rgbTriple;
- RGBQUAD FAR * pRGBQUAD;
-
- if (_lread (fh, (LPSTR)&bihHeader, sizeof(DWORD)) < sizeof(DWORD))
- return DIB_BADFILE;
-
- if (bihHeader.biSize != sizeof(BITMAPINFOHEADER)) {
- // it must be a BITMAPCOREHEADER guy, so read in the header, then
- // translate it to the regular format
- //
- if (_lread (fh, (LPSTR)&bchHeader.bcWidth,
- sizeof(BITMAPCOREHEADER) - sizeof(DWORD)) <
- sizeof(BITMAPCOREHEADER) - sizeof(DWORD)) {
- GlobalUnlock(*hDib);
- GlobalFree(*hDib);
- return DIB_BADFILE;
- }
-
- bihHeader.biSize = sizeof(BITMAPINFOHEADER);
- bihHeader.biWidth = bchHeader.bcWidth;
- bihHeader.biHeight = bchHeader.bcHeight;
- bihHeader.biPlanes = bchHeader.bcPlanes;
- bihHeader.biBitCount = bchHeader.bcBitCount;
- bihHeader.biCompression = BI_RGB;
- bihHeader.biXPelsPerMeter = 0;
- bihHeader.biYPelsPerMeter = 0;
-
- switch (bihHeader.biBitCount) {
- case 1:
- numColors = 2;
- break;
- case 4:
- numColors = 16;
- break;
- case 8:
- numColors = 256;
- break;
- default:
- /* A 24 bitcount DIB has no color table */
- numColors = 0;
- }
-
- bihHeader.biClrUsed = numColors;
- bihHeader.biClrImportant = numColors;
-
- dwBits = bihHeader.biWidth * bihHeader.biBitCount * bihHeader.biPlanes;
- dwBytes = (dwBits + 31L) / 32L * 4L;
- bihHeader.biSizeImage = dwBytes * bihHeader.biHeight;
-
- *(LPBITMAPINFOHEADER)hpWrkPtr = bihHeader;
- hpWrkPtr += sizeof(BITMAPINFOHEADER);
-
- pRGBQUAD = (RGBQUAD FAR *)hpWrkPtr;
-
- // read and translate the palette table
- //
- for (i=0; i < bihHeader.biClrUsed; i++) {
- _lread (fh, (LPSTR)&rgbTriple, sizeof(RGBTRIPLE));
- pRGBQUAD->rgbBlue = rgbTriple.rgbtBlue;
- pRGBQUAD->rgbGreen = rgbTriple.rgbtGreen;
- pRGBQUAD->rgbRed = rgbTriple.rgbtRed;
- pRGBQUAD->rgbReserved = NULL;
- pRGBQUAD++;
- }
- hpWrkPtr = (LPSTR)pRGBQUAD;
-
- fsize -= sizeof(BITMAPCOREHEADER) +
- bihHeader.biClrUsed * sizeof(RGBTRIPLE);
-
- fhead.bfSize = fsize + sizeof(BITMAPFILEHEADER) +
- sizeof(BITMAPINFOHEADER) +
- bihHeader.biClrUsed * sizeof(RGBQUAD);
-
- } else {
- // it's a "regular" DIB header, so just read in the rest of it
- //
- if (_lread (fh, (LPSTR)&bihHeader.biWidth,
- sizeof(BITMAPINFOHEADER) - sizeof(DWORD)) <
- sizeof(BITMAPINFOHEADER) - sizeof(DWORD)) {
- GlobalUnlock(*hDib);
- GlobalFree(*hDib);
- return DIB_BADFILE;
- }
-
- *(LPBITMAPINFOHEADER)hpWrkPtr = bihHeader;
- hpWrkPtr += sizeof(BITMAPINFOHEADER);
-
- wPaletteTableSize = bihHeader.biClrUsed * sizeof(RGBQUAD);
-
- if (_lread (fh, hpWrkPtr, wPaletteTableSize) < wPaletteTableSize) {
- GlobalUnlock(*hDib);
- GlobalFree(*hDib);
- return DIB_BADFILE;
- }
- hpWrkPtr += wPaletteTableSize;
-
- fsize -= sizeof(BITMAPINFOHEADER) + wPaletteTableSize;
- }
- }
-
- biSize = fsize;
-
- // Read in the DIB
- while (biSize > 0L)
- {
- if (biSize > 64000L)
- wrksz = 64000;
- else
- wrksz = (WORD) biSize;
-
- if (!(wrksz = _lread(fh, hpWrkPtr, wrksz)))
- {
- // Error out.
- GlobalUnlock(*hDib);
- GlobalFree(*hDib);
- return DIB_BADFILE;
- }
- hpWrkPtr += wrksz;
- biSize -= wrksz;
- }
-
- GlobalUnlock(*hDib);
- GlobalReAlloc(*hDib, fhead.bfSize, GMEM_MOVEABLE);
-
- return DIB_COOL;
- }
-
- static void NEAR PASCAL GetDibSize( HANDLE hDib, short FAR *width, short FAR *height )
- /*
- This function returns the width and height in pixels of hDib;
- and stores the results in *width and *height.
-
- Returns:
-
- Void
- */
- {
- LPBITMAPINFOHEADER lpb;
-
-
- if ((lpb = (LPBITMAPINFOHEADER)GlobalLock(hDib)) != 0L)
- {
- *width = lpb->biWidth;
- *height = lpb->biHeight;
- GlobalUnlock(hDib);
- }
- }
-
-
- static void NEAR PASCAL DibPaint( HANDLE hDib, HDC dc, short left, short top )
- /*
- This function stretches hDib to the passed dc. It assumes the palette is
- already set.
-
- Returns:
-
- Void
- */
- {
- LPBITMAPINFOHEADER lpbi;
- LPSTR pBuf;
-
- if ((lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib)) != 0L)
- {
- pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
-
- StretchDIBits(dc, left, top, (WORD)lpbi->biWidth, (WORD)lpbi->biHeight, 0, 0,
- (WORD)lpbi->biWidth, (WORD)lpbi->biHeight, pBuf, (LPBITMAPINFO)lpbi,
- DIB_RGB_COLORS, SRCCOPY);
-
- GlobalUnlock(hDib);
- }
- }
-
-
- static WORD NEAR PASCAL PaletteSize (LPBITMAPINFOHEADER lpbi)
- /*
- This function calculates the palette size in bytes.
-
- Returns:
-
- Palette size in number of bytes.
- */
- {
- return DibNumColors(lpbi) * sizeof(RGBQUAD);
- }
-
-
- static WORD NEAR PASCAL DibNumColors (LPBITMAPINFOHEADER lpbi)
- /*
- This function determines the number of colors in the DIB by looking at
- the BitCount filed in the info block.
-
- Returns:
-
- The number of colors in the DIB.
-
- */
- {
- int bits;
-
- if (lpbi->biClrUsed != 0)
- return (WORD)lpbi->biClrUsed;
- bits = lpbi->biBitCount;
-
- switch (bits)
- {
- case 1:
- return 2;
- case 4:
- return 16;
- case 8:
- return 256;
- default:
- /* A 24 bitcount DIB has no color table */
- return 0;
- }
- }
-
-
- static HANDLE NEAR PASCAL DibCopy( HANDLE hDib )
- /*
- This function copies the passed dib and returns a HANDLE to the copy.
-
- Returns:
-
- HANDLE - handle to copied DIB.
- 0 - insufficient memory.
- */
- {
- HANDLE rv;
- DWORD size;
- char huge *s;
- char huge *d;
-
- size = GlobalSize(hDib);
- if ((rv = GlobalAlloc(GHND, size)) != NULL)
- {
- d = (char huge *)GlobalLock(rv);
- s = (char huge *)GlobalLock(hDib);
- for(; size > 0; ++s, ++d, --size)
- *d = *s;
-
- GlobalUnlock(rv);
- GlobalUnlock(hDib);
- }
-
- return rv;
- }
-
-
- static HPALETTE NEAR PASCAL CreateThePal( HANDLE hDib )
- /*
- This function creates a palette from the passed DIB - hDib.
-
- Returns:
-
- the HPALETTE if successfull
- 0 - if error
-
- Please NOTE: if the palette is incomplete it will be padded with the color
- white.
- */
- {
- short i;
- short NumColors;
- HANDLE hLog;
- HPALETTE hPal=0;
- LPBITMAPINFOHEADER lpBi;
- RGBQUAD FAR *lpOrig;
- LPLOGPALETTE lpPal;
-
- // Allocate a buffer large enough for a 256 color palette
- if ((hLog = GlobalAlloc(GHND, TOTAL_PALETTE_SIZE)))
- {
-
- lpPal = (LPLOGPALETTE)GlobalLock(hLog);
- lpBi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
-
- lpOrig = (RGBQUAD FAR *)((LPSTR)lpBi + (WORD)lpBi->biSize);
-
- NumColors = DibNumColors(lpBi);
-
- lpPal->palVersion = 0x300;
- lpPal->palNumEntries = 0x100;
-
- /* Copy the palette to the temporary buffer */
- for (i=0; i<NumColors; ++i)
- {
- lpPal->palPalEntry[i].peRed = lpOrig[i].rgbRed;
- lpPal->palPalEntry[i].peGreen = lpOrig[i].rgbGreen;
- lpPal->palPalEntry[i].peBlue = lpOrig[i].rgbBlue;
- lpPal->palPalEntry[i].peFlags = 0;
- }
-
- // Fill in the rest of the palette to white in case it is an incomplete palette
- for( i=NumColors; i<256; ++i)
- {
- lpPal->palPalEntry[i].peFlags = 0;
- lpPal->palPalEntry[i].peRed = COLOR_WHITE;
- lpPal->palPalEntry[i].peGreen = COLOR_WHITE;
- lpPal->palPalEntry[i].peBlue = COLOR_WHITE;
- }
-
- /* Create the palette */
- hPal = CreatePalette(lpPal);
-
- GlobalUnlock(hDib);
- GlobalUnlock(hLog);
- GlobalFree(hLog);
- }
-
- return hPal;
- }
-