//
// cursor.cc
//
// (c) Copyright 1993, San Diego State University -- College of Sciences
//       (See the COPYRIGHT file for more Copyright information)
//
// This file deals with the different cursors which may be used
//
#include <xview/xview.h>
#include <xview/svrimage.h>
#include <xview/cursor.h>
#include <xview/notify.h>


static Cursor		busy_cursor[2];
static Server_image	busy_image[2];
static Cursor		old_cursor;
static int			current_cursor = 0;

#define	BLINK_DELAY	200000

static unsigned short busy1_bits[] = {
#include "icons/gopher1"
};

static unsigned short busy2_bits[] = {
#include "icons/gopher2"
};

//***************************************************************************
// void init_cursors()
//
static void init_cursors()
{
	static int	had_init = FALSE;

	if (had_init)
		return;

	had_init = TRUE;

	busy_image[0] = (Server_image) xv_create(NULL, SERVER_IMAGE,
		XV_WIDTH,					64,
		XV_HEIGHT,					64,
		SERVER_IMAGE_BITS,			busy1_bits,
		NULL);
	busy_cursor[0] = (Cursor) xv_create(NULL, CURSOR,
		CURSOR_IMAGE,				busy_image[0],
		CURSOR_XHOT,				32,
		CURSOR_YHOT,				32,
		NULL);
	busy_image[1] = (Server_image) xv_create(NULL, SERVER_IMAGE,
		XV_WIDTH,					64,
		XV_HEIGHT,					64,
		SERVER_IMAGE_BITS,			busy2_bits,
		NULL);
	busy_cursor[1] = (Cursor) xv_create(NULL, CURSOR,
		CURSOR_IMAGE,				busy_image[1],
		CURSOR_XHOT,				32,
		CURSOR_YHOT,				32,
		NULL);
}


//***************************************************************************
// Server_image get_gopher(int n)
//
Server_image get_gopher(int n)
{
	return busy_image[n];
}


static int	isbusy = FALSE;

//***************************************************************************
// static Notify_value blink_cursor(Frame frame, int which)
//
Notify_value blink_cursor(Frame frame, int which)
{
	which = which;

	current_cursor ^= 1;

	Xv_opaque	sub;
	int			n = 1;
	while ((sub = (Xv_opaque) xv_get(frame, FRAME_NTH_SUBWINDOW, n)) != NULL)
	{
		xv_set(sub,
			WIN_CURSOR,					busy_cursor[current_cursor],
			NULL);
		n++;
	}
	return (Notify_value) 0;
}


//***************************************************************************
// void frame_busy(Frame frame)
//
void frame_busy(Frame frame)
{
	notify_dispatch();
	if (isbusy)
		return;
	isbusy = TRUE;
	init_cursors();
	old_cursor = (Cursor) xv_get(frame, WIN_CURSOR);
	xv_set(frame,
		FRAME_BUSY,					TRUE,
		NULL);

	//
	// Now go through all sub windows and change their cursor
	//
	Xv_opaque	sub;
	int			n = 1;
	while ((sub = (Xv_opaque) xv_get(frame, FRAME_NTH_SUBWINDOW, n)) != NULL)
	{
		xv_set(sub,
			WIN_CURSOR,					busy_cursor[0],
			NULL);
		n++;
	}

	//
	// Start the timer to change the cursor icon every once in a while
	//
	struct itimerval	timer;
	timer.it_value.tv_usec = BLINK_DELAY;
	timer.it_value.tv_sec = 0;
	timer.it_interval.tv_usec = BLINK_DELAY;
	timer.it_interval.tv_sec = 0;
	notify_set_itimer_func(frame, (Notify_func) blink_cursor, ITIMER_REAL, &timer, NULL);
}


//***************************************************************************
// void frame_unbusy(Frame frame)
//
void frame_unbusy(Frame frame)
{
	//
	// First stop the interval timer which is blinking the cursor
	//
	notify_set_itimer_func(frame, NOTIFY_FUNC_NULL, ITIMER_REAL, NULL, NULL);

	notify_dispatch();
	if (!isbusy)
		return;
	isbusy = FALSE;
	init_cursors();
	xv_set(frame,
		FRAME_BUSY,					FALSE,
		NULL);

	//
	// Now go through all sub windows and change their cursor
	//
	Xv_opaque	sub;
	int			n = 1;
	while ((sub = (Xv_opaque) xv_get(frame, FRAME_NTH_SUBWINDOW, n)) != NULL)
	{
		xv_set(sub,
			WIN_CURSOR,					old_cursor,
			NULL);
		n++;
	}
}


