home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
WIN_BMP
/
FRCICN13.ZIP
/
SUPPORT.C
< prev
Wrap
C/C++ Source or Header
|
1994-02-15
|
30KB
|
1,287 lines
/*
Auto: smake ForceIcon
*/
/* $Revision Header built automatically *************** (do not edit) ************
**
** ⌐ Copyright by GuntherSoft
**
** File : SnakeSYS:CPrgs/Utils/ForceIcon/Support.c
** Created on : Friday, 22.10.93 16:38:41
** Created by : Kai Iske
** Current revision : V1.0
**
**
** Purpose
** -------
** - Support-Routines for ForceIcon
**
** Revision V1.0
** --------------
** created on Friday, 22.10.93 16:38:41 by Kai Iske. LogMessage :
** --- Initial release ---
**
*********************************************************************************/
/**********************************************************************/
/* Routines for this module */
/**********************************************************************/
static UWORD ComputeX(UWORD value, UWORD FontX);
static UWORD ComputeY(UWORD value, UWORD FontY);
static void __stdargs ComputeFont(struct Screen *WorkScreen, UWORD width, UWORD height, struct TextAttr *Font, char *FontName, UWORD *OffX, UWORD *OffY, UWORD *FontX, UWORD *FontY);
static void SetGadShortCut(UWORD Type, struct NewGadget *NewGad);
static BOOL GetDosEntries(struct List *VolList, ULONG Mode);
static void SortPartialList(struct List *VolList, UWORD Left, UWORD Right);
/**********************************************************************/
/* External variables */
/**********************************************************************/
extern struct ExecBase *SysBase;
extern struct SignalSemaphore MySemaphore;
extern struct List VolumeList;
extern struct IClass *GetFileClass;
/**********************************************************************/
/* Global variables */
/**********************************************************************/
static struct RastPort ComputeRPort;
/**********************************************************************/
/* Vars for Busy-Pointer */
/**********************************************************************/
static UWORD __chip BusyPtr[] =
{
0x0000,0x0000,0x0400,0x07C0,0x0000,0x07C0,
0x0100,0x0380,0x0000,0x07E0,0x07C0,0x1FF8,
0x1FF0,0x3FEC,0x3FF8,0x7FDE,0x3FF8,0x7FBE,
0x7FFC,0xFF7F,0x7EFC,0xFFFF,0x7FFC,0xFFFF,
0x3FF8,0x7FFE,0x3FF8,0x7FFE,0x1FF0,0x3FFC,
0x07C0,0x1FF8,0x0000,0x07E0,0x0000,0x0000
};
/**********************************************************************/
/* Calc X-Position */
/**********************************************************************/
static UWORD ComputeX(UWORD value, UWORD FontX)
{
return((UWORD)(((FontX * value) + 2) / 8));
}
/**********************************************************************/
/* Calc Y-Position */
/**********************************************************************/
static UWORD ComputeY(UWORD value, UWORD FontY)
{
return(( UWORD )((( FontY * value ) + 2 ) / 8 ));
}
/**********************************************************************/
/* Calc resolution and correct font */
/**********************************************************************/
static void __stdargs ComputeFont(struct Screen *WorkScreen, UWORD width, UWORD height, struct TextAttr *Font, char *FontName, UWORD *OffX, UWORD *OffY, UWORD *FontX, UWORD *FontY)
{
// Get Font-Structure
strcpy(FontName, WorkScreen->RastPort.Font->tf_Message.mn_Node.ln_Name);
Font->ta_Name = FontName;
Font->ta_YSize = *FontY = WorkScreen->RastPort.Font->tf_YSize;
Font->ta_Style = FS_NORMAL;
Font->ta_Flags = 0;
*FontX = WorkScreen->RastPort.Font->tf_XSize;
// Calc offsets
*OffX = WorkScreen->WBorLeft;
*OffY = WorkScreen->RastPort.TxHeight + WorkScreen->WBorTop + 1;
// A Ok ???
if(width && height)
{
if((ComputeX(width, *FontX) + *OffX + WorkScreen->WBorRight) > WorkScreen->Width)
goto UseTopaz;
if((ComputeY(height, *FontY) + *OffY + WorkScreen->WBorBottom) > WorkScreen->Height)
goto UseTopaz;
}
return;
// FallBack to Topaz8
UseTopaz:
strcpy(FontName, "topaz.font");
*FontX = *FontY = Font->ta_YSize = 8;
}
/**********************************************************************/
/* Open a window with a background pattern */
/**********************************************************************/
BOOL OpenWin(
UWORD Left,
UWORD Top,
UWORD Width,
UWORD Height,
struct Gadget **BaseGadget,
UWORD NumGads,
struct _Object **GetFile,
struct NewGadget *NewGads,
UWORD *GTypes,
ULONG *GTags,
struct Gadget **MyGads,
struct Window **Handle,
char *Title,
ULONG IDCMP,
ULONG FLAGS,
UWORD MLeft,
UWORD MTop,
UWORD MWidth,
UWORD MHeight,
struct TextAttr *WinTxtAttr,
char *WinTxtFontName,
struct VisualInfo **VisInfo)
{
UWORD Raster[4] =
{
0xAAAA,
0x5555,
};
struct Screen *MyScreen;
struct Rectangle ScrRec;
struct NewGadget ng;
struct Gadget *g;
struct TextFont *MyFont = NULL;
UWORD lc, tc;
UWORD wleft, wtop, ww, wh, OffX, OffY, FontX, FontY,
swidth, sheight;
if(!(MyScreen = LockPubScreen("Workbench")))
return(FALSE);
if(!(*VisInfo = GetVisualInfo(MyScreen, TAG_DONE)))
goto error;
// Get Font and dimensions
ComputeFont(MyScreen, Width, Height, WinTxtAttr, WinTxtFontName, &OffX, &OffY, &FontX, &FontY);
// Set RastPort Font
InitRastPort(&ComputeRPort);
if(!(MyFont = OpenFont(WinTxtAttr)))
{
if(!(MyFont = OpenDiskFont(WinTxtAttr)))
goto error;
}
SetFont(&ComputeRPort, MyFont);
// Get size of window
ww = ComputeX(Width, FontX);
wh = ComputeY(Height, FontY);
// Get info about Screenmode
if(!QueryOverscan(GetVPModeID(&MyScreen->ViewPort), &ScrRec, OSCAN_TEXT))
goto error;
// Center window
swidth = min((ScrRec.MaxX + 1), MyScreen->Width);
sheight = min((ScrRec.MaxY + 1), MyScreen->Height);
wleft = ((swidth - ww - 1) >> 1) - ((MyScreen->LeftEdge < 0) ? MyScreen->LeftEdge : 0);
wtop = ((sheight - wh - 1) >> 1) - ((MyScreen->TopEdge < 0) ? MyScreen->TopEdge : 0);
// Build GetFile image
if(GetFile)
{
if(!(*GetFile = NewObject(GetFileClass, NULL, GT_VisualInfo, *VisInfo, IA_Width, ComputeX(20, FontX), IA_Height, ComputeY(14, FontY), TAG_DONE)))
goto error;
}
// Create gadgets
if(!(g = CreateContext(BaseGadget)))
goto error;
for(lc = 0, tc = 0; lc < NumGads; lc++)
{
CopyMem((char *)&NewGads[lc], (char *)&ng, (long)sizeof(struct NewGadget));
ng.ng_VisualInfo = *VisInfo;
ng.ng_TextAttr = WinTxtAttr;
ng.ng_LeftEdge = OffX + ComputeX(ng.ng_LeftEdge, FontX);
ng.ng_TopEdge = OffY + ComputeY(ng.ng_TopEdge, FontY);
ng.ng_Width = ComputeX(ng.ng_Width, FontX);
ng.ng_Height = ComputeY(ng.ng_Height, FontY);
// Set gadget`s shortcut
SetGadShortCut(GTypes[lc], &ng);
// Check for ListView
if(GTypes[lc] == LISTVIEW_KIND)
{
struct TagItem *tmp;
if(tmp = FindTagItem(GTLV_ShowSelected, (struct TagItem *)>ags[tc]))
{
if(tmp->ti_Data)
tmp->ti_Data = (ULONG)g;
else
{
// With a normal ShowSelected,
// adjust width according to version of OS
if(((struct Library *)SysBase)->lib_Version < 39)
ng.ng_Height -= 8;
}
}
}
// Create gadget
MyGads[lc] = g = CreateGadgetA(GTypes[lc], g, &ng, (struct TagItem *)>ags[tc]);
// Error ???
if(!g)
goto error;
// Set GetFile image
if(GTypes[lc] == GENERIC_KIND && GetFile)
{
struct TagItem *tmp;
BOOL Disabled = FALSE;
if((tmp = FindTagItem(GA_Disabled, (struct TagItem *)>ags[tc])))
Disabled = (BOOL)tmp->ti_Data;
g->Flags |= GFLG_GADGIMAGE | GFLG_GADGHIMAGE | ((Disabled) ? GFLG_DISABLED : 0);
g->Activation |= GACT_RELVERIFY;
g->GadgetType |= GTYP_BOOLGADGET;
g->GadgetRender = (APTR)*GetFile;
g->SelectRender = (APTR)*GetFile;
}
// Patch String/Integer Gadgets
if(GTypes[lc] == STRING_KIND || GTypes[lc] == INTEGER_KIND)
{
((struct StringInfo *)g->SpecialInfo)->Extension->ActivePens[0] = 1;
((struct StringInfo *)g->SpecialInfo)->Extension->ActivePens[1] = 2;
}
while(GTags[tc])
tc += 2;
tc++;
}
// Close Font
CloseFont(MyFont);
// Open window
if(!(*Handle = OpenWindowTags(NULL,
WA_Left, wleft,
WA_Top, wtop,
WA_Width, ww + OffX + MyScreen->WBorRight,
WA_Height, wh + OffY + MyScreen->WBorBottom,
WA_IDCMP, IDCMP,
WA_Flags, FLAGS,
WA_Title, Title,
WA_CustomScreen, MyScreen,
TAG_DONE)))
goto error;
// Clear userdata-field
(*Handle)->UserData = NULL;
// Unlock Pub screen
UnlockPubScreen(NULL, MyScreen);
if(MLeft && MTop && MWidth && MHeight)
{
// Draw Raster
SetAPen((*Handle)->RPort, 2);
SetAfPt((*Handle)->RPort, Raster, 1);
RectFill((*Handle)->RPort, (*Handle)->BorderLeft, (*Handle)->BorderTop, (*Handle)->Width - (*Handle)->BorderRight - 1, (*Handle)->Height - (*Handle)->BorderBottom - 1);
SetAfPt((*Handle)->RPort, NULL, 0);
// Clear gadget areas and draw bevelbox
SetAPen((*Handle)->RPort, 0);
wleft = OffX + ComputeX(MLeft, FontX);
wtop = OffY + ComputeY(MTop, FontY);
RectFill((*Handle)->RPort, wleft, wtop, wleft + ComputeX(MWidth, FontX) - 1, wtop + ComputeY(MHeight, FontY) - 1);
DrawBevelBox((*Handle)->RPort, wleft, wtop,
ComputeX(MWidth, FontX),
ComputeY(MHeight, FontY),
GT_VisualInfo, *VisInfo, GTBB_Recessed, TRUE,
TAG_DONE);
}
// Add gadgets and display them
AddGList((*Handle), *BaseGadget, -1, -1, NULL);
RefreshGadgets(*BaseGadget, (*Handle), NULL);
GT_RefreshWindow((*Handle), NULL );
return(TRUE);
error:
if(MyScreen)
UnlockPubScreen(NULL, MyScreen);
if(MyFont)
CloseFont(MyFont);
return(FALSE);
}
/**********************************************************************/
/* Close a window again */
/**********************************************************************/
void CloseWin(struct Window **Handle, struct Gadget **MyGad, struct VisualInfo **VisInfo, struct _Object **GetFile)
{
if(*Handle)
{
CloseWindow((*Handle));
*Handle = NULL;
}
if(*MyGad)
{
FreeGadgets((*MyGad));
*MyGad = NULL;
}
if(*VisInfo)
{
FreeVisualInfo(*VisInfo);
*VisInfo = NULL;
}
if(GetFile && *GetFile)
{
DisposeObject(*GetFile);
*GetFile = NULL;
}
}
/**********************************************************************/
/* Set a gadget`s shortcut */
/**********************************************************************/
static void SetGadShortCut(UWORD Type, struct NewGadget *NewGad)
{
char *UnderScore, MyChar;
ULONG EventType = 0;
// Get char of ShortCut
if(NewGad->ng_GadgetText && (UnderScore = (char *)strchr(NewGad->ng_GadgetText, '_')))
{
MyChar = *(UnderScore + 1);
NewGad->ng_UserData = (void *)ToUpper(MyChar);
}
// Set type of event suited for Keystroke activation
switch(Type)
{
case BUTTON_KIND :
case CYCLE_KIND :
case LISTVIEW_KIND :
case CHECKBOX_KIND :
{
EventType = IDCMP_GADGETUP;
break;
}
case STRING_KIND :
case INTEGER_KIND :
{
EventType = IDCMP_GADGETDOWN;
break;
}
}
if(EventType)
NewGad->ng_UserData = (void *)((ULONG)NewGad->ng_UserData | (EventType << 8));
}
/**********************************************************************/
/* Get device and volume lists */
/**********************************************************************/
BOOL GetDevVolList(struct List *VolList)
{
NewList(VolList);
VolList->lh_Type = 0;
if(GetDosEntries(VolList, LDF_DEVICES))
{
if(GetDosEntries(VolList, LDF_VOLUMES))
{
SortList(VolList, FALSE);
return(TRUE);
}
}
return(FALSE);
}
/**********************************************************************/
/* Collect available volumes */
/**********************************************************************/
static BOOL GetDosEntries(struct List *VolList, ULONG Mode)
{
struct DosList *DList;
struct VolEntry *NewEntry;
BOOL RetVal = FALSE;
// Lock DOS-List of Volumes
if((DList = LockDosList(Mode|LDF_READ)))
{
// Loop for all entries
while(DList)
{
// Get next entry
if(!(DList = NextDosEntry(DList, Mode|LDF_READ)))
RetVal = TRUE;
else
{
BOOL DoGet = TRUE;
if(DList->dol_Type == DLT_DEVICE)
{
struct FileSysStartupMsg *FSSM = (struct FileSysStartupMsg *)BADDR(DList->dol_misc.dol_handler.dol_Startup);
DoGet = FALSE;
if(FSSM && TypeOfMem(FSSM) && TypeOfMem(BADDR(FSSM->fssm_Device)) && TypeOfMem(BADDR(FSSM->fssm_Environ)))
{
if(*((char *)BADDR(FSSM->fssm_Device)) != 255)
{
struct DosEnvec *DE = (struct DosEnvec *)BADDR(FSSM->fssm_Environ);
if(DE && TypeOfMem(DE))
{
if(DE->de_Surfaces && DE->de_BlocksPerTrack)
DoGet = TRUE;
}
}
}
}
if(DoGet)
{
// Alloc memory for new entry
if((NewEntry = AllocVec(sizeof(struct VolEntry), MEMF_CLEAR)))
{
// Add to list
AddTail(VolList, (struct Node *)NewEntry);
NewEntry->Link.ln_Name = NewEntry->VolName;
NewEntry->Link.ln_Type = Mode;
VolList->lh_Type++;
strcpy(NewEntry->VolName, ((char *)BADDR(DList->dol_Name) + 1));
}
else
DList = NULL;
}
}
}
// Unlock DOS-List again
UnLockDosList(Mode|LDF_READ);
}
if(!RetVal)
DisplayError(ERR_NOTALL, NULL);
return(RetVal);
}
/**********************************************************************/
/* Release Volume-Nodes */
/**********************************************************************/
void FreeDevVolList(struct List *VolList)
{
struct Node *DelNode;
while((DelNode = RemHead(VolList)))
FreeVec(DelNode);
}
/**********************************************************************/
/* Check for gadget shortcuts */
/**********************************************************************/
void CheckKeys(ULONG *MsgClass, UWORD *MsgCode, UWORD *GadID, BOOL *KeyUse, struct Gadget **MsgGad, struct Gadget **EditGads, UWORD NumGads)
{
register int i;
// Key pressed ???
if(*MsgClass == IDCMP_VANILLAKEY)
{
// Key released ???
if(!(*MsgCode & IECODE_UP_PREFIX))
{
// ESC hit ??? -> Return CLOSE WINDOW
if(*MsgCode == ESCKEY)
*MsgClass = IDCMP_CLOSEWINDOW;
// On Return, search for the first String/Integer gadget
else if(*MsgCode == 0x0d)
{
// Search for gadget
for(i = 0; i < NumGads; i++)
{
// This is the one
if((EditGads[i]->GadgetType & GTYP_STRGADGET) && !(EditGads[i]->Flags & GFLG_DISABLED))
{
// Set flags and vars
*MsgGad = EditGads[i];
*MsgClass = IDCMP_ACTSTRGAD;
*KeyUse = TRUE;
break;
}
}
}
else
{
// Get Char hit
*MsgCode = (UWORD)ToUpper((char)*MsgCode);
// Search for suited gadget
for(i = 0; i < NumGads; i++)
{
if(((ULONG)EditGads[i]->UserData & 0x000000ff) == (ULONG)*MsgCode)
{
// Set flags
*MsgGad = EditGads[i];
*GadID = (*MsgGad)->GadgetID;
*MsgClass = ((ULONG)(*MsgGad)->UserData & 0x0000ff00) >> 8;
*KeyUse = TRUE;
break;
}
}
}
}
}
else
*KeyUse = FALSE;
}
/**********************************************************************/
/* Handle a listview gadget */
/**********************************************************************/
ULONG HandleListViewGad(struct Gadget *Gad, struct Window *MsgWin, BOOL KeyUse, UWORD MsgCode, UWORD MsgQual, LONG Val, ULONG Min, ULONG Max)
{
if(KeyUse)
{
// Key hit
if(MsgQual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
{
// On SHIFT move up
if((Val != Min) && (Val != -1))
Val--;
}
else
{
// On NON-SHIFT move down
if(Val != Max)
Val++;
}
// Set gadget
if(Val != -1)
{
GT_SetGadgetAttrs(Gad, MsgWin, NULL,
GTLV_Selected, Val,
GTLV_Top, Val,
TAG_DONE);
}
}
else
// Otherwiese simply get Message-Code
Val = MsgCode;
return((ULONG)Val);
}
/**********************************************************************/
/* Handle a cycle gadget */
/**********************************************************************/
ULONG HandleCycleGad(struct Gadget *Gad, struct Window *MsgWin, BOOL KeyUse, UWORD MsgCode, UWORD MsgQual, ULONG Val, ULONG Min, ULONG Max)
{
if(KeyUse)
{
// Key hit
if(MsgQual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
{
// On SHIFT move upward, on minimum jump to highest entry
if(Val == Min)
Val = Max;
else
Val--;
}
else
{
// On NON-SHIFT move downward, on maximum jump to lowest entry
if(Val == Max)
Val = Min;
else
Val++;
}
// Set gadget
GT_SetGadgetAttrs(Gad, MsgWin, NULL,
GTCY_Active, Val,
TAG_DONE);
}
else
// Otherwise simply get MsgCode
Val = MsgCode;
return(Val);
}
/**********************************************************************/
/* Get an entry from a list */
/**********************************************************************/
APTR GetListEntry(struct List *List, WORD EntryNum)
{
struct Node *ThisEntry = NULL, *CheckEntry;
// Search list for entry
if(!IsListEmpty((struct List *)List) && EntryNum >= 0)
{
CheckEntry = List->lh_Head;
while(CheckEntry->ln_Succ && EntryNum)
{
CheckEntry = CheckEntry->ln_Succ;
EntryNum--;
}
if(!EntryNum)
ThisEntry = CheckEntry;
}
return(ThisEntry);
}
/**********************************************************************/
/* Set a window to Busy */
/**********************************************************************/
void BusyWindow(struct Window *Window, struct Requester *MyReq)
{
if(Window)
{
// Clear Requester structure
setmem((void *)MyReq, sizeof(struct Requester), 0);
// Open Requester and store address within UserData
Window->UserData = (char *)Request(MyReq, Window);
// Set Pointer
if(SysBase->LibNode.lib_Version < 39)
SetPointer(Window, &BusyPtr[0], 16, 16, -6, 0);
else
SetWindowPointer(Window, WA_BusyPointer, TRUE, TAG_DONE);
}
}
/**********************************************************************/
/* UnBusy a window */
/**********************************************************************/
void UnBusyWindow(struct Window *Window, struct Requester *MyReq)
{
if(Window)
{
// Close Requester
if(Window->UserData)
EndRequest(MyReq, Window);
Window->UserData = NULL;
// Reset Pointer
if(SysBase->LibNode.lib_Version < 39)
ClearPointer(Window);
else
SetWindowPointer(Window, TAG_DONE);
}
}
/**********************************************************************/
/* Save Prefs to disk/env */
/**********************************************************************/
BOOL SavePrefs(BOOL EnvMode)
{
// On ENV: mode, simply save to ENV: only
if(DoSavePrefs("ENV:ForceIcon_prefs.iff"))
{
// Otherwise write to envarc: as well
if(!EnvMode)
return(DoSavePrefs("ENVARC:ForceIcon_prefs.iff"));
else
return(TRUE);
}
return(FALSE);
}
BOOL DoSavePrefs(char *PrefsName)
{
struct IFFHandle *PrefsHandle;
LONG Error;
BOOL GoOn = FALSE;
UWORD VersChunk[] =
{
VERNUM,
REVNUM
};
// Get handle for IFF
if((PrefsHandle = AllocIFF()))
{
// Open file for save
if((PrefsHandle->iff_Stream = Open(PrefsName, MODE_NEWFILE)))
{
// Init Handle
InitIFFasDOS(PrefsHandle);
// Open Handle
if(!(Error = OpenIFF(PrefsHandle, IFFF_WRITE)))
{
// Write FORM chunk
if(!(Error = PushChunk(PrefsHandle, 'FOIC', 'FORM', IFFSIZE_UNKNOWN)))
{
// Write version chunk
if(!(Error = PushChunk(PrefsHandle, 'FOIC', 'VERS', IFFSIZE_UNKNOWN)))
{
if((Error = WriteChunkBytes(PrefsHandle, &VersChunk[0], (sizeof(UWORD) * 2))) == (sizeof(UWORD) * 2))
Error = PopChunk(PrefsHandle);
else
Error = IoErr();
}
// Write Prefs chunk
if(!Error && !(Error = PushChunk(PrefsHandle, 'FOIC', 'PREF', IFFSIZE_UNKNOWN)))
{
struct VolEntry *ThisEntry = (struct VolEntry *)VolumeList.lh_Head;
UWORD NumEntries = VolumeList.lh_Type;
BOOL NoErr = TRUE;
// Write all entries of volume list
if((Error = WriteChunkBytes(PrefsHandle, &NumEntries, sizeof(UWORD))) == sizeof(UWORD))
{
while(NumEntries-- && NoErr)
{
UWORD EntryType = ThisEntry->Link.ln_Type;
if((Error = WriteChunkBytes(PrefsHandle, &EntryType, sizeof(UWORD))) == sizeof(UWORD))
{
if((Error = WriteChunkBytes(PrefsHandle, &ThisEntry->VolName, 130)) == 130)
{
if((Error = WriteChunkBytes(PrefsHandle, &ThisEntry->IconName, 256)) == 256)
{
if((Error = WriteChunkBytes(PrefsHandle, &ThisEntry->Left, (sizeof(UWORD) * 4))) != (sizeof(UWORD) * 4))
NoErr = FALSE;
}
}
}
ThisEntry = (struct VolEntry *)ThisEntry->Link.ln_Succ;
}
if(NoErr)
{
if(!(Error = PopChunk(PrefsHandle)))
GoOn = TRUE;
}
}
}
}
if((Error = PopChunk(PrefsHandle)))
GoOn = FALSE;
CloseIFF(PrefsHandle);
}
Close(PrefsHandle->iff_Stream);
}
else
Error = IoErr();
FreeIFF(PrefsHandle);
}
else
Error = ERR_NOMEM;
if(!GoOn)
DisplayError(Error, (ULONG)PrefsName, NULL);
return(GoOn);
}
/**********************************************************************/
/* Load in settings */
/**********************************************************************/
void LoadPrefs(void)
{
// Try env: first, then envarc:
if(!DoLoadPrefs("ENV:ForceIcon_prefs.iff"))
DoLoadPrefs("ENVARC:ForceIcon_prefs.iff");
}
BOOL DoLoadPrefs(char *PrefsName)
{
struct IFFHandle *PrefsHandle;
struct StoredProperty *SP;
UWORD *VersCheck;
LONG Error;
BOOL GoOn = FALSE;
// Initialize Lists first
NewList(&VolumeList);
VolumeList.lh_Type = 0;
// Get Prefs Handle
if((PrefsHandle = AllocIFF()))
{
// Open file
if((PrefsHandle->iff_Stream = Open(PrefsName, MODE_OLDFILE)))
{
// Init handle
InitIFFasDOS(PrefsHandle);
// Open Handle
if(!(Error = OpenIFF(PrefsHandle, IFFF_READ)))
{
// Search for version chunk
if(!(Error = PropChunk(PrefsHandle, 'FOIC', 'VERS')))
{
// Stop at prefs
if(!(Error = StopChunk(PrefsHandle, 'FOIC', 'PREF')))
{
// Start parsing
if(!(Error = ParseIFF(PrefsHandle, IFFPARSE_SCAN)))
{
// Try to find version chunk
if((SP = FindProp(PrefsHandle, 'FOIC', 'VERS')))
{
VersCheck = (UWORD *)SP->sp_Data;
// Check Version number
if(((*VersCheck) <= VERNUM) && ((*(VersCheck+1)) <= REVNUM))
{
struct VolEntry *ThisEntry;
UWORD NumEntries, EntryType;
BOOL NoErr = TRUE;
// Read in prefs
if((Error = ReadChunkBytes(PrefsHandle, &NumEntries, sizeof(UWORD))) == sizeof(UWORD))
{
VolumeList.lh_Type = NumEntries;
while(NumEntries-- && NoErr)
{
if((ThisEntry = AllocVec(sizeof(struct VolEntry), MEMF_CLEAR)))
{
AddTail(&VolumeList, (struct Node *)ThisEntry);
ThisEntry->Link.ln_Name = ThisEntry->VolName;
if((Error = ReadChunkBytes(PrefsHandle, &EntryType, sizeof(UWORD))) == sizeof(UWORD))
{
ThisEntry->Link.ln_Type = EntryType;
if((Error = ReadChunkBytes(PrefsHandle, &ThisEntry->VolName, 130)) == 130)
{
if((Error = ReadChunkBytes(PrefsHandle, &ThisEntry->IconName, 256)) == 256)
{
if((Error = ReadChunkBytes(PrefsHandle, &ThisEntry->Left, (sizeof(UWORD) * 4))) != (sizeof(UWORD) * 4))
NoErr = FALSE;
}
}
}
}
else
NoErr = FALSE;
}
GoOn = NoErr;
}
if(!NoErr)
Error = IoErr();
}
}
}
}
}
CloseIFF(PrefsHandle);
}
Close(PrefsHandle->iff_Stream);
}
else
Error = IoErr();
FreeIFF(PrefsHandle);
}
else
Error = ERR_NOMEM;
if(!GoOn && Error != ERROR_OBJECT_NOT_FOUND)
DisplayError(Error, (ULONG)PrefsName);
return(GoOn);
}
/**********************************************************************/
/* Get a filename */
/**********************************************************************/
BOOL GetFileName(struct Window *Window, char *Title, char *FileName)
{
struct Rectangle ScrRec;
struct FileRequester *FileReq;
char Drawer[256],
File[256];
UWORD Left, Top, Width, Height, i;
BOOL Result = FALSE;
if(QueryOverscan(GetVPModeID(&Window->WScreen->ViewPort), &ScrRec, OSCAN_TEXT))
{
Width = ((ScrRec.MaxX - ScrRec.MinX + 1) * 45) / 100;
Height = ((ScrRec.MaxY - ScrRec.MinY + 1) * 8) / 10;
Left = (((ScrRec.MaxX + 1) - Width) >> 1) - Window->WScreen->LeftEdge;
Top = (((ScrRec.MaxY + 1) - Height) >> 1) - Window->WScreen->TopEdge;
// Get initial path
if(PathPart(FileName) != (UBYTE *)&FileName[0])
{
for(i = 0; i < 256; i++)
Drawer[i] = '\0';
strncpy(Drawer, FileName, (PathPart(FileName) - FileName));
}
else
strcpy(Drawer, "");
// Get FileName
strcpy(File, FilePart(FileName));
if((FileReq = AllocAslRequestTags(ASL_FileRequest,
ASLFR_Screen, Window->WScreen,
ASLFR_Window, Window,
ASLFR_PrivateIDCMP, TRUE,
ASLFR_SleepWindow, TRUE,
ASLFR_TitleText, Title,
ASLFR_InitialDrawer, (ULONG)Drawer,
ASLFR_InitialFile, (ULONG)File,
ASLFR_InitialLeftEdge, Left,
ASLFR_InitialTopEdge, Top,
ASLFR_InitialWidth, Width,
ASLFR_InitialHeight, Height,
ASLFR_InitialPattern, "#?.info",
TAG_DONE)))
{
if(AslRequest(FileReq, NULL) && (strlen(FileReq->fr_File)))
{
// Remove filetypes
strcpy(FileName, "");
AddPart(FileName, FileReq->fr_Drawer, 256);
AddPart(FileName, FileReq->fr_File, 256);
Result = TRUE;
}
FreeAslRequest(FileReq);
}
}
return(Result);
}
/**********************************************************************/
/* Check for existance of a volume within the user list */
/**********************************************************************/
BOOL CheckExists(char *Name)
{
BOOL RetVal = FALSE;
ObtainSemaphore(&MySemaphore);
if(!IsListEmpty(&VolumeList))
{
struct VolEntry *ThisEntry = (struct VolEntry *)VolumeList.lh_Head;
do
{
if(!stricmp(ThisEntry->VolName, Name))
RetVal = TRUE;
ThisEntry = (struct VolEntry *)ThisEntry->Link.ln_Succ;
} while(!RetVal && ThisEntry->Link.ln_Succ);
}
ReleaseSemaphore(&MySemaphore);
return(RetVal);
}
/**********************************************************************/
/* Sort the complete list of devices/volumes */
/**********************************************************************/
void SortList(struct List *VolList, BOOL DisplayType)
{
UWORD First, Last;
if(DisplayType)
{
First = LDF_VOLUMES;
Last = LDF_DEVICES;
}
else
{
First = LDF_DEVICES;
Last = LDF_VOLUMES;
}
// Sort partial lists within one list
if(!IsListEmpty(VolList))
{
struct VolEntry *ThisEntry = (struct VolEntry *)VolList->lh_Head;
UWORD NumEntries = VolList->lh_Type;
UWORD Left = 0, Right = 0;
// Find boundaries of first type of entries
while(ThisEntry->Link.ln_Type == First && NumEntries)
{
Right++;
NumEntries--;
ThisEntry = (struct VolEntry *)ThisEntry->Link.ln_Succ;
}
// Sort`em
if(Left < Right)
{
SortPartialList(VolList, Left, Right);
Left = Right;
}
// Look for second type of entries
while(ThisEntry->Link.ln_Type == Last && NumEntries)
{
Right++;
NumEntries--;
ThisEntry = (struct VolEntry *)ThisEntry->Link.ln_Succ;
}
// Sort`em
if(Left < Right)
SortPartialList(VolList, Left, Right);
}
}
/**********************************************************************/
/* Sort partial list, either devices or volumes */
/**********************************************************************/
static void SortPartialList(struct List *VolList, UWORD Left, UWORD Right)
{
UWORD i, j;
// This is a simply Insertion Sort
// I don`t think that there will be too many entries,
// so this algorithm will do it. (IMHO)
for(i = Left + 1; i < Right; i++)
{
struct VolEntry Spare, *CheckEntry;
j = i;
Spare = *((struct VolEntry *)GetListEntry(VolList, i));
CheckEntry = (struct VolEntry *)GetListEntry(VolList, j - 1);
while(stricmp(CheckEntry->VolName, Spare.VolName) > 0 && j > Left)
{
struct VolEntry *RightEntry = (struct VolEntry *)CheckEntry->Link.ln_Succ;
strcpy(RightEntry->VolName, CheckEntry->VolName);
strcpy(RightEntry->IconName, CheckEntry->IconName);
RightEntry->Left = CheckEntry->Left;
RightEntry->Top = CheckEntry->Top;
RightEntry->UseAlt = CheckEntry->UseAlt;
j--;
CheckEntry = (struct VolEntry *)CheckEntry->Link.ln_Pred;
}
CheckEntry = (struct VolEntry *)GetListEntry(VolList, j);
strcpy(CheckEntry->VolName, Spare.VolName);
strcpy(CheckEntry->IconName, Spare.IconName);
CheckEntry->Left = Spare.Left;
CheckEntry->Top = Spare.Top;
CheckEntry->UseAlt = Spare.UseAlt;
}
}