/*
 * status.c: handles the status line updating, etc for IRCII 
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 */

#if 0
static	char	rcsid[] = "$Id: status.c,v 1.15 1994/03/18 13:40:48 mrgreen Exp $";
#endif

#include "irc.h"

#include "dcc.h"
#include "term.h"
#include "status.h"
#include "server.h"
#include "vars.h"
#include "hook.h"
#include "input.h"
#include "edit.h"
#include "window.h"
#include "screen.h"
#include "mail.h"
#include "output.h"
#include "names.h"
#include "ircaux.h"
#include "translat.h"

extern	time_t	time _((time_t *));

extern	char	*update_clock _((int));
static	char	*convert_format _((char *, int));
static	char	*status_nickname _((Window *));
static	char	*status_query_nick _((Window *));
static	char	*status_right_justify _((Window *));
static	char	*status_chanop _((Window *));
static	char	*status_channel _((Window *));
static	char	*status_server _((Window *));
static	char	*status_mode _((Window *));
static	char	*status_umode _((Window *));
static	char	*status_insert_mode _((Window *));
static	char	*status_overwrite_mode _((Window *));
static	char	*status_away _((Window *));
static	char	*status_oper _((Window *));
static	char	*status_user0 _((Window *));
static	char	*status_user1 _((Window *));
static	char	*status_user2 _((Window *));
static	char	*status_user3 _((Window *));
/* It'd be nice to see a few more of these... -- Jake [WinterHawk] Khuon */
static	char	*status_user4 _((Window *));
static	char	*status_user5 _((Window *));
static	char	*status_user6 _((Window *));
static	char	*status_user7 _((Window *));
static	char	*status_user8 _((Window *));
static	char	*status_user9 _((Window *));
/* We'll save these for later... I'm lazy -- Jake [WinterHawk] Khuon
static	char	*status_user10 _((Window *));
static	char	*status_user11 _((Window *));
static	char	*status_user12 _((Window *));
static	char	*status_user13 _((Window *));
static	char	*status_user14 _((Window *));
static	char	*status_user15 _((Window *));
static	char	*status_user16 _((Window *));
static	char	*status_user17 _((Window *));
static	char	*status_user18 _((Window *));
static	char	*status_user19 _((Window *));
static	char	*status_user20 _((Window *));
*/
static	char	*status_dcc _((Window *));
static	char	*status_hold _((Window *));
static	char	*status_version _((Window *));
static	char	*status_clock _((Window *));
static	char	*status_hold_lines _((Window *));
static	char	*status_window _((Window *));
static	char	*status_mail _((Window *));
static	char	*status_refnum _((Window *));
static	char	*status_null_function _((Window *));
static	char	*status_notify_windows _((Window *));
static	char	*status_voice _((Window *));
static	void	status_make_printable _((unsigned char *, int));

/*
 * Maximum number of "%" expressions in a status line format.  If you change
 * this number, you must manually change the sprintf() in make_status 
 *
 *
 * This number will need to change to 50 when I impliment more status_user
 * variables.					-- Jake [WinterHawk] Khuon
 */
#define MAX_FUNCTIONS 40

/* The format statements to build each portion of the status line */
static	char	*mode_format = (char *) 0;
static	char	*umode_format = (char *) 0;
static	char	*status_format[3] = {NULL, NULL, NULL};
static	char	*query_format = (char *) 0;
static	char	*clock_format = (char *) 0;
static	char	*hold_lines_format = (char *) 0;
static	char	*channel_format = (char *) 0;
static	char	*mail_format = (char *) 0;
static	char	*server_format = (char *) 0;
static	char	*notify_format = (char *) 0;

/*
 * status_func: The list of status line function in the proper order for
 * display.  This list is set in convert_format() 
 */
static	char	*(*status_func[3][MAX_FUNCTIONS]) _((Window *));

/* func_cnt: the number of status line functions assigned */
static	int	func_cnt[3];

static	int	alarm_hours,		/* hour setting for alarm in 24 hour time */
		alarm_minutes;		/* minute setting for alarm */

/* Stuff for the alarm */
static	struct itimerval clock_timer = { { 10L, 0L }, { 1L, 0L } };
static	struct itimerval off_timer = { { 0L, 0L }, { 0L, 0L } };

static	RETSIGTYPE alarmed _((int));

/* alarmed: This is called whenever a SIGALRM is received and the alarm is on */
#ifdef __STDC__
static	RETSIGTYPE alarmed (int unused)
#else
static	RETSIGTYPE alarmed(unused)
	int	unused;
#endif
{
	say("The time is %s", update_clock(GET_TIME));
	term_beep();
	term_beep();
	term_beep();
}

/*
 * alarm_switch: turns on and off the alarm display.  Sets the system timer
 * and sets up a signal to trap SIGALRMs.  If flag is 1, the alarmed()
 * routine will be activated every 10 seconds or so.  If flag is 0, the timer
 * and signal stuff are reset 
 */
