/* This file is part of icobundle Copyright (C) 2003-7 Toby Thain, toby@telegraphics.com.au This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "file_io.h" #include "ico.h" #include "ico_io.h" #include "bundle.h" int bundle(int nfiles,FILEREF outfile){ FILEREF f; ICONDIR id; ICONDIRENTRY ide,*direntries=NULL,*pdir; BITMAPINFOHEADER bih; unsigned long pos,resbytes,iconoffset=0; long count; int i,j,a,e,pass,iconcount,valid,ispng; char *indata,s[0x100]; iconcount = valid = 0; for(pass = 1; pass <= 2; ++pass){ for(a = 1, j = 0; a <= nfiles; ++a){ if( (f = opennth(a)) ){ if(!read_icondir(f,&id)){ //if(id.idType != 1 && pass == 1) // fprintf(stderr,"## warning: idType = %d?\n",id.idType); for(i = 0, pos = FIRST_ICONDIRENTRY; i < id.idCount; pos += SIZEOF_ICONDIRENTRY, ++i) if( !SetFPos(f,fsFromStart,pos) && !read_icondirentry(f,&ide) && !SetFPos(f,fsFromStart,ide.dwImageOffset) ){ if( !read_bitmapinfoheader(f,&bih) ){ if( !(ispng = bih.biSize == PNG_MAGIC) ) resbytes = SIZEOF_BMIHEADER + sizeof(RGBQUAD)*(bih.biBitCount>8 ? 0 : (1<1?"s":""); #endif ++valid; }else{ if( (e = SetFPos(outfile,fsFromStart,iconoffset)) ){ bad("can't seek to output position"); }else{ if( (indata = malloc(ide.dwBytesInRes)) ){ count = ide.dwBytesInRes; if(SetFPos(f,fsFromStart,ide.dwImageOffset) || FSRead(f,&count,indata)) bad("can't read icon"); count = ide.dwBytesInRes; if(FSWrite(outfile,&count,indata)) bad("can't write icon"); free(indata); }else bad("can't get memory to read icon"); } ide.dwImageOffset = iconoffset; iconoffset += ide.dwBytesInRes; direntries[j] = ide; } ++j; /*fprintf(stderr,"## ERROR: dwBytesInRes should be %ld (not %ld)\n",resbytes,ide.dwBytesInRes)*/ ; }else if(pass == 1) bad("invalid BITMAPINFOHEADER; skipping icon"); }else{ if(pass == 1) bad("can't read BITMAPINFOHEADER; skipping file"); break; } }else{ if(pass == 1) bad("can't read ICONDIRENTRY; skipping file"); break; } }else if(pass == 1) bad("can't read ICONDIR"); FSClose(f); }else bad("can't open input file"); } if(pass == 1){ iconcount = j; if( !(direntries = calloc(iconcount,sizeof(ICONDIRENTRY))) ){ bad("can't calloc()!"); break; } SetFPos(outfile,fsFromStart,0); id.idReserved = 0; id.idType = IDTYPE_ICON; id.idCount = iconcount; if(write_icondir(outfile,&id)){ bad("can't write ICONDIR"); break; } /* write placeholder icon directory */ count = iconcount*(long)SIZEOF_ICONDIRENTRY; if(FSWrite(outfile,&count,direntries)){ bad("can't write icon directory"); break; } iconoffset = FIRST_ICONDIRENTRY + iconcount*(long)SIZEOF_ICONDIRENTRY; //fseek(outfile,iconoffset,SEEK_SET); } } if(pass == 3){ if(SetFPos(outfile,fsFromStart,FIRST_ICONDIRENTRY)) bad("can't seek to write first dir entry"); for(i = 0, pdir = direntries; i < iconcount; ++i){ //printf("ICONDIRENTRY[%2d] @%7ld (%7ld)\n",i,pdir->dwImageOffset,pdir->dwBytesInRes); if(write_icondirentry(outfile,pdir++)){ bad("can't write ICONDIRENTRY"); break; } } if(i == iconcount){ if(iconcount){ sprintf(s,"Bundled %d icons from %d input files.\n",valid,nfiles); note(s); }else note("No icons found, wrote empty icon suite"); return 1; } } return 0; }