mirror of
https://github.com/ctm/executor.git
synced 2025-01-06 19:31:44 +00:00
407 lines
10 KiB
C
407 lines
10 KiB
C
#include "go.h"
|
|
#include "display.h"
|
|
#include <assert.h>
|
|
|
|
#include "initicons.proto.h"
|
|
|
|
icontableentry **icontable[ICONTABLESIZE], g_foldericons, g_diskicons;
|
|
icontableentry *g_foldericonsptr, *g_diskiconsptr;
|
|
applist **sigowners[TEXTEDITORPOS + 1];
|
|
|
|
/* NOTE: the default doc must be the last item. Its type should really be special
|
|
cased, but it's the default anyway so if a document has a goofy filetype
|
|
it will get the correct information regardless.
|
|
*/
|
|
|
|
typeinfo typearray[] =
|
|
{
|
|
'ffil', FONTBAND, NOACTION, FONTICONNUM, 0,
|
|
'FFIL', FONTBAND, NOACTION, FONTSCICONNUM, 0,
|
|
'tfil', FONTBAND, NOACTION, TTFONTICONNUM, 0,
|
|
'dfil', DABAND, OPENDA, DAICONNUM, 0,
|
|
'DFIL', DABAND, OPENDA, DASCICONNUM, 0,
|
|
'APPL', APPBAND, LAUNCH, DEFAULTAPPLICONNUM, 0,
|
|
'|!@$', DOCBAND, LAUNCHCREATOR, DEFAULTDOCICONNUM, 0,
|
|
};
|
|
|
|
ControlHandle
|
|
getnewiconcontrol (WindowPtr wp, char **path, long parid,
|
|
short vrefnum, Str255 s)
|
|
{
|
|
item **h;
|
|
Rect r;
|
|
ControlHandle c;
|
|
|
|
SetRect (&r, 0, 0, ICONWIDTHUSED, ICONHEIGHTUSED);
|
|
c = NewControl (wp, &r, s, false, 0, 0, 0, ICONCONTROL, 0);
|
|
h = (item **) NewHandle (sizeof (item));
|
|
(*h)->path = path;
|
|
(*h)->ioparid = parid;
|
|
(*h)->vrefnum = vrefnum;
|
|
(*h)->selected = false;
|
|
(*h)->view = ICONVIEW;
|
|
(*c)->contrlRfCon = 0L;
|
|
(*c)->contrlData = (Handle) h;
|
|
#ifdef THINK_C
|
|
(*c)->contrlAction = (ProcPtr) -1L;
|
|
#else
|
|
(*c)->contrlAction = (ControlActionUPP) -1L;
|
|
#endif
|
|
return c;
|
|
}
|
|
|
|
#define NOTFOUND -1
|
|
short
|
|
localidlookup (short localid, iconentry ** iconarray, short n)
|
|
{
|
|
short i;
|
|
|
|
for (i = 0; i < n; i++)
|
|
if ((*iconarray)[i].localid == localid)
|
|
/*-->*/ return i;
|
|
return NOTFOUND;
|
|
/* TODO: ALERT */
|
|
}
|
|
|
|
void
|
|
dobundle (short *spacemade, iconentry *** iconarray, char **h)
|
|
{
|
|
/* todo: get rid of the *h += n stuff and make a datatype */
|
|
short k, pos, numentries;
|
|
ResType type;
|
|
identry *idarray;
|
|
Handle h2;
|
|
|
|
type = *(OSType *) *h;
|
|
*h += 4;
|
|
numentries = *(short *) *h + 1;
|
|
*h += 2;
|
|
if (*spacemade == 0)
|
|
{
|
|
*iconarray = (iconentry **) NewHandle (numentries * sizeof (iconentry));
|
|
*spacemade = numentries;
|
|
idarray = (identry *) *h;
|
|
if (type == 'ICN#')
|
|
{
|
|
for (k = 0; k < numentries; k++)
|
|
{
|
|
(**iconarray)[k].resid = idarray[k].resid;
|
|
(**iconarray)[k].localid = idarray[k].localid;
|
|
}
|
|
}
|
|
else if (type == 'FREF')
|
|
{
|
|
for (k = 0; k < numentries; k++)
|
|
{
|
|
h2 = (Handle) Get1Resource ('FREF', idarray[k].resid);
|
|
(**iconarray)[k].type = *(OSType *) *h2;
|
|
(**iconarray)[k].localid = *(short *) (*h2 + 4);
|
|
ReleaseResource (h2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* there shouldn't be any other types */
|
|
assert (0);
|
|
/* ALERT */
|
|
}
|
|
*h += numentries * sizeof (identry);
|
|
}
|
|
else
|
|
{
|
|
#if 0
|
|
/* todo: find out if this assert can ever fail */
|
|
/* It can, but the code should work anyways. This should be looked into further. */
|
|
assert (*spacemade == numentries);
|
|
#endif /* 0 */
|
|
idarray = (identry *) * h;
|
|
if (type == 'ICN#')
|
|
{
|
|
for (k = 0; k < numentries; k++)
|
|
{
|
|
pos = localidlookup (idarray[k].localid, *iconarray, numentries);
|
|
if (pos != NOTFOUND)
|
|
(**iconarray)[pos].resid = idarray[k].resid;
|
|
}
|
|
}
|
|
else if (type == 'FREF')
|
|
{
|
|
for (k = 0; k < numentries; k++)
|
|
{
|
|
/*
|
|
* It is my understanding the first two bytes mean nothing. IMVI says they must be
|
|
* unique, but doesn't use them, but keeps them in for backwards compatibility. They
|
|
* are local fref ids
|
|
*/
|
|
h2 = (Handle) Get1Resource ('FREF', idarray[k].resid);
|
|
pos = localidlookup (*(short *) (*h2 + 4), *iconarray, numentries);
|
|
if (pos != NOTFOUND)
|
|
(**iconarray)[pos].type = *(ResType *) * h2;
|
|
ReleaseResource (h2);
|
|
}
|
|
}
|
|
else
|
|
/* there shouldn't be any other types */
|
|
assert (0);
|
|
*h += numentries * sizeof (identry);
|
|
}
|
|
}
|
|
#undef NOTFOUND
|
|
|
|
typeinfo *
|
|
gettypeinfo (OSType type)
|
|
{
|
|
short i;
|
|
|
|
for (i = 0; i < NELEM (typearray); i++)
|
|
if (type == typearray[i].filetype)
|
|
return &typearray[i];
|
|
return &typearray[NELEM (typearray) - 1];
|
|
}
|
|
|
|
void
|
|
geticons (icontableentry ** node, short id)
|
|
{
|
|
Handle h;
|
|
|
|
#define geticonhandle(field, type) \
|
|
h = (Handle) Get1Resource(type, id); \
|
|
HandToHand(&h); \
|
|
(*node)->field = h;
|
|
|
|
geticonhandle (icnsh, 'ICN#');
|
|
geticonhandle (icssh, 'ics#');
|
|
geticonhandle (icl8, 'icl8');
|
|
geticonhandle (icl4, 'icl4');
|
|
geticonhandle (ics8, 'ics8');
|
|
geticonhandle (ics4, 'ics4');
|
|
|
|
#undef geticonhandle
|
|
}
|
|
|
|
void
|
|
inithash (void)
|
|
{
|
|
short i;
|
|
icontableentry **node;
|
|
|
|
g_foldericonsptr = &g_foldericons;
|
|
g_foldericons.sig = (OSType) 0;
|
|
g_foldericons.type = (OSType) 0;
|
|
g_foldericons.next = 0;
|
|
geticons (&g_foldericonsptr, FOLDERICONNUM);
|
|
|
|
g_diskiconsptr = &g_diskicons;
|
|
g_diskicons.sig = (OSType) 0;
|
|
g_diskicons.type = (OSType) 0;
|
|
g_diskicons.next = 0;
|
|
geticons (&g_diskiconsptr, DISKICONNUM);
|
|
|
|
for (i = 0; i < ICONTABLESIZE; i++)
|
|
icontable[i] = 0;
|
|
for (i = 0; i < NELEM (typearray); i++)
|
|
{
|
|
node = (icontableentry **) NewHandle (sizeof (icontableentry));
|
|
(*node)->sig = (OSType) 0;
|
|
(*node)->type = typearray[i].filetype;
|
|
(*node)->next = 0;
|
|
geticons (node, typearray[i].iconid);
|
|
typearray[i].iconh = node;
|
|
}
|
|
for (i = 0; i < SIGARRAYSIZE; i++)
|
|
sigowners[i] = 0;
|
|
}
|
|
|
|
icontableentry **
|
|
gethash (OSType type, OSType creator)
|
|
{
|
|
unsigned short hashval;
|
|
icontableentry **np;
|
|
|
|
hashval = ((unsigned long) type + (unsigned long) creator) % ICONTABLESIZE;
|
|
for (np = icontable[hashval]; np != 0; np = (*np)->next)
|
|
{
|
|
if (((*np)->type == type) && ((*np)->sig == creator))
|
|
return np;
|
|
}
|
|
|
|
return gettypeinfo (type)->iconh;
|
|
}
|
|
|
|
void
|
|
hashicons (ControlHandle c)
|
|
{
|
|
/* todo: worry about filenames in FREFs */
|
|
/* get FREF, BNDL, ICN#, ics#, icl8, ics8, icl4, ics4 */
|
|
/* BNDL is:
|
|
4 bytes of signature
|
|
2 bytes of 0 [signature resource id?]
|
|
2 bytes of <number of main entries - 1> (almost always 1)
|
|
numberofmainentries *
|
|
4 bytes of 'ICN#' or 'FREF'
|
|
2 bytes of <number of entries - 1>
|
|
numberofentries *
|
|
2 bytes of localid
|
|
2 bytes of resid
|
|
*/
|
|
/* todo: see what happens with multiple BNDLs */
|
|
|
|
char *p;
|
|
short i, j, spacemade, nummain, numbndls;
|
|
unsigned short hashval;
|
|
iconentry **iconarray;
|
|
icontableentry **node;
|
|
Handle h;
|
|
OSType signature;
|
|
short refnum, sigid;
|
|
unsigned char state;
|
|
applist **ah;
|
|
|
|
refnum = openappres (c);
|
|
numbndls = Count1Resources ('BNDL');
|
|
for (i = 1; i <= numbndls; i++)
|
|
{
|
|
h = (Handle) Get1IndResource ('BNDL', i);
|
|
state = HGetState (h);
|
|
HLock (h);
|
|
p = *h;
|
|
signature = *(OSType *) p;
|
|
p += 4;
|
|
sigid = *(short *) p;
|
|
p += 2;
|
|
|
|
hashval = (unsigned long) signature % SIGARRAYSIZE;
|
|
#define CONTROLPROBLEMS
|
|
#ifndef CONTROLPROBLEMS
|
|
for (ah = sigowners[hashval]; ah != 0 && (*ah)->sig != signature; ah = (*ah)->next)
|
|
;
|
|
if (ah == 0)
|
|
{
|
|
#endif /* CONTROLPROBLEMS */
|
|
ah = sigowners[hashval];
|
|
sigowners[hashval] = (applist **) NewHandle (sizeof (applist));
|
|
(*sigowners[hashval])->next = ah;
|
|
(*sigowners[hashval])->parid = (*(item **) (*c)->contrlData)->ioparid;
|
|
(*sigowners[hashval])->vrefnum = (*(item **) (*c)->contrlData)->vrefnum;
|
|
(*sigowners[hashval])->sig = signature;
|
|
mystr255copy ((*sigowners[hashval])->name, (*c)->contrlTitle);
|
|
#ifndef CONTROLPROBLEMS
|
|
}
|
|
#endif /* CONTROLPROBLEMS */
|
|
|
|
/* todo: find out if nummain must == 2 */
|
|
nummain = *(short *) p + 1;
|
|
p += 2;
|
|
|
|
spacemade = 0;
|
|
for (j = 0; j < nummain; j++)
|
|
{
|
|
dobundle (&spacemade, &iconarray, &p);
|
|
}
|
|
|
|
for (j = 0; j < spacemade; j++)
|
|
{
|
|
hashval = ((unsigned long) signature + (unsigned long) (*iconarray)[j].type)
|
|
% ICONTABLESIZE;
|
|
for (node = icontable[hashval]; node != 0 &&
|
|
((*node)->sig != signature || (*node)->type != (*iconarray)[j].type);
|
|
node = (*node)->next)
|
|
;
|
|
if (node == 0)
|
|
{
|
|
node = (icontableentry **) NewHandle (sizeof (icontableentry));
|
|
(*node)->sig = signature;
|
|
(*node)->type = (*iconarray)[j].type;
|
|
(*node)->next = icontable[hashval];
|
|
geticons (node, (*iconarray)[j].resid);
|
|
icontable[hashval] = node;
|
|
}
|
|
}
|
|
DisposHandle ((Handle) iconarray);
|
|
HSetState (h, state);
|
|
ReleaseResource (h);
|
|
}
|
|
CloseResFile (refnum);
|
|
}
|
|
|
|
void
|
|
setoneicon (ControlHandle c)
|
|
{
|
|
CInfoPBRec pb;
|
|
item **ih;
|
|
typeinfo *tip;
|
|
|
|
ih = (item **) (*c)->contrlData;
|
|
pb.hFileInfo.ioFDirIndex = 0;
|
|
pb.hFileInfo.ioVRefNum = (*ih)->vrefnum;
|
|
pb.hFileInfo.ioDirID = (*ih)->ioparid;
|
|
pb.hFileInfo.ioNamePtr = (*c)->contrlTitle;
|
|
PBGetCatInfo (&pb, false);
|
|
if (pb.hFileInfo.ioFlAttrib & DIRBIT)
|
|
{
|
|
(*ih)->iconfam = &g_foldericonsptr;
|
|
(*ih)->action = OPENDIR;
|
|
(*ih)->size = 0;
|
|
(*ih)->moddate = pb.dirInfo.ioDrMdDat;
|
|
}
|
|
else
|
|
{
|
|
(*ih)->iconfam = gethash (pb.hFileInfo.ioFlFndrInfo.fdType,
|
|
pb.hFileInfo.ioFlFndrInfo.fdCreator);
|
|
tip = gettypeinfo (pb.hFileInfo.ioFlFndrInfo.fdType);
|
|
(*ih)->action = tip->action;
|
|
(*ih)->size = pb.hFileInfo.ioFlLgLen;
|
|
(*ih)->moddate = pb.hFileInfo.ioFlMdDat;
|
|
}
|
|
}
|
|
|
|
void
|
|
seticons (void)
|
|
{
|
|
bandinfo *b;
|
|
short i, j;
|
|
|
|
b = &bands[VOLBAND];
|
|
for (i = 0; i < b->numitems; i++)
|
|
(*(item **) (*(**b->items)[i])->contrlData)->iconfam = &g_diskiconsptr;
|
|
b = &bands[FOLDERBAND];
|
|
for (i = 0; i < b->numitems; i++)
|
|
(*(item **) (*(**b->items)[i])->contrlData)->iconfam = &g_foldericonsptr;
|
|
for (i = 0; i < NUMBANDS; i++)
|
|
if (i != VOLBAND && i != FOLDERBAND)
|
|
{
|
|
b = &bands[i];
|
|
for (j = 0; j < b->numitems; j++)
|
|
setoneicon ((**b->items)[j]);
|
|
}
|
|
}
|
|
|
|
short
|
|
openappres (ControlHandle c)
|
|
{
|
|
/* TODO: check error conditions */
|
|
WDPBRec wdpb;
|
|
short refnum;
|
|
short resloadval;
|
|
|
|
wdpb.ioVRefNum = (*(item **) (*c)->contrlData)->vrefnum;
|
|
wdpb.ioWDDirID = (*(item **) (*c)->contrlData)->ioparid;
|
|
wdpb.ioWDProcID = 0;
|
|
wdpb.ioNamePtr = 0;
|
|
PBOpenWD (&wdpb, false);
|
|
#ifdef THINK_C
|
|
resloadval = ResLoad;
|
|
#else
|
|
resloadval = LMGetResLoad ();
|
|
#endif
|
|
SetResLoad (false);
|
|
refnum = OpenRFPerm ((*c)->contrlTitle, wdpb.ioVRefNum, fsRdPerm);
|
|
SetResLoad (resloadval);
|
|
PBCloseWD (&wdpb, false);
|
|
if (refnum == -1)
|
|
{
|
|
/* todo: alert */
|
|
}
|
|
return refnum;
|
|
}
|