Files
amiwm-neo/libami/iconlib.c
Adrian Chadd 4162377f10 [libami] more compile warning fixes
* fix 32/64 bit int size printing stuff
* more if braces
2022-02-26 11:31:37 -08:00

581 lines
13 KiB
C

#include "libami.h"
#include "alloc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifndef AMIGAOS
#define WBDISK 1
#define WBDRAWER 2
#define WBTOOL 3
#define WBPROJECT 4
#define WBGARBAGE 5
#define WBDEVICE 6
#define WBKICK 7
#define WBAPPICON 8
#define WB_DISKMAGIC 0xe310
char *BumpRevision(char *newbuf, char *oldname)
{
char tmpbuf[32];
int n;
if(!strncmp(oldname, "copy_of_", 8)) {
sprintf(newbuf, "copy_2_of_%.*s", 20, oldname);
} else if(2==sscanf(oldname, "copy_%d_of_%30s", &n, tmpbuf)) {
sprintf(newbuf, "copy_%d_of_", n+1);
tmpbuf[30-strlen(newbuf)]='\0';
strcat(newbuf, tmpbuf);
} else {
sprintf(newbuf, "copy_of_%.*s", 22, oldname);
}
return newbuf;
}
BOOL DeleteDiskObject(char *name)
{
int res;
#ifdef HAVE_ALLOCA
char *infoname=alloca(strlen(name)+8);
#else
char *infoname=malloc(strlen(name)+8);
if(infoname==NULL)
return FALSE;
#endif
sprintf(infoname, "%s.info", name);
res=unlink(infoname)>=0;
#ifndef HAVE_ALLOCA
free(infoname);
#endif
return res;
}
char *FindToolType(char **toolTypeArray, char *typeName)
{
char *p;
while((p=*toolTypeArray++)) {
char *p2=typeName;
while(*p2)
if(ToUpper(*p2)!=ToUpper(*p))
break;
else { p2++; p++; }
if(!*p2) {
if(!*p) return p;
if(*p=='=') return p+1;
}
}
return NULL;
}
void FreeDiskObject(struct DiskObject *diskobj)
{
if(diskobj->do_Gadget.GadgetRender) free(diskobj->do_Gadget.GadgetRender);
if(diskobj->do_Gadget.SelectRender) free(diskobj->do_Gadget.SelectRender);
if(diskobj->do_DefaultTool) free(diskobj->do_DefaultTool);
if(diskobj->do_ToolTypes) {
char *p, **pp=diskobj->do_ToolTypes;
while((p=*pp++)) free(p);
free(diskobj->do_ToolTypes);
}
if(diskobj->do_DrawerData) free(diskobj->do_DrawerData);
if(diskobj->do_ToolWindow) free(diskobj->do_ToolWindow);
free(diskobj);
}
static UWORD getu16(char **p)
{
union { UWORD n; char b[2]; } v;
#ifdef LAME_ENDIAN
v.b[1]=*(*p)++;
v.b[0]=*(*p)++;
#else
v.b[0]=*(*p)++;
v.b[1]=*(*p)++;
#endif
return v.n;
}
static WORD get16(char **p)
{
union { WORD n; char b[2]; } v;
#ifdef LAME_ENDIAN
v.b[1]=*(*p)++;
v.b[0]=*(*p)++;
#else
v.b[0]=*(*p)++;
v.b[1]=*(*p)++;
#endif
return v.n;
}
static ULONG getu32(char **p)
{
union { ULONG n; char b[4]; } v;
#ifdef LAME_ENDIAN
v.b[3]=*(*p)++;
v.b[2]=*(*p)++;
v.b[1]=*(*p)++;
v.b[0]=*(*p)++;
#else
v.b[0]=*(*p)++;
v.b[1]=*(*p)++;
v.b[2]=*(*p)++;
v.b[3]=*(*p)++;
#endif
return v.n;
}
static LONG get32(char **p)
{
union { LONG n; char b[4]; } v;
#ifdef LAME_ENDIAN
v.b[3]=*(*p)++;
v.b[2]=*(*p)++;
v.b[1]=*(*p)++;
v.b[0]=*(*p)++;
#else
v.b[0]=*(*p)++;
v.b[1]=*(*p)++;
v.b[2]=*(*p)++;
v.b[3]=*(*p)++;
#endif
return v.n;
}
#define SANITYMAXLEN (1<<20)
static char *loadstring(FILE *f)
{
ULONG l;
char buf[4], *p=buf;
if(1!=fread(buf, 4, 1, f) || (l=getu32(&p))>SANITYMAXLEN || !(p=malloc(l)))
return NULL;
fread(p, 1, l, f);
return p;
}
static char **loadtooltypes(FILE *f)
{
LONG i, n;
char **p, buf[4], *tp=buf;
if(1!=fread(buf, 4, 1, f) || (n=(getu32(&tp)>>2))>SANITYMAXLEN ||
!(p=calloc(n, sizeof(char *))))
return NULL;
--n;
for(i=0; i<n; i++)
if(!(p[i]=loadstring(f))) {
while(--i>=0)
free(p[i]);
free(p);
return NULL;
}
return p;
}
#define MAXICONSIZE 2000
static struct Image *loadimage(FILE *f)
{
char buf[20], *p=buf;
WORD le, te, w, h, d;
int imgsz;
struct Image *im;
if(1!=fread(buf, 20, 1, f))
return NULL;
le=get16(&p); te=get16(&p); w=get16(&p); h=get16(&p); d=get16(&p);
if(w<=0 || w>MAXICONSIZE || h<=0 || h>MAXICONSIZE || d<1 || d>8)
return NULL;
imgsz=2*((w+15)>>4)*h*d;
if(!(im=malloc(imgsz+sizeof(struct Image))))
return NULL;
im->LeftEdge=le; im->TopEdge=te; im->Width=w; im->Height=h;
im->Depth=d; im->ImageData=(UWORD*)getu32(&p);
im->PlanePick=*p++; im->PlaneOnOff=*p++;
im->NextImage=(struct Image *)getu32(&p);
if(im->ImageData) {
im->ImageData=(UWORD *)(im+1);
fread(im->ImageData, 1, imgsz, f);
}
return im;
}
static struct Image *backfillimage(struct Image *im)
{
return NULL;
}
#define GETBITS(v,n) do{if(bits<(n)){if(!srclen--)return dst-dst0;data=(data\
<<8)|*src++;bits+=8;};v=(data>>(bits-(n)))&((1<<(n))-1);bits-=(n);}while(0)
static LONG unpack_rle(unsigned char *src, LONG srclen, char *dst, LONG dstlen,
int bpp, int comp)
{
char *dst0 = dst;
unsigned char *srcn = src+srclen;
int bits=0, data=0;
if(!comp) {
if(srclen>dstlen)
srclen = dstlen;
memcpy(dst, src, srclen);
return srclen;
}
while(dstlen>0) {
int code;
GETBITS(code, 8);
if(code&0x80) {
char rpt;
GETBITS(rpt, bpp);
code -= 0x100;
if((dstlen-=(1-code))<0)
break;
do { *dst++ = rpt; } while(code++);
} else {
if((dstlen-=(code+1))<0)
break;
do GETBITS(*dst++, bpp); while(code--);
}
}
if(src != srcn)
fprintf(stderr, "Warning: Left %d bytes unused.\n", (int) (srcn-src));
return dst-dst0;
}
static void decode_IMAG(unsigned char *buf, LONG len, int width, int height,
APTR *im)
{
struct {
int transp, ncolors, flags, bodycomp, palcomp, bpp;
int bodybytes, palbytes;
} hdr;
char *dbuf;
struct Image *ii;
if(len<10)
return;
hdr.transp = *buf++;
hdr.ncolors = (*buf++)+1;
hdr.flags = *buf++;
hdr.bodycomp = *buf++;
hdr.palcomp = *buf++;
hdr.bpp = *buf++;
hdr.bodybytes = ((buf[0]<<8)|(buf[1]))+1;
hdr.palbytes = ((buf[2]<<8)|(buf[3]))+1;
buf+=4;
len -= 10;
if(!(hdr.flags&1))
hdr.transp = -1;
if(!(hdr.flags&2))
hdr.ncolors = 0;
if(hdr.bodybytes > len)
hdr.bodybytes = len;
if(hdr.palbytes+hdr.bodybytes > len)
hdr.palbytes = len-hdr.bodybytes;
if(hdr.bodycomp>1 || hdr.palcomp>1)
return;
if((dbuf = malloc(sizeof(struct Image)+width*height+3*hdr.ncolors+3))==NULL)
return;
/* body */
if(unpack_rle(buf, hdr.bodybytes, dbuf+sizeof(struct Image), width*height,
hdr.bpp, hdr.bodycomp) != width*height) {
free(dbuf);
return;
}
/* palette */
if(unpack_rle(buf+hdr.bodybytes, hdr.palbytes,
dbuf+sizeof(struct Image)+width*height+3, 3*hdr.ncolors,
8, hdr.palcomp) != 3*hdr.ncolors) {
free(dbuf);
return;
}
if(*im != NULL)
free(*im);
*im = (APTR) (ii = (struct Image *)dbuf);
dbuf += sizeof(struct Image);
ii->ImageData = (UWORD *)dbuf;
dbuf += width*height;
*dbuf++ = hdr.transp;
*dbuf++ = hdr.ncolors-1;
*dbuf++ = hdr.flags;
ii->LeftEdge = ii->TopEdge = 0;
ii->Width = width;
ii->Height = height;
ii->Depth = -1;
ii->PlanePick = ii->PlaneOnOff = 0;
ii->NextImage = NULL;
return;
}
static void decode_glowicon(struct DiskObject *diskobj, char *glow, LONG len)
{
int imgno=0, gotface=0;
struct { char width, height; UWORD dunno1, dunno2; } face;
while(len>=8) {
ULONG id = getu32(&glow);
LONG clen = get32(&glow);
char *chunk = glow;
len -= 8;
if(clen<0)
clen = len;
if(clen>len)
break;
switch(id) {
case 0x46414345: /* FACE */
if(clen>=6) {
face.width = 1+*chunk++;
face.height = 1+*chunk++;
face.dunno1 = getu16(&chunk);
face.dunno2 = getu16(&chunk);
gotface = 1;
diskobj->do_Gadget.Width = face.width;
diskobj->do_Gadget.Height = face.height;
break;
}
break;
case 0x494d4147: /* IMAG */
if(!gotface || imgno>1)
break;
decode_IMAG((unsigned char *)chunk, clen, face.width, face.height,
(imgno++? &diskobj->do_Gadget.SelectRender :
&diskobj->do_Gadget.GadgetRender));
break;
}
if(clen&1)
clen++;
len -= clen;
glow += clen;
}
}
static struct DiskObject *int_load_do(char *filename)
{
FILE *f;
struct DiskObject *diskobj;
char buf[78], *p=buf;
int error=0;
if((f=fopen(filename, "r"))) {
if(1==fread(buf, 78, 1, f) &&
(diskobj=calloc(1, sizeof(struct DiskObject)))) {
diskobj->do_Magic=getu16(&p); diskobj->do_Version=getu16(&p);
if(diskobj->do_Magic!=WB_DISKMAGIC) {
free(diskobj);
return NULL;
}
diskobj->do_Gadget.NextGadget=(struct Gadget *)getu32(&p);
diskobj->do_Gadget.LeftEdge=get16(&p);
diskobj->do_Gadget.TopEdge=get16(&p);
diskobj->do_Gadget.Width=get16(&p); diskobj->do_Gadget.Height=get16(&p);
diskobj->do_Gadget.Flags=getu16(&p);
diskobj->do_Gadget.Activation=getu16(&p);
diskobj->do_Gadget.GadgetType=getu16(&p);
diskobj->do_Gadget.GadgetRender=(APTR)getu32(&p);
diskobj->do_Gadget.SelectRender=(APTR)getu32(&p);
diskobj->do_Gadget.GadgetText=(struct IntuiText *)getu32(&p);
diskobj->do_Gadget.MutualExclude=get32(&p);
diskobj->do_Gadget.SpecialInfo=(APTR)getu32(&p);
diskobj->do_Gadget.GadgetID=getu16(&p);
diskobj->do_Gadget.UserData=(APTR)getu32(&p);
diskobj->do_Type=*p; p+=2;
diskobj->do_DefaultTool=(char *)getu32(&p);
diskobj->do_ToolTypes=(char **)getu32(&p);
diskobj->do_CurrentX=get32(&p);
diskobj->do_CurrentY=get32(&p);
diskobj->do_DrawerData=(struct DrawerData *)getu32(&p);
diskobj->do_ToolWindow=(char *)getu32(&p);
diskobj->do_StackSize=get32(&p);
if(diskobj->do_DrawerData) {
struct DrawerData *dd;
if(1==fread(buf, 56, 1, f) &&
(diskobj->do_DrawerData=dd=calloc(1, sizeof(struct DrawerData)))) {
p=buf;
dd->dd_NewWindow.LeftEdge=get16(&p);
dd->dd_NewWindow.TopEdge=get16(&p);
dd->dd_NewWindow.Width=get16(&p);
dd->dd_NewWindow.Height=get16(&p);
dd->dd_NewWindow.DetailPen=*p++;
dd->dd_NewWindow.BlockPen=*p++;
dd->dd_NewWindow.IDCMPFlags=getu32(&p);
dd->dd_NewWindow.Flags=getu32(&p);
dd->dd_NewWindow.FirstGadget=(struct Gadget *)getu32(&p);
dd->dd_NewWindow.CheckMark=(struct Image *)getu32(&p);
dd->dd_NewWindow.Title=(UBYTE *)getu32(&p);
dd->dd_NewWindow.Screen=(struct Screen *)getu32(&p);
dd->dd_NewWindow.BitMap=(struct BitMap *)getu32(&p);
dd->dd_NewWindow.MinWidth=get16(&p);
dd->dd_NewWindow.MinHeight=get16(&p);
dd->dd_NewWindow.MaxWidth=getu16(&p);
dd->dd_NewWindow.MaxHeight=getu16(&p);
dd->dd_NewWindow.Type=getu16(&p);
dd->dd_CurrentX=get32(&p);
dd->dd_CurrentY=get32(&p);
} else error++;
}
if(!(diskobj->do_Gadget.GadgetRender=loadimage(f)))
error++;
if(diskobj->do_Gadget.Flags&2)
if(!(diskobj->do_Gadget.SelectRender=loadimage(f)))
error++;
else ;
else if(diskobj->do_Gadget.Flags&1)
if(!(diskobj->do_Gadget.SelectRender=
backfillimage((struct Image *)diskobj->do_Gadget.GadgetRender)))
error++;
else ;
else diskobj->do_Gadget.SelectRender=NULL;
if(diskobj->do_DefaultTool)
if(!(diskobj->do_DefaultTool=loadstring(f)))
error++;
if(diskobj->do_ToolTypes)
if(!(diskobj->do_ToolTypes=loadtooltypes(f)))
error++;
if(diskobj->do_ToolWindow)
if(!(diskobj->do_ToolWindow=loadstring(f)))
error++;
if(diskobj->do_DrawerData && diskobj->do_Version) {
char buf[6], *p=buf;
if(1==fread(buf, 6, 1, f)) {
diskobj->do_DrawerData->dd_Flags=getu32(&p);
diskobj->do_DrawerData->dd_ViewModes=getu16(&p);
}
}
if(diskobj->do_Version) {
/* Check for GlowIcon */
char buf[8], *p = buf, *glowicon;
LONG len;
if(1==fread(buf, 4, 1, f) && !strncmp(buf, "FORM", 4) &&
1==fread(buf, 8, 1, f) && !strncmp(buf+4, "ICON", 4) &&
(len = get32(&p))>4 && (glowicon = malloc(len))!=NULL) {
if(1==fread(glowicon, len-4, 1, f))
decode_glowicon(diskobj, glowicon, len-4);
free(glowicon);
}
}
if(!error) {
fclose(f);
return diskobj;
}
FreeDiskObject(diskobj);
}
fclose(f);
}
return NULL;
}
struct DiskObject *GetDefDiskObject(LONG def_type)
{
static char *defnames[]= {
"disk", "drawer", "tool", "project",
"garbage", "device", "kick", "appicon"
};
static char *icondir=NULL;
static int l;
char *buf;
struct DiskObject *diskobj;
if(def_type<WBDISK || def_type>WBAPPICON)
return NULL;
if(!icondir) {
if(!(icondir = get_current_icondir())) {
return NULL;
} else {
l = strlen(icondir);
}
}
#ifdef HAVE_ALLOCA
buf = alloca(l+18);
#else
buf = malloc(l+18);
if(buf==NULL) return NULL;
#endif
sprintf(buf, "%s/def_%s.info", icondir, defnames[def_type-WBDISK]);
diskobj=int_load_do(buf);
#ifndef HAVE_ALLOCA
free(buf);
#endif
return diskobj;
}
struct DiskObject *GetDiskObject(char *name)
{
struct DiskObject *diskobj;
#ifdef HAVE_ALLOCA
char *buf = alloca(strlen(name)+6);
#else
char *buf = malloc(strlen(name)+6);
if(buf==NULL) return NULL;
#endif
sprintf(buf, "%s.info", name);
diskobj=int_load_do(buf);
#ifndef HAVE_ALLOCA
free(buf);
#endif
return diskobj;
}
struct DiskObject *GetDiskObjectNew(char *name)
{
struct DiskObject *d;
struct stat st;
if((d=GetDiskObject(name))) return d;
if(stat(name, &st)<0) return NULL;
if(S_ISREG(st.st_mode))
if(st.st_mode&0555)
return GetDefDiskObject(WBTOOL);
else
return GetDefDiskObject(WBPROJECT);
else if(S_ISDIR(st.st_mode))
return GetDefDiskObject(WBDRAWER);
else if(S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
return GetDefDiskObject(WBDEVICE);
else
return NULL;
}
#ifdef notdef
BOOL MatchToolValue(char *typeString, char *value)
{
}
BOOL PutDiskObject(char *name, struct DiskObject *diskobj)
{
}
#endif
#endif