#ident "@(#)status.c 1.11"
/*
 * 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 
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "irc.h"

#include "ircterm.h"
#include "status.h"
#include "server.h"
#include "vars.h"
#include "hook.h"
#include "input.h"
#include "commands.h"
#include "window.h"
#include "screen.h"
#include "output.h"
#include "names.h"
#include "ircaux.h"
#include "misc.h"
#include "hash.h"
#include "fset.h"

#define MY_BUFFER 150

extern time_t start_time;
extern char *DCC_get_current_transfer(void);
extern char *ltoa(long);
extern int get_count_stat, send_count_stat;

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_lag(Window *);
static char *status_dcc(Window *);
static char *status_msgcount(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_refnum(Window *);
static char *status_topic(Window *);
static char *status_null_function(Window *);
static char *status_notify_windows(Window *);
static char *convert_sub_format(char *, char);
static char *status_voice(Window *);
static char *status_dcccount(Window *);
static char *status_position(Window *);

#define cparse(format, str) convert_output_format(get_fset_var(format), "%s", str)

char *time_format = NULL;	/* XXX Bogus XXX */
char *strftime_24hour = "%R";
char *strftime_12hour = "%I:%M%p";

/*----------------------------*/
/* New stuff                  */

static char *mode_format;
static char *umode_format;
static char *topic_format;
static char *query_format;
static char *clock_format;
static char *hold_lines_format;
static char *channel_format;
static char *server_format;
static char *notify_format;
static char *status_lag_format;
static char *msgcount_format;
static char *dcccount_format;
static char *status_format[2];

#define MAX_FUNCTIONS 33

static char *(*status_func[2][MAX_FUNCTIONS]) _((Window *));
static int func_cnt[3];

static char *status_format[2];

/*-----------------------------*/

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

    t = time(NULL);
    time_val = localtime(&t);
    if (flag == RESET_TIME || time_val->tm_min != min || time_val->tm_hour != hour) {
	int server = from_server;

	from_server = primary_server;

	if (time_format)	/* XXXX Bogus XXXX */
	    strftime(time_str, 60, time_format, time_val);
	else if (get_int_var(CLOCK_24HOUR_VAR))
	    strftime(time_str, 60, strftime_24hour, time_val);
	else
	    strftime(time_str, 60, strftime_12hour, time_val);

	if ((time_val->tm_min != min) || (time_val->tm_hour != hour)) {
	    hour = time_val->tm_hour;
	    min = time_val->tm_min;
	    do_hook(TIMER_LIST, "%02d:%02d", hour, min);
	}
	if ((t - start_time) > 20)
	    check_serverlag(get_server_itsname(from_server));
	from_server = server;
	return (time_str);
    }
    if (flag == GET_TIME)
	return (time_str);
    else
	return (NULL);
}

void reset_clock(Window * win, char *unused, int unused1)
{
    update_clock(RESET_TIME);
    update_all_status(curr_scr_win, NULL, 0);
}

/*
 * 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. 
 */
