/******************************************************************** Copyright (C) 2000 Bassoukos Tassos 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., 675 Mass Ave, Cambridge, MA 02139, USA. *********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #ifdef HAVE_ESD #include #endif #include "main.h" #include "pixmap.h" #include "guiprefs.h" #include "hldat.h" typedef struct { char awpx[4]; guint16 ver; guint16 pad2; guint32 pad1; guint32 one; guint32 width_real; guint32 height; guint32 width_bytes,b,c,d,data_size; guint8 r_trans,g_trans,b_trans,a_trans; guint32 numcolors; guint32 zero; guint8 numbits,f,g,h; guint16 has_trans,z; } HLHdr; static GList *hldat_files=NULL; static Icon *icon_number[MAX_ICON_NUM+1]; static void read_icon_names(HotlineFile *hf,int block){ char buf[2048]; guint16 int16; guint32 int32; int val,len,pos=32; int i,total=0,j; fseek(hf->file,32,SEEK_SET); for(j=0;j<=block;j++){ fread(&int32,4,1,hf->file); pos+=4; i=GUINT32_FROM_BE(int32); for(;i>0;i--){ fread(&int16,2,1,hf->file);pos+=2; if((val=GUINT16_FROM_BE(int16))!=0){ len=val; val=0; } else { fread(&int16,2,1,hf->file);pos+=2; val=GUINT16_FROM_BE(int16); fread(&int16,2,1,hf->file); pos+=2; len=GUINT16_FROM_BE(int16); } fread(buf,len,1,hf->file); pos+=len; buf[len]=0; if(j==block){ if(icon_number[val]==NULL){ printf(_("%d (%s) has no icon def!\n"),val,buf); } else { if(icon_number[val]->name==NULL && icon_number[val]->hf==hf) icon_number[val]->name=strdup(buf[0]==0?buf+1:buf); } } len=(4-(pos&3))&3; pos+=len; fread(buf,len,1,hf->file); total+=1; } } for(i=0;inumicons;i++) if(hf->icons[i].name==NULL && icon_number[hf->icons[i].number]->hf==hf){ sprintf(buf,"Unnamed icon %d",hf->icons[i].number); hf->icons[i].name=strdup(buf); } } static GdkImlibImage *get_image_for_icon(FILE *f,Icon *i,int min_width,int min_height,gboolean asis){ int j,x,y; HLHdr hdr; int numcolors,off_im=0,off_xpm=0; int read_width=0; int pixmap_width=0,pixmap_height=0; struct { guint8 r,g,b,pad; } colors[257]; GdkImlibImage *im; guint8 *fimage,*rimage,*imline; fseek(f,i->offset,SEEK_SET); fread(&hdr,64,1,f); if(strncmp(hdr.awpx,"AWPX",4)!=0) abort(); if(GUINT16_FROM_BE(hdr.ver)!=1) abort(); if(hdr.numbits!=8 && hdr.numbits!=32) abort(); hdr.has_trans=GUINT16_FROM_BE(hdr.has_trans); numcolors=GUINT32_FROM_BE(hdr.numcolors); read_width=GUINT32_FROM_BE(hdr.width_bytes); if((numcolors==0 &&hdr.numbits!=32)|| numcolors>257) printf("%05d %d %d %s (%d)\n",i->number,i->offset,i->size,i->name,numcolors); pixmap_width=i->width=GUINT32_FROM_BE(hdr.width_real); pixmap_height=i->height=GUINT32_FROM_BE(hdr.height); if(asis==FALSE){ if(i->width<=min_width){ off_xpm=0; off_im=(min_width-i->width)/2; i->width=min_width; } else { off_im=0; off_xpm=(i->width-min_width)/2; i->width=i->width-off_xpm; } if(i->heightheight=min_height; } else { off_im=0; off_xpm=0; } rimage=malloc(i->width*i->height*3); fimage=malloc(pixmap_width*pixmap_height*3); imline=malloc(read_width); /* colors & transparency */ if(hdr.numbits==8){ fread(&colors[0],4,numcolors,f); if(hdr.has_trans==0 && asis==FALSE){ hdr.r_trans=colors[numcolors].r=0xff; hdr.g_trans=colors[numcolors].g=0x00; hdr.b_trans=colors[numcolors].b=0xff; hdr.has_trans=1; } } if(hdr.has_trans!=0){ for(j=(i->width*i->height)*3;j>0;){ rimage[--j]=hdr.b_trans; rimage[--j]=hdr.g_trans; rimage[--j]=hdr.r_trans; } } /* read pixmap from disk */ j=0; if(hdr.numbits==8){ for(y=0;yheight/2-pixmap_height/2; for(y=0;ywidth;x++){ rimage[((y+j)*i->width+x)*3+0]=fimage[(y*pixmap_width+x-off_im+off_xpm)*3+0]; rimage[((y+j)*i->width+x)*3+1]=fimage[(y*pixmap_width+x-off_im+off_xpm)*3+1]; rimage[((y+j)*i->width+x)*3+2]=fimage[(y*pixmap_width+x-off_im+off_xpm)*3+2]; } } /* HACK: fscking gnome_stock demands that transparent areas must be 0xff00ff ... :-/ */ if((hdr.has_trans!=0) && (hdr.r_trans!=0xff || hdr.g_trans!=0 || hdr.b_trans!=0xff)){ /* printf("%d %d %s %d %d %d\n",i->number,hdr.has_trans,i->name,hdr.r_trans,hdr.g_trans,hdr.b_trans); */ for(j=0;j<(i->width*i->height)*3;j+=3){ if(rimage[j] ==0xff && rimage[j+1]==0x00 && rimage[j+2]==0xff){ rimage[j+2]=0xfe; } if(rimage[j] ==hdr.r_trans && rimage[j+1]==hdr.g_trans && rimage[j+2]==hdr.b_trans){ rimage[j]=0xff; rimage[j+1]=0; rimage[j+2]=0xff; } } hdr.r_trans=0xff; hdr.g_trans=0; hdr.b_trans=0xff; } im=gdk_imlib_create_image_from_data(rimage,NULL,i->width,i->height); if(hdr.has_trans!=0){ GdkImlibColor c; c.r=hdr.r_trans; c.g=hdr.g_trans; c.b=hdr.b_trans; gdk_imlib_set_image_shape(im,&c); /* printf("%s %d %d %d\n",i->name,hdr.r_trans,hdr.g_trans,hdr.b_trans); */ } free(rimage); free(fimage); free(imline); return im; } static void read_icon(FILE *f,Icon *i,int min_w,int min_h,gboolean as_is){ i->image=get_image_for_icon(f,i,min_w,min_h,as_is); gdk_imlib_render(i->image,i->image->rgb_width,i->image->rgb_height); i->pixmap=gdk_imlib_move_image(i->image); i->mask=gdk_imlib_move_mask(i->image); } static void check_hotline_dat(char *name){ HotlineFile *hf; FILE *f; char buf[1024]; guint32 int32; int num_blocks,j,i,pos,icon_block=-1; Icon *icon; struct { guint32 number; guint32 pad; guint32 size; guint32 offset; } item; struct { char type[4]; guint32 count; } hdr; if(name==NULL) return; f=fopen(name,"r"); if(f==NULL) return; fread(buf,1,32-4,f); fread(&int32,1,4,f); int32=GUINT32_FROM_BE(int32); fseek(f,int32+32,SEEK_SET); pos=ftell(f); fread(&int32,1,4,f); if(GUINT32_FROM_BE(int32)!=pos){ printf(_("%s: not in hotline.dat format.\n"),name); fclose(f); return; } hf=calloc(1,sizeof(HotlineFile)); hf->file=f; hf->filename=strdup(name); hf->sounds=NULL; hf->numsounds=0; hf->numicons=0; hf->icons=NULL; fread(&buf[0],8,1,f); fread(&int32,1,4,f); num_blocks=GUINT32_FROM_BE(int32); fread(buf,16*num_blocks,1,f); for(j=0;jnumicons=GUINT32_FROM_BE(hdr.count); hf->icons=calloc(hf->numicons,sizeof(Icon)); for(i=0,icon=hf->icons;inumicons;i++,icon++){ fread(&item,16,1,f); icon->name=NULL; icon->offset=GUINT32_FROM_BE(item.offset); icon->size=GUINT32_FROM_BE(item.size); icon->number=GUINT32_FROM_BE(item.number); icon->mask=NULL; icon->image=NULL; icon->pixmap=NULL; icon->hf=hf; if(icon_number[icon->number]==NULL) icon_number[icon->number]=icon; } icon_block=j; } else if(strncmp(hdr.type,"SOUN",4)==0){ hf->numsounds=GUINT32_FROM_BE(hdr.count); hf->sounds=malloc(sizeof(HFSound)*hf->numsounds); for(i=0;inumsounds;i++){ fread(&item,16,1,f); hf->sounds[i].offset=GUINT32_FROM_BE(item.offset); hf->sounds[i].size=GUINT32_FROM_BE(item.size); hf->sounds[i].number=GUINT32_FROM_BE(item.number); hf->sounds[i].esd_id=-1; hf->sounds[i].hf=hf; } } else { for(i=GUINT32_FROM_BE(hdr.count);i>0;i--) fread(buf,16,1,f); } } if(icon_block!=-1) read_icon_names(hf,icon_block); hldat_files=g_list_append(hldat_files,hf); } void init_hotline_dat(void){ int i; GList *gl; for(i=0;idata); } } static void ensure_icon(int num){ if(icon_number[num]==NULL || icon_number[num]->hf==NULL) return; if(icon_number[num]->image==NULL) read_icon(icon_number[num]->hf->file,icon_number[num],32,0,FALSE); } void get_icon_by_num(int num,GdkPixmap **image,GdkBitmap **mask,int *width){ num&=MAX_ICON_NUM; ensure_icon(num); if(icon_number[num]==NULL){ if(image!=NULL) *image=NULL; if(mask!=NULL) *mask=NULL; if(width!=NULL) *width=0; return; } if(image!=NULL) *image=icon_number[num]->pixmap; if(mask!=NULL) *mask=icon_number[num]->mask; if(width!=NULL) *width=icon_number[num]->width; } Icon *get_icon(int num){ num&=MAX_ICON_NUM; ensure_icon(num); return icon_number[num]; } GdkImlibImage *get_image_icon(int num,int min_w,int min_h,gboolean as_is){ Icon i; if(icon_number[num]==NULL || icon_number[num]->hf==NULL) return NULL; i=*icon_number[num]; return get_image_for_icon(i.hf->file,&i,min_w,min_h,as_is); } void get_image_of_icon(int num,GdkPixmap **image,GdkBitmap **mask){ GdkPixmap *im=NULL; GdkBitmap *ma=NULL; if(icon_number[num]!=NULL && icon_number[num]->hf!=NULL){ if(icon_number[num]->full_pixmap==NULL){ GdkImlibImage *im=get_image_icon(num,0,0,TRUE); if(im!=NULL){ gdk_imlib_render(im,im->rgb_width,im->rgb_height); icon_number[num]->full_pixmap=gdk_imlib_move_image(im); icon_number[num]->full_mask = gdk_imlib_move_mask(im); gdk_imlib_destroy_image(im); if(icon_number[num]->full_pixmap!=NULL) gdk_pixmap_ref(icon_number[num]->full_pixmap); if(icon_number[num]->full_mask!=NULL) gdk_bitmap_ref(icon_number[num]->full_mask); } } im=icon_number[num]->full_pixmap; ma=icon_number[num]->full_mask; } if(image!=NULL) *image=im; if(mask!=NULL) *mask=ma; } void load_all_icons(GtkWidget *progressbar){ float total=0,cur=0.0; int i; for(i=0;iheight<=18) { if(SMALL==TRUE && (icon_number[i]->width<=32)) func(icon_number[i],data); else if(SMALL==FALSE && icon_number[i]->width>32) func(icon_number[i],data); } } #ifndef HAVE_ESD void play_sound(HLSound id){} #else /* HAVE_ESD */ static HFSound *find_sound(HLSound id){ GList *gl; int i; HotlineFile *hf; for(gl=hldat_files;gl!=NULL;gl=gl->next){ hf=gl->data; for(i=0;inumsounds;i++) if(hf->sounds[i].number==id) return &hf->sounds[i]; } return NULL; } static void load_sound(HFSound *s){ struct { char awsn[4]; guint16 version; guint8 channels; guint8 bytes_per_sample; guint32 rate; guint32 sample_size1; guint32 zero[3]; guint32 sample_size2; } hdr; int esd_format=ESD_MONO|ESD_BITS8|ESD_STREAM|ESD_PLAY; int size,pos=0,len; char name[256],*sample; if(s->esd_id!=-1) return; size=s->size; sprintf(name,"hotline sample %d",s->number); fseek(s->hf->file,s->offset,SEEK_SET); fread(&hdr,sizeof(hdr),1,s->hf->file); if(strncmp(hdr.awsn,"AWSN",4)!=0){ fprintf(stderr,"Sample %d in %s: unknown format\n",s->number,s->hf->filename); return; } size=GUINT32_FROM_BE(hdr.sample_size1); if(size!=GUINT32_FROM_BE(hdr.sample_size2) || hdr.channels!=1 || hdr.bytes_per_sample!=1){ fprintf(stderr,"Sample %d in %s: unsupported.\n",s->number,s->hf->filename); return; } sample=malloc(size); fread(sample,size,1,s->hf->file); s->esd_id=esd_sample_cache(gnome_sound_connection,esd_format, GUINT32_FROM_BE(hdr.rate),size,name); while(size>0){ len=write(gnome_sound_connection,sample+pos,size); size-=len; pos+=len; if(len==-1) perror("load_sound:"); } if(esd_confirm_sample_cache(gnome_sound_connection)!=s->esd_id){ s->esd_id=-1; fprintf(stderr,"error sending sample %d from %s\n",s->number,s->hf->filename); } } void play_sound(HLSound id){ HFSound *s=find_sound(id); int a; if(s==NULL || guiprefs_check_play_sound(id)==0) return; if(gnome_sound_connection==-1) return; if(s->esd_id==-1) load_sound(s); a=0; if(s->esd_id!=-1) esd_sample_play(gnome_sound_connection,s->esd_id); a=1; } #endif