/*=========================================================================*/
/*                                                                         */
/* ICOREAD.C                                                               */
/*                                                                         */
/* Responsible for reading the icon in from an external ICO file.          */
/*                                                                         */
/* (C) Copyright 1990, 1991  Marc Adler/Magma Systems  All Rights Reserved */
/*                                                                         */
/*=========================================================================*/

#include <stdio.h>
#include <ctype.h>
#include <memory.h>
#include <dos.h>
#include <fcntl.h>
#include <io.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <string.h>
#include <windows.h>
#include "ico.h"


int ICORead(hWnd, pszFile)
  HWND hWnd;
  char *pszFile;
{
  HDC  hDC;
  int  fd;
  int  i;
  char pFilename[65];

  HANDLE hANDMask;
  PSTR pANDMask;
  long nPictureSize;
  int  nTotalBytesPerLine;

  HANDLE hBitmapBytes;
  LPSTR  lpBitmapBytes;
  HANDLE      hbmi;
  LPBITMAPINFO lpbmi;

  extern BYTE rgb[16][3];
  extern HWND hWndColor;


  /*
    Open the ICO file
  */
  strcpy(pFilename, pszFile);
  if (strchr(pFilename, '.') == NULL)
    strcat(pFilename, ".ico");
  if ((fd = open(pFilename, O_RDONLY | O_BINARY)) < 0)
  {
    MessageBox(hWndMain, "Couldn't open file", NULL, MB_OK);
    return FALSE;
  }
  strcpy(IconInfo.szFilename, pFilename);

  /*
    Read the icon header and the icon directory entry
  */
  read(fd, (char *) &IconHeader, sizeof(IconHeader));
  read(fd, (char *) &IconDir, sizeof(IconDir));

  /*
    Make sure that we are dealing with 16-color icons...
  */
  if (IconDir.ColorCount != 16)
  {
    MessageBox(hWnd, "IKE can only deal with 16-color icons.", "Read Error",
               MB_OK | MB_ICONEXCLAMATION);
    return FALSE;
  }

  /*
    Free the memory taken up by the previous icon bitmap.
  */
  if (IconInfo.hBitmapInfo)
  {
    GlobalUnlock(IconInfo.hBitmapInfo);
    GlobalFree(IconInfo.hBitmapInfo);
    IconInfo.hBitmapInfo = NULL;
  }

  hbmi = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, 
                     (DWORD) sizeof(BITMAPINFOHEADER) + 16*sizeof(RGBQUAD));
  IconInfo.hBitmapInfo = hbmi;
  lpbmi = (LPBITMAPINFO) GlobalLock(hbmi);
  if (lpbmi == NULL)
  {
    MessageBox(hWnd, "Can't lock lpbmi", "Read", MB_OK);
    close(fd);
    return FALSE;
  }
  _lread(fd, (LPSTR) lpbmi, sizeof(BITMAPINFOHEADER) + 16*sizeof(RGBQUAD));
  for (i = 0;  i < 16;  i++)
    _fmemcpy(rgb[i], &lpbmi->bmiColors[i], 3);
  GlobalUnlock(hbmi);

  /*
    First, let's read the AND mask in. This is found at the tail end
    of the bitmap data. We move (length*height/8) bytes backwards from
    (icoDIBOffset + icoDIBSize), and at that point, we find the AND
    mask.
  */
  hANDMask = LocalAlloc(LMEM_FIXED, IconDir.Width*IconDir.Height/8);
  pANDMask = LocalLock(hANDMask);
  if (pANDMask == NULL)
  {
    MessageBox(hWndMain, "Can't allocate AND mask buffer", NULL, MB_OK);
    close(fd);
    return FALSE;
  }
  lseek(fd, (long)
        IconDir.icoDIBOffset+IconDir.icoDIBSize-(IconDir.Width*IconDir.Height/8),
        0);
  _lread(fd, (LPSTR) pANDMask, IconDir.Width*IconDir.Height/8);
  LocalUnlock(hANDMask);
  LocalFree(hANDMask);

  /*
    Allocate a global buffer to hold the bitmap data. The size of the
    bitmap is the area in the pixel rectangle divided by 8-bits-per-byte,
    times the number of color planes.
  */
  switch (IconDir.ColorCount)
  {
    case 2 : /* 1 byte = 8 pixels */
      nTotalBytesPerLine = IconDir.Width / 8;
      break;
    case 8 : /* 1 byte = 2 pixels??? */
      nTotalBytesPerLine = IconDir.Width / 2;
      break;
    case 16 : /* 1 byte = 2 pixels */
      nTotalBytesPerLine = IconDir.Width / 2;
      break;
  }
  nPictureSize = (long) nTotalBytesPerLine * IconDir.Height;


  if (IconInfo.hBitmapBits)
  {
    GlobalUnlock(IconInfo.hBitmapBits);
    GlobalFree(IconInfo.hBitmapBits);
    IconInfo.hBitmapBits = NULL;
  }

  hBitmapBytes = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, nPictureSize);
  IconInfo.hBitmapBits = hBitmapBytes;
  if (hBitmapBytes == NULL)
  {
    MessageBox(hWndMain, "Can't allocate global bitmap buffer", NULL, MB_OK);
    close(fd);
    return FALSE;
  }
  lpBitmapBytes = GlobalLock(hBitmapBytes);
  if (lpBitmapBytes == NULL)
  {
    MessageBox(hWndMain, "Can't lock global bitmap buffer", NULL, MB_OK);
    close(fd);
    return FALSE;
  }


  /*
    Now read the bitmap image in.
  */
  lseek(fd, (long)
        IconDir.icoDIBOffset + IconDir.icoDIBSize -
        (IconDir.Width*IconDir.Height/8) - (nTotalBytesPerLine*IconDir.Height),
        0);
  _lread(fd, lpBitmapBytes, (int) (nTotalBytesPerLine*IconDir.Height));
  GlobalUnlock(hBitmapBytes);

  /*
    Cause the edit and image windows to be repainted
  */
  InvalidateRect(hWnd, (LPRECT) NULL, TRUE);
  InvalidateRect(hWndActualImage, (LPRECT) NULL, TRUE);
  InvalidateRect(hWndColor, (LPRECT) NULL, TRUE);
  close(fd);
  return TRUE;
}


#ifdef DEBUG
Dump(char *szFile, char huge *p, int iHeight, int iWidth)
{
  int i, j;
  FILE *fp;

  fp = fopen(szFile, "w");
  for (i = 0;  i < iHeight;  i++)
  {
    for (j = 0;  j < iWidth;  j++)
      fprintf(fp, "%02x", (unsigned char) *p++);
    fprintf(fp, "\n");
  }

  fflush(fp);
  fclose(fp);
}
#endif