static char *convert_sub_format(char *format, char c)
{
    char buffer[BIG_BUFFER_SIZE + 1];
    static char bletch[] = "%% ";
    char *ptr = NULL;
    int dont_got_it = 1;

    if (format == NULL)
	return (NULL);
    *buffer = (char) 0;
    memset(buffer, 0, sizeof(buffer));
    while (format) {
	if ((ptr = (char *) strchr(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);
}

static char *convert_format(char *format, int k)
{
    char buffer[BIG_BUFFER_SIZE + 1];
    char *ptr;
    int *cp;
    int doit = 1;

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

	    cp = &func_cnt[k];

	    if (*cp < MAX_FUNCTIONS) {
		switch (*(ptr++)) {
		case '&':
		    new_free(&dcccount_format);
		    status_func[k][(*cp)++] = status_dcccount;
		    dcccount_format = convert_sub_format(get_string_var(STATUS_DCCCOUNT_VAR), '&');
		    break;

		case '%':
		    strmcat(buffer, "%", BIG_BUFFER_SIZE);
		    doit = 0;
		    break;
		case '>':
		    status_func[k][(*cp)++] = status_right_justify;
		    break;

		case '^':
		    new_free(&msgcount_format);
		    msgcount_format = convert_sub_format(get_string_var(STATUS_MSGCOUNT_VAR), '^');
		    strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		    status_func[k][(*cp)++] = status_msgcount;
		    break;

		case '@':
		    status_func[k][(*cp)++] = status_chanop;
		    break;

		case '+':
		    new_free(&mode_format);
		    mode_format = convert_sub_format(get_string_var(STATUS_MODE_VAR), '+');
		    status_func[k][(*cp)++] = status_mode;
		    break;
		case '-':
		    new_free(&topic_format);
		    topic_format = convert_sub_format(get_string_var(STATUS_TOPIC_VAR), '-');
		    status_func[k][(*cp)++] = status_topic;
		    break;
		case 'L':
		    new_free(&umode_format);
		    umode_format = convert_sub_format(get_string_var(STATUS_UMODE_VAR), '#');
		    status_func[k][(*cp)++] = status_umode;
		    break;
		case '=':
		    status_func[k][(*cp)++] = status_voice;
		    break;
		case '*':
		    status_func[k][(*cp)++] = status_oper;
		    break;

		case 'A':
		    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');
		    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');
		    status_func[k][(*cp)++] = status_channel;
		    break;
		case 'D':
		    status_func[k][(*cp)++] = status_dcc;
		    break;
		case 'E':
		    break;
		case 'F':
		    new_free(&notify_format);
		    notify_format = convert_sub_format(get_string_var(STATUS_NOTIFY_VAR), 'F');
		    status_func[k][(*cp)++] = status_notify_windows;
		    break;
		case 'G':
		    break;
		case 'H':
		    status_func[k][(*cp)++] = status_hold;
		    break;
		case 'I':
		    status_func[k][(*cp)++] = status_insert_mode;
		    break;
		case '#':
		    new_free(&status_lag_format);
		    status_lag_format = convert_sub_format(get_string_var(STATUS_LAG_VAR), 'L');
		    status_func[k][(*cp)++] = status_lag;
		    break;
		case 'N':
		    status_func[k][(*cp)++] = status_nickname;
		    break;
		case 'O':
		    status_func[k][(*cp)++] = status_overwrite_mode;
		    break;
		case 'P':
		    status_func[k][(*cp)++] = status_position;
		    break;
		case 'Q':
		    new_free(&query_format);
		    query_format = convert_sub_format(get_string_var(STATUS_QUERY_VAR), 'Q');
		    status_func[k][(*cp)++] = status_query_nick;
		    break;
		case 'R':
		    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');
		    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');
		    status_func[k][(*cp)++] = status_clock;
		    break;
		case 'V':
		    status_func[k][(*cp)++] = status_version;
		    break;
		case 'W':
		    status_func[k][(*cp)++] = status_window;
		    break;
		}
		if (doit)
		    strmcat(buffer, "%s", BIG_BUFFER_SIZE);
		else
		    doit = 1;

	    } else
		ptr++;
	} else
	    strmcat(buffer, format, BIG_BUFFER_SIZE);
	format = ptr;
    }
    return m_strdup(buffer);
}

char *alias_special_char(char **, char *, char *, char *, int *);

static void fix_status_buffer(char *buffer, int ansi)
{
    char rhs_buffer[3 * BIG_BUFFER_SIZE + 1];
    int in_rhs = 0, ch_lhs = 0, ch_rhs = 0, pr_lhs = 0, pr_rhs = 0, start_rhs = -1, i;

    int len = 0;

    if (ansi)
	len = count_ansi(buffer, -1);
    /* 
     * Count out the characters.
     * Walk the entire string, looking for nonprintable
     * characters.  We count all the printable characters
     * on both sides of the %> tag.
     */
    for (i = 0; buffer[i]; i++) {
	/* 
	 * The FIRST such %> tag is used.
	 * Using multiple %>s is bogus.
	 */
	if (buffer[i] == '\f' && start_rhs == -1) {
	    start_rhs = i;
	    in_rhs = 1;
	}
	/* 
	 * Is it NOT a printable character?
	 */
	else if (buffer[i] == REV_TOG ||
		 buffer[i] == UND_TOG || buffer[i] == ALL_OFF || buffer[i] == BOLD_TOG || (ansi && vt100_decode(buffer[i]))) {
	    if (!in_rhs)
		ch_lhs++;
	    else
		ch_rhs++;
	}
	/* 
	 * So it is a printable character.
	 */
	else {
	    if (!in_rhs)
		ch_lhs++, pr_lhs++;
	    else
		ch_rhs++, pr_rhs++;
	}

	/* 
	 * Dont allow more than CO printable characters
	 */
	if (pr_lhs + pr_rhs >= term_cols + len) {
	    buffer[i] = 0;
	    break;
	}
    }
    /* 
     * Now if we have a rhs, then we have to adjust it.
     */
    if (start_rhs != -1) {
	strcpy(rhs_buffer, buffer + start_rhs + 1);

	/* 
	 * now we put it back.
	 */
	if (pr_lhs + pr_rhs < term_cols)
	    sprintf(buffer + start_rhs, "%*s%s", term_cols - 1 - pr_lhs - pr_rhs, empty_str, rhs_buffer);
	else
	    strcpy(buffer + start_rhs, rhs_buffer);
    } else {
	int chars = term_cols - pr_lhs - 1;
	int count;
	char c;

	if (get_int_var(STATUS_NO_REPEAT_VAR))
	    c = ' ';
	else
	    c = buffer[ch_lhs - 1];

	for (count = 0; count <= chars; count++)
	    buffer[ch_lhs + count] = c;
	buffer[ch_lhs + chars] = 0;
    }

}

void build_status(Window * win, char *format, int unused)
{
    int i, k;
    char *f = NULL;

    if (!win)
	return;

    for (k = 0; k < 2; k++) {
	new_free(&(status_format[k]));
	func_cnt[k] = 0;
	for (i = 0; i < MAX_FUNCTIONS; i++)
	    status_func[k][i] = status_null_function;
	switch (k) {
	case 0:
	    f = get_string_var(STATUS_FORMAT_VAR);
	    break;
	case 1:
	    f = get_string_var(STATUS_FORMAT2_VAR);
	    break;
	}

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

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

void make_status(Window * win)
{
    char buffer[3 * BIG_BUFFER_SIZE + 1];
    char *func_value[MAX_FUNCTIONS + 10] = { NULL };
    char **output;

    int len = 1, status_line, ansi = get_int_var(DISPLAY_ANSI_VAR);

    /* The second status line is only displayed in the bottom window and should always be displayed, no matter what SHOW_STATUS_ALL is 
     * set to - krys */
    for (status_line = 0; status_line < win->w_status_size; status_line++) {
	int position = 0;
	int line = status_line, i;

	if (!status_format[line])
	    continue;
	for (i = 0; i < MAX_FUNCTIONS; i++)
	    func_value[i] = (status_func[line][i]) (win);
	len = 1;

	if (get_int_var(REVERSE_STATUS_VAR))
	    buffer[0] = get_int_var(REVERSE_STATUS_VAR) ? REV_TOG : ' ';
	else
	    len = 0;

	snprintf(buffer + len, BIG_BUFFER_SIZE * 3,
		 status_format[line],
		 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]);

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

	fix_status_buffer(buffer, ansi);
	output = split_up_line(buffer);

	if (!win->status_line[status_line] || strcmp(output[0], win->status_line[status_line]))
	{
	    Screen *old_current_screen;
	    char *st = NULL;

	    malloc_strcpy(&win->status_line[status_line], buffer);
	    old_current_screen = current_screen;
	    set_current_screen(win->screen);
	    if (ansi)
		st = cparse((line == 1) ? FORMAT_STATUS2_FSET : FORMAT_STATUS_FSET, output[0]);

	    term_move_cursor(position, win->bottom + status_line);

	    output_line(st ? st : output[0]);

	    cursor_in_display();
	    set_current_screen(old_current_screen);
	}
    }

    cursor_to_input();
}

static char *status_nickname(Window * window)
{

    if ((connected_to_server) && !get_int_var(SHOW_STATUS_ALL_VAR)
	&& (!window->current_channel) && (window->screen->current_window != window))
	return empty_str;
    else
	return (get_server_nickname(window->server));
}

static char *status_server(Window * window)
{
    char *name;
    static char my_buffer[MY_BUFFER + 1] = "\0";

    if (connected_to_server) {
	if (window->server != -1) {
	    if (server_format) {
		name = get_server_name(window->server);
		snprintf(my_buffer, MY_BUFFER, server_format, name);
	    } else
		*my_buffer = 0;
	} else
	    strcpy(my_buffer, " No Server");
    } else
	*my_buffer = 0;
    return (my_buffer);
}

static char *status_query_nick(Window * window)
{
    static char my_buffer[MY_BUFFER + 1] = "\0";

    if (window->query_nick && query_format) {
	snprintf(my_buffer, MY_BUFFER, query_format, window->query_nick);
	return my_buffer;
    } else
	return (empty_str);
}

static char *status_right_justify(Window * window)
{
    static char my_buffer[] = "\f";

    return (my_buffer);
}

static char *status_notify_windows(Window * window)
{
    int doneone = 0;
    char buf2[MY_BUFFER + 2];
    static char my_buffer[MY_BUFFER + 1] = "\0";
    Window *old_window;

    if (get_int_var(SHOW_STATUS_ALL_VAR) || window == window->screen->current_window) {
	old_window = window;
	*buf2 = '\0';
#ifdef NEW_NOTIFY
	strcat(buf2, "[");
#endif
	window = NULL;
	while (traverse_all_windows(&window)) {
#ifdef NEW_NOTIFY
	    doneone++;
	    if (window->visible)
		strmcat(buf2, "*", MY_BUFFER);
	    else if (window->miscflags & WINDOW_NOTIFIED) {
		if (who_level & window->notify_level) {
		    strmcat(buf2, "%G", MY_BUFFER);
		    strmcat(buf2, ltoa(window->refnum), MY_BUFFER);
		} else {
		    strmcat(buf2, "%R", MY_BUFFER);
		    strmcat(buf2, ltoa(window->refnum), MY_BUFFER);
		}
	    } else
		strmcat(buf2, ltoa(window->refnum), MY_BUFFER);
#else
	    if (window->miscflags & WINDOW_NOTIFIED) {
		if (doneone++)
		    strmcat(buf2, ",", MY_BUFFER);
		strmcat(buf2, ltoa(window->refnum), MY_BUFFER);
	    }
#endif
	}
	window = old_window;
    }
#ifdef NEW_NOTIFY
    strmcat(buf2, "]", MY_BUFFER);
#endif
    if (doneone && notify_format) {
#ifdef NEW_NOTIFY
	char *p;

	p = convert_output_format(buf2, NULL, NULL);
	chop(p, 4);
	snprintf(my_buffer, MY_BUFFER, notify_format, p);
#else
	snprintf(my_buffer, MY_BUFFER, notify_format, buf2);
#endif
	return (my_buffer);
    }
    return empty_str;
}

static char *status_clock(Window * window)
{
    static char my_buf[MY_BUFFER + 1] = "\0";

    if ((get_int_var(CLOCK_VAR) && clock_format) && (get_int_var(SHOW_STATUS_ALL_VAR) || (window == window->screen->current_window)))
	snprintf(my_buf, MY_BUFFER, clock_format, update_clock(GET_TIME));
    else
	*my_buf = 0;
    return (my_buf);
}

static char *status_mode(Window * window)
{
    char *mode = NULL;
    static char my_buffer[MY_BUFFER + 1] = "\0";

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

static char *status_umode(Window * window)
{
    char localbuf[MY_BUFFER + 1];
    static char my_buffer[MY_BUFFER + 1] = "\0";

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

    if (*localbuf != '\0' && umode_format)
	snprintf(my_buffer, MY_BUFFER, umode_format, localbuf);
    else
	*my_buffer = 0;
    return (my_buffer);
}

static char *status_chanop(Window * window)
{
    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_str);
}

static char *status_hold_lines(Window * window)
{
    int num;
    static char my_buffer[MY_BUFFER + 1] = "\0";

    if ((num = (window->lines_held / 10) * 10)) {
	snprintf(my_buffer, MY_BUFFER, hold_lines_format, ltoa(num));
	return (my_buffer);
    } else
	return (empty_str);
}

static char *status_msgcount(Window * window)
{
    static char my_buffer[MY_BUFFER + 1] = "\0";

    if (get_int_var(MSGCOUNT_VAR) && msgcount_format) {
	snprintf(my_buffer, MY_BUFFER, msgcount_format, ltoa(get_int_var(MSGCOUNT_VAR)));
	return (my_buffer);
    } else
	return (empty_str);
}

static char *status_channel(Window * window)
{
    char channel[IRCD_BUFFER_SIZE + 1];
    static char my_buffer[IRCD_BUFFER_SIZE + 1] = "\0";

    if (window->current_channel /* && chan_is_connected(s, window->server) */ ) {
	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)) && ((int) strlen(channel) > num))
	    channel[num] = (char) 0;
	snprintf(my_buffer, IRCD_BUFFER_SIZE, channel_format, channel);
	return (my_buffer);
    }
    return (empty_str);
}

