home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / disks / disk399.lzh / TrackDisplay / TrackDisplay.c < prev    next >
C/C++ Source or Header  |  1990-11-02  |  12KB  |  620 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1990 by MXM
  4.  *
  5.  *    Name .....: TrackDisplay.c
  6.  *    Created ..: Friday 07-Sep-90 11:03
  7.  *    Revision .: 0
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    07-Sep-90       Olsen           Created this file!
  12.  *
  13.  * $Revision Header ********************************************************/
  14.  
  15.     /* System includes. */
  16.  
  17. #include <intuition/intuitionbase.h>
  18. #include <libraries/dosextens.h>
  19. #include <workbench/startup.h>
  20. #include <devices/trackdisk.h>
  21. #include <graphics/gfxbase.h>
  22. #include <hardware/intbits.h>
  23. #include <exec/execbase.h>
  24. #include <exec/memory.h>
  25. #include <exec/alerts.h>
  26.  
  27. #define __NO_PRAGMAS 1
  28.  
  29. #include <functions.h>
  30.  
  31.     /* Global and shared data. */
  32.  
  33. extern struct ExecBase    *SysBase;
  34. struct IntuitionBase    *IntuitionBase;
  35. struct GfxBase        *GfxBase;
  36. struct Window        *Window;
  37. struct RastPort        *RPort;
  38.  
  39. struct Interrupt    *TrackInterrupt;
  40.  
  41. struct WBStartup    *WBenchMsg;
  42.  
  43.     /* The four drive IORequests. */
  44.  
  45. struct IOExtTD        *TrackRequest[4];
  46. struct MsgPort        *TrackPort[4];
  47.  
  48.     /* Additional track data. */
  49.  
  50. SHORT             TrackNumber[4];
  51. SHORT             TrackData[4];
  52. BYTE             TrackAvailable[4];
  53.  
  54.     /* Main process identifier. */
  55.  
  56. struct Process        *TrackProcess;
  57.  
  58.     /* Track offset and text spot. */
  59.  
  60. BYTE             Offset,Spot;
  61.  
  62.     /* Default title string. */
  63.  
  64. char            *TrackString = "DF0: -- DF1: -- DF2: -- DF3: --";
  65.  
  66.     /* Current directory for segment split. */
  67.  
  68. BPTR             RemoteCurrentDir;
  69.  
  70.     /* Default window, dimensions and position are filled in later. */
  71.  
  72. struct NewWindow NewWindow =
  73. {
  74.     0,0,
  75.     0,0,
  76.     0,1,
  77.     CLOSEWINDOW | ACTIVEWINDOW | INACTIVEWINDOW,
  78.     RMBTRAP | WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE,
  79.     (struct Gadget *)NULL,
  80.     (struct Image *)NULL,
  81.     (UBYTE *)NULL,
  82.     (struct Screen *)NULL,
  83.     (struct BitMap *)NULL,
  84.     0,0,0,0,
  85.     WBENCHSCREEN
  86. };
  87.  
  88.     /* TrackHandler():
  89.      *
  90.      *    Interrupt routine to check if trackdisk.device has
  91.      *    moved the head to a different track.
  92.      */
  93.  
  94. LONG
  95. TrackHandler()
  96. {
  97.     SHORT    Number;
  98.     SHORT    i,DoSig;
  99.  
  100.     int_start();
  101.  
  102.         /* Don't send a refresh signal. */
  103.  
  104.     DoSig = FALSE;
  105.  
  106.         /* Check all drives. */
  107.  
  108.     for(i = 0 ; i < 4 ; i++)
  109.     {
  110.             /* Driver is available. */
  111.  
  112.         if(TrackAvailable[i])
  113.         {
  114.                 /* This line will pick up the current
  115.                  * disk track from the approriate disk
  116.                  * unit. You may say that we are relying
  117.                  * on undefined structures. This is right
  118.                  * for Kickstart 1.3 and below, while
  119.                  * starting with Kickstart 1.4 the current
  120.                  * track indicator has moved into the public
  121.                  * portion of the trackdisk unit.
  122.                  */
  123.  
  124.             Number = (*(SHORT *)((ULONG)TrackRequest[i] -> iotd_Req . io_Unit + Offset) >> 1);
  125.  
  126.                 /* Has the track number changed? */
  127.  
  128.             if(TrackNumber[i] == Number)
  129.                 TrackData[i] = -1;
  130.             else
  131.             {
  132.                     /* It has. Prepare to flag the
  133.                      * main process to update the
  134.                      * window.
  135.                      */
  136.  
  137.                 TrackNumber[i] = TrackData[i] = Number;
  138.                 DoSig = TRUE;
  139.             }
  140.         }
  141.         else
  142.             TrackData[i] = -1;
  143.     }
  144.  
  145.         /* If necessary tell the main process to update the
  146.          * window.
  147.          */
  148.  
  149.     if(DoSig)
  150.         Signal((struct Task *)TrackProcess,SIGBREAKF_CTRL_D);
  151.  
  152.     int_end();
  153.  
  154.     return(0);
  155. }
  156.  
  157.     /* CloseAll():
  158.      *
  159.      *    Closes everything we have allocated in order to
  160.      *    display the tracks.
  161.      */
  162.  
  163. VOID
  164. CloseAll()
  165. {
  166.     BYTE i;
  167.  
  168.         /* Remove and deallocate the interrupt. */
  169.  
  170.     if(TrackInterrupt)
  171.     {
  172.         RemIntServer(INTB_VERTB,TrackInterrupt);
  173.  
  174.         FreeMem(TrackInterrupt,sizeof(struct Interrupt));
  175.     }
  176.  
  177.         /* Free all drives. */
  178.  
  179.     for(i = 0 ; i < 4 ; i++)
  180.     {
  181.         if(TrackAvailable[i])
  182.             CloseDevice(TrackRequest[i]);
  183.  
  184.         if(TrackRequest[i])
  185.             DeleteExtIO(TrackRequest[i]);
  186.  
  187.         if(TrackPort[i])
  188.             DeletePort(TrackPort[i]);
  189.     }
  190.  
  191.         /* Unlock the remote directory. */
  192.  
  193.     if(RemoteCurrentDir)
  194.         UnLock(RemoteCurrentDir);
  195.  
  196.         /* Close the window. */
  197.  
  198.     if(Window)
  199.         CloseWindow(Window);
  200.  
  201.         /* Close the libraries. */
  202.  
  203.     if(GfxBase)
  204.         CloseLibrary(GfxBase);
  205.  
  206.     if(IntuitionBase)
  207.         CloseLibrary(IntuitionBase);
  208.  
  209.         /* Return the Workbench Message. */
  210.  
  211.     if(WBenchMsg)
  212.     {
  213.         Forbid();
  214.         ReplyMsg(&WBenchMsg -> sm_Message);
  215.     }
  216. }
  217.  
  218.     /* OpenAll():
  219.      *
  220.      *    Opens everything we need to display the tracks.
  221.      */
  222.  
  223. BYTE
  224. OpenAll()
  225. {
  226.     BYTE i;
  227.  
  228.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",LIBRARY_MINIMUM)))
  229.         return(FALSE);
  230.  
  231.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",LIBRARY_MINIMUM)))
  232.         return(FALSE);
  233.  
  234.         /* Check if we are running under control of Exec 2.x. */
  235.  
  236.     if(SysBase -> LibNode . lib_Version > 34)
  237.     {
  238.         struct Screen WBenchScreen;
  239.  
  240.             /* The current track is stored in the
  241.              * 27th word behind the driver unit.
  242.              */
  243.  
  244.         Offset = 54;
  245.  
  246.             /* Adapt the window dimensions to the current
  247.              * system font.
  248.              */
  249.  
  250.         NewWindow . Width = 20 + 24 + 31 * GfxBase -> DefaultFont -> tf_XSize;
  251.  
  252.         Spot = 24;
  253.  
  254.         if(!GetScreenData(&WBenchScreen,sizeof(struct Screen),WBENCHSCREEN,NULL))
  255.             return(FALSE);
  256.  
  257.             /* Center the window. */
  258.  
  259.         NewWindow . LeftEdge = (WBenchScreen . Width - NewWindow . Width) >> 1;
  260.     }
  261.     else
  262.     {
  263.         struct Screen WBenchScreen;
  264.  
  265.             /* The current track is stored in the
  266.              * 37th word behind the driver unit.
  267.              */
  268.  
  269.         Offset = 74;
  270.  
  271.             /* Adapt the window dimensions to the current
  272.              * system font.
  273.              */
  274.  
  275.         NewWindow . Width = 34 + 50 + 31 * GfxBase -> DefaultFont -> tf_XSize;
  276.  
  277.         Spot = 30;
  278.  
  279.             /* Get the dimensions of the Workbench screen. */
  280.  
  281.         if(!GetScreenData(&WBenchScreen,sizeof(struct Screen),WBENCHSCREEN,NULL))
  282.             return(FALSE);
  283.  
  284.             /* Center the window. */
  285.  
  286.         NewWindow . LeftEdge = (WBenchScreen . Width - NewWindow . Width) >> 1;
  287.  
  288.             /* Fill in the default title. */
  289.  
  290.         NewWindow . Title = (UBYTE *)TrackString;
  291.     }
  292.  
  293.         /* Adjust the window height. */
  294.  
  295.     NewWindow . Height = GfxBase -> DefaultFont -> tf_YSize + 2;
  296.  
  297.         /* Open the window. */
  298.  
  299.     if(!(Window = (struct Window *)OpenWindow(&NewWindow)))
  300.         return(FALSE);
  301.  
  302.         /* Open the disk drives. */
  303.  
  304.     for(i = 0 ; i < 4 ; i++)
  305.     {
  306.         if(!(TrackPort[i] = (struct MsgPort *)CreatePort(NULL,0)))
  307.             return(FALSE);
  308.  
  309.         if(!(TrackRequest[i] = (struct IOExtTD *)CreateExtIO(TrackPort[i],sizeof(struct IOExtTD))))
  310.             return(FALSE);
  311.  
  312.         if(!OpenDevice(TD_NAME,i,TrackRequest[i],TDF_ALLOW_NON_3_5))
  313.             TrackAvailable[i] = TRUE;
  314.  
  315.         TrackNumber[i] = -1;
  316.     }
  317.  
  318.         /* Allocate memory for the interrupt driver. */
  319.  
  320.     if(!(TrackInterrupt = (struct Interrupt *)AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC | MEMF_CLEAR)))
  321.         return(FALSE);
  322.  
  323.     RPort = Window -> RPort;
  324.  
  325.         /* Set the window colours according to the current
  326.          * system colours.
  327.          */
  328.  
  329.     if(SysBase -> LibNode . lib_Version > 34)
  330.     {
  331.         SetAPen(RPort,1);
  332.         SetBPen(RPort,2);
  333.     }
  334.     else
  335.     {
  336.         SetAPen(RPort,0);
  337.         SetBPen(RPort,1);
  338.     }
  339.  
  340.     SetDrMd(RPort,JAM2);
  341.  
  342.         /* Fill in the interrupt. */
  343.  
  344.     TrackInterrupt -> is_Node . ln_Type    = NT_INTERRUPT;
  345.     TrackInterrupt -> is_Node . ln_Name    = "Track Interrupt";
  346.     TrackInterrupt -> is_Code        = (APTR)TrackHandler;
  347.  
  348.         /* Add the interrupt server. */
  349.  
  350.     AddIntServer(INTB_VERTB,TrackInterrupt);
  351.  
  352.     return(TRUE);
  353. }
  354.  
  355.     /* _main():
  356.      *
  357.      *    The main routine - performs segment split, fires off the
  358.      *    interrupt and updates the main window.
  359.      */
  360.  
  361. LONG
  362. _main()
  363. {
  364.     STATIC char        *ProcName = "Trackdisplay © Copyright 1990 by MXM, all rights reserved";
  365.     STATIC BYTE         SegmentSplit = FALSE;
  366.  
  367.     ULONG             DeadCode = 0xDEADC0DE;
  368.  
  369.     ULONG             SignalSet;
  370.  
  371.     struct IntuiMessage    *Massage;
  372.     ULONG             Class;
  373.  
  374.     BYTE             i;
  375.  
  376.     TrackProcess = (struct Process *)SysBase -> ThisTask;
  377.  
  378.         /* Are we running from a CLI? If so, perform
  379.          * segment split.
  380.          */
  381.  
  382.     if(TrackProcess -> pr_CLI)
  383.         SegmentSplit = TRUE;
  384.  
  385.         /* Pick up the Workbench startup. */
  386.  
  387.     if(!TrackProcess -> pr_CLI && !SegmentSplit)
  388.     {
  389.         WaitPort(&TrackProcess -> pr_MsgPort);
  390.  
  391.         WBenchMsg = (struct WBStartup *)GetMsg(&TrackProcess -> pr_MsgPort);
  392.  
  393.         if(WBenchMsg -> sm_ArgList)
  394.             CurrentDir(WBenchMsg -> sm_ArgList -> wa_Lock);
  395.     }
  396.  
  397.         /* Are we to do the segment split? */
  398.  
  399.     if(SegmentSplit)
  400.     {
  401.         struct CommandLineInterface *CLI;
  402.  
  403.             /* Get a pointer to the current CLI structure. */
  404.  
  405.         if(CLI = (struct CommandLineInterface *)BADDR(TrackProcess -> pr_CLI))
  406.         {
  407.                 /* Make a private copy of the current
  408.                  * directory Lock.
  409.                  */
  410.  
  411.             CurrentDir(RemoteCurrentDir = CurrentDir(NULL));
  412.             RemoteCurrentDir = DupLock(RemoteCurrentDir);
  413.  
  414.                 /* Create a new process from our
  415.                  * own program code.
  416.                  */
  417.  
  418.             if(CreateProc(ProcName,0,CLI -> cli_Module,4000))
  419.             {
  420.                     /* Keep program segment list
  421.                      * from getting unloaded.
  422.                      */
  423.  
  424.                 CLI -> cli_Module = NULL;
  425.  
  426.                 return(RETURN_OK);
  427.             }
  428.             else
  429.             {
  430.                     /* Oops! Process creation failed.
  431.                      * I suppose we're really broken.
  432.                      */
  433.  
  434.                 Alert(AT_Recovery|AG_ProcCreate|AO_Unknown,&DeadCode);
  435.  
  436.                 UnLock(RemoteCurrentDir);
  437.  
  438.                 return(RETURN_FAIL);
  439.             }
  440.         }
  441.         else
  442.         {
  443.                 /* At this point we have a copy of the
  444.                  * lock on the current directory of
  445.                  * the creating process. We have lost
  446.                  * the link to the CLI and will need
  447.                  * to transform our segment list in order
  448.                  * to get it unloaded or at least removed
  449.                  * when we are finally falling through.
  450.                  */
  451.  
  452.             if(!strcmp(TrackProcess -> pr_Task . tc_Node . ln_Name,ProcName))
  453.             {
  454.                 struct MemList    *MemList;
  455.                 BPTR        *SegList,*LastSeg;
  456.                 USHORT         Count = 0;
  457.  
  458.                     /* Get the pointer to our segment
  459.                      * list.
  460.                      */
  461.  
  462.                 SegList = (BPTR *)BADDR(TrackProcess -> pr_SegList);
  463.  
  464.                     /* The third longword points
  465.                      * to our real segment list, the
  466.                      * first two are DOS-private.
  467.                      */
  468.  
  469.                 SegList = (BPTR *)BADDR(SegList[3]);
  470.  
  471.                     /* Remember the segment list. */
  472.  
  473.                 LastSeg = SegList;
  474.  
  475.                     /* Count the number of segments. */
  476.  
  477.                 while(SegList)
  478.                 {
  479.                     SegList = (BPTR *)BADDR(*SegList);
  480.                     Count++;
  481.                 }
  482.  
  483.                     /* Try to allocate a MemList with
  484.                      * enough entries to hold both
  485.                      * the MemList and the segments.
  486.                      */
  487.  
  488.                 if(MemList = (struct MemList *)AllocMem(sizeof(struct MemList) + sizeof(struct MemEntry) * (Count - 1),MEMF_PUBLIC|MEMF_CLEAR))
  489.                 {
  490.                         /* Restore the segment pointer. */
  491.  
  492.                     SegList = LastSeg;
  493.  
  494.                         /* Set the number of entries. */
  495.  
  496.                     MemList -> ml_NumEntries = Count;
  497.  
  498.                     Count = 0;
  499.  
  500.                         /* Add all the segments to the
  501.                          * memory list.
  502.                          */
  503.  
  504.                     while(SegList)
  505.                     {
  506.                             /* Start of segment. */
  507.  
  508.                         MemList -> ml_me[Count] . me_Addr    = (APTR)&SegList[-1];
  509.  
  510.                             /* Length of segment. */
  511.  
  512.                         MemList -> ml_me[Count] . me_Length    = SegList[-1];
  513.  
  514.                             /* Get pointer to next segment. */
  515.  
  516.                         SegList = (BPTR *)BADDR(*SegList);
  517.  
  518.                         Count++;
  519.                     }
  520.  
  521.                         /* Add the memory list to the list
  522.                          * of memlists to be deallocated
  523.                          * on exit.
  524.                          */
  525.  
  526.                     AddTail(&TrackProcess -> pr_Task . tc_MemEntry,&MemList -> ml_Node);
  527.  
  528.                         /* Change to the last current
  529.                          * directory.
  530.                          */
  531.  
  532.                     CurrentDir(RemoteCurrentDir);
  533.                 }
  534.                 else
  535.                 {
  536.                         /* AllocMem failed. We
  537.                          * will show our hand and
  538.                          * try to back out backwards.
  539.                          */
  540.  
  541.                     Alert(AT_Recovery|AG_NoMemory|AO_Unknown,&DeadCode);
  542.  
  543.                     UnLock(RemoteCurrentDir);
  544.                     return(RETURN_FAIL);
  545.                 }
  546.             }
  547.         }
  548.     }
  549.  
  550.         /* We're done, now go on running the real program. */
  551.  
  552.     if(OpenAll())
  553.     {
  554.         FOREVER
  555.         {
  556.                 /* Wait for a signal. */
  557.  
  558.             SignalSet = Wait((1 << Window -> UserPort -> mp_SigBit) | SIGBREAKF_CTRL_D);
  559.  
  560.                 /* Are we to update the window? */
  561.  
  562.             if(SignalSet & SIGBREAKF_CTRL_D)
  563.             {
  564.                     /* Check all drives. */
  565.  
  566.                 for(i = 0 ; i < 4 ; i++)
  567.                 {
  568.                         /* Is the track valid? */
  569.  
  570.                     if(TrackData[i] != -1)
  571.                     {
  572.                             /* Put the number into the
  573.                              * string.
  574.                              */
  575.  
  576.                         TrackString[5 + 8 * i + 0] = '0' + TrackData[i] / 10;
  577.                         TrackString[5 + 8 * i + 1] = '0' + TrackData[i] % 10;
  578.  
  579.                             /* Print the string. */
  580.  
  581.                         Move(RPort,Spot,GfxBase -> DefaultFont -> tf_Baseline + 1);
  582.                         Text(RPort,TrackString,31);
  583.                     }
  584.                 }
  585.             }
  586.  
  587.                 /* Are we to close the window? */
  588.  
  589.             if(SignalSet & (1 << Window -> UserPort -> mp_SigBit))
  590.             {
  591.                 while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  592.                 {
  593.                     Class = Massage -> Class;
  594.  
  595.                     ReplyMsg((struct Message *)Massage);
  596.  
  597.                         /* Close the window. */
  598.  
  599.                     if(Class == CLOSEWINDOW)
  600.                     {
  601.                         CloseAll();
  602.  
  603.                         return(RETURN_OK);
  604.                     }
  605.                     else
  606.                     {
  607.                             /* Simply refresh
  608.                              * the contents of
  609.                              * the window.
  610.                              */
  611.  
  612.                         Move(RPort,Spot,GfxBase -> DefaultFont -> tf_Baseline + 1);
  613.                         Text(RPort,TrackString,31);
  614.                     }
  615.                 }
  616.             }
  617.         }
  618.     }
  619. }
  620.