home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d154 / wicon.lha / Wicon / winfo.c < prev    next >
C/C++ Source or Header  |  1987-06-15  |  13KB  |  611 lines

  1. /*************************************************************************
  2.  *
  3.  *    WINFO.c     for wicon.c a *Window iconifier
  4.  *
  5.  *    1.7 24-Apr-88        Copyright (c) 1987  Steven Sweeting 16-Dec-87
  6.  *
  7.  *    Contains routines for maintaining the Winfo[] data structures
  8.  *
  9.  *
  10.  *    Semaphores are used to make sure that the Winfo[] data structure
  11.  *    is never accessed by two processes at the same time. (Note:
  12.  *    CloseWindows and OpenWindows are both vectored to the routines
  13.  *    below.
  14.  *
  15.  *    Note: I have used Procure & Vacate for my function names but these
  16.  *          functions in the Amiga are slightly DIFFERENT. I am using
  17.  *          SignalSemaphores (as opposed to just Semaphores), with the
  18.  *          ObtainSemaphore & ReleaseSemaphore routines.
  19.  *
  20.  *    When a process obtains a semaphore, (Procures), every other process
  21.  *    who trys to Procure the same Semaphore will be blocked (made to
  22.  *    Wait()) until the original process gives up, or releases (Vacates)
  23.  *    that Semaphore.
  24.  *
  25.  *    Semaphores are new to 1.2. eg LockIBase() now uses them.
  26.  *
  27.  *    { yes I know V stands for Signal and P for Wait but I was never
  28.  *      good at Dutch and I like Acronyms!-}
  29.  *
  30.  ************************************************************************/
  31.  
  32. #ifdef DEBUG
  33. #define Static
  34. #else  DEBUG
  35. #define Static static
  36. #endif DEBUG
  37.  
  38. #include "wicon.h"
  39. #include <ctype.h>
  40. #include <exec/semaphores.h>    /* Amazing ! they work too :-) */
  41.  
  42. #define     PULL(w)     {\
  43.                 (w)->RPort->Layer->Flags &= ~LAYERBACKDROP;\
  44.                 WindowToFront( w );\
  45.                 Delay(1L);\
  46.                 ActivateWindow( w );\
  47.             }
  48.  
  49. #define     PUSH(w)     { \
  50.                 (w)->RPort->Layer->Flags |= LAYERBACKDROP;\
  51.                 WindowToBack( w );\
  52.                 Delay(1L);\
  53.             }
  54.  
  55. /* The Delay(1L)s above are used to given Intuition a fighting chance
  56.    to do the Window..() routines. */
  57.  
  58. struct    SignalSemaphore WiconSemaphore;
  59.  
  60. /*************************************************************************
  61.  *  W_Init  - Initialises Semaphore structure for use
  62.  *          as signalling
  63.  *  30-Dec-87
  64.  */
  65.  
  66. W_Init()
  67. {
  68.     InitSemaphore( &WiconSemaphore );
  69. }
  70.  
  71. /*************************************************************************
  72.  * W_Procure - obtains a lock on Winfo[]
  73.  *           blocking wait
  74.  * 30-Dec-87
  75.  */
  76.  
  77. W_Procure()
  78. {
  79.     ObtainSemaphore( &WiconSemaphore );
  80. }
  81.  
  82. /*************************************************************************
  83.  * W_Vacate - releases a lock on Winfo[]
  84.  *
  85.  *  30-Dec-87
  86.  */
  87.  
  88. W_Vacate()
  89. {
  90.     ReleaseSemaphore( &WiconSemaphore );
  91. }
  92.  
  93. /*************************************************************************
  94.  * W_Delete - deletes a Winfo[] entry, we must already have
  95.  *                W_Procure ed
  96.  *  01-Jan-88
  97.  */
  98.  
  99. W_Delete(index)
  100. WORD    index;
  101. {
  102.  
  103.     Winfo[index].IconWindow = NULL;
  104.     Winfo[index].Window     = NULL;
  105.     Winfo[index].Flags        = 0;
  106.  
  107.     if (Winfos-1==index)
  108.     Winfos--;
  109. }
  110.  
  111. /*************************************************************************
  112.  * W_Pull - Winfo[index].IconWindow was pushed, which means
  113.  *             we should Pull Winfo[index].Window
  114.  *             Called from W_Push
  115.  *  02-Jan-88
  116.  */
  117.  
  118. W_Pull( Window, index )
  119. struct Window *Window;
  120. WORD          index;
  121. {
  122.  
  123.  
  124.     W_Procure();        /* We want to access the Winfo[] structure, if
  125.                someone else is using it, the W_Procure() will
  126.                make us Wait() until they are finished */
  127.  
  128.     if (Winfo[index].IconWindow == Window)
  129.     {
  130.         if (Winfo[index].Flags & WINFO_CLOSING)
  131.         {
  132.         W_Vacate(); /* That window is being closed, forget it! */
  133.         return;
  134.         }
  135.         else
  136.         {
  137.         if (Winfo[index].Flags & WINFO_WAIT)
  138.         {
  139.             /* this is the only process that should be using the
  140.                WINFO_WAIT flag */
  141.             DBG("WICON: a Window has WAIT?\n");
  142.             W_Vacate();
  143.             return;
  144.         }
  145.         else
  146.         {
  147.             /* Now other processes can't access the Winfo[]
  148.                structure for this window, eg through our CloseWindow
  149.                vector */
  150.             Winfo[index].Flags |= WINFO_WAIT;
  151.         }
  152.         }
  153.     }
  154.     else
  155.     {
  156.         W_Vacate();
  157.         return;
  158.     }
  159.  
  160.     W_Vacate();
  161.  
  162.     /* At this stage we have suspended the particular window from closing
  163.        because we have our own WAIT on it. we must release this when we are
  164.        finished so that other things can continue */
  165.  
  166.     PUSH( Winfo[index].IconWindow );
  167.  
  168.     /* Does the Mac-like rubber banding */
  169.  
  170.     SizeRec( Window->WScreen, &(Winfo[index].IconWindow->LeftEdge),
  171.                   &(Winfo[index].Window->LeftEdge)      );
  172.  
  173.     /* The hidden window magically reappears... */
  174.  
  175.     PULL( Winfo[index].Window );
  176.  
  177.     W_Procure();
  178.     {
  179.     Winfo[index].Flags ^= WINFO_WAIT;
  180.     }
  181.     W_Vacate();
  182.  
  183. }
  184.  
  185.  
  186. /*************************************************************************
  187.  * W_CheckWindow - check our list of windows that it does exist
  188.  *           this is mainly because I'm paranoid, but a
  189.  *           Window may get closed before we get a message
  190.  *           saying we have pushed this particular window
  191.  *  30-Dec-88
  192.  */
  193.  
  194. LONG W_CheckWindow( Window )
  195. struct    Window *Window;
  196. {
  197.     struct  Window  *CheckWindow;
  198.  
  199.     /* Don't trust anyone, check that the Window exists for ourselves */
  200.  
  201.     Forbid();
  202.  
  203.     CheckWindow = WiconScreen->FirstWindow;
  204.  
  205.     while (CheckWindow)
  206.     {
  207.     if (CheckWindow == Window)
  208.         break;
  209.  
  210.     CheckWindow = CheckWindow->NextWindow;
  211.     }
  212.  
  213.     Permit();
  214.  
  215.     return ((LONG)CheckWindow);
  216. }
  217.  
  218.  
  219. /*************************************************************************
  220.  *
  221.  * W_Push - a window has been pushed 21-Apr-87
  222.  *
  223.  */
  224. W_Push( Window )
  225. struct    Window *Window;
  226. {
  227.     WORD    i;
  228.  
  229.     W_Procure();
  230.  
  231.     for (i=0;i<Winfos;i++)
  232.     if (Winfo[i].IconWindow == Window)
  233.         break;
  234.  
  235.     if (i!=Winfos)
  236.     {
  237.     W_Vacate();
  238.  
  239.     W_Pull( Window, i );
  240.  
  241.     return;
  242.     }
  243.  
  244.     for (i=0;i<Winfos;i++)
  245.     {
  246.     if (Winfo[i].Window == Window)
  247.     {
  248.         /* We're in business */
  249.  
  250.         if (Winfo[i].Flags & WINFO_CLOSING)
  251.         {
  252.         W_Vacate();
  253.         return;
  254.         }
  255.  
  256.         if (Winfo[i].Flags & WINFO_WAIT)
  257.         {
  258.         DBG("WICON: Window, WAIT active?\n");
  259.         W_Vacate();
  260.         return;
  261.         }
  262.  
  263.         break;
  264.     }
  265.     }
  266.  
  267.     if (i==Winfos)  /* Then we need to create a new entry */
  268.     {
  269.     if (!W_CheckWindow(Window))     /* Check its existence */
  270.     {
  271.         W_Vacate();
  272.         return;
  273.     }
  274.  
  275.     if ((Window->RPort->Layer->Flags & LAYERBACKDROP) ||
  276.         ((Window->Flags & WBENCHWINDOW ) && (!Arg_WBWs)) )
  277.     {
  278.         W_Vacate();
  279.         return;
  280.     }
  281.  
  282.     for (i=0;i<Winfos;i++)                      /* search for empty slot */
  283.         if ((Winfo[i].Flags & WINFO_USED)==0)
  284.         break;
  285.  
  286.     if (i==MAXWINFO)
  287.     {
  288.         DBG("WICON: not enough Winfo slots\n");
  289.         W_Vacate();
  290.         return;
  291.     }
  292.  
  293.     if (i==Winfos)
  294.         Winfos++;
  295.  
  296.     Winfo[i].Window     = Window;
  297.     Winfo[i].Flags        = 0;
  298.     Winfo[i].IconWindow = NULL;
  299.     }
  300.  
  301.     /* Here we are saying (to CloseWindow & W_Close), I am playing with
  302.        these data structures, don't touch until I say so */
  303.  
  304.     Winfo[i].Flags |= (WINFO_WAIT | WINFO_USED);
  305.  
  306.     W_Vacate();
  307.  
  308.  
  309.     PUSH( Winfo[i].Window );
  310.  
  311.     if (Winfo[i].IconWindow)
  312.     {
  313.     SizeRec( Window->WScreen, &(Winfo[i].Window->LeftEdge),
  314.                     &(Winfo[i].IconWindow->LeftEdge) );
  315.  
  316.     if (Arg_Sticky)
  317.     {
  318.         struct Window *w = Winfo[i].IconWindow;
  319.         WindowToFront( w );
  320.         Delay(1L);
  321.         ActivateWindow( w );
  322.         if (w->TopEdge < 5) /* almost hidden behind screen title */
  323.             MoveWindow(w, 5, 0);
  324.     }
  325.     else
  326.         PULL( Winfo[i].IconWindow );
  327.  
  328.     W_Procure();
  329.     {
  330.         Winfo[i].Flags ^= WINFO_WAIT;
  331.     }
  332.     W_Vacate();
  333.     }
  334.     else
  335.     {
  336.     struct NewWindow NewWindow;
  337.  
  338.     /* No I didn't copy this from that textbook :-> */
  339.  
  340.  
  341.     NewWindow.LeftEdge    = Window->LeftEdge;   /* See also */
  342.     NewWindow.TopEdge     = Window->TopEdge;    /* GetNextIconPos */
  343.     NewWindow.Screen      = Window->WScreen;
  344.     NewWindow.Flags       = ACTIVATE | SMART_REFRESH | WINDOWDRAG
  345.                   | (Arg_Sticky || !Arg_Depth ? 0 : WINDOWDEPTH);
  346.     NewWindow.Width       = Arg_Chars * NewWindow.Screen->RastPort.TxWidth
  347.                   + (NewWindow.Flags & WINDOWDEPTH ? 52 : 0 );
  348.     NewWindow.Height      = 10;
  349.     NewWindow.DetailPen   = 1;
  350.     NewWindow.BlockPen    = 2;
  351.     NewWindow.IDCMPFlags  = 0;   /* we have to put some in later */
  352.     NewWindow.FirstGadget = NULL;
  353.     NewWindow.CheckMark   = NULL;
  354.     NewWindow.Title       = Window->Title;
  355.     NewWindow.BitMap      = NULL;
  356.     NewWindow.MinWidth    = 50;
  357.     NewWindow.MinHeight   = 10;
  358.     NewWindow.MaxWidth    = -1;
  359.     NewWindow.MaxHeight   = 15;
  360.     NewWindow.Type          = CUSTOMSCREEN;
  361.  
  362.     GetNextIconPos( &NewWindow );   /* Overwrite Edges if Arg_Lines */
  363.  
  364.     /* Do a couple of minor checks here for Limits */
  365.  
  366.     if (NewWindow.LeftEdge + NewWindow.Width > NewWindow.Screen->Width)
  367.         if (NewWindow.Screen->Width > NewWindow.Width)
  368.         NewWindow.LeftEdge = NewWindow.Screen->Width - NewWindow.Width;
  369.  
  370.     SizeRec( Window->WScreen, &(Winfo[i].Window->LeftEdge),
  371.                            &(NewWindow.LeftEdge) );
  372.  
  373.  
  374.     if ( (Winfo[i].IconWindow = OldOpenWindow(&NewWindow)) == NULL) /* failure */
  375.     {
  376.         PULL( Winfo[i].Window );
  377.  
  378.         W_Procure();
  379.         {
  380.         W_Delete(i);
  381.         }
  382.         W_Vacate();
  383.     }
  384.     else
  385.     {
  386.         SetWindowTitles(Winfo[i].IconWindow, -1L, Winfo[i].Window->ScreenTitle);
  387.  
  388.         /* Intuition won't give us a DRAG bar if we open a
  389.          * window.Flags |= BACKDROP, so to get the desired effect we open
  390.          * one normally, make it a BACKDROP, then WindowToBack(), and
  391.          * WindowToFront() it to get it between the WorkBench Window
  392.          * (icons etc.) and other (normal) windows. ie acting like a
  393.          * draggable icon
  394.          */
  395.  
  396.         if (Arg_Sticky)
  397.         {
  398.         register struct Window *w = Winfo[i].IconWindow;
  399.  
  400.         w->RPort->Layer->Flags |= LAYERBACKDROP;
  401.         WindowToBack( w );
  402.         Delay( 1L );
  403.         WindowToFront( w );
  404.         }
  405.  
  406.         W_Procure();
  407.         {
  408.         Winfo[i].Flags ^= WINFO_WAIT;
  409.         }
  410.         W_Vacate();
  411.     }
  412.  
  413.     }
  414.  
  415. }   /* W_Push */
  416.  
  417.  
  418. /*************************************************************************
  419.  *
  420.  *  W_Close - closes a window if it is not locked
  421.  *
  422.  */
  423.  
  424. W_Close( Window )
  425. struct    Window    *Window;
  426. {
  427.  
  428.     WORD    i,Found=FALSE,Flags;
  429.  
  430.     static struct BoxInfo ToBox = { 0,0,0,0 };
  431.        struct BoxInfo FromBox;
  432.  
  433.     if (Window->WScreen != WiconScreen)
  434.     {
  435.     if (!Arg_AllScreens)
  436.         return ( OldCloseWindow( Window ) );
  437.     }
  438.     else
  439.     {
  440.     W_Procure();
  441.  
  442.     for (i=0;i<Winfos;i++)  /* Is this window under our management ? */
  443.     {
  444.         if (Winfo[i].Window == Window)
  445.         {
  446.         /* We're in business */
  447.         if (Winfo[i].Flags & WINFO_CLOSING)
  448.         {
  449.             /* Give up its closing anyway (should never happen) */
  450.             W_Vacate();
  451.             return;
  452.         }
  453.  
  454.         if (Winfo[i].Flags & WINFO_WAIT)
  455.             /* someone's got it, wait for it */
  456.             while (Winfo[i].Flags & WINFO_WAIT)
  457.             {
  458.             W_Vacate();
  459.             Delay(5L);  /* 5/50ths of a second */
  460.             W_Procure();
  461.             }
  462.  
  463.         Winfo[i].Flags |= WINFO_CLOSING;
  464.         Found = TRUE;
  465.         break;    /* Quit the for loop */
  466.         }
  467.     }
  468.  
  469.     W_Vacate();
  470.     }
  471.  
  472.     FromBox = *((struct BoxInfo *)&Window->LeftEdge);
  473.  
  474.     OldCloseWindow( Window );
  475.  
  476.     ToBox.LeftEdge = FromBox.LeftEdge + (FromBox.Width  >> 1);
  477.     ToBox.TopEdge  = FromBox.TopEdge  + (FromBox.Height >> 1);
  478.  
  479.     SizeRec( Window->WScreen, &FromBox, &ToBox );
  480.  
  481.     if (Found)
  482.     {
  483.     /* Note: the IconWindow may be no longer there (W_Cleanup()) */
  484.  
  485.     if (Winfo[i].IconWindow)
  486.     {
  487.         Flags = Winfo[i].IconWindow->RPort->Layer->Flags;
  488.         FromBox = *((struct BoxInfo *)&Window->TopEdge);
  489.  
  490.         OldCloseWindow( Winfo[i].IconWindow );
  491.  
  492.         if (!(Flags & LAYERBACKDROP))
  493.         {
  494.         ToBox.LeftEdge = FromBox.LeftEdge + FromBox.Width  >> 1;
  495.         ToBox.TopEdge  = FromBox.TopEdge  + FromBox.Height >> 1;
  496.  
  497.         SizeRec( Winfo[i].IconWindow->WScreen, &FromBox, &ToBox );
  498.         }
  499.     }
  500.  
  501.     W_Procure();
  502.  
  503.      W_Delete(i);
  504.  
  505.     W_Vacate();
  506.  
  507.     }
  508.  
  509. } /* W_Close */
  510.  
  511. /*************************************************************************
  512.  *
  513.  * W_Cleanup - restores all the windows back
  514.  *
  515.  */
  516.  
  517. W_Cleanup()
  518. {
  519.     WORD    i;
  520.     WORD    WinfoSize=Winfos;
  521.  
  522.     W_Procure();
  523.  
  524.     for (i=0;i<WinfoSize;i++)
  525.     {
  526.     if (Winfo[i].Flags & WINFO_USED)
  527.     {
  528.         if ((Winfo[i].Flags & WINFO_CLOSING)==0 )
  529.         {
  530.         Winfo[i].Flags |= WINFO_WAIT;
  531.  
  532.         W_Vacate();
  533.  
  534.         if (Winfo[i].IconWindow)
  535.             OldCloseWindow( Winfo[i].IconWindow );
  536.  
  537.         if  (Winfo[i].Window->RPort->Layer->Flags & LAYERBACKDROP)
  538.             PULL( Winfo[i].Window );
  539.  
  540.         W_Procure();
  541.  
  542.         W_Delete(i);
  543.         }
  544.     }
  545.     }
  546.  
  547.     W_Vacate();
  548.  
  549.     Winfos = 0;
  550. }
  551.  
  552. /*************************************************************************
  553.  *
  554.  * _wb_parse - stub so we don't get Manx C's
  555.  *
  556.  */
  557.  
  558. _wb_parse()
  559. {}
  560.  
  561. /*************************************************************************
  562.  *
  563.  * GetNextIconPos - keeps track of the last icon position, and creates
  564.  *            a non-overlapping line of them
  565.  * 21-Apr-88
  566.  */
  567. GetNextIconPos( NewWindow )
  568. struct NewWindow *NewWindow;
  569. {
  570. #define YGAP    (2)      /* spacing */
  571. #define XGAP    (4)       /* between icons */
  572.  
  573.     static WORD IconX=0,IconY=0;
  574.     static short Top;
  575.  
  576.     short width  = NewWindow->Width + XGAP;
  577.     short height = NewWindow->Height + YGAP;
  578.  
  579.     if (Arg_Lines)
  580.     {
  581.     if (IconY==0)
  582.     /* Set up everything & first position */
  583.     {
  584.         IconX = 0;
  585.         IconY = Top = WiconScreen->Height - height * Arg_Lines;
  586.     }
  587.     else
  588.     /* back for more */
  589.     {
  590.         if ((IconX += width) > WiconScreen->Width - NewWindow->Width)
  591.         {
  592.         IconX = 0;
  593.         if (IconY < Top)
  594.         {
  595.             if ((IconY -= height) < 0)    /* building upwards */
  596.                IconY = 0;  /* 100's of windows or a small screen */
  597.         }
  598.         else
  599.         {
  600.             if ((IconY += height) > WiconScreen->Height - NewWindow->Height)
  601.             IconY = Top - height;
  602.         }
  603.         }
  604.     }
  605.     NewWindow->TopEdge  = IconY;
  606.     NewWindow->LeftEdge = IconX;
  607.     }
  608.  
  609. } /* GetNextIconPos */
  610.  
  611.