/*
 * LastActiveWindow.c
 *
 * Routines to make Yak remember last active window on screen already visited
 * Part of Yak.
 *
 * Gael Marziou, 6/94.
 */
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <proto/exec.h>
#include <proto/intuition.h>

#include "code.h"


#define SCREEN_ARRAY_SIZE 10

struct {
	struct Screen *Screen;
	struct Window *Window;
} ScreenArray[SCREEN_ARRAY_SIZE];


/* Find a screen in our list */

UBYTE
FoundScreenInList( struct Screen *Screen)
{
	UBYTE i=0;

	/* Try to found a screen that matches ours */
	while ((ScreenArray[i].Screen  != Screen) && 
		   (i<SCREEN_ARRAY_SIZE-1))
	{
		i++;
	}

	if ((i == SCREEN_ARRAY_SIZE - 1) && 
		(ScreenArray[i].Screen  != Screen))
	{
		i = SCREEN_ARRAY_SIZE;
	}
	return(i);
}

/* Try to find dead screens in our list in order to provide some space 
 * If it succeeds, it will return a free index in ScreenArray otherwise 
 * it will return SCREEN_ARRAY_SIZE.
 */

UBYTE 
GarbageCollectorScreenArray(void)
{
	struct Screen *scr;
    UBYTE i;
	ULONG lock;
	BOOL  Lost;
	UBYTE result = SCREEN_ARRAY_SIZE;

	lock = LockIBase(0);

	for (i=0; i<SCREEN_ARRAY_SIZE-1 ; i++)
	{
		Lost = TRUE;
		for (scr = FS; scr && Lost ; scr = scr->NextScreen)
		{
			Lost = (scr != ScreenArray[i].Screen);
		}
		if (Lost)
		{
			/* Remove dead screen */
			ScreenArray[i].Screen = NULL;
			result = i;
		}
	}
	UnlockIBase(lock);
	return(result);
}


/* Store active window of current screen */

void
RememberActiveWindow(void)
{
	ULONG lock;
	struct Window *win;
	UBYTE i;
 
	lock = LockIBase(0);
	win = AW;
	UnlockIBase(lock);

	if (win)
	{
		i = FoundScreenInList(win->WScreen);
		if (i < SCREEN_ARRAY_SIZE)
		{
			ScreenArray[i].Window = win; 
		}
		else
		{
			/* Our screen hasn't been yet visited so add it to our list */
			i = FoundScreenInList(NULL);
			if (i == SCREEN_ARRAY_SIZE)
			{
				/* We haven't found a free space, try to free some */
				i = GarbageCollectorScreenArray();
			}
			if (i < SCREEN_ARRAY_SIZE)
			{
				/* We have found a free space */
				ScreenArray[i].Screen = win->WScreen;
				ScreenArray[i].Window = win; 
			}
		}
	}
}


/* Returns a pointer on active window of last time we visit this screen 
 * if possible.
 */

struct Window 
*LastActiveWindow(struct Screen *CurrentScreen)
{
    struct Window *win;
	UBYTE i;

    if (CurrentScreen)
    {
		/* default */
		win = CurrentScreen->FirstWindow;

		i = FoundScreenInList(CurrentScreen);	
		if (i < SCREEN_ARRAY_SIZE)
		{
			/* Is our window still alive or still on our screen ? */
			for (win = CurrentScreen->FirstWindow; win ; win = win->NextWindow)
			{
				if (win == ScreenArray[i].Window)
					break;
			}
			if (!win) 
				win = CurrentScreen->FirstWindow;
		}
	}
	else
	{
		win = NULL;
	}
    return(win);
}




#ifdef DEBUG_LAW

/* Well it has been debugged but who knows, it can help in the future */


void
main(void)
{
	char c = 0;
	struct Screen *scr;
    ULONG i;
	ULONG lock;
    
	while(c!='q')
	{
		scanf("%c",&c);
		switch (c)
		{
		  case 'r':	
			for (i=0; i<SCREEN_ARRAY_SIZE; i++)
			{
				printf("i = %d\n",i);
				if (ScreenArray[i].Screen)
				{
					printf("ScreenArray[%d].Screen = %d\n",i,ScreenArray[i].Screen);
					if (ScreenArray[i].Window->Title)
						printf("ScreenArray[%d].Window->Title = %s\n",i,ScreenArray[i].Window->Title);
				}
			}
			break;

		  case 'c':
			lock = LockIBase(0);
			scr = FS;
			UnlockIBase(lock);
			
			RememberActiveWindow();
			ScreenToFront(scr->NextScreen);
			Delay(200);
			RememberActiveWindow();
			break;

		  case 'g': 
			GarbageCollectorScreenArray();
			break;

		  case 'a':
			scanf("%d",&i);
			if (LastActiveWindow(ScreenArray[i].Screen))
			{
				if (LastActiveWindow(ScreenArray[i].Screen)->Title)
					printf("LastActiveWindow(ScreenArray[%d].Screen)->Title = %s\n",i,LastActiveWindow(ScreenArray[i].Screen)->Title);
			}
			else
			{
				printf("NULL\n");
			}
			break;
		}
	}

}

#endif

