home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
disks
/
disk399.lzh
/
TrackDisplay
/
TrackDisplay.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-02
|
12KB
|
620 lines
/* $Revision Header * Header built automatically - do not edit! *************
*
* (C) Copyright 1990 by MXM
*
* Name .....: TrackDisplay.c
* Created ..: Friday 07-Sep-90 11:03
* Revision .: 0
*
* Date Author Comment
* ========= ======== ====================
* 07-Sep-90 Olsen Created this file!
*
* $Revision Header ********************************************************/
/* System includes. */
#include <intuition/intuitionbase.h>
#include <libraries/dosextens.h>
#include <workbench/startup.h>
#include <devices/trackdisk.h>
#include <graphics/gfxbase.h>
#include <hardware/intbits.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <exec/alerts.h>
#define __NO_PRAGMAS 1
#include <functions.h>
/* Global and shared data. */
extern struct ExecBase *SysBase;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Window *Window;
struct RastPort *RPort;
struct Interrupt *TrackInterrupt;
struct WBStartup *WBenchMsg;
/* The four drive IORequests. */
struct IOExtTD *TrackRequest[4];
struct MsgPort *TrackPort[4];
/* Additional track data. */
SHORT TrackNumber[4];
SHORT TrackData[4];
BYTE TrackAvailable[4];
/* Main process identifier. */
struct Process *TrackProcess;
/* Track offset and text spot. */
BYTE Offset,Spot;
/* Default title string. */
char *TrackString = "DF0: -- DF1: -- DF2: -- DF3: --";
/* Current directory for segment split. */
BPTR RemoteCurrentDir;
/* Default window, dimensions and position are filled in later. */
struct NewWindow NewWindow =
{
0,0,
0,0,
0,1,
CLOSEWINDOW | ACTIVEWINDOW | INACTIVEWINDOW,
RMBTRAP | WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE,
(struct Gadget *)NULL,
(struct Image *)NULL,
(UBYTE *)NULL,
(struct Screen *)NULL,
(struct BitMap *)NULL,
0,0,0,0,
WBENCHSCREEN
};
/* TrackHandler():
*
* Interrupt routine to check if trackdisk.device has
* moved the head to a different track.
*/
LONG
TrackHandler()
{
SHORT Number;
SHORT i,DoSig;
int_start();
/* Don't send a refresh signal. */
DoSig = FALSE;
/* Check all drives. */
for(i = 0 ; i < 4 ; i++)
{
/* Driver is available. */
if(TrackAvailable[i])
{
/* This line will pick up the current
* disk track from the approriate disk
* unit. You may say that we are relying
* on undefined structures. This is right
* for Kickstart 1.3 and below, while
* starting with Kickstart 1.4 the current
* track indicator has moved into the public
* portion of the trackdisk unit.
*/
Number = (*(SHORT *)((ULONG)TrackRequest[i] -> iotd_Req . io_Unit + Offset) >> 1);
/* Has the track number changed? */
if(TrackNumber[i] == Number)
TrackData[i] = -1;
else
{
/* It has. Prepare to flag the
* main process to update the
* window.
*/
TrackNumber[i] = TrackData[i] = Number;
DoSig = TRUE;
}
}
else
TrackData[i] = -1;
}
/* If necessary tell the main process to update the
* window.
*/
if(DoSig)
Signal((struct Task *)TrackProcess,SIGBREAKF_CTRL_D);
int_end();
return(0);
}
/* CloseAll():
*
* Closes everything we have allocated in order to
* display the tracks.
*/
VOID
CloseAll()
{
BYTE i;
/* Remove and deallocate the interrupt. */
if(TrackInterrupt)
{
RemIntServer(INTB_VERTB,TrackInterrupt);
FreeMem(TrackInterrupt,sizeof(struct Interrupt));
}
/* Free all drives. */
for(i = 0 ; i < 4 ; i++)
{
if(TrackAvailable[i])
CloseDevice(TrackRequest[i]);
if(TrackRequest[i])
DeleteExtIO(TrackRequest[i]);
if(TrackPort[i])
DeletePort(TrackPort[i]);
}
/* Unlock the remote directory. */
if(RemoteCurrentDir)
UnLock(RemoteCurrentDir);
/* Close the window. */
if(Window)
CloseWindow(Window);
/* Close the libraries. */
if(GfxBase)
CloseLibrary(GfxBase);
if(IntuitionBase)
CloseLibrary(IntuitionBase);
/* Return the Workbench Message. */
if(WBenchMsg)
{
Forbid();
ReplyMsg(&WBenchMsg -> sm_Message);
}
}
/* OpenAll():
*
* Opens everything we need to display the tracks.
*/
BYTE
OpenAll()
{
BYTE i;
if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",LIBRARY_MINIMUM)))
return(FALSE);
if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",LIBRARY_MINIMUM)))
return(FALSE);
/* Check if we are running under control of Exec 2.x. */
if(SysBase -> LibNode . lib_Version > 34)
{
struct Screen WBenchScreen;
/* The current track is stored in the
* 27th word behind the driver unit.
*/
Offset = 54;
/* Adapt the window dimensions to the current
* system font.
*/
NewWindow . Width = 20 + 24 + 31 * GfxBase -> DefaultFont -> tf_XSize;
Spot = 24;
if(!GetScreenData(&WBenchScreen,sizeof(struct Screen),WBENCHSCREEN,NULL))
return(FALSE);
/* Center the window. */
NewWindow . LeftEdge = (WBenchScreen . Width - NewWindow . Width) >> 1;
}
else
{
struct Screen WBenchScreen;
/* The current track is stored in the
* 37th word behind the driver unit.
*/
Offset = 74;
/* Adapt the window dimensions to the current
* system font.
*/
NewWindow . Width = 34 + 50 + 31 * GfxBase -> DefaultFont -> tf_XSize;
Spot = 30;
/* Get the dimensions of the Workbench screen. */
if(!GetScreenData(&WBenchScreen,sizeof(struct Screen),WBENCHSCREEN,NULL))
return(FALSE);
/* Center the window. */
NewWindow . LeftEdge = (WBenchScreen . Width - NewWindow . Width) >> 1;
/* Fill in the default title. */
NewWindow . Title = (UBYTE *)TrackString;
}
/* Adjust the window height. */
NewWindow . Height = GfxBase -> DefaultFont -> tf_YSize + 2;
/* Open the window. */
if(!(Window = (struct Window *)OpenWindow(&NewWindow)))
return(FALSE);
/* Open the disk drives. */
for(i = 0 ; i < 4 ; i++)
{
if(!(TrackPort[i] = (struct MsgPort *)CreatePort(NULL,0)))
return(FALSE);
if(!(TrackRequest[i] = (struct IOExtTD *)CreateExtIO(TrackPort[i],sizeof(struct IOExtTD))))
return(FALSE);
if(!OpenDevice(TD_NAME,i,TrackRequest[i],TDF_ALLOW_NON_3_5))
TrackAvailable[i] = TRUE;
TrackNumber[i] = -1;
}
/* Allocate memory for the interrupt driver. */
if(!(TrackInterrupt = (struct Interrupt *)AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC | MEMF_CLEAR)))
return(FALSE);
RPort = Window -> RPort;
/* Set the window colours according to the current
* system colours.
*/
if(SysBase -> LibNode . lib_Version > 34)
{
SetAPen(RPort,1);
SetBPen(RPort,2);
}
else
{
SetAPen(RPort,0);
SetBPen(RPort,1);
}
SetDrMd(RPort,JAM2);
/* Fill in the interrupt. */
TrackInterrupt -> is_Node . ln_Type = NT_INTERRUPT;
TrackInterrupt -> is_Node . ln_Name = "Track Interrupt";
TrackInterrupt -> is_Code = (APTR)TrackHandler;
/* Add the interrupt server. */
AddIntServer(INTB_VERTB,TrackInterrupt);
return(TRUE);
}
/* _main():
*
* The main routine - performs segment split, fires off the
* interrupt and updates the main window.
*/
LONG
_main()
{
STATIC char *ProcName = "Trackdisplay © Copyright 1990 by MXM, all rights reserved";
STATIC BYTE SegmentSplit = FALSE;
ULONG DeadCode = 0xDEADC0DE;
ULONG SignalSet;
struct IntuiMessage *Massage;
ULONG Class;
BYTE i;
TrackProcess = (struct Process *)SysBase -> ThisTask;
/* Are we running from a CLI? If so, perform
* segment split.
*/
if(TrackProcess -> pr_CLI)
SegmentSplit = TRUE;
/* Pick up the Workbench startup. */
if(!TrackProcess -> pr_CLI && !SegmentSplit)
{
WaitPort(&TrackProcess -> pr_MsgPort);
WBenchMsg = (struct WBStartup *)GetMsg(&TrackProcess -> pr_MsgPort);
if(WBenchMsg -> sm_ArgList)
CurrentDir(WBenchMsg -> sm_ArgList -> wa_Lock);
}
/* Are we to do the segment split? */
if(SegmentSplit)
{
struct CommandLineInterface *CLI;
/* Get a pointer to the current CLI structure. */
if(CLI = (struct CommandLineInterface *)BADDR(TrackProcess -> pr_CLI))
{
/* Make a private copy of the current
* directory Lock.
*/
CurrentDir(RemoteCurrentDir = CurrentDir(NULL));
RemoteCurrentDir = DupLock(RemoteCurrentDir);
/* Create a new process from our
* own program code.
*/
if(CreateProc(ProcName,0,CLI -> cli_Module,4000))
{
/* Keep program segment list
* from getting unloaded.
*/
CLI -> cli_Module = NULL;
return(RETURN_OK);
}
else
{
/* Oops! Process creation failed.
* I suppose we're really broken.
*/
Alert(AT_Recovery|AG_ProcCreate|AO_Unknown,&DeadCode);
UnLock(RemoteCurrentDir);
return(RETURN_FAIL);
}
}
else
{
/* At this point we have a copy of the
* lock on the current directory of
* the creating process. We have lost
* the link to the CLI and will need
* to transform our segment list in order
* to get it unloaded or at least removed
* when we are finally falling through.
*/
if(!strcmp(TrackProcess -> pr_Task . tc_Node . ln_Name,ProcName))
{
struct MemList *MemList;
BPTR *SegList,*LastSeg;
USHORT Count = 0;
/* Get the pointer to our segment
* list.
*/
SegList = (BPTR *)BADDR(TrackProcess -> pr_SegList);
/* The third longword points
* to our real segment list, the
* first two are DOS-private.
*/
SegList = (BPTR *)BADDR(SegList[3]);
/* Remember the segment list. */
LastSeg = SegList;
/* Count the number of segments. */
while(SegList)
{
SegList = (BPTR *)BADDR(*SegList);
Count++;
}
/* Try to allocate a MemList with
* enough entries to hold both
* the MemList and the segments.
*/
if(MemList = (struct MemList *)AllocMem(sizeof(struct MemList) + sizeof(struct MemEntry) * (Count - 1),MEMF_PUBLIC|MEMF_CLEAR))
{
/* Restore the segment pointer. */
SegList = LastSeg;
/* Set the number of entries. */
MemList -> ml_NumEntries = Count;
Count = 0;
/* Add all the segments to the
* memory list.
*/
while(SegList)
{
/* Start of segment. */
MemList -> ml_me[Count] . me_Addr = (APTR)&SegList[-1];
/* Length of segment. */
MemList -> ml_me[Count] . me_Length = SegList[-1];
/* Get pointer to next segment. */
SegList = (BPTR *)BADDR(*SegList);
Count++;
}
/* Add the memory list to the list
* of memlists to be deallocated
* on exit.
*/
AddTail(&TrackProcess -> pr_Task . tc_MemEntry,&MemList -> ml_Node);
/* Change to the last current
* directory.
*/
CurrentDir(RemoteCurrentDir);
}
else
{
/* AllocMem failed. We
* will show our hand and
* try to back out backwards.
*/
Alert(AT_Recovery|AG_NoMemory|AO_Unknown,&DeadCode);
UnLock(RemoteCurrentDir);
return(RETURN_FAIL);
}
}
}
}
/* We're done, now go on running the real program. */
if(OpenAll())
{
FOREVER
{
/* Wait for a signal. */
SignalSet = Wait((1 << Window -> UserPort -> mp_SigBit) | SIGBREAKF_CTRL_D);
/* Are we to update the window? */
if(SignalSet & SIGBREAKF_CTRL_D)
{
/* Check all drives. */
for(i = 0 ; i < 4 ; i++)
{
/* Is the track valid? */
if(TrackData[i] != -1)
{
/* Put the number into the
* string.
*/
TrackString[5 + 8 * i + 0] = '0' + TrackData[i] / 10;
TrackString[5 + 8 * i + 1] = '0' + TrackData[i] % 10;
/* Print the string. */
Move(RPort,Spot,GfxBase -> DefaultFont -> tf_Baseline + 1);
Text(RPort,TrackString,31);
}
}
}
/* Are we to close the window? */
if(SignalSet & (1 << Window -> UserPort -> mp_SigBit))
{
while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
{
Class = Massage -> Class;
ReplyMsg((struct Message *)Massage);
/* Close the window. */
if(Class == CLOSEWINDOW)
{
CloseAll();
return(RETURN_OK);
}
else
{
/* Simply refresh
* the contents of
* the window.
*/
Move(RPort,Spot,GfxBase -> DefaultFont -> tf_Baseline + 1);
Text(RPort,TrackString,31);
}
}
}
}
}
}