/* r4bit.c (c)Copyright Sequiter Software Inc., 1991-1994. All rights reserved. */ #include "d4all.h" #ifdef S4WINDOWS #define ABS(x) ((x<0)?-1*(x):x) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B') #define BYTES_PER_READ 32767 #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4) #define IS_WIN30_DIB(lpbi) ((*(LPDWORD) (lpbi)) == sizeof (BITMAPINFOHEADER)) DWORD PASCAL kwrite ( int, VOID FAR *, DWORD ); WORD S4FUNCTION DIBNumColors (LPSTR lpbi) { WORD wBitCount; /* If this is a Windows style DIB, the number of colors in the */ /* color table can be less than the number of bits per pixel */ /* allows for (i.e. lpbi->biClrUsed can be set to some value). */ /* If this is the case, return the appropriate value. */ if (IS_WIN30_DIB (lpbi)) { DWORD dwClrUsed; dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed; if (dwClrUsed) return (WORD) dwClrUsed; } /* Calculate the number of colors in the color table based on */ /* the number of bits per pixel for the DIB. */ if (IS_WIN30_DIB (lpbi)) wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount; else wBitCount = ((LPBITMAPCOREHEADER) lpbi)->bcBitCount; switch (wBitCount) { case 1: return 2; case 4: return 16; case 8: return 256; default: return 0; } } WORD S4FUNCTION PaletteSize (LPSTR lpbi) { if (IS_WIN30_DIB (lpbi)) return (DIBNumColors (lpbi) * sizeof (RGBQUAD)); else return (DIBNumColors (lpbi) * sizeof (RGBTRIPLE)); } LPSTR S4FUNCTION FindDIBBits (LPSTR lpbi) { return (lpbi + *(LPDWORD)lpbi + PaletteSize (lpbi)); } HANDLE S4FUNCTION GetDIB ( LPSTR fname, CODE4 *code_base ) { int hFile; OFSTRUCT ofs; HANDLE hDIB; char fname2[14]; FILE4 file; u4name_piece( fname2, sizeof(fname2), fname, 0, 1 ); SetCursor(LoadCursor(NULL, IDC_WAIT)); if( file4open( &file, code_base, fname2, 1 ) == 0 ) { file4close( &file ); if ((hFile = OpenFile (fname2, &ofs, OF_READ)) != -1) { hDIB = ReadDIBFile (hFile); _lclose (hFile); SetCursor(LoadCursor(NULL, IDC_ARROW)); return hDIB; } } else e4set( code_base, 0 ); if ((hFile = OpenFile (fname, &ofs, OF_READ)) != -1) { hDIB = ReadDIBFile (hFile); _lclose (hFile); SetCursor(LoadCursor(NULL, IDC_ARROW)); return hDIB; } SetCursor(LoadCursor(NULL, IDC_ARROW)); return NULL; } /************************************************************************* Function: MyRead (int, LPSTR, DWORD) Purpose: Routine to read files greater than 64K in size. Returns: TRUE if successful. FALSE if an error occurs. Comments: History: Date Reason 6/1/91 Created *************************************************************************/ BOOL MyRead (int hFile, LPSTR lpBuffer, DWORD dwSize) { #ifndef S4WIN32 char huge *lpInBuf = (char huge *) lpBuffer; #else char *lpInBuf = (char *) lpBuffer; #endif int nBytes; while (dwSize) { nBytes = (int) (dwSize > (DWORD) BYTES_PER_READ ? BYTES_PER_READ : LOWORD (dwSize)); if (_lread (hFile, (LPSTR) lpInBuf, nBytes) != (WORD) nBytes) return FALSE; dwSize -= nBytes; lpInBuf += nBytes; } return TRUE; } /************************************************************************* Function: ReadDIBFile (int) Purpose: Reads in the specified DIB file into a global chunk of memory. Returns: A handle to a dib (hDIB) if successful. NULL if an error occurs. Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything from the end of the BITMAPFILEHEADER structure on is returned in the global memory handle. History: Date Author Reason 6/1/91 Created 6/27/91 Removed PM bitmap conversion routines. 6/31/91 Removed logic which overallocated memory (to account for bad display drivers). 11/08/91 Again removed logic which overallocated memory (it had creeped back in!) *************************************************************************/ HANDLE S4FUNCTION ReadDIBFile (int hFile) { BITMAPFILEHEADER bmfHeader; DWORD dwBitsSize; HANDLE hDIB; LPSTR pDIB; /* get length of DIB in bytes for use when reading */ dwBitsSize = filelength (hFile); /* Go read the DIB file header and check if it's valid. */ if ((_lread (hFile, (LPSTR) &bmfHeader, sizeof (bmfHeader)) != sizeof (bmfHeader)) || (bmfHeader.bfType != DIB_HEADER_MARKER)) { /* DIBError (ERR_NOT_DIB); */ return NULL; } /* Allocate memory for DIB */ hDIB = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize - sizeof(BITMAPFILEHEADER)); if (hDIB == 0) { /* DIBError (ERR_MEMORY); */ return NULL; } pDIB = GlobalLock (hDIB); /* Go read the bits. */ if (!MyRead (hFile, pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER))) { GlobalUnlock (hDIB); GlobalFree (hDIB); return NULL; } GlobalUnlock (hDIB); return hDIB; } /**************************************************************************** FUNCTION : lwrite(int fh, VOID FAR *pv, DWORD ul) PURPOSE : Writes data in steps of 32k till all the data is written. RETURNS : 0 - If write did not proceed correctly. number of bytes written otherwise. ****************************************************************************/ DWORD PASCAL kwrite (int fh, VOID FAR *pv, DWORD ul) { DWORD ulT = ul; #ifndef S4WIN32 BYTE huge *hp = (unsigned char huge *)pv; #else BYTE *hp = pv; #endif while (ul > BYTES_PER_READ) { if (_lwrite(fh, (LPSTR)hp, (WORD)BYTES_PER_READ) != BYTES_PER_READ) return 0; ul -= BYTES_PER_READ; hp += BYTES_PER_READ; } if (_lwrite(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul) return 0; return ulT; } /**************************************************************************** FUNCTION : WriteDIB(LPSTR szFile,HANDLE hdib) PURPOSE : Write a global handle in CF_DIB format to a file. RETURNS : TRUE - if successful. FALSE - otherwise ****************************************************************************/ BOOL S4FUNCTION WriteDIB (LPSTR szFile, HANDLE hdib) { BITMAPFILEHEADER hdr; LPBITMAPINFOHEADER lpbi; int fh; OFSTRUCT of; if (!hdib) return FALSE; fh = OpenFile (szFile, &of, OF_CREATE|OF_READWRITE); if (fh == -1) return FALSE; lpbi = (LPBITMAPINFOHEADER)GlobalLock (hdib); /* Fill in the fields of the file header */ hdr.bfType = DIB_HEADER_MARKER; hdr.bfSize = GlobalSize (hdib) + sizeof (BITMAPFILEHEADER); hdr.bfReserved1 = 0; hdr.bfReserved2 = 0; hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize + PaletteSize((LPSTR)lpbi); /* Write the file header */ if (!_lwrite (fh, (LPSTR)&hdr, sizeof (BITMAPFILEHEADER))) { GlobalUnlock (hdib); _lclose (fh); return FALSE; } /* Write the DIB header and the bits */ if (!kwrite (fh, (LPSTR)lpbi, GlobalSize (hdib))) { GlobalUnlock (hdib); _lclose (fh); return FALSE; } GlobalUnlock (hdib); _lclose (fh); return TRUE; } #endif