static char *status_insert_mode(Window * window)
{
    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_str);
}

static char *status_overwrite_mode(Window * window)
{
    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_str);
}

static char *status_away(Window * window)
{
    char *text;

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

static char *status_hold(Window * window)
{
    char *text;

    if (window->holding_something && (text = get_string_var(STATUS_HOLD_VAR)))
	return (text);
    return (empty_str);
}

static char *status_lag(Window * window)
{
    static char my_buffer[MY_BUFFER + 1] = "\0";
    char *p = NULL;

    if ((window->server > -1) && status_lag_format) {
	if (get_server_lag(window->server) > -1) {
	    p = m_sprintf("%2d", get_server_lag(window->server));
	    snprintf(my_buffer, MY_BUFFER, status_lag_format, p);
	    new_free(&p);
	} else
	    snprintf(my_buffer, MY_BUFFER, status_lag_format, "??");
	return (my_buffer);
    }
    return empty_str;
}

static char *status_topic(Window * window)
{
    static char my_buffer[MY_BUFFER + 1] = "\0";
    char tmp_buffer[MY_BUFFER + 1];
    struct channel *chan;

    if (window && window->current_channel && topic_format) {
	if ((chan = lookup_channel(window->current_channel, window->server, 0))) {
	    strmcpy(tmp_buffer, chan->topic ? chan->topic : "No Topic", MY_BUFFER - strlen(topic_format));
	    snprintf(my_buffer, MY_BUFFER, topic_format, stripansicodes(tmp_buffer));
	    return (my_buffer);
	}
    }
    return empty_str;
}

static char *status_oper(Window * window)
{
    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 || (window->screen->current_window == window)))
	return (text);
    return (empty_str);
}

static char *status_voice(Window * window)
{
    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_str;
}

static char *status_window(Window * window)
{
    char *text;

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

static char *status_refnum(Window * window)
{
    static char my_buffer[MY_BUFFER + 1];

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

static char *status_version(Window * window)
{
    if ((connected_to_server) && !get_int_var(SHOW_STATUS_ALL_VAR)
	&& (window->screen->current_window != window))
	return (empty_str);
    return ((char *) PACKAGE_VERSION);
}

static char *status_dcccount(Window * window)
{
    static char my_buffer[MY_BUFFER + 1];

    if (dcccount_format) {
	char tmp[30];

	strcpy(tmp, ltoa(send_count_stat));
	snprintf(my_buffer, MY_BUFFER, dcccount_format, ltoa(get_count_stat), tmp);
	return my_buffer;
    }
    return empty_str;
}

static char *status_null_function(Window * window)
{
    return empty_str;
}

static char *status_dcc(Window * window)
{
    return DCC_get_current_transfer();
}

static char *status_position(Window * window)
{
    static char my_buffer[81];

    snprintf(my_buffer, 80, "(%d-%d)", window->lines_scrolled_back, window->distance_from_display);
    return my_buffer;
}


syntax highlighted by Code2HTML, v. 0.9.1