#ifdef __STDC__
static	void	alarm_switch (int flag)
#else
static	void alarm_switch(flag)
	int	flag;
#endif
{
	static	int	alarm_on = 0;

	if (flag)
	{
		if (!alarm_on)
		{
			setitimer(ITIMER_REAL, &clock_timer,
				(struct itimerval *) 0);
			(void) MY_SIGNAL(SIGALRM, alarmed, 0);
			alarm_on = 1;
		}
	}
	else if (alarm_on)
	{
		setitimer(ITIMER_REAL, &off_timer, (struct itimerval *) 0);
		(void) MY_SIGNAL(SIGALRM, SIG_IGN, 0);
		alarm_on = 0;
	}
}

/*
 * set_alarm: given an input string, this checks it's validity as a clock
 * type time thingy.  It accepts two time formats.  The first is the HH:MM:XM
 * format where HH is between 1 and 12, MM is between 0 and 59, and XM is
 * either AM or PM.  The second is the HH:MM format where HH is between 0 and
 * 23 and MM is between 0 and 59.  This routine also looks for one special
 * case, "OFF", which sets the alarm string to null 
 */
#ifdef __STDC__
void	set_alarm (char *str)
#else
void set_alarm(str)
	char	*str;
#endif
{
	char	hours[10],
		minutes[10],
		merid[3];
	char	time_str[10];
	int	c,
		h,
		m,
		min_hours,
		max_hours;

	if (str == (char *) 0)
	{
		alarm_switch(0);
		return;
	}
	if (!my_stricmp(str, var_settings[OFF]))
	{
		set_string_var(CLOCK_ALARM_VAR, (char *) 0);
		alarm_switch(0);
		return;
	}

	c = sscanf(str, " %2[^:]:%2[^paPA]%2s ", hours, minutes, merid);
	switch (c)
	{
	case 2:
		min_hours = 0;
		max_hours = 23;
		break;
	case 3:
		min_hours = 1;
		max_hours = 12;
		upper(merid);
		break;
	default:
		say("CLOCK_ALARM: Bad time format.");
		set_string_var(CLOCK_ALARM_VAR, (char *) 0);
		return;
	}

	h = atoi(hours);
	m = atoi(minutes);
	if (h >= min_hours && h <= max_hours && isdigit(hours[0]) &&
		(isdigit(hours[1]) || hours[1] == (char) 0))
	{
		if (m >= 0 && m <= 59 && isdigit(minutes[0]) &&
				isdigit(minutes[1]))
		{
			alarm_minutes = m;
			alarm_hours = h;
			if (max_hours == 12)
			{
				if (merid[0] != 'A')
				{
					if (merid[0] == 'P')
					{
						if (h != 12)
							alarm_hours += 12;
					}
					else
					{
	say("CLOCK_ALARM: alarm time must end with either \"AM\" or \"PM\"");
	set_string_var(CLOCK_ALARM_VAR, (char *) 0);
					}
				}
                                else
                                {
                                        if (h == 12)
                                                alarm_hours = 0;
                                }
				if (merid[1] == 'M')
				{
					sprintf(time_str, "%02d:%02d%s", h, m,
						merid);
					set_string_var(CLOCK_ALARM_VAR,
						time_str);
				}
				else
				{
	say("CLOCK_ALARM: alarm time must end with either \"AM\" or \"PM\"");
	set_string_var(CLOCK_ALARM_VAR, (char *) 0);
				}
			}
			else
			{
				sprintf(time_str, "%02d:%02d", h, m);
				set_string_var(CLOCK_ALARM_VAR, time_str);
			}
		}
		else
		{
	say("CLOCK_ALARM: alarm minutes value must be between 0 and 59.");
	set_string_var(CLOCK_ALARM_VAR, (char *) 0);
		}
	}
	else
	{
		say("CLOCK_ALARM: alarm hour value must be between %d and %d.",
			min_hours, max_hours);
		set_string_var(CLOCK_ALARM_VAR, (char *) 0);
	}
}

/* update_clock: figures out the current time and returns it in a nice format */
#ifdef __STDC__
char	*update_clock (int flag)
#else
char	* update_clock(flag)
	int	flag;
