/******************************************************************************
 * This file is part of a software distribution, which is furnished under the *
 * terms of a license.  Use of this software  by any means is subject to this *
 * license  and  signifies  the  acceptance of  the  licensing  terms  stated *
 * therein. Please see  the file LICENSE in the  top-level directory  of this *
 * software  distribution  for detailed copyright  disclaimers  and licensing *
 * terms.                                                                     *
 ******************************************************************************
 * Copryight (c) by Andreas S. Wetzel - All rights reserved.                  *
 ******************************************************************************/

/* $Id: statusbar.c,v 1.2 2001/03/19 14:54:02 mickey Exp $ */

#include <vchat.h>
#include <proto_common.h>

#include <sys/ioctl.h>

/*** Globals ***/

u_long var_space = 0;

STAT_ITEM st_item[STAT_MAX];

u_char prio_to_item[] =
{
	STAT_LOGO,
	STAT_VARSP,
	STAT_FLAGS,
	STAT_CLOCK,
	STAT_CHAN,
	STAT_NICK,
	STAT_SERVER,
	STAT_ONLINE,
	STAT_SIZE,
	STAT_TERM
};

u_char item_to_prio[] = {0, 2, 3, 6, 7, 5, 4, 1, 9, 8};

/*** Externals ***/

extern int in_chat_window;

extern VP vp;
extern ED *ed;
extern VTCAP vtcap;
extern VCONN sconn;

/*** Code ***/

void init_status(void)
{
	u_char tbuf[6];
	time_t now;

	time(&now);

	BZERO(&tbuf, 6);
	strftime(tbuf, 6, "%H:%M", localtime(&now));

	/*
	 * Initialize certain commandline elements
	 */

	alter_status(STAT_LOGO, " VChat ");

	update_flags();

	alter_status(STAT_CLOCK, "%s ", tbuf);
	alter_status(STAT_ONLINE, "00:00 ");
	alter_status(STAT_NICK, "%s ", vp.nick);
	alter_status(STAT_CHAN, "%d ", 0);
	alter_status(STAT_TERM, "%s ", vp.emulation);
	alter_status(STAT_SIZE, "%dx%d ", vtcap.cols, vtcap.rows);
	alter_status(STAT_SERVER, "%s ", sconn.host);
}

void alter_status(u_char item, char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);

	vsprintf(st_item[item].buf, fmt, ap);

	st_item[item].flags |= NEEDS_UPDATE;

	va_end(ap);
}

void update_flags(void)
{
	u_char	statbuf[] = "_ _ _";

	if(vp.logswitch == 1)
		statbuf[4] = 'L';

	if(vp.cmdmode == 1)
		statbuf[0] = 'S';

	alter_status(STAT_FLAGS, "%s ", statbuf);
	update_status(0);
}

void update_status(u_char redraw)
{
	static	u_char	old_prio = -1;
	static	u_short old_size_x = -1;
	static	u_short old_size_y = -1;
	u_char	maxpri;

	/*
	 * Lock out signals until completed
	 */

	vlock(LOCK, (V_IO | V_TIMER | V_WINCH));

	/*
	 * Calculate max priority
	 */

	maxpri = status_maxpriority();

	/*
	 * Check if window size or priority
	 * has changed since last update.
	 */

	if(redraw || maxpri != old_prio || vtcap.cols != old_size_x || vtcap.rows != old_size_y)
	{
		full_update(maxpri);
	}
	else
	{
		optimized_update(maxpri);
	}

	old_size_x = vtcap.cols;
	old_size_y = vtcap.rows;
	old_prio = maxpri;

	/*
	 * Release SIGWINCH
	 */

	vlock(UNLOCK, (V_IO | V_TIMER | V_WINCH));
}

/*
 * Berechnen der maximalen Prioritaet die
 * bei der aktuellen Bildschirmbreite
 * zur Ausgabe kommen kann, sowie der
 * Breite des variablen space.
 */

u_char status_maxpriority(void)
{
	int size = 0;
	u_char prio = 0;


	for(prio = 0; prio < STAT_MAX; prio++)
	{
		if(prio_to_item[prio] == STAT_VARSP)
			continue;

		if((size + strlen(st_item[prio_to_item[prio]].buf)) <= vtcap.cols)
			size += strlen(st_item[prio_to_item[prio]].buf);
		else
			break;
	}

	var_space = (vtcap.cols - size);

	return(prio-1);
}

