home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / CVTICONS.ZIP / CVTICONS.C < prev    next >
C/C++ Source or Header  |  1991-09-14  |  25KB  |  715 lines

  1. /*****************************************************************************
  2.  
  3.   CvtIcons.exe Copyright @ 1991 Jay Giganti All Rights Reserved
  4.  
  5.               All Options are Mutually Exclusive
  6.  
  7.          x : Extracts Icons from Windows ICO file(s)
  8.          w : Converts ICO files from PM to Windows
  9.          p : Converts ICO files from Windows to PM
  10.          ? : Displays this screen
  11.  
  12.         Usage CVTICONS -option File (Wild Cards Accepted)
  13.  
  14.         examples cvticons -x c:\windows\*.*
  15.                  cvticons -p *.ico
  16.  
  17.         example 1 : will extract all icons from the files in c:\windows
  18.                     directory and will create them in your current directory
  19.  
  20.         example 2 : will convert all ICO files in your current directory
  21.                     into ICP files in the PM format in your current directory
  22.         
  23. This program currently does three things.
  24. Extracts Icons:
  25.   It will extract Icons from windows EXE and DLL files.  It scans through
  26.   these files and will create a file with and extension of .ICO based upon
  27.   2 things.  First it will look in the resource table for any Names, if it
  28.   finds a name it will use up to 8 characters of it to create the file
  29.   name.  If There were no names found in the resource table, or there were
  30.   more icons than names, (ie -- several Icons in one directory entry) then
  31.   the icon name will containg the first 5 characters if the program it is
  32.   stripping it from, and then append a 3 digit number,m thus you can process
  33.   a file with up 1000 icons in it.  
  34.   side note:  I stripped a file form the MS-DOS program  under windows and
  35.               found a 64x64 OS/2 1.1 icon format.
  36.  
  37. Converts Icons To PM Format:
  38.   This will translate an ICO file into a PM format.  It creates the file
  39.   with an .ICP extension.  Currently I will only copy one Icon from each ICO
  40.   file, since this is how I write them.  If Needed I will add multiple
  41.   icons per ICO file handling.  The format for the icon will be written
  42.   in its current dimensions, ie: a 32x32 stays 32x32. Under OS/2 1.2 it
  43.   seems that if they are not 64x64 then it is not in a device independent (DI)
  44.   format, thus when loaded into the Icon Editor, you are told the It has
  45.   created on for you, if you save the file, then this 64x64 DI format will
  46.   be written to disk along with the origional 32x32 format.  I have the Icon
  47.   Editor do all translation.  In the furture I might do the streching required
  48.   to create a 64x64 bitmap and thus the resulting PM file will be smaller 
  49.   and the icon editor won't complain.  The reason it would be smaller is 
  50.   because there would only be one format stored in it.
  51.  
  52. Converts Icons To Windows 3.0 Format:
  53.   This will translate a PM Icon file into a Windows format.  It will translate
  54.   all Icons in the file, as long as they are <= 32x32.  I might add the
  55.   functionality to squeeze 64x64 to 32x32 but the Icon edititor does a good
  56.   job.  Thus if you have a 64x64 then select a VGA type and it will be 
  57.   converted to a 32x32 format which I can read and save in a file.  The
  58.   file will be named with the filename and the extensions .ICW. If there
  59.   is more than one Icon which is <= 32x32 then the next filename will be
  60.   created with the first 6 characters of the filename plus a 2 digit number
  61.   and then .ICW appended to it.
  62.  
  63.   In the future I will port this to a Windows and PM app but this does the
  64.   job for now.  It is a dos program.  Also I will probably add the ability
  65.   to read and write multiple icons per ICO file, and the ability to extract
  66.   icons from windows files and convert them directly to PM format.  Currently
  67.   you have to extract and then convert.  I also will probably add the ability
  68.   to extract Icons from OS/2 files.  Until then I hope this utility helps.
  69.  
  70. ****************************************************************************/
  71.  
  72. #include <stdio.h>
  73. #include <stdlib.h>
  74. #include <io.h>
  75. #include <fcntl.h>
  76. #include <string.h>
  77. #include <malloc.h>
  78. #include <ctype.h>
  79. #include <conio.h>
  80. #include <sys\types.h>
  81. #include <sys\stat.h>
  82. #include "stdefs.h"
  83. #include "newexe.h"
  84. #include "rsrcico.h"
  85. #include "rsrcbmp.h"
  86. #include "cvticons.h"
  87. #include "os2defs.h"
  88.  
  89. extern int  GetOpt(int nArgc, char **szArgv, char *szOpts);
  90. extern int  gnOptInd;
  91. extern char *gszOptArg;
  92.  
  93.                 /* Global Variables */
  94. static short gfhInFile;
  95. static short gfhOutFile;
  96. static char  gIconNames[1000][9];
  97. static WORD  gwNames;
  98. static char  gszFileName[13];
  99. /***************************************************************************
  100.    Main -- Entry point
  101. ****************************************************************************/
  102. short main(short nArgc, char **szArgv)
  103. {
  104.   int         nCntr;
  105.   BYTE        Flag = NONE;
  106.   char        *Name;
  107.   
  108.   if (nArgc < 2)
  109.     DisplayUsage();
  110.   
  111.   nCntr = GetOpt(nArgc, szArgv, "?pwx");
  112.   switch(nCntr)
  113.   {
  114.     case 'x' :
  115.       Flag = EXTRACT;
  116.       break;
  117.  
  118.     case 'p' :
  119.       Flag = TO_PM;
  120.       break;
  121.            
  122.     case 'w' :
  123.       Flag = TO_WIN;
  124.       break;
  125.     
  126.     case '?' :
  127.       DisplayUsage();
  128.   }     
  129.   if (Flag == NONE)
  130.   {
  131.     DisplayUsage();
  132.     return 0;
  133.   }
  134.   for(nCntr = 0; gnOptInd < nArgc; ++gnOptInd)
  135.   {    
  136.     if (nCntr++ == 23)
  137.     {
  138.       printf("\t\t\t==> Hit Any Key To Continue <==");
  139.       (void) getche();
  140.       printf("\n\n");
  141.       nCntr = 0;
  142.     }    
  143.     gfhInFile = open(szArgv[gnOptInd], O_BINARY | O_RDONLY); 
  144.     if (gfhInFile == -1)
  145.     {
  146.       printf("Could Not Open File\n");
  147.       continue;
  148.     }
  149.     Name = GetFileName(szArgv[gnOptInd]);
  150.     strcpy(gszFileName, Name);
  151.     printf("%-12s : ", gszFileName);
  152.     switch (Flag)
  153.     {
  154.       case EXTRACT:
  155.         ExtractFileInfo();
  156.         break;
  157.         
  158.       case TO_PM:
  159.         ConvertToPM();
  160.         break;
  161.         
  162.       default:
  163.         ConvertToWin();
  164.         break;
  165.     }
  166.     close(gfhInFile);
  167.   }
  168.   return 0;
  169. }
  170. /***************************************************************************/
  171. /* Get File Name : Gets Just the Filename -- Strips Drive and Directory    */
  172. /***************************************************************************/
  173. void GetFileName(char *FullName)
  174. {
  175.   char *pCh;
  176.   
  177.   pCh = FullName;
  178.   while (*pCh != '\0')
  179.     ++pCh;
  180.   --pCh;           
  181.                     /* Locate Start Of File Name */
  182.   while (pCh > FullName && *pCh != '\\' && *pCh != ':' && *pCh != '/')
  183.     --pCh;
  184.   if (pCh > FullName)
  185.     ++pCh;         /* Move To Right Of Pathname Separator */
  186.  
  187.   return pCh;
  188. }
  189.  
  190. /***************************************************************************/
  191. /* Fatal -- issues a diagnostic message and terminates               */
  192. /***************************************************************************/
  193. void Fatal(char *szMesg)
  194. {
  195.   strcat(szMesg, "\n");
  196.   fputs("Error : ", stderr);
  197.   fputs(szMesg, stderr);
  198.   exit(2);
  199. }
  200. /***************************************************************************/
  201. /***************************************************************************/
  202. void DisplayUsage(void)
  203. {
  204.   printf("\n\n\n\t      -- CvtIcons : Copyright @ 1991 Jay Giganti --\n\n");
  205.   printf("\tExtracts Icons from EXE & DLL Window Files Creating ICO files\n");
  206.   printf("\tConverts Icons between Windows and Program Manager formats\n");
  207.   printf("\tCreates the ICO file name from entry in the resource table\n");
  208.   printf("\n\tCurrently Only 1 Icon per WIN ICO File will be converted\n");
  209.   printf("\tWhen Converting, the new file will be created with an\n");
  210.   printf("\tExtension of either ICP or ICW; depending on option\n");
  211.   printf("\tAn Icons dimensions, in PM format, must be 32x32 or less\n\n");
  212.   printf("\n\t\t    All Options are Mutually Exclusive\n\n");
  213.   printf("\t\tx : Extracts Icons from Windows ICO file(s)\n");
  214.   printf("\t\tw : Converts ICO files from PM to Windows\n");
  215.   printf("\t\tp : Converts ICO files from Windows to PM\n");
  216.   printf("\t\t? : Displays this screen\n");
  217.   printf("\n\t      Usage CVTICONS -option File (Wild Cards Accepted)\n");
  218.   exit(1);
  219. }
  220. /***************************************************************************/
  221. /***************************************************************************/
  222. void ExtractFileInfo(void)
  223. {
  224.   OLDEXEHDR OldHdr;
  225.   NEWEXEHDR NewHdr;
  226.   BYTE      byBits;
  227.   
  228.   switch(byBits = GetFileType(&OldHdr))
  229.   {      
  230.     case DOS:
  231.       printf("Is A Non Windows Application\n");
  232.       return;
  233.  
  234.     case WIN:
  235.       lseek(gfhInFile, OldHdr.dwNewExeOfs, SEEK_SET);
  236.       read(gfhInFile, (PSTR) &NewHdr, sizeof(NewHdr));
  237.       if ((NewHdr.bySigByte1 != 'N') || (NewHdr.bySigByte2 != 'E'))
  238.       {
  239.         printf("Has An Improper Signature for a Windows App\n");
  240.         return;
  241.       }
  242.       ProcessResources(NewHdr.wResourceOfs + OldHdr.dwNewExeOfs,
  243.                    NewHdr.wResidentOfs - NewHdr.wResourceOfs);
  244.       break;          
  245.  
  246.     default :
  247.       printf("Is An Unknown file format\n");
  248.       return;
  249.   }
  250. }
  251. /***************************************************************************/
  252. /***************************************************************************/
  253. BYTE GetFileType(OLDEXEHDR *Hdr)
  254. {
  255.   read(gfhInFile, (PSTR)Hdr, sizeof *(Hdr));
  256.   if((Hdr->bySigByte1 != 'M') || (Hdr->bySigByte2 != 'Z'))
  257.     return 0;
  258.   if(Hdr->wRelocOfs == 0x40)
  259.     return WIN;
  260.   else
  261.     return DOS;
  262. }
  263. /***************************************************************************/
  264. /***************************************************************************/
  265. void ProcessResources(DWORD dwOfs, WORD wSize)
  266. {
  267.   RSRCTBL    rt;
  268.   WORD       wShiftCount;
  269.   WORD       wBits;
  270.   RSRCENTRY  *re;
  271.   long         lOfs;
  272.   BYTE       bHasIcons;
  273.   
  274.   bHasIcons = FALSE;
  275.   if (wSize)
  276.   {
  277.     lseek(gfhInFile, dwOfs, SEEK_SET);
  278.     read(gfhInFile, &rt, sizeof(rt));
  279.     wShiftCount = rt.wShiftCount;
  280.     while (rt.wType != 0)
  281.     {      
  282.       if ((re =(RSRCENTRY *)malloc(rt.wFollowing*sizeof(RSRCENTRY))) == NULL)
  283.     Fatal("Unable to allocate memory for Resource Entries");
  284.       read(gfhInFile, re, sizeof(RSRCENTRY) * rt.wFollowing);
  285.       wBits = rt.wType & 0x7FFF;
  286.       if (wBits == RS_ICON || wBits == RS_RESNAMES)
  287.       {
  288.         lOfs = tell(gfhInFile);
  289.         if (wBits == RS_ICON)
  290.         {
  291.           bHasIcons = TRUE;
  292.           if (rt.wFollowing > 1)
  293.             printf("Processing %u Icons\n", rt.wFollowing);
  294.           else
  295.             printf("Processing %u Icon\n", rt.wFollowing);          
  296.           ProcessIcons(rt.wFollowing, wShiftCount, re);
  297.         }
  298.         else
  299.         {
  300.           GetResourceNames((long)((long)re->wOffset << wShiftCount));
  301.           if(gwNames == 1)
  302.             printf("Located 1 Name - ");
  303.           if(gwNames > 1)
  304.             printf("Located %d Names - ", gwNames);
  305.         }
  306.         lseek(gfhInFile, lOfs, SEEK_SET);
  307.       }
  308.       free(re);
  309.       read(gfhInFile, &rt, sizeof(rt));
  310.     }
  311.     if (!bHasIcons)
  312.       printf("Does Not Contain Any Icons\n");
  313.   }
  314.   else
  315.     printf("Does Not Contain Any Resources\n");
  316. }
  317. /***************************************************************************/
  318. /***************************************************************************/
  319. void ProcessIcons(WORD wEntries,  WORD wShiftCount, RSRCENTRY *re)
  320.   ICOHDR    icoHdr;
  321.   char      szFileName[13];
  322.   char      szBuf[4];
  323.   RSRCENTRY *pre;
  324.   PSTR      pRsrc;
  325.   long      lOfs;  
  326.   WORD      wSize;
  327.   WORD      wCntr;
  328.   char      *pExt;
  329.   int       nEnd;
  330.     
  331.   icoHdr.wReserved = 0x0000;
  332.   icoHdr.wType     = 0x0001;
  333.   icoHdr.wCount    = 0x0001;
  334.   wSize            = sizeof(BITMAPINFOHEADER);  
  335.   if ((pRsrc = (PSTR)malloc(wSize)) == NULL)
  336.     Fatal("Unable to allocate memory for Resource Entry");
  337.     
  338.   for (wCntr = 0; wCntr < wEntries; wCntr++)
  339.   {
  340.     pre  = (re + wCntr);                     /*Set to curent Resource entry */
  341.     lOfs = (long)pre->wOffset << wShiftCount;/*Calculate offset to seek to  */
  342.     lseek(gfhInFile, lOfs,  SEEK_SET);  
  343.     read(gfhInFile,  pRsrc, wSize);
  344.     if (wCntr >= gwNames)
  345.     {
  346.       pExt = strrchr(gszFileName, '.');
  347.       nEnd = strlen(gszFileName) - strlen(pExt);
  348.       if (nEnd > 5)
  349.         nEnd = 5;
  350.       strncpy(szFileName, gszFileName, nEnd);
  351.       szFileName[nEnd] = '\0';
  352.       sprintf(szBuf, "%.3d", wCntr);
  353.       strcat(szFileName, szBuf);
  354.     }
  355.     else
  356.       strcpy(szFileName, gIconNames[wCntr]);
  357.     strcat(szFileName, ".ICO");
  358.     if ((gfhOutFile= open(szFileName, O_BINARY | O_CREAT | O_TRUNC | O_WRONLY,
  359.          S_IREAD  | S_IWRITE)) == -1)
  360.     {
  361.       printf("Could Not Create file %s\n", szFileName);
  362.       Fatal("File IO Error");
  363.     }
  364.     write(gfhOutFile, (PSTR)&icoHdr, sizeof(icoHdr));
  365.     WriteIconDIB((PBITMAPINFOHEADER)pRsrc);
  366.     close(gfhOutFile);
  367.   }
  368.   free(pRsrc);
  369. }
  370. /***************************************************************************/
  371. /***************************************************************************/
  372. void GetResourceNames(long lOfs)
  373. {
  374.   RESNAMES ResNames;
  375.   char     Buff[3];
  376.   WORD     wNbr,
  377.            wLen,
  378.            wCntr = 0;
  379.   char     Name[100];
  380.   
  381.   lseek(gfhInFile, lOfs, SEEK_SET);
  382.   gwNames = 0;
  383.   read(gfhInFile, &ResNames, sizeof(ResNames));
  384.   while (ResNames.wLen)
  385.   {
  386.     wCntr++;
  387.     ResNames.wLen -= 8;
  388.     read(gfhInFile, Buff, 2);
  389.     wNbr = *(WORD *)Buff;
  390.     if (!(ResNames.wType & 0x8000))
  391.       read(gfhInFile, Buff, 1);
  392.     read(gfhInFile, &Name, ResNames.wLen + 1);
  393.     if ((ResNames.wType & 0x7FFF) == RS_ICONDIR)
  394.     { 
  395.       wLen = strlen(Name);
  396.       if (wLen > 8)
  397.         wLen = 8;
  398.       strncpy(gIconNames[gwNames], Name, wLen);
  399.       gIconNames[gwNames][wLen] = '\0';
  400.       if (gwNames++ == 1000)
  401.         Fatal("To Many Icons In This File");
  402.     }    
  403.     read(gfhInFile, &ResNames, sizeof (RESNAMES));
  404.   }
  405. }
  406. /***************************************************************************/
  407. /***************************************************************************/
  408. void WriteIconDIB(PBITMAPINFOHEADER pRsrc)
  409. {
  410.   RGBQUAD  *pRgb;
  411.   WORD     wSize;
  412.   PSTR     pImage;
  413.   ICODIR   icoDir;
  414.   WORD     wColors;
  415.   WORD     wXORSize;
  416.   WORD     wANDSize;
  417.   
  418.   if (pRsrc->biSize != sizeof(BITMAPINFOHEADER))
  419.     printf("Conatins An Old Icon Format\n");
  420.   else
  421.   {
  422.     wColors = DIBNumColors((WORD)pRsrc->biClrUsed,pRsrc->biBitCount);
  423.     icoDir.byWidth     = (BYTE)pRsrc->biWidth;
  424.     icoDir.byHeight    = (BYTE)pRsrc->biHeight / 2;
  425.     icoDir.byColors    = (BYTE)wColors;
  426.     icoDir.byReserved1 = 0x00;               
  427.     icoDir.wReserved2  = (WORD)pRsrc->biPlanes;
  428.     icoDir.wReserved3  = (WORD)pRsrc->biBitCount;
  429.     wANDSize           = (WORD)(icoDir.byWidth * (icoDir.byHeight / 2)) >> 3;
  430.     if (pRsrc->biBitCount > 1)
  431.       wXORSize         = wANDSize * pRsrc->biBitCount;
  432.     else
  433.       wXORSize         = wANDSize * pRsrc->biPlanes;
  434.     pRsrc->biSizeImage = (long)(wANDSize +  wXORSize); 
  435.     icoDir.dwDIBSize   = pRsrc->biSizeImage + pRsrc->biSize + 
  436.                          wColors * sizeof(RGBQUAD);
  437.     icoDir.dwDIBOfs    = sizeof(ICOHDR) + sizeof(ICODIR);    
  438.     pRsrc->biClrUsed   = wColors;
  439.     write(gfhOutFile, (PSTR)&icoDir, sizeof(ICODIR));
  440.     write(gfhOutFile, (PSTR)pRsrc, (WORD)pRsrc->biSize);
  441.     wSize = (WORD)pRsrc->biClrUsed * sizeof(RGBQUAD);
  442.     if ((pRgb = (RGBQUAD *)malloc(wSize)) == NULL)
  443.       Fatal("Unable to allocate memory for Color Table");
  444.     read (gfhInFile, (PSTR)pRgb, wSize);
  445.     write(gfhOutFile, (PSTR)pRgb, wSize);
  446.     free(pRgb);
  447.     if ((pImage = (PSTR)malloc((WORD)pRsrc->biSizeImage)) == NULL)
  448.       Fatal("Unable to allocate memory for Icon Image");
  449.     read (gfhInFile, pImage, (WORD)pRsrc->biSizeImage);
  450.     write(gfhOutFile, pImage, (WORD)pRsrc->biSizeImage);
  451.     free(pImage);
  452.   }
  453. }
  454. /***************************************************************************/
  455. /***************************************************************************/
  456. WORD DIBNumColors(WORD wClrUsed, WORD wBitCount)
  457. {
  458.   if(wClrUsed)
  459.     return wClrUsed;
  460.  
  461.   switch(wBitCount)
  462.   {
  463.     case 1  : return   2;
  464.     case 3  : return   8;
  465.     case 4  : return  16;
  466.     case 8  : return 256;
  467.     default : return  16;
  468.   }
  469. }
  470. /***************************************************************************/
  471. /***************************************************************************/
  472. void ConvertToPM(void)
  473. {
  474.   char                  szFileName[13];
  475.   int                   nLen;
  476.   ICOHDR                icoHdr;
  477.   BITMAPINFOHEADER      Bmi;
  478.   ICODIR                icoDir;
  479.   PSTR                  pXORBits;
  480.   PSTR                  pANDBits;
  481.   RGBQUAD               *pRGB;
  482.   WORD                  wANDSize;
  483.   WORD                  wXORSize;
  484.   WORD                  wSize;
  485.   BITMAPARRAYFILEHEADER bafhHdr;
  486.   OS2_BITMAPFILEHEADER  bfhHdr;
  487.   WORD                  wColors;
  488.   char                  MonoRGBDefaults[]= {0x00,0x00,0x00,0xFF,0xFF,0xFF};
  489.   WORD                  wCntr;
  490.   
  491.   
  492.   read(gfhInFile, (PSTR)&icoHdr, sizeof(icoHdr));
  493.   if (icoHdr.wReserved != 0x0000 && icoHdr.wType != 0x0001)
  494.   {
  495.     printf("Invalid Windows ICO File Format\n");
  496.     return;
  497.   }
  498.   nLen = strlen(gszFileName);
  499.   if (nLen > 12)
  500.     nLen = 12;
  501.   strncpy(szFileName, gszFileName, nLen);
  502.   szFileName[nLen - 1] = 'P';
  503.   szFileName[nLen]     = '\0';
  504.   if ((gfhOutFile = open(szFileName, O_BINARY | O_CREAT | O_TRUNC | O_WRONLY,
  505.                                      S_IREAD  | S_IWRITE)) == -1)
  506.   {
  507.     printf("Could Not Create file %s\n", szFileName);
  508.     Fatal("File IO Error");
  509.   }
  510.   if (icoHdr.wCount > 1)
  511.     printf("%d Images Found : Only Writing 1 - ", icoHdr.wCount);  
  512.   printf("Converting To File %s\n", szFileName);
  513.   
  514.   read(gfhInFile, (PSTR)&icoDir, sizeof(icoDir));  
  515.   lseek(gfhInFile, icoDir.dwDIBOfs, SEEK_SET);
  516.   read(gfhInFile, (PSTR)&Bmi, sizeof(Bmi));
  517.   wColors = DIBNumColors((WORD)Bmi.biClrUsed, Bmi.biBitCount);
  518.   wSize   = wColors * sizeof(RGBQUAD);
  519.   if ((pRGB = (RGBQUAD *)malloc(wSize)) == NULL)
  520.     Fatal("Unable To Allocate Color Table");
  521.   read(gfhInFile, (PSTR)pRGB, wSize);
  522.   wANDSize = (WORD)(Bmi.biWidth * (Bmi.biHeight / 2)) >> 3;
  523.   if (Bmi.biBitCount > 1)
  524.     wXORSize = wANDSize * Bmi.biBitCount;
  525.   else
  526.     wXORSize = wANDSize * Bmi.biPlanes;
  527.   
  528.   if ((pXORBits = (PSTR) malloc(wXORSize)) == NULL)
  529.     Fatal("Unable To Allocate Memory For XOR Bit Map");
  530.   if ((pANDBits = (PSTR) malloc(wANDSize)) == NULL)
  531.     Fatal("Unable To Allocate Memory For AND Bit Map");    
  532.   read(gfhInFile, pXORBits, wXORSize); 
  533.   read(gfhInFile, pANDBits, wANDSize);  
  534.     
  535.   bafhHdr.usType            = BFT_BITMAPARRAY;
  536.   bafhHdr.cbSize            = sizeof(bafhHdr);
  537.   bafhHdr.offNext           = 0L;
  538.   bafhHdr.cxDisplay         = 0;
  539.   bafhHdr.cyDisplay         = 0;
  540.   bafhHdr.bfh.usType        = BFT_COLORICON;
  541.   bafhHdr.bfh.cbSize        = sizeof(bafhHdr.bfh);
  542.   bafhHdr.bfh.xHotspot      = 0;
  543.   bafhHdr.bfh.yHotspot      = 0;
  544.   bafhHdr.bfh.offBits       = sizeof(bafhHdr) + sizeof(bfhHdr) + 
  545.                               (2  +  wColors) * sizeof(RGB);
  546.   bafhHdr.bfh.bmp.cbFix     = sizeof(bafhHdr.bfh.bmp);
  547.   bafhHdr.bfh.bmp.cx        = (WORD)Bmi.biWidth;
  548.   bafhHdr.bfh.bmp.cy        = (WORD)Bmi.biHeight;
  549.   bafhHdr.bfh.bmp.cPlanes   = 1;
  550.   bafhHdr.bfh.bmp.cBitCount = 1;
  551.   
  552.   bfhHdr.usType        = BFT_COLORICON;
  553.   bfhHdr.cbSize        = sizeof(bfhHdr);
  554.   bfhHdr.xHotspot      = 0;
  555.   bfhHdr.yHotspot      = 0;
  556.   bfhHdr.offBits       = bafhHdr.bfh.offBits  + wANDSize * 2;
  557.  
  558.   bfhHdr.bmp.cbFix     = sizeof(bfhHdr.bmp);
  559.   bfhHdr.bmp.cx        = (WORD)Bmi.biWidth;
  560.   bfhHdr.bmp.cy        = (WORD)Bmi.biHeight / 2;
  561.   bfhHdr.bmp.cPlanes   = 1;
  562.   if (Bmi.biBitCount > 1)
  563.     bfhHdr.bmp.cBitCount = Bmi.biBitCount;
  564.   else
  565.     bfhHdr.bmp.cBitCount = Bmi.biPlanes;
  566.   
  567.   write(gfhOutFile, (PSTR)&bafhHdr,         sizeof(bafhHdr));
  568.   write(gfhOutFile, (PSTR)MonoRGBDefaults,  sizeof(MonoRGBDefaults));
  569.   write(gfhOutFile, (PSTR)&bfhHdr,          sizeof(bfhHdr));
  570.   for (wCntr = 0; wCntr < wColors; wCntr++)
  571.     write(gfhOutFile, (PSTR)(pRGB + wCntr), sizeof(RGB)); 
  572.   write(gfhOutFile, pANDBits, wANDSize);
  573.   write(gfhOutFile, pANDBits, wANDSize);
  574.   write(gfhOutFile, pXORBits, wXORSize);
  575.   free(pANDBits);
  576.   free(pXORBits);
  577.   free(pRGB);  
  578.   close(gfhOutFile);
  579. }
  580.  
  581. /***************************************************************************/
  582. /***************************************************************************/
  583. void ConvertToWin(void)
  584. {
  585.   BITMAPARRAYFILEHEADER bafh;
  586.   OS2_BITMAPFILEHEADER  bfh;
  587.   BYTE                  Done = FALSE;
  588.   char                  szFileName[13];
  589.   int                   nLen;
  590.   ICOHDR                icoHdr;
  591.   BITMAPINFOHEADER      Bmi;
  592.   ICODIR                icoDir;
  593.   PSTR                  pXORBits;
  594.   PSTR                  pANDBits;
  595.   RGB                   *pRGB;
  596.   WORD                  wANDSize;
  597.   WORD                  wXORSize;
  598.   WORD                  wSize;
  599.   WORD                  wColors;
  600.   WORD                  wCntr;
  601.   RGBQUAD               RGBQ;
  602.   WORD                  wIndex = 0;
  603.   char                  szBuf[3];
  604.   char                  *pExt;
  605.   
  606.   printf("Dimensions: ");
  607.   bafh.offNext = 0L;
  608.   while(!Done)
  609.   {    
  610.     lseek(gfhInFile, bafh.offNext, SEEK_SET);
  611.     read(gfhInFile, (PSTR)&bafh, sizeof(bafh));     
  612.     if (bafh.usType != 0x4142)
  613.     {
  614.       printf("Invalid PM ICO Format\n");
  615.       return;
  616.     }
  617.     wSize = 2 * sizeof(RGB);
  618.     lseek(gfhInFile, (long)wSize, SEEK_CUR);
  619.     read(gfhInFile, (PSTR)&bfh, sizeof(bfh));
  620.     printf("%.2dx%.2d", bfh.bmp.cx, bfh.bmp.cy);
  621.     if (bfh.bmp.cx <= 32 && bfh.bmp.cy <= 32)
  622.     {
  623.       printf("* ");
  624.       icoHdr.wReserved = 0x0000;
  625.       icoHdr.wType     = 0x0001;
  626.       icoHdr.wCount    = 0x0001;
  627.       if (wIndex++ == 0)
  628.       {
  629.         nLen = strlen(gszFileName);
  630.         if (nLen > 12)          
  631.           nLen = 12;
  632.         strncpy(szFileName, gszFileName, nLen);        
  633.         szFileName[nLen - 1] = 'W';
  634.         szFileName[nLen]     = '\0';
  635.       }
  636.       else
  637.       {
  638.         pExt = strrchr(gszFileName, '.');
  639.         nLen = strlen(gszFileName) - strlen(pExt);
  640.         if (nLen > 6)
  641.           nLen = 6;
  642.         strncpy(szFileName, gszFileName, nLen);
  643.         szFileName[nLen] = '\0';
  644.         sprintf(szBuf, "%.2d", wIndex);
  645.         strcat(szFileName, szBuf);
  646.         strcat(szFileName, ".ICW");
  647.       }        
  648.       if ((gfhOutFile= open(szFileName, O_BINARY| O_CREAT| O_TRUNC| O_WRONLY,
  649.                                         S_IREAD | S_IWRITE)) == -1)
  650.       {
  651.         printf("Could Not Create file %s\n", szFileName);
  652.         Fatal("File IO Error");
  653.       }
  654.       write(gfhOutFile, (PSTR)&icoHdr, sizeof(icoHdr));
  655.       Bmi.biSize          = sizeof(Bmi);
  656.       Bmi.biWidth         = (DWORD)bafh.bfh.bmp.cx;
  657.       Bmi.biHeight        = (DWORD)bafh.bfh.bmp.cy;
  658.       Bmi.biPlanes        = bfh.bmp.cPlanes;
  659.       Bmi.biBitCount      = bfh.bmp.cBitCount;
  660.       Bmi.biCompression   = 0L;
  661.       Bmi.biXPelsPerMeter = 0L;
  662.       Bmi.biYPelsPerMeter = 0L;
  663.       wColors             = DIBNumColors(0, Bmi.biBitCount);
  664.       Bmi.biClrUsed       = wColors;
  665.       Bmi.biClrImportant  = 0;      
  666.       icoDir.byWidth      = (BYTE)Bmi.biWidth;
  667.       icoDir.byHeight     = (BYTE)Bmi.biHeight;
  668.       icoDir.byColors     = (BYTE)Bmi.biClrUsed;
  669.       icoDir.byReserved1  = 0x00;               
  670.       icoDir.wReserved2   = Bmi.biPlanes;
  671.       icoDir.wReserved3   = Bmi.biBitCount;
  672.       wANDSize            = (WORD)(bfh.bmp.cx * bfh.bmp.cy) >> 3;
  673.       if (Bmi.biBitCount > 1)
  674.         wXORSize          = wANDSize * Bmi.biBitCount;
  675.       else
  676.         wXORSize          = wANDSize * Bmi.biPlanes;
  677.       Bmi.biSizeImage     = (long)(wANDSize +  wXORSize); 
  678.       icoDir.dwDIBSize    = Bmi.biSizeImage + Bmi.biSize + wColors 
  679.                           * sizeof(RGBQUAD);
  680.       icoDir.dwDIBOfs     = sizeof(ICOHDR) + sizeof(ICODIR);
  681.       write(gfhOutFile, (PSTR)&icoDir, sizeof(ICODIR));
  682.       write(gfhOutFile, (PSTR)&Bmi, sizeof(Bmi));
  683.       wSize = wColors * sizeof(RGB);
  684.       if ((pRGB = (RGB *)malloc(wSize)) == NULL)
  685.         Fatal("Unable to allocate memory for Color Table");
  686.       read (gfhInFile, (PSTR)pRGB, wSize);
  687.       for (wCntr = 0; wCntr < wColors; wCntr++)
  688.       {
  689.         memcpy((PSTR)&RGBQ, (pRGB + wCntr), sizeof(RGB));
  690.         RGBQ.rgbReserved = 0x00;
  691.         write(gfhOutFile, (PSTR)&RGBQ, sizeof(RGBQ));
  692.       }      
  693.       free(pRGB);
  694.       if ((pANDBits = (PSTR)malloc(wANDSize)) == NULL)
  695.         Fatal("Unable to allocate memory for AND Bits");
  696.       if ((pXORBits = (PSTR)malloc(wXORSize)) == NULL)
  697.         Fatal("Unable to allocate memory for XOR Bits");      
  698.       lseek(gfhInFile, bafh.bfh.offBits, SEEK_SET);      
  699.       read(gfhInFile, pANDBits, wANDSize);
  700.       lseek(gfhInFile, bfh.offBits, SEEK_SET);
  701.       read(gfhInFile, pXORBits, wXORSize);
  702.       write(gfhOutFile, pXORBits, wXORSize);
  703.       write(gfhOutFile, pANDBits, wANDSize);
  704.       free(pXORBits);
  705.       free(pANDBits);
  706.       close(gfhOutFile);
  707.     }
  708.     else
  709.       printf(" ");
  710.    if (!bafh.offNext)
  711.      Done = TRUE;
  712.   }
  713.   printf("\n");
  714. }