/*
 *  SWINDOWS    A program to allow you to open windows on any screen by
 *              supplying the screen name in thw window title
 *
 *              Copyright 1989 by Davide P. Cervone.
 *  You may use this code, provided this copywrite notice is kept intact.
 */

#include "swHandler.h"


SLISTITEM ScreenList = NULL;    /* the linked list of ScreenListItems */
WLISTITEM WindowList = NULL;    /* the linked list of WindowListItems */


/*
 *  FreeScreenListItem()
 *
 *  Unlink the item from the list, and change the list pointer if
 *  this item was first in the list.
 *  Then free the memory in use by the item.
 */

void FreeScreenListItem(theScreen)
SLISTITEM theScreen;
{
   Forbid();
   if (theScreen->Next) theScreen->Next->Prev = theScreen->Prev;
   if (theScreen->Prev) theScreen->Prev->Next = theScreen->Next;
   if (theScreen == ScreenList)    ScreenList = theScreen->Next;
   FREE(ScreenListItem,theScreen);
   Permit();
}


/*
 *  FreeWindowListItem
 *
 *  Unlink the item from the list, and change the list pointer if
 *  this item was first in the list.  
 *  Then free the memory in use by the item.
 */

void FreeWindowListItem(theWindow)
WLISTITEM theWindow;
{
   Forbid();
   if (theWindow->Next) theWindow->Next->Prev = theWindow->Prev;
   if (theWindow->Prev) theWindow->Prev->Next = theWindow->Next;
   if (theWindow == WindowList)    WindowList = theWindow->Next;
   FREE(WindowListItem,theWindow);
   Permit();
}


/*
 *  NewScreenListItem()
 *
 *  Create a new instance of a ScreenListItem.
 *  If successfull, then
 *    Set the pointer to the Intuition screen.
 *    Add the item into the list.
 *  return the pointer to the new item.
 */

static SLISTITEM NewScreenListItem(theScreen)
struct Screen *theScreen;
{
   SLISTITEM ScreenItem;
   
   if (NEW(ScreenListItem,ScreenItem))
   {
      Forbid();
      ScreenItem->Screen = theScreen;
      ScreenItem->Next = ScreenList;
      ScreenItem->Prev = NULL;
      if (ScreenList) ScreenList->Prev = ScreenItem;
      ScreenList = ScreenItem;
      Permit();
   }
   return(ScreenItem);
}


/*
 *  AddWindowListItem()
 *
 *  For a pre-existing WindowListItem,
 *  Set the window pointer, and add the item into the linked list.
 */

void AddWindowListItem(WindowItem,theWindow)
WLISTITEM WindowItem;
struct Window *theWindow;
{
   Forbid();
   WindowItem->Window = theWindow;
   WindowItem->Next = WindowList;
   WindowItem->Prev = NULL;
   if (WindowList) WindowList->Prev = WindowItem;
   WindowList = WindowItem;
   Permit();
}


/*
 *  FindScreenListItem()
 *
 *  Look through the linked list for the specified screen.
 *  If not found, then try to create a new list item for the screen.
 *  If successful or if it already existed, then increment its use count
 *    (so that the item will not be removed while we are using it)
 *  return the found (or new) screen list item.
 */

SLISTITEM FindScreenListItem(theScreen)
struct Screen *theScreen;
{
   SLISTITEM ScreenItem;
   
   Forbid();
   ScreenItem = ScreenList;
   while (ScreenItem && ScreenItem->Screen != theScreen)
      ScreenItem = ScreenItem->Next;
   if (ScreenItem == NULL) ScreenItem = NewScreenListItem(theScreen);
   if (ScreenItem) ScreenItem->UseCount++;
   Permit();
   return(ScreenItem);
}


/*
 *  UnuseScreenListItem()
 *
 *  Decement the use count for the item.
 *  If this was the last use, then
 *    If a task is waiting to close this screen,
 *      signal that it is now OK to close the screen.
 *    Free the memory in use by the screen item.
 */

void UnuseScreenListItem(ScreenItem)
SLISTITEM ScreenItem;
{
   Forbid();
   ScreenItem->UseCount--;
   if (ScreenItem->UseCount <= 0)
   {
      if (ScreenItem->CloseTask)
         Signal(ScreenItem->CloseTask,ScreenItem->CloseSignal);
      FreeScreenListItem(ScreenItem);
   }
   Permit();
}