void full_update(u_char maxpri)
{
	u_char i;

	if(HAS_SRC && !in_chat_window)
		tputs(vtcap.csave, 1, (void *)outc);

	mv(1, (vtcap.rows - 1));

	if(HAS_COLOR)
	{
		tputs(vtcap.off, 1, (void *)outc);
		tputs(tparm(vtcap.set_fg_color, 7), 1, (void *)outc);
		tputs(tparm(vtcap.set_bg_color, 4), 1, (void *)outc);
	}
	else
	{
		tputs(vtcap.reverse, 1, (void *)outc);
	}

	if(vtcap.bold)
		tputs(vtcap.bold, 1, (void *)outc);

	for(i = 0; i < STAT_MAX; i++)
	{
		if(item_to_prio[i] > maxpri)
			continue;

		if(i == STAT_VARSP)
		{
			printf("%*s", (int)var_space, " ");
			st_item[i].size = var_space;
		}
		else if(i == STAT_LOGO)
		{
			if(HAS_COLOR)
			{
				tputs(tparm(vtcap.set_fg_color, 5), 1, (void *)outc);
				printf(" V");
				tputs(tparm(vtcap.set_fg_color, 3), 1, (void *)outc);
				printf("Chat ");
				tputs(tparm(vtcap.set_fg_color, 7), 1, (void *)outc);
			}
			else
			{
				printf("%s", st_item[i].buf);
			}

			st_item[i].size = strlen(st_item[i].buf);
		}
		else
		{
			printf("%s", st_item[i].buf);
			st_item[i].size = strlen(st_item[i].buf);
		}

		st_item[i].flags &= ~NEEDS_UPDATE;
	}

	if(vtcap.off)
		tputs(vtcap.off, 1, (void *)outc);

	if(HAS_SRC && !in_chat_window)
	{
		tputs(vtcap.crestore, 1, (void *)outc);
	}
	else
	{
		mv(ED_SCRPOS, vtcap.rows);
		in_chat_window = 0;
	}
}

void optimized_update(u_char maxpri)
{
	u_short offset = 1;
	u_char has_changed = 0;
	u_char action = 0;
	u_char i;

	for(i = 0; i < STAT_MAX; i++)
	{
		/*
		 * Skip items with priority > maxpri
		 */

		if(item_to_prio[i] > maxpri)
			continue;

		/*
		 * Optimize update
		 */

		if(!has_changed)
		{
			if(st_item[i].flags & NEEDS_UPDATE)
			{
				if(HAS_SRC && !in_chat_window && !action)
					tputs(vtcap.csave, 1, (void *)outc);

				mv(offset, (vtcap.rows - 1));

				if(!action)
				{
					action = 0xff;

					if(HAS_COLOR)
					{
						tputs(tparm(vtcap.set_bg_color, 4), 1, (void *)outc);
						tputs(tparm(vtcap.set_fg_color, 7), 1, (void *)outc);
					}
					else
					{
						tputs(vtcap.reverse, 1, (void *)outc);
					}

					if(vtcap.bold)
						tputs(vtcap.bold, 1, (void *)outc);

				}

				if(strlen(st_item[i].buf) != st_item[i].size)
					has_changed = 0xff;

				if(i == STAT_VARSP)
				{
					printf("%*s", (int)var_space, " ");
					st_item[i].size = var_space;
				}
				else if(i == STAT_LOGO)
				{
					if(HAS_COLOR)
					{
						tputs(tparm(vtcap.set_fg_color, 5), 1, (void *)outc);
						printf(" V");
						tputs(tparm(vtcap.set_fg_color, 3), 1, (void *)outc);
						printf("Chat ");
						tputs(tparm(vtcap.set_fg_color, 7), 1, (void *)outc);
					}
					else
					{
						printf("%s", st_item[i].buf);
					}

					st_item[i].size = strlen(st_item[i].buf);
				}
				else
				{
					printf("%s", st_item[i].buf);
					st_item[i].size = strlen(st_item[i].buf);
				}

				st_item[i].flags &= ~NEEDS_UPDATE;
				offset += st_item[i].size;
			}
			else
			{
					offset += st_item[i].size;
					continue;
			}
		}
		else
		{
			if(i == STAT_VARSP)
			{
				printf("%*s", (int)var_space, " ");
				st_item[i].size = var_space;
			}
			else if(i == STAT_LOGO)
			{
				if(HAS_COLOR)
				{
					tputs(tparm(vtcap.set_fg_color, 5), 1, (void *)outc);
					printf(" V");
					tputs(tparm(vtcap.set_fg_color, 3), 1, (void *)outc);
					printf("Chat ");
					tputs(tparm(vtcap.set_fg_color, 7), 1, (void *)outc);
				}
				else
				{
					printf("%s", st_item[i].buf);
				}

				st_item[i].size = strlen(st_item[i].buf);
			}
			else
			{
				printf("%s", st_item[i].buf);
				st_item[i].size = strlen(st_item[i].buf);
			}

			st_item[i].flags &= ~NEEDS_UPDATE;
		}
	} /* Loop */

	if(action)
	{
		if(vtcap.off)
			tputs(vtcap.off, 1, (void *)outc);

		if(HAS_SRC && !in_chat_window)
		{
			tputs(vtcap.crestore, 1, (void *)outc);
		}
		else
		{
			mv(ED_SCRPOS, vtcap.rows);
			in_chat_window = 0;
		}
	}
}


syntax highlighted by Code2HTML, v. 0.9.1