/* $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 #include #include #include #include #include #include #include #include #define __NO_PRAGMAS 1 #include /* 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); } } } } } }