/* Enhanced NCSA Mosaic from Spyglass "Guitar" Copyright 1994 Spyglass, Inc. All Rights Reserved */ /**************************************************************************** * NCSA Mosaic for Microsoft Windows * * Software Development Group * * National Center for Supercomputing Applications * * University of Illinois at Urbana-Champaign * * 605 E. Springfield, Champaign, IL 61820 * * mosaic@ncsa.uiuc.edu * * * * Copyright (C) 1993, 1994, Board of Trustees of the University of Illinois * * * * NCSA Mosaic software, both binary and source (hereafter, Software) is * * copyrighted by The Board of Trustees of the University of Illinois * * (UI), and ownership remains with the UI. * * * * The UI grants you (hereafter, Licensee) a license to use the Software * * for academic, research and internal business purposes only, without a * * fee. Licensee may distribute the binary and source code (if released) * * to third parties provided that the copyright notice and this statement * * appears on all copies and that no charge is associated with such * * copies. * * * * Licensee may make derivative works. However, if Licensee distributes * * any derivative work based on or derived from the Software, then * * Licensee will (1) notify NCSA regarding its distributing of the * * derivative work, and (2) clearly notify users that such derivative * * work is a modified version and not the original NCSA Mosaic * * distributed by the UI. * * * * Any Licensee wishing to make commercial use of the Software should * * contact the UI, c/o NCSA, to negotiate an appropriate license for such * * commercial use. Commercial use included (1) integration of all or * * part of the source code into a product for sale or license by or on * * behalf of Licensee to third parties, or (2) distribution of the binary * * code or source code to third parties that need it to utilize a * * commercial product sold or licensed by or on behalf of Licensee. * * * * UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR * * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED * * WARRANTY. THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE * * USERS OF THIS SOFTWARE. * * * * By using or copying this Software, Licensee agrees to abide by the * * copyright law and all other applicable laws of the U.S. including, but * * not limited to, export control laws, and the terms of this license. * * UI shall have the right to terminate this license immediately by * * written notice upon Licensee's breach of, or non-compliance with, any * * of its terms. Licensee may be held legally responsible for any * * copyright infringement that is caused or encouraged by Licensee's * * failure to abide by the terms of this license. * * * ****************************************************************************/ #include "all.h" #ifdef FEATURE_IMG_THREADS #include "safestrm.h" #include "decoder.h" #endif unsigned const char nibMask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 }; #define MAX_LINE 512 #ifdef MAC /* Convert the raw data into an image. Note that the image pointer has the data in reverse line order (as for Windows DIBs). In the interests of code sharing, I just politely reverse it back to correct order here while I'm padding it. */ static GWorldPtr XBMImageToGW(int w, int h, char *image, int imgbytes) { GWorldPtr gw; Rect r; Boolean bOK = TRUE; int n; int rowbytes; Ptr base; SetRect(&r, 0, 0, w, h); if (bOK) { gw = GTR_ALLOCGWORLD(1, &r, NULL); bOK = bOK && (gw != NULL); } bOK = bOK && LockPixels(gw->portPixMap); if (bOK) { rowbytes = (**gw->portPixMap).rowBytes & 0x7fff; base = GetPixBaseAddr(gw->portPixMap); image += (h - 1) * imgbytes; for (n = 0; n < h; n++) { BlockMove((Ptr) image, base, imgbytes); image -= imgbytes; base += rowbytes; } UnlockPixels(gw->portPixMap); } return (bOK) ? gw : NULL; } #endif /* MAC */ #ifndef FEATURE_IMG_THREADS /* ** This function returns a pointer to malloced memory ** which must be freed (except on the MAC) */ #if defined(UNIX) unsigned char *ReadXBM(unsigned char *pMem, long *w, long *h) #endif #ifdef WIN32 unsigned char *ReadXBM(unsigned char *pMem, long far * w, long far * h) #endif #ifdef MAC GWorldPtr ReadXBM(unsigned char *pMem, long *w, long *h) #endif { char line[MAX_LINE], *name_and_type; unsigned char *szCurLoc; char *t; unsigned char *ptr, *dataP; long bytes_per_line, version10p, raster_length, padding, win_extra_bytes_per_line; int i, bytes, temp = 0, value; int Ncolors, charspp, xpmformat; int blackbit = 1; int whitebit = 0; int line_idx = 0, file_idx = 0; int n; static char spaces[] = " \t"; char *tok; char *end; #ifdef MAC GWorldPtr gw; #endif *w = 0; *h = 0; Ncolors = 0; charspp = 0; xpmformat = 0; for (;;) { for (line_idx = 0; line_idx < MAX_LINE; line_idx++) { if (!pMem[file_idx]) return NULL; if (pMem[file_idx] == EOF) return NULL; if (pMem[file_idx] == '\n' || pMem[file_idx] == '\r') { file_idx++; if (pMem[file_idx] == '\n' || pMem[file_idx] == '\r') file_idx++; break; } line[line_idx] = pMem[file_idx]; file_idx++; } line[line_idx] = '\0'; tok = strtok(line, spaces); if (!tok) return NULL; if (!strcmp(tok, "#define")) { name_and_type = strtok(NULL, spaces); if (!name_and_type) continue; if (NULL == (t = strrchr(name_and_type, '_'))) t = name_and_type; else t++; tok = strtok(NULL, spaces); if (!tok) continue; value = strtol(tok, &end, 10); if (!strcmp("width", t)) *w = value; else if (!strcmp("height", t)) *h = value; else if (!strcmp("ncolors", t)) Ncolors = value; else if (!strcmp("pixel", t)) charspp = value; continue; } if (!strcmp(tok, "static")) { t = strtok(NULL, spaces); if (!t) continue; if (!strcmp(t, "unsigned")) { t = strtok(NULL, spaces); if (!t) continue; } if (!strcmp(t, "short")) { version10p = 1; break; } else if (!strcmp(t, "char")) { version10p = 0; t = strtok(NULL, spaces); if (*t == '*') xpmformat = 1; break; } } else continue; } if (xpmformat) { XX_DMsg(DBG_IMAGE, ("Can't Handle XPM format inlined images!\n")); return (NULL); } if (*w == 0) { XX_DMsg(DBG_IMAGE, ("Can't read image w = 0!\n")); return (NULL); } if (*h == 0) { XX_DMsg(DBG_IMAGE, ("Can't read image h = 0!\n")); return (NULL); } padding = 0; if (((*w % 16) >= 1) && ((*w % 16) <= 8) && version10p) { padding = 1; } bytes_per_line = ((*w + 7) / 8) + padding; #ifdef WIN32 if (bytes_per_line % 4) win_extra_bytes_per_line = (4 - (bytes_per_line % 4)) % 4; // 0-3, extra padding for long boundaries. else #endif win_extra_bytes_per_line = 0; raster_length = bytes_per_line * *h; dataP = (unsigned char *) GTR_MALLOC((bytes_per_line + +win_extra_bytes_per_line) * (*h)); if (dataP == NULL) { return (NULL); } szCurLoc = &pMem[file_idx]; ptr = dataP; if (version10p) { long cnt = 0; long lim = (bytes_per_line - padding) * 8; for (bytes = 0; bytes < raster_length; bytes += 2) { while (*szCurLoc == '\r' || *szCurLoc == '\n') szCurLoc++; value = strtol(szCurLoc, &end, 16); szCurLoc += (strcspn((const char far *) szCurLoc, /*{*/ ",}") + 1); for (n = 0; n < 8; n++) { temp += (value & 0x01) << (n - 1); value = value >> 1; } value = temp & 0xff; for (i = 0; i < 8; i++) { if (cnt < (*w)) { if (value & nibMask[i]) *ptr++ = (unsigned char) blackbit; else *ptr++ = (unsigned char) whitebit; } if (++cnt >= lim) cnt = 0; } if ((!padding) || ((bytes + 2) % bytes_per_line)) { value = temp >> 8; for (i = 0; i < 8; i++) { if (cnt < (*w)) { if (value & nibMask[i]) *ptr++ = (unsigned char) blackbit; else *ptr++ = (unsigned char) whitebit; } if (++cnt >= lim) cnt = 0; } } } } else { /* TODO UNIX gui/x_xbm.c has some bReverseBitmap stuff in it ** that might have to be moved in here. It only affects code ** in this block. */ long cnt = 0; #ifdef UNIX Boolean bReverseBitmap; if (BitmapBitOrder(display) == LSBFirst) bReverseBitmap = TRUE; #else ptr += (*h - 1) * (bytes_per_line + win_extra_bytes_per_line); #endif for (bytes = 0; bytes < raster_length; bytes++) { while (*szCurLoc == '\r' || *szCurLoc == '\n') szCurLoc++; value = strtol(szCurLoc, &end, 16); szCurLoc += (strcspn((const char far *) szCurLoc, /*{*/ ",}") + 1); #ifdef UNIX if (bReverseBitmap) { for (n = 0, temp = 0; n < 8; n++) { temp += (value & 0x01) << (n); value = value >> 1; } } else { for (n = 0, temp = 0; n < 8; n++) { temp += (value & 0x80) >> (n); value = value << 1; } } #else for (n = 0, temp = 0; n < 8; n++) { temp += (value & 0x01) << (7 - n); value = value >> 1; } #endif value = temp & 0xff; *ptr++ = (unsigned char) value; if (++cnt == bytes_per_line) { for (cnt = 0; cnt < win_extra_bytes_per_line; cnt++) *ptr++ = (unsigned char) 0; #ifndef UNIX ptr -= 2 * (bytes_per_line + win_extra_bytes_per_line); #endif cnt = 0; } } } #if defined(WIN32) || defined (UNIX) return dataP; #endif #ifdef MAC gw = XBMImageToGW(*w, *h, dataP, bytes_per_line); GTR_FREE(dataP); return gw; #endif } #else unsigned char *ReadXBM(void *pdecoderObject, long far * w, long far * h) { char line[MAX_LINE+2], *name_and_type; char *t; unsigned char *ptr, *dataP; long bytes_per_line, version10p, raster_length, padding, win_extra_bytes_per_line; int i, bytes, temp = 0, value; int Ncolors, charspp, xpmformat; int blackbit = 1; int whitebit = 0; int line_idx = 0; char lookahead = 0; int n; static char spaces[] = " \t"; char *tok; char *end; PDECODER pdecoder = pdecoderObject; PSAFESTREAM pSSInput = pDC_GetStream(pdecoderObject); #ifdef FEATURE_IMG_THREADS PIMGCBINFO pImgCBInfo = NULL; #endif #ifdef FEATURE_IMG_THREADS if (pdecoderObject) pImgCBInfo = pDC_GetOutput(pdecoderObject); #endif *w = 0; *h = 0; Ncolors = 0; charspp = 0; xpmformat = 0; for (;;) { line_idx = 0; if (lookahead) { line[0] = lookahead; lookahead = 0; line_idx = 1; } for (; line_idx < MAX_LINE; line_idx++) { if (cbSS_Read(pSSInput,&line[line_idx],1) != 1) return NULL; if (line[line_idx] == EOF) return NULL; if (line[line_idx] == '\n' || line[line_idx] == '\r') { if (cbSS_Read(pSSInput,&line[line_idx],1) != 1) return NULL; if (line[line_idx] == EOF) return NULL; if (line[line_idx] != '\n' && line[line_idx] != '\r') lookahead = line[line_idx]; break; } } line[line_idx] = '\0'; tok = strtok(line, spaces); if (!tok) return NULL; if (!strcmp(tok, "#define")) { name_and_type = strtok(NULL, spaces); if (!name_and_type) continue; if (NULL == (t = strrchr(name_and_type, '_'))) t = name_and_type; else t++; tok = strtok(NULL, spaces); if (!tok) continue; value = strtol(tok, &end, 10); if (!strcmp("width", t)) *w = value; else if (!strcmp("height", t)) *h = value; else if (!strcmp("ncolors", t)) Ncolors = value; else if (!strcmp("pixel", t)) charspp = value; continue; } if (!strcmp(tok, "static")) { t = strtok(NULL, spaces); if (!t) continue; if (!strcmp(t, "unsigned")) { t = strtok(NULL, spaces); if (!t) continue; } if (!strcmp(t, "short")) { version10p = 1; break; } else if (!strcmp(t, "char")) { version10p = 0; t = strtok(NULL, spaces); if (*t == '*') xpmformat = 1; break; } } else continue; } if (xpmformat) { XX_DMsg(DBG_IMAGE, ("Can't Handle XPM format inlined images!\n")); return (NULL); } if (*w == 0) { XX_DMsg(DBG_IMAGE, ("Can't read image w = 0!\n")); return (NULL); } if (*h == 0) { XX_DMsg(DBG_IMAGE, ("Can't read image h = 0!\n")); return (NULL); } padding = 0; if (((*w % 16) >= 1) && ((*w % 16) <= 8) && version10p) { padding = 1; } bytes_per_line = ((*w + 7) / 8) + padding; if (bytes_per_line % 4) win_extra_bytes_per_line = (4 - (bytes_per_line % 4)) % 4; // 0-3, extra padding for long boundaries. else win_extra_bytes_per_line = 0; raster_length = bytes_per_line * *h; dataP = (unsigned char *) GTR_MALLOC((bytes_per_line + win_extra_bytes_per_line) * (*h)); if (dataP == NULL) { return (NULL); } DC_PostStatus(pdecoder,DC_WHKnown); line_idx = 0; if (lookahead) { line_idx = 1; line[0] = lookahead; } ptr = dataP; if (version10p) { long cnt = 0; long lim = (bytes_per_line - padding) * 8; for (bytes = 0; bytes < raster_length; bytes += 2) { if (line_idx == 0) { for (;;) { if (cbSS_Read(pSSInput,&line[0],1) != 1) goto exitPoint; if (line[0] != '\r' && line[0] != '\n') { line_idx = 1; break; } } } for (;;) { if (cbSS_Read(pSSInput,&line[line_idx],1) != 1) { if (line_idx == 0) goto exitPoint; break; } if (line[line_idx] == ',' || line[line_idx] == '}') { break; } if (line_idx < MAX_LINE) line_idx++; } line[line_idx] = '\0'; value = strtol(line, &end, 16); line_idx = 0; for (n = 0; n < 8; n++) { temp += (value & 0x01) << (n - 1); value = value >> 1; } value = temp & 0xff; for (i = 0; i < 8; i++) { if (cnt < (*w)) { if (value & nibMask[i]) *ptr++ = (unsigned char) blackbit; else *ptr++ = (unsigned char) whitebit; } if (++cnt >= lim) cnt = 0; } if ((!padding) || ((bytes + 2) % bytes_per_line)) { value = temp >> 8; for (i = 0; i < 8; i++) { if (cnt < (*w)) { if (value & nibMask[i]) *ptr++ = (unsigned char) blackbit; else *ptr++ = (unsigned char) whitebit; } if (++cnt >= lim) cnt = 0; } } } } else { /* TODO UNIX gui/x_xbm.c has some bReverseBitmap stuff in it ** that might have to be moved in here. It only affects code ** in this block. */ long cnt = 0; ptr += (*h - 1) * (bytes_per_line + win_extra_bytes_per_line); for (bytes = 0; bytes < raster_length; bytes++) { if (line_idx == 0) { for (;;) { if (cbSS_Read(pSSInput,&line[0],1) != 1) goto exitPoint; if (line[0] != '\r' && line[0] != '\n') { line_idx = 1; break; } } } for (;;) { if (cbSS_Read(pSSInput,&line[line_idx],1) != 1) { if (line_idx == 0) goto exitPoint; break; } if (line[line_idx] == ',' || line[line_idx] == '}') { break; } if (line_idx < MAX_LINE) line_idx++; } line[line_idx] = '\0'; value = strtol(line, &end, 16); line_idx = 0; for (n = 0, temp = 0; n < 8; n++) { temp += (value & 0x01) << (7 - n); value = value >> 1; } value = temp & 0xff; *ptr++ = (unsigned char) value; if (++cnt == bytes_per_line) { for (cnt = 0; cnt < win_extra_bytes_per_line; cnt++) *ptr++ = (unsigned char) 0; ptr -= 2 * (bytes_per_line + win_extra_bytes_per_line); cnt = 0; } } } exitPoint: return dataP; } #endif