#endif
{
	static	char	time_str[10];
	static	int	min = -1,
			hour = -1;
	struct tm	*time_val;
	char	*merid;
	time_t	t;

	t = time(0);
	time_val = localtime(&t);
	if (get_string_var(CLOCK_ALARM_VAR))
	{
		if ((time_val->tm_hour == alarm_hours) &&
				(time_val->tm_min == alarm_minutes))
			alarm_switch(1);
		else
			alarm_switch(0);
	}
	if (flag == RESET_TIME || time_val->tm_min != min || time_val->tm_hour != hour)
	{
		int	tmp_hour,
			tmp_min,
			server;

		tmp_hour = time_val->tm_hour;
		tmp_min = time_val->tm_min;

		if (get_int_var(CLOCK_24HOUR_VAR))
			merid = empty_string;
		else
		{
			if (time_val->tm_hour < 12)
				merid = "AM";
			else
				merid = "PM";
			if (time_val->tm_hour > 12)
				time_val->tm_hour -= 12;
			else if (time_val->tm_hour == 0)
				time_val->tm_hour = 12;
		}
		server = from_server;
		from_server = primary_server;
                if (time_val->tm_hour < 10)  /* no more 08:00 */
                        sprintf(time_str, "%01d:%02d%s", time_val->tm_hour,
                                time_val->tm_min, merid);
                else
	                sprintf(time_str, "%02d:%02d%s", time_val->tm_hour,
		                time_val->tm_min, merid);
		if ((tmp_min != min) || (tmp_hour != hour))
		{
			hour = tmp_hour;
			min = tmp_min;
			do_hook(TIMER_LIST, "%s", time_str);
		}
		do_hook(IDLE_LIST, "%ld", (t - idle_time) / 60L);
		from_server = server;
		return (time_str);
	}
	if (flag == GET_TIME)
		return(time_str);
	else
		return ((char *) 0);
}

#ifdef __STDC__
void	reset_clock (char *unused)
#else
void reset_clock(unused)
	char	*unused;
#endif
{
	update_clock(RESET_TIME);
	update_all_status();
}

/*
 * convert_sub_format: This is used to convert the formats of the
 * sub-portions of the status line to a format statement specially designed
 * for that sub-portions.  convert_sub_format looks for a single occurence of
 * %c (where c is passed to the function). When found, it is replaced by "%s"
 * for use is a sprintf.  All other occurences of % followed by any other
 * character are left unchanged.  Only the first occurence of %c is
 * converted, all subsequence occurences are left unchanged.  This routine
 * mallocs the returned string. 
 */
#ifdef __STDC__
static	char	*convert_sub_format (char *format, char c)
#else
static	char	* convert_sub_format(format, c)
	char	*format;
	char	c;
#endif
{
		char	buffer[BIG_BUFFER_SIZE + 1];
	static	char	bletch[] = "%% ";
		char	*ptr = (char *) 0;
		int	dont_got_it = 1;

	if (format == (char *) 0)
		return ((char *) 0);
	*buffer = (char) 0;
	while (format)
	{
		if ((ptr = (char *) index(format, '%')) != NULL)
		{
			*ptr = (char) 0;
			strmcat(buffer, format, BIG_BUFFER_SIZE);
			*(ptr++) = '%';
			if ((*ptr == c) && dont_got_it)
			{
				dont_got_it = 0;
				strmcat(buffer, "%s", BIG_BUFFER_SIZE);
			}
			else
			{
				bletch[2] = *ptr;
				strmcat(buffer, bletch, BIG_BUFFER_SIZE);
			}
			ptr++;
		}
		else
			strmcat(buffer, format, BIG_BUFFER_SIZE);
		format = ptr;
	}
	malloc_strcpy(&ptr, buffer);
	return (ptr);
}

#ifdef __STDC__
static	char	*convert_format (char *format, int k)
#else
static	char	* convert_format(format, k)
	char	*format;
	int	k;
#endif
{
	char	buffer[BIG_BUFFER_SIZE + 1];
	char	*ptr;
	int	cp;

	*buffer = 0;
	while (format)
	{
		if ((ptr = (char *) index(format, '%')) != NULL)
		{
			*ptr = 0;
			strmcat(buffer, format, BIG_BUFFER_SIZE);
			*ptr = '%';
			ptr++;

			cp = func_cnt[k];
			if (cp < MAX_FUNCTIONS)
			{
/* So i alphabatized them.  Sue me. */
switch (*(ptr++))
{
	case 'A':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_away;
		break;
	case 'B':
		new_free(&hold_lines_format);
		hold_lines_format = convert_sub_format(get_string_var(STATUS_HOLD_LINES_VAR), 'B');
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_hold_lines;
		break;
	case 'C':
		new_free(&channel_format);
		channel_format = convert_sub_format(get_string_var(STATUS_CHANNEL_VAR), 'C');
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_channel;
		break;
	case 'D':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_dcc;
		break;
	case 'E':
		break; /* nothing to do */
	case 'F':
		new_free(&notify_format);
		notify_format = convert_sub_format(get_string_var(STATUS_NOTIFY_VAR), 'F');
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_notify_windows;
		break;
	case 'G': 
		break; /* nothing to do */
	case 'H':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_hold;
		break;
	case 'I':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_insert_mode;
		break;
	case 'J':
		break; /* nothing to do */
	case 'K':
		break; /* nothing to do */
	case 'L':
		break; /* nothing to do */
	case 'M':
		new_free(&mail_format);
		mail_format = convert_sub_format(get_string_var(STATUS_MAIL_VAR), 'M');
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_mail;
		break;
	case 'N':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_nickname;
		break;
	case 'O':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_overwrite_mode;
		break;
	case 'P':
		break; /* nothing to do */
	case 'Q':
		new_free(&query_format);
		query_format = convert_sub_format(get_string_var(STATUS_QUERY_VAR), 'Q');
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_query_nick;
		break;
	case 'R':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_refnum;
		break;
	case 'S':
		new_free(&server_format);
		server_format = convert_sub_format(get_string_var(STATUS_SERVER_VAR), 'S');
		strmcat(buffer,"%s",BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_server;
		break;
	case 'T':
		new_free(&clock_format);
		clock_format = convert_sub_format(get_string_var(STATUS_CLOCK_VAR), 'T');
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_clock;
		break;
	case 'U':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user0;
		break;
	case 'V':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_version;
		break;
	case 'W':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_window;
		break;
	case 'X':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user1;
		break;
	case 'Y':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user2;
		break;
	case 'Z':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user3;
		break;

	case '#': /* 35 */
		new_free(&umode_format);
		umode_format = convert_sub_format(get_string_var(STATUS_UMODE_VAR), '#');
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_umode;
		break;
	case '%': /* 37 */
		strmcat(buffer, "%", BIG_BUFFER_SIZE);
		break;
	case '*': /* 42 */
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_oper;
		break;
	case '+': /* 43 */
		new_free(&mode_format);
		mode_format = convert_sub_format(get_string_var(STATUS_MODE_VAR), '+');
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_mode;
		break;
	case '=': /* 61 */
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_voice;
		break;
	case '>': /* 62 */
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_right_justify;
		break;
	case '@': /* 64 */
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_chanop;
		break;

	/* status_user[0..3] are redundant of U, X, Y, and Z -- Jake [WinterHawk] Khuon */
	case '0':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user0;
		break;
	case '1':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user1;
		break;
	case '2':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user2;
		break;
	case '3':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user3;
		break;
	/* These babies are new additions. -- Jake [WinterHawk] Khuon */
	case '4':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user4;
		break;
	case '5':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user5;
		break;
	case '6':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user6;
		break;
	case '7':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user7;
		break;
	case '8':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user8;
		break;
	case '9':
		strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		status_func[k][cp++] = status_user9;
		break;

	/* no default..?? - phone, jan 1993 */
	/* empty is a good default -lynx, mar 93 */
}
			}
			else
				ptr++;
			func_cnt[k] = cp;
		}
		else
			strmcat(buffer, format, BIG_BUFFER_SIZE);
		format = ptr;
	}

	return m_strdup(buffer);
}

#ifdef __STDC__
void	build_status (char *format)
#else
void 	build_status(format)
	char	*format;
#endif
{
	int i,k;

	for (k = 0; k < 3; k++)
	{
		new_free((char **)&status_format[k]);
		func_cnt[k] = 0;

		if (k == 0)
			format = get_string_var(STATUS_FORMAT_VAR);
		else if (k == 1)
			format = get_string_var(STATUS_FORMAT1_VAR);
		else if (k == 2)
			format = get_string_var(STATUS_FORMAT2_VAR);

		if (format)
			status_format[k] = convert_format(format, k);

		for (i = func_cnt[k]; i < MAX_FUNCTIONS; i++)
			status_func[k][i] = status_null_function;
	}
	update_all_status();
}


#ifdef __STDC__
void	make_status (Window *window)
#else
void 	make_status(window)
	Window	*window;
#endif
{
	int 	i,
		len,
		k,
		RJustifyPos = -1,
		RealPosition;
	u_char	buffer[BIG_BUFFER_SIZE + 1];
	char	*func_value[MAX_FUNCTIONS];


	for (k = 0; k < window->double_status + 1; k++)
	{
		int	l;

		if (k)
			l = 2;
		else if (window->double_status)
			l = 1;
		else
			l = 0;

		if (!dumb && status_format[l])
		{
			for (i = 0; i < MAX_FUNCTIONS; i++)
				func_value[i] = (status_func[l][i])(window);
			*buffer = get_int_var(REVERSE_STATUS_LINE_VAR) ? REV_TOG : ' ';

			sprintf(buffer + 1, status_format[l],
			    func_value[0], func_value[1],
			    func_value[2], func_value[3], func_value[4], func_value[5],
			    func_value[6], func_value[7], func_value[8], func_value[9],
			    func_value[10], func_value[11], func_value[12],
			    func_value[13], func_value[14], func_value[15],
			    func_value[16], func_value[17], func_value[18],
			    func_value[19], func_value[20], func_value[21],
			    func_value[22], func_value[23], func_value[24],
			    func_value[25], func_value[26], func_value[27],
			    func_value[28], func_value[29], func_value[30],
			    func_value[31], func_value[32], func_value[33],
			    func_value[34], func_value[35], func_value[36], 
			    func_value[37], func_value[38], func_value[39]); 

			/*  
			 * Patched 26-Mar-93 by Aiken
			 * make_window now right-justifies everything 
			 * after a %>  -- it's also more efficient.
			 */
			RealPosition = 0;
			RJustifyPos = -1;

			for (i = 0; buffer[i]; i++)
			{
				/* formfeed is a marker for left/right border */
				if (buffer[i] == '\f')
					RJustifyPos = i;
				else if (buffer[i] != REV_TOG && 
				         buffer[i] != UND_TOG && 
					 buffer[i] != ALL_OFF && 
					 buffer[i] != BOLD_TOG)
				{
					if (RealPosition == CO)
					{
						buffer[i] = '\0';
						break;
					}
					RealPosition++;
				}
			}

			/* 
			 * note that i points to the nul, 
			 * RealPosition is vis.chars 
			 */

			if (RJustifyPos == -1)
				RJustifyPos = i;
			else
			{
				/* get rid of the marker */
				strcpy(buffer+RJustifyPos, buffer+RJustifyPos+1);
				i--;
			}

			if (get_int_var(FULL_STATUS_LINE_VAR))
			{
				int	diff;
				char	c;

				if ((RJustifyPos == 0) || get_int_var(STATUS_NO_REPEAT_VAR))
					c = ' ';
				else
					c = buffer[RJustifyPos - 1];

				diff = CO - RealPosition;

				for ( ; i >= RJustifyPos; i--)
					buffer[i + diff] = buffer[i];

				for (i++ ; diff > 0 ; diff--, i++)
					buffer[i] = c;
			}

			len = strlen(buffer);
			buffer[len] = ALL_OFF;
			buffer[len+1] = (char) 0;

			status_make_printable(buffer, len);

	/*
	 * Thanks to Max Bell (mbell@cie.uoregon.edu) for info about TVI
	 * terminals and the sg terminal capability 
	 */
			RealPosition = 0;
			if (window->status_line[k] && (SG == -1))
			{
				for (i = 0; buffer[i] && window->status_line[k][i]; i++)
				{
					if (buffer[i] != (u_char)window->status_line[k][i])
						break;
					if (buffer[i] != REV_TOG && 
					    buffer[i] != UND_TOG && 
					    buffer[i] != ALL_OFF && 
					    buffer[i] != BOLD_TOG)
						RealPosition++;
				}
			}
			else
				i = 0;

			if ((len = strlen(buffer + i)) || 
			     buffer[i] || !window->status_line[k] || 
			     window->status_line[k][i])
			{
				Screen *old_current_screen;

				old_current_screen = current_screen;
				set_current_screen(window->screen);
				term_move_cursor(RealPosition, window->bottom + k);
				output_line(buffer, NULL, i);
				cursor_in_display();
				if (term_clear_to_eol())
					term_space_erase(len);
				malloc_strcpy(&window->status_line[k], buffer);
				set_current_screen(old_current_screen);
			}
		}
	}
	cursor_to_input();
}

#ifdef __STDC__
static	char 	*status_nickname (Window *window)
#else
static	char	* status_nickname(window)
	Window	*window;
#endif
{
	if ((connected_to_server == 1) && !get_int_var(SHOW_STATUS_ALL_VAR)
	    && (!window->current_channel) && (window->screen->current_window != window))
		return empty_string;

	return get_server_nickname(window->server);
}

#ifdef __STDC__
static	char	*status_server (Window *window)
#else
static	char	* status_server(window)
	Window	*window;
#endif
{
	char	*rest,
		*name;
static	char	my_buffer[64];

	if (connected_to_server != 1)
	{
		if (window->server != -1)
		{
			if (server_format)
			{
				name = get_server_name(window->server);
				if ((rest = index(name, '.')) != NULL)
				{
					if (rest - name > 31)
						rest = name + 31;

					if (is_number(name))
						sprintf(my_buffer, server_format, name);
					else
					{
						*rest = '\0';
						sprintf(my_buffer, server_format, name);
						*rest = '.';
					}
				}
				else
					sprintf(my_buffer, server_format, name);
			}
			else
				strcpy(my_buffer, empty_string);
		}
		else
			strcpy(my_buffer, "No Server");
	}
	else
		strcpy(my_buffer, empty_string);

	return my_buffer;
}

#ifdef __STDC__
static	char	*status_query_nick (Window *window)
#else
static	char	* status_query_nick(window)
	Window	*window;
#endif
{
	static char my_buffer[LONG_NICKNAME_LEN + 1];

	if (window->query_nick && query_format)
	{
		sprintf(my_buffer, query_format, window->query_nick);
		return my_buffer;
	}

	return empty_string;
}

#ifdef __STDC__
static	char	*status_right_justify (Window *window)
#else
static	char	*status_right_justify(window)
	Window	*window;
#endif
{
	static char my_buffer[] = "\f";
	return my_buffer;
}

#ifdef __STDC__
static	char	*status_notify_windows (Window *window)
#else
static	char	*status_notify_windows(window)
	Window	*window;
#endif
{
	int	doneone = 0;
	int	flag = 1;
	char	buf2[81];
static	char	my_buffer[81];

	if (get_int_var(SHOW_STATUS_ALL_VAR) || window == window->screen->current_window)
	{
		*buf2 = 0;
		while ((window = traverse_all_windows(&flag)) != NULL)
		{
			if (window->miscflags & WINDOW_NOTIFIED)
			{
				if (doneone++)
					strmcat(buf2, ",", 80);
				strmcat(buf2, ltoa(window->refnum), 80);
			}
		}
	}
	if (doneone && notify_format)
	{
		sprintf(my_buffer, notify_format, buf2);
		return my_buffer;
	}

	return empty_string;
}

#ifdef __STDC__
static	char	*status_clock (Window *window)
#else
static	char	*status_clock(window)
	Window	*window;
#endif
{
	static	char	my_buffer[81];

	if ((get_int_var(CLOCK_VAR) && clock_format)  &&
	    (get_int_var(SHOW_STATUS_ALL_VAR) ||
	    (window == window->screen->current_window)))
		sprintf(my_buffer, clock_format, update_clock(GET_TIME));
	else
		strcpy(my_buffer, empty_string);

	return my_buffer;
}

#ifdef __STDC__
static	char	*status_mode (Window *window)
#else
static	char	*status_mode(window)
	Window	*window;
#endif
{
	char	*mode = (char *) 0;
static  char    my_buffer[81];

	*my_buffer = 0;
	if (window->current_channel)
	{
                mode = get_channel_mode((window->current_channel), window->server);
		if (mode && *mode && mode_format)
			sprintf(my_buffer, mode_format, mode);
	}
	return my_buffer;
}


#ifdef __STDC__
static	char	*status_umode (Window *window)
#else
static	char	*status_umode(window)
	Window	*window;
#endif
{
	char	localbuf[20];
static	char	my_buffer[81];

	if ((connected_to_server == 1) && !get_int_var(SHOW_STATUS_ALL_VAR)
	    && (window->screen->current_window != window))
		strcpy(localbuf, empty_string);
	else
	{
		if (window->server >= 0)
			strmcpy(localbuf, get_umode(window->server), 19);
		else
			strcpy(localbuf, empty_string);
	}

	if (*localbuf!='\0')
		sprintf(my_buffer, umode_format, localbuf);
	else
		strcpy(my_buffer, empty_string);

	return my_buffer;
}

#ifdef __STDC__
static	char	*status_chanop (Window *window)
#else
static	char	*status_chanop(window)
	Window	*window;
#endif
{
	char	*text;

	if (window->current_channel &&
	    get_channel_oper(window->current_channel, window->server) &&
	    (text = get_string_var(STATUS_CHANOP_VAR)))
		return text;
	else
		return empty_string;
}


#ifdef __STDC__
static	char	*status_hold_lines (Window *window)
#else
static	char	*status_hold_lines(window)
	Window	*window;
#endif
{
	int	num;
static	char	my_buffer[81];

	if ((num = window->held_lines - window->held_lines % 10))
	{
		sprintf(my_buffer, hold_lines_format, ltoa(num));
		return my_buffer;
	}
	else
		return empty_string;
}

#ifdef __STDC__
static	char	*status_channel (Window *window)
#else
static	char	*status_channel(window)
	Window	*window;
#endif
{
	char 	channel[IRCD_BUFFER_SIZE + 1];
static	char	my_buffer[IRCD_BUFFER_SIZE + 1];

	if (window->current_channel)
	{
		int num;

		if (get_int_var(HIDE_PRIVATE_CHANNELS_VAR) &&
		    is_channel_mode(window->current_channel, MODE_PRIVATE | MODE_SECRET, window->server))
			strmcpy(channel, "*private*", IRCD_BUFFER_SIZE);
		else
			strmcpy(channel, window->current_channel, IRCD_BUFFER_SIZE);

		if ((num = get_int_var(CHANNEL_NAME_WIDTH_VAR)) && (strlen(channel) > num))
			channel[num] = 0;

		sprintf(my_buffer, channel_format, channel);
		return my_buffer;
	}

	return empty_string;
}

#ifdef __STDC__
static	char	*status_voice (Window *window)
#else
static	char	*status_voice (window)
Window *window;
#endif
{
	char *text;

	if (window->current_channel &&
	    get_channel_voice(window->current_channel, window->server) &&
	    !get_channel_oper(window->current_channel, window->server) &&
	    (text = get_string_var(STATUS_VOICE_VAR)))
		return text;

	return empty_string;
}

#ifdef __STDC__
static	char	*status_mail (Window *window)
#else
static	char	*status_mail(window)
	Window	*window;
#endif
{
	char	*number;
static	char	my_buffer[81];

	if ((get_int_var(MAIL_VAR) && (number = check_mail()) && mail_format) &&
	    (get_int_var(SHOW_STATUS_ALL_VAR) ||
	    (window == window->screen->current_window)))
	{
		sprintf(my_buffer, mail_format, number);
		return my_buffer;
	}

	return empty_string;
}

#ifdef __STDC__
static	char	*status_insert_mode (Window *window)
#else
static	char	*status_insert_mode(window)
	Window	*window;
#endif
{
	char	*text;

	if (get_int_var(INSERT_MODE_VAR) && (get_int_var(SHOW_STATUS_ALL_VAR)
	    || (window->screen->current_window == window)))
		if ((text = get_string_var(STATUS_INSERT_VAR)))
			return text;

	return empty_string;
}

#ifdef __STDC__
static	char	*status_overwrite_mode (Window *window)
#else
static	char	*status_overwrite_mode(window)
	Window	*window;
#endif
{
	char	*text;

	if (!get_int_var(INSERT_MODE_VAR) && (get_int_var(SHOW_STATUS_ALL_VAR)
	    || (window->screen->current_window == window)))
		if ((text = get_string_var(STATUS_OVERWRITE_VAR)))
			return text;

	return empty_string;
}

#ifdef __STDC__
static	char	*status_away (Window *window)
#else
static	char	*status_away(window)
	Window	*window;
#endif
{
	char	*text;

	if ((connected_to_server == 1) && !get_int_var(SHOW_STATUS_ALL_VAR)
	    && (window->screen->current_window != window))
			return empty_string;
	else
	{
		if (server_list[window->server].away && (text = get_string_var(STATUS_AWAY_VAR)))
			return text;
		else
			return empty_string;
	}
}

#ifdef __STDC__
static	char	*status_user0 (Window *window)
#else
static	char	*status_user0(window)
	Window	*window;
#endif
{
	char	*text;

	if ((text = get_string_var(STATUS_USER_VAR)) &&
	    (get_int_var(SHOW_STATUS_ALL_VAR) ||
	    (window == window->screen->current_window)))
			return text;
	else
			return empty_string;
}

#ifdef __STDC__
static	char	*status_user1 (Window *window)
#else
static  char    *status_user1(window)
	Window  *window;
#endif
{
	char	*text;

        if ((text = get_string_var(STATUS_USER1_VAR)) &&
            (get_int_var(SHOW_STATUS_ALL_VAR) ||
            (window == window->screen->current_window)))
			return text;
        else
			return empty_string;
}

#ifdef __STDC__
static	char	*status_user2 (Window *window)
#else
static  char    *status_user2(window)
	Window  *window;
#endif
{
	char	*text;

        if ((text = get_string_var(STATUS_USER2_VAR)) &&
            (get_int_var(SHOW_STATUS_ALL_VAR) ||
            (window == window->screen->current_window)))
			return text;
        else
			return empty_string;
}

#ifdef __STDC__
static	char	*status_user3 (Window *window)
#else
static  char    *status_user3(window)
	Window  *window;
#endif
{
	char	*text;

        if ((text = get_string_var(STATUS_USER3_VAR)) &&
            (get_int_var(SHOW_STATUS_ALL_VAR) ||
            (window == window->screen->current_window)))
			return text;
	else
			return empty_string;
}

#ifdef __STDC__
static	char	*status_user4(Window *window)
#else
static	char 	*status_user4(window)
	Window  *window;
#endif
{
	char	*text;

	if ((text = get_string_var(STATUS_USER4_VAR)) &&
		!(get_int_var(SHOW_STATUS_ALL_VAR)) &&
		(window != window->screen->current_window))
			return text;
	else
			return empty_string;
}

#ifdef __STDC__
static	char	*status_user5 (Window *window)
#else
static	char 	*status_user5(window)
	Window  *window;
#endif
{
	char	*text;

	if ((text = get_string_var(STATUS_USER5_VAR)) &&
		!(get_int_var(SHOW_STATUS_ALL_VAR)) &&
		(window != window->screen->current_window))
			return text;
	else
			return empty_string;
}

#ifdef __STDC__
static	char	*status_user6(Window *window)
#else
static	char 	*status_user6(window)
	Window  *window;
#endif
{
	char	*text;

	if ((text = get_string_var(STATUS_USER6_VAR)) &&
		!(get_int_var(SHOW_STATUS_ALL_VAR)) &&
		(window != window->screen->current_window))
			return text;
	else
			return empty_string;
}

#ifdef __STDC__
static	char	*status_user7(Window *window)
#else
static	char 	*status_user7(window)
	Window  *window;
#endif
{
	char	*text;

	if ((text = get_string_var(STATUS_USER7_VAR)) &&
		!(get_int_var(SHOW_STATUS_ALL_VAR)) &&
		(window != window->screen->current_window))
			return text;
	else
			return empty_string;
}

#ifdef __STDC__
static	char	*status_user8 (Window *window)
#else
static	char 	*status_user8(window)
	Window  *window;
#endif
{
	char *text;

	if ((text = get_string_var(STATUS_USER8_VAR)) &&
		!(get_int_var(SHOW_STATUS_ALL_VAR)) &&
		(window != window->screen->current_window))
			return text;
	else
			return empty_string;
}

#ifdef __STDC__
static	char	*status_user9 (Window *window)
#else
static	char 	*status_user9(window)
	Window  *window;
#endif
{
	char	*text;

	if ((text = get_string_var(STATUS_USER9_VAR)) &&
		!(get_int_var(SHOW_STATUS_ALL_VAR)) &&
		(window != window->screen->current_window))
			return text;
	else
			return empty_string;
}

#ifdef __STDC__
static	char	*status_hold (Window *window)
#else
static	char	*status_hold(window)
	Window	*window;
#endif
{
	char *text;

	if (window->held && (text = get_string_var(STATUS_HOLD_VAR)))
		return text;
	else
		return empty_string;
}

#ifdef __STDC__
static	char	*status_oper (Window *window)
#else
static	char	*status_oper(window)
	Window	*window;
#endif
{
	char *text;

	if (get_server_operator(window->server) &&
			(text = get_string_var(STATUS_OPER_VAR)) &&
			(get_int_var(SHOW_STATUS_ALL_VAR) ||
			connected_to_server != 1 || 
			(window->screen->current_window == window)))
		return text;
	else
		return empty_string;
}

#ifdef __STDC__
static	char	*status_window (Window *window)
#else
static	char	*status_window(window)
	Window	*window;
#endif
{
	char *text;

	if ((text = get_string_var(STATUS_WINDOW_VAR)) &&
	    (number_of_windows() > 1) && (window->screen->current_window == window))
		return text;
	else
		return empty_string;
}

#ifdef __STDC__
static	char	*status_refnum (Window *window)
#else
static	char	*status_refnum(window)
	Window	*window;
#endif
{
	static char my_buffer[81];

	strcpy(my_buffer, window->name ? window->name : ltoa(window->refnum));
	return my_buffer;
}

#ifdef __STDC__
static	char	*status_version (Window *window)
#else
static	char	*status_version(window)
	Window	*window;
#endif
{
	if ((connected_to_server == 1) && !get_int_var(SHOW_STATUS_ALL_VAR)
	    && (window->screen->current_window != window))
		return empty_string;

	return (char *)irc_version; /* XXXX */
}


#ifdef __STDC__
static	char	*status_null_function (Window *window)
#else
static	char	*
status_null_function(window)
	Window	*window;
#endif
{
	return empty_string;
}

#ifdef __STDC__
static char *status_dcc (Window *window)
#else
static char *status_dcc (window)
Window *window;
#endif
{
	return DCC_get_current_transfer();
}


/*
 * pass an already allocated char array with n bits, and this
 * gets rid of nasty unprintables.
 */
#ifdef __STDC__
static	void	status_make_printable (unsigned char *str, int n)
#else
static	void status_make_printable(str, n)
	unsigned char	*str;
	int n;
#endif
{
	unsigned char	*s;
	int	pos;
	char	buffer[BIG_BUFFER_SIZE];

	if (!str || !*str)
		return;

	/*bzero(buffer, BIG_BUFFER_SIZE);*/
	*buffer = 0;
	for (pos = 0, s = str; s && pos < BIG_BUFFER_SIZE && pos < n; s++)
	{
		if (translation)
			*s = transToClient[*s];
		if (*s < 32)
		{
			switch(*s)
			{
				case UND_TOG:
				case ALL_OFF:
				case REV_TOG:
				case BOLD_TOG:
					buffer[pos++] = *s;
					break;
				default:
					buffer[pos++] = REV_TOG;
					buffer[pos++] = (*s & 0x7f) | 0x40;
					buffer[pos++] = REV_TOG;
					break;
			}
		}
		else if ((unsigned char) 0x7f == *s)
		{
			buffer[pos++] = REV_TOG;
			buffer[pos++] = '?';
			buffer[pos++] = REV_TOG;
		}
		else
			buffer[pos++] = *s;
	}
	buffer[pos] = '\0';
	strncpy(str, buffer, pos);
}
