/*
 * vars.c: All the dealing of the irc variables are handled here. 
 *
 *
 * Written By Michael Sandrof
 *
 * Copyright(c) 1990 
 *
 * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
 */


#include "irc.h"

#include "status.h"
#include "window.h"
#include "lastlog.h"
#include "log.h"
#include "crypt.h"
#include "history.h"
#include "notify.h"
#include "vars.h"
#include "input.h"
#include "ircaux.h"
#include "whois.h"
#include "ircterm.h"
#include "output.h"
#include "screen.h"
#include "list.h"
#include "server.h"
#include "window.h"
#include "misc.h"
#include "stack.h"
#include "alist.h"
#include "hash2.h"
#include "cset.h"
#include "module.h"
#include "tcl_bx.h"
void add_tcl_vars(void);


#ifdef WANT_CD
#include "cdrom.h"
#endif
#ifdef TRANSLATE
#include "translat.h"
#endif

#ifdef WINNT
#include <windows.h>
extern DWORD gdwPlatform;
#endif

char	*var_settings[] =
{
	"OFF", "ON", "TOGGLE"
};


extern	char	*auto_str;

extern  Screen	*screen_list, *current_screen;

int	loading_global = 0;

extern ChannelList default_statchan;


enum VAR_TYPES	find_variable _((char *, int *));
static	void	exec_warning _((Window *, char *, int));
static	void	input_warning _((Window *, char *, int));
static	void	eight_bit_characters _((Window *, char *, int));
static	void	set_realname _((Window *, char *, int));
static	void	set_numeric_string _((Window *, char *, int));
static	void	set_user_mode _((Window *, char *, int));
static	void	set_ov_mode _((Window *, char *, int));
static	void	set_away_time _((Window *, char *, int));
static	void	reinit_screen _((Window *, char *, int));
	void	reinit_status _((Window *, char *, int));
	int	save_formats _((FILE *));
static	void	update_max_recursions _((Window *, char *, int));
static	void	set_clock_format (Window *, char *, int);
	void	create_fsets (Window *);
	void	setup_ov_mode (int, int);
	
/*
 * irc_variable: all the irc variables used.  Note that the integer and
 * boolean defaults are set here, which the string default value are set in
 * the init_variables() procedure 
 */

static	IrcVariable irc_variable[] =
{
	{ "AINV",			INT_TYPE_VAR,	DEFAULT_AINV, NULL, NULL, 0, VIF_BITCHX },
	{ "ALWAYS_SPLIT_BIGGEST",	BOOL_TYPE_VAR,	DEFAULT_ALWAYS_SPLIT_BIGGEST, NULL, NULL, 0, 0 },
	{ "ANNOY_KICK",			BOOL_TYPE_VAR,	DEFAULT_ANNOY_KICK, NULL, NULL, 0, VIF_BITCHX },
	{ "AOP",			BOOL_TYPE_VAR,	DEFAULT_AOP_VAR, NULL, NULL, 0, VIF_BITCHX  },
	{ "APPEND_LOG",			BOOL_TYPE_VAR,	1, NULL, NULL, 0, VIF_BITCHX }, 
	
	{ "AUTOCK",			BOOL_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "AUTOKICK_ON_VERSION",	BOOL_TYPE_VAR,  0, NULL, NULL, 0, VIF_BITCHX },
	{ "AUTO_AWAY",			BOOL_TYPE_VAR,  1, NULL, NULL, 0, VIF_BITCHX },
	{ "AUTO_AWAY_TIME",		INT_TYPE_VAR,	60*10, NULL, set_away_time, 0, VIF_BITCHX  },
	{ "AUTO_NSLOOKUP",		BOOL_TYPE_VAR,  DEFAULT_AUTO_NSLOOKUP, NULL, NULL, 0, VIF_BITCHX  },
	{ "AUTO_RECONNECT",		BOOL_TYPE_VAR,	1, NULL, NULL, 0, VIF_BITCHX },
	{ "AUTO_REJOIN",		INT_TYPE_VAR,   DEFAULT_AUTO_REJOIN, NULL, NULL, 0, VIF_BITCHX  },
	{ "AUTO_RESPONSE",		STR_TYPE_VAR,	0, NULL, reinit_autoresponse, 0, VIF_BITCHX },
	{ "AUTO_UNBAN",			INT_TYPE_VAR,	60*10, NULL, NULL, 0, VIF_BITCHX },
	{ "AUTO_UNMARK_AWAY",		BOOL_TYPE_VAR,	DEFAULT_AUTO_UNMARK_AWAY, NULL, NULL, 0, 0 },
	{ "AUTO_WHOWAS",		BOOL_TYPE_VAR,	DEFAULT_AUTO_WHOWAS, NULL, NULL, 0, 0 },
	{ "BEEP",			BOOL_TYPE_VAR,	DEFAULT_BEEP, NULL, NULL, 0, VIF_BITCHX },
	{ "BEEP_ALWAYS",		BOOL_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "BEEP_MAX",			INT_TYPE_VAR,	DEFAULT_BEEP_MAX, NULL, NULL, 0, 0 },
	{ "BEEP_ON_MSG",		STR_TYPE_VAR,	0, NULL, set_beep_on_msg, 0, VIF_BITCHX },
	{ "BEEP_WHEN_AWAY",		INT_TYPE_VAR,	DEFAULT_BEEP_WHEN_AWAY, NULL, NULL, 0, VIF_BITCHX },
	{ "BITCH",			BOOL_TYPE_VAR,  0, NULL, NULL, 0, VIF_BITCHX },
	{ "BITCHX_HELP",		STR_TYPE_VAR,   0, NULL, NULL, 0, VIF_BITCHX },
	{ "BOLD_VIDEO",			BOOL_TYPE_VAR,	DEFAULT_BOLD_VIDEO, NULL, NULL, 0, 0 },
	{ "BOT_LOG",			BOOL_TYPE_VAR,	1, NULL, NULL, 0, VIF_BITCHX  },
	{ "BOT_LOGFILE",		STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX  },
	{ "BOT_MODE",			BOOL_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "BOT_PASSWD",			STR_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "BOT_RETURN",			STR_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "BOT_TCL",			BOOL_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "CDCC_FLOOD_AFTER",		INT_TYPE_VAR,	3, NULL, NULL, 0, VIF_BITCHX  },
	{ "CDCC_FLOOD_RATE",		INT_TYPE_VAR,	4,NULL, NULL, 0, VIF_BITCHX  },
	{ "CDCC_PROMPT",		STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "CDCC_SECURITY",		INT_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX  },
#ifdef WANT_CD
	{ "CD_DEVICE",			STR_TYPE_VAR,	0, NULL, set_cd_device, 0, VIF_BITCHX },
#else
	{ "CD_DEVICE",			STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
#endif
	{ "CHANNEL_NAME_WIDTH",		INT_TYPE_VAR,	DEFAULT_CHANNEL_NAME_WIDTH, NULL, update_all_status, 0, 0 },
	{ "CHECK_BEEP_USERS",		BOOL_TYPE_VAR,  DEFAULT_CHECK_BEEP_USERS, NULL, NULL, 0, 0 },
	{ "CLIENT_INFORMATION",		STR_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "CLOAK",			INT_TYPE_VAR,	DEFAULT_CLOAK, NULL, update_all_status, 0, VIF_BITCHX },
	{ "CLOCK",			BOOL_TYPE_VAR,	DEFAULT_CLOCK, NULL, update_all_status, 0, 0 },
	{ "CLOCK_24HOUR",		BOOL_TYPE_VAR,	DEFAULT_CLOCK_24HOUR, NULL, reset_clock, 0, 0 },
	{ "CLOCK_FORMAT",		STR_TYPE_VAR,	0, NULL, set_clock_format, 0, 0 },
	{ "CMDCHARS",			STR_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "COMMAND_MODE",		BOOL_TYPE_VAR,	DEFAULT_COMMAND_MODE, NULL, NULL, 0, 0 },
	{ "COMMENT_BREAKAGE",		BOOL_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "COMPRESS_MODES",		BOOL_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "CONNECT_TIMEOUT",		INT_TYPE_VAR,	DEFAULT_CONNECT_TIMEOUT, NULL, NULL, 0, 0 },
	{ "CONTINUED_LINE",		STR_TYPE_VAR,	0, NULL, set_continued_lines, 0, 0 },
	{ "CPU_SAVER_AFTER",		INT_TYPE_VAR,	DEFAULT_CPU_SAVER_AFTER, NULL, NULL, 0, VIF_BITCHX },
	{ "CPU_SAVER_EVERY",		INT_TYPE_VAR,	DEFAULT_CPU_SAVER_EVERY, NULL, NULL, 0, VIF_BITCHX },
	{ "CTCP_DELAY",			INT_TYPE_VAR,	3, NULL, NULL, 0, VIF_BITCHX },
	{ "CTCP_FLOOD_PROTECTION",	BOOL_TYPE_VAR,	DEFAULT_CTCP_FLOOD_PROTECTION, NULL, NULL, 0, 0 },
	{ "CTCP_VERBOSE",		BOOL_TYPE_VAR,	DEFAULT_VERBOSE_CTCP, NULL, NULL, 0, 0 },
	{ "CTOOLZ_DIR",			STR_TYPE_VAR,   0, NULL, NULL, 0, VIF_BITCHX },
	{ "DCC_AUTOGET",		BOOL_TYPE_VAR,	DEFAULT_DCC_AUTOGET, NULL, NULL, 0, VIF_BITCHX },
	{ "DCC_AUTORENAME",		BOOL_TYPE_VAR,	1, NULL, NULL, 0, VIF_BITCHX },
	{ "DCC_BAR_TYPE",		INT_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "DCC_BLOCK_SIZE",		INT_TYPE_VAR,	DEFAULT_DCC_BLOCK_SIZE, NULL, NULL, 0, VIF_BITCHX },
	{ "DCC_DLDIR",			STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "DCC_FAST",			BOOL_TYPE_VAR,	DEFAULT_DCC_FAST, NULL, NULL, 0, VIF_BITCHX },
	{ "DCC_GET_LIMIT",		INT_TYPE_VAR,	DEFAULT_DCC_GET_LIMIT, NULL, NULL, 0, VIF_BITCHX },
	{ "DCC_MAX_AUTOGET_SIZE",	INT_TYPE_VAR,	DEFAULT_MAX_AUTOGET_SIZE, NULL, 0, VIF_BITCHX },
	{ "DCC_QUEUE_LIMIT",		INT_TYPE_VAR,	DEFAULT_DCC_QUEUE_LIMIT, NULL, NULL, 0, VIF_BITCHX },
	{ "DCC_SEND_LIMIT",		INT_TYPE_VAR,	DEFAULT_DCC_SEND_LIMIT, NULL, NULL, 0, VIF_BITCHX },
	{ "DCC_ULDIR",			STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "DEBUG",			INT_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "DEFAULT_REASON",		STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "DEOPFLOOD",			BOOL_TYPE_VAR,	DEFAULT_DEOPFLOOD, NULL, NULL, 0, VIF_BITCHX },
	{ "DEOPFLOOD_TIME",		INT_TYPE_VAR,	DEFAULT_DEOPFLOOD_TIME, NULL, NULL, 0, VIF_BITCHX },
	{ "DEOP_ON_DEOPFLOOD",		INT_TYPE_VAR,	DEFAULT_DEOP_ON_DEOPFLOOD, NULL, NULL, 0, VIF_BITCHX },
	{ "DEOP_ON_KICKFLOOD",		INT_TYPE_VAR,	DEFAULT_DEOP_ON_KICKFLOOD, NULL, NULL, 0, VIF_BITCHX },
	{ "DISPATCH_UNKNOWN_COMMANDS",	BOOL_TYPE_VAR,	DEFAULT_DISPATCH_UNKNOWN_COMMANDS, NULL, NULL, 0, 0 },
	{ "DISPLAY",			BOOL_TYPE_VAR,	DEFAULT_DISPLAY, NULL, NULL, 0, 0 },
	{ "DISPLAY_ANSI",		BOOL_TYPE_VAR,	DEFAULT_DISPLAY_ANSI, NULL, reinit_screen, 0, VIF_BITCHX },
	{ "DOUBLE_STATUS_LINE",		INT_TYPE_VAR,	1, NULL, reinit_status, 0, VIF_BITCHX },
	{ "EIGHT_BIT_CHARACTERS",	BOOL_TYPE_VAR,	DEFAULT_EIGHT_BIT_CHARACTERS, NULL, eight_bit_characters, 0, VIF_BITCHX },
	{ "EXEC_PROTECTION",		BOOL_TYPE_VAR,	DEFAULT_EXEC_PROTECTION, NULL, exec_warning, 0, VF_NODAEMON },
	{ "FAKE_SPLIT_PATS",		STR_TYPE_VAR,	0, NULL, NULL, 0, 0 },

	{ "FLOATING_POINT_MATH_VAR",	BOOL_TYPE_VAR,	DEFAULT_FLOATING_POINT_MATH, NULL, NULL, 0, 0 },
	{ "FLOOD_AFTER",		INT_TYPE_VAR,	DEFAULT_FLOOD_AFTER, NULL, NULL, 0, VIF_BITCHX },
	{ "FLOOD_KICK",			BOOL_TYPE_VAR,	DEFAULT_FLOOD_KICK, NULL, NULL, 0, VIF_BITCHX },
	{ "FLOOD_PROTECTION",		BOOL_TYPE_VAR,	DEFAULT_FLOOD_PROTECTION, NULL, NULL, 0, VIF_BITCHX },
	{ "FLOOD_RATE",			INT_TYPE_VAR,	DEFAULT_FLOOD_RATE, NULL, NULL, 0, VIF_BITCHX },
	{ "FLOOD_USERS",		INT_TYPE_VAR,	DEFAULT_FLOOD_USERS, NULL, NULL, 0, VIF_BITCHX },
	{ "FLOOD_WARNING",		BOOL_TYPE_VAR,	DEFAULT_FLOOD_WARNING, NULL, NULL, 0, VIF_BITCHX },

	{ "FTP_GRAB",			BOOL_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "FULL_STATUS_LINE",		BOOL_TYPE_VAR,	DEFAULT_FULL_STATUS_LINE, NULL, update_all_status, 0, 0 },
	{ "HACKING",			INT_TYPE_VAR,	DEFAULT_HACKING, NULL, NULL, 0, VIF_BITCHX },
	{ "HACK_OPS",			BOOL_TYPE_VAR,	0, NULL, NULL, 0, 0},
	{ "HARD_UH_NOTIFY",		BOOL_TYPE_VAR,  1, NULL, NULL, 0, VIF_BITCHX },
	{ "HEBREW_TOGGLE",		BOOL_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "HELP_PAGER",			BOOL_TYPE_VAR,	DEFAULT_HELP_PAGER, NULL, NULL, 0, 0 },
	{ "HELP_PATH",			STR_TYPE_VAR,	0, NULL, NULL, 0, VF_EXPAND_PATH|VF_NODAEMON },
	{ "HELP_PROMPT",		BOOL_TYPE_VAR,	DEFAULT_HELP_PROMPT, NULL, NULL, 0, 0 },
	{ "HELP_WINDOW",		BOOL_TYPE_VAR,	DEFAULT_HELP_WINDOW, NULL, NULL, 0, 0 },
	{ "HIDE_PRIVATE_CHANNELS",	BOOL_TYPE_VAR,	DEFAULT_HIDE_PRIVATE_CHANNELS, NULL, update_all_status, 0, 0 },
	{ "HIGHLIGHT_CHAR",		STR_TYPE_VAR,	0, NULL, set_highlight_char, 0, 0 },
	{ "HISTORY",			INT_TYPE_VAR,	DEFAULT_HISTORY, NULL, set_history_size, 0, VF_NODAEMON },
	{ "HOLD_MODE",			BOOL_TYPE_VAR,	DEFAULT_HOLD_MODE, NULL, reset_line_cnt, 0, 0 },
	{ "HOLD_MODE_MAX",		INT_TYPE_VAR,	DEFAULT_HOLD_MODE_MAX, NULL, NULL, 0, 0 },
	{ "HTTP_GRAB",			BOOL_TYPE_VAR,  0, NULL, NULL, 0, VIF_BITCHX }, 
	{ "IDENT_HACK",			STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "IDLE_CHECK",			INT_TYPE_VAR,	120, NULL, NULL, 0, VIF_BITCHX },
	{ "IGNORE_TIME",		INT_TYPE_VAR,	600, NULL, NULL, 0, VIF_BITCHX },
	{ "INDENT",			BOOL_TYPE_VAR,	DEFAULT_INDENT, NULL, NULL, 0, 0 },
	{ "INPUT_ALIASES",		BOOL_TYPE_VAR,	DEFAULT_INPUT_ALIASES, NULL, NULL, 0, 0 },
	{ "INPUT_PROMPT",		STR_TYPE_VAR,	0, NULL, set_input_prompt, 0, 0 },
	{ "INPUT_PROTECTION",		BOOL_TYPE_VAR,	DEFAULT_INPUT_PROTECTION, NULL, input_warning, 0, 0 },
	{ "INSERT_MODE",		BOOL_TYPE_VAR,	DEFAULT_INSERT_MODE, NULL, update_all_status, 0, 0 },
	{ "INVERSE_VIDEO",		BOOL_TYPE_VAR,	DEFAULT_INVERSE_VIDEO, NULL, NULL, 0, 0 },
	{ "JOINFLOOD",			BOOL_TYPE_VAR,	DEFAULT_JOINFLOOD, NULL, NULL, 0, VIF_BITCHX },
	{ "JOINFLOOD_TIME",		INT_TYPE_VAR,	DEFAULT_JOINFLOOD_TIME, NULL, NULL, 0, VIF_BITCHX },
	{ "KICKFLOOD",			BOOL_TYPE_VAR,	DEFAULT_KICKFLOOD, NULL, NULL, 0, VIF_BITCHX  },
	{ "KICKFLOOD_TIME",		INT_TYPE_VAR,	DEFAULT_KICKFLOOD_TIME, NULL, NULL, 0, VIF_BITCHX  },
	{ "KICK_IF_BANNED",		BOOL_TYPE_VAR,  DEFAULT_KICK_IF_BANNED, NULL, NULL, 0, VIF_BITCHX },
	{ "KICK_ON_DEOPFLOOD",		INT_TYPE_VAR,   DEFAULT_KICK_ON_DEOPFLOOD, NULL, NULL, 0, VIF_BITCHX },
	{ "KICK_ON_JOINFLOOD",		INT_TYPE_VAR,	DEFAULT_KICK_ON_JOINFLOOD, NULL, NULL, 0, VIF_BITCHX },
	{ "KICK_ON_KICKFLOOD",		INT_TYPE_VAR,   DEFAULT_KICK_ON_KICKFLOOD, NULL, NULL, 0, VIF_BITCHX  },
	{ "KICK_ON_NICKFLOOD",		INT_TYPE_VAR,   DEFAULT_KICK_ON_NICKFLOOD, NULL, NULL, 0, VIF_BITCHX  },
	{ "KICK_ON_PUBFLOOD",		INT_TYPE_VAR,   DEFAULT_KICK_ON_PUBFLOOD, NULL, NULL, 0, VIF_BITCHX  },
	{ "KICK_OPS",			BOOL_TYPE_VAR,	DEFAULT_KICK_OPS, NULL, NULL, 0, VIF_BITCHX  },
	{ "LAMELIST",			BOOL_TYPE_VAR,	DEFAULT_LAMELIST, NULL, NULL, 0, VIF_BITCHX },
	{ "LASTLOG",			INT_TYPE_VAR,	DEFAULT_LASTLOG, NULL, set_lastlog_size, 0, 0 },
	{ "LASTLOG_ANSI",		BOOL_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "LASTLOG_LEVEL",		STR_TYPE_VAR,	0, NULL, set_lastlog_level, 0, 0 },
	{ "LLOOK",			BOOL_TYPE_VAR,	DEFAULT_LLOOK, NULL, NULL, 0, VIF_BITCHX  },
	{ "LLOOK_DELAY",		INT_TYPE_VAR,	DEFAULT_LLOOK_DELAY, NULL, NULL, 0, VIF_BITCHX  },
	{ "LOAD_PATH",			STR_TYPE_VAR,	0, NULL, NULL, 0, VF_NODAEMON },
	{ "LOG",			BOOL_TYPE_VAR,	DEFAULT_LOG, NULL, logger, 0, 0 },
	{ "LOGFILE",			STR_TYPE_VAR,	0, NULL, set_log_file, 0, VF_NODAEMON },
	{ "MAIL",			INT_TYPE_VAR,	DEFAULT_MAIL, NULL, update_all_status, 0, VIF_BITCHX },
	{ "MAX_DEOPS",			INT_TYPE_VAR,	2, NULL, 0, VIF_BITCHX  },
	{ "MAX_IDLEKICKS",		INT_TYPE_VAR,	2, NULL, 0, VIF_BITCHX  },
	{ "MAX_RECURSIONS",		INT_TYPE_VAR,	DEFAULT_MAX_RECURSIONS, NULL, update_max_recursions, 0, 0 },
	{ "MIRCS",			BOOL_TYPE_VAR,  0, NULL, NULL, 0, VIF_BITCHX  },
	{ "MODE_STRIPPER",		BOOL_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "MSGCOUNT",			INT_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "MSGLOG",			BOOL_TYPE_VAR,	DEFAULT_MSGLOG, NULL, NULL, 0, 0 },
	{ "MSGLOG_FILE",		STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX|VF_EXPAND_PATH },
	{ "MSGLOG_LEVEL",		STR_TYPE_VAR,	0, NULL, set_msglog_level, 0, VIF_BITCHX},
	{ "NEXT_SERVER_ON_LOCAL_KILL",  BOOL_TYPE_VAR,  0, NULL, NULL, 0, VIF_BITCHX  },

	{ "NICKFLOOD",			BOOL_TYPE_VAR,	DEFAULT_NICKFLOOD, NULL, NULL, 0, VIF_BITCHX  },
	{ "NICKFLOOD_TIME",		INT_TYPE_VAR,	DEFAULT_NICKFLOOD_TIME, NULL, NULL, 0, VIF_BITCHX  },
	{ "NICK_COMPLETION",		BOOL_TYPE_VAR,	1, NULL, NULL, 0, VIF_BITCHX  },
	{ "NICK_COMPLETION_CHAR",	CHAR_TYPE_VAR,  0, NULL, NULL, 0, VIF_BITCHX },
	{ "NICK_COMPLETION_TYPE",	INT_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX  },
	{ "NOTIFY_HANDLER",		STR_TYPE_VAR, 	0, NULL, set_notify_handler, 0, 0 },
	{ "NOTIFY_LEVEL",		STR_TYPE_VAR,	0, NULL, set_notify_level, 0, 0 },
	{ "NOTIFY_ON_TERMINATION",	BOOL_TYPE_VAR,	DEFAULT_NOTIFY_ON_TERMINATION, NULL, NULL, 0, VF_NODAEMON },
	{ "NO_CTCP_FLOOD",		BOOL_TYPE_VAR,	DEFAULT_NO_CTCP_FLOOD, NULL, NULL, 0, 0 },
	{ "NUM_BANMODES",		INT_TYPE_VAR,   4, NULL, NULL, 0, VIF_BITCHX },
	{ "NUM_OF_WHOWAS",		INT_TYPE_VAR,	4, NULL, NULL, 0, VIF_BITCHX },
	{ "NUM_OPMODES",		INT_TYPE_VAR,   3, NULL, NULL, 0, VIF_BITCHX },
	{ "OPER_MODES",			STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "OV",				BOOL_TYPE_VAR,  0, NULL, set_ov_mode, 0, VIF_BITCHX },
	{ "PAD_CHAR",			CHAR_TYPE_VAR,	DEFAULT_PAD_CHAR, NULL, NULL, 0, 0 },
	{ "PING_TYPE",			INT_TYPE_VAR,   DEFAULT_PING_TYPE, NULL, NULL, 0, VIF_BITCHX  },
	{ "PROTECT_CHANNELS",		STR_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "PUBFLOOD",			BOOL_TYPE_VAR,	DEFAULT_PUBFLOOD, NULL, NULL, 0, VIF_BITCHX },
	{ "PUBFLOOD_TIME",		INT_TYPE_VAR,	DEFAULT_PUBFLOOD_TIME, NULL, NULL, 0, VIF_BITCHX  },
	{ "REALNAME",			STR_TYPE_VAR,	0, 0, set_realname, 0, VF_NODAEMON },
	{ "REASON_TYPE",		INT_TYPE_VAR,	DEFAULT_REASON_TYPE, NULL, 0, VIF_BITCHX  },
	{ "REVERSE_STATUS",		BOOL_TYPE_VAR,	0, NULL, reinit_status, 0, 0 },
	{ "SAME_WINDOW_ONLY",		BOOL_TYPE_VAR,	DEFAULT_SAME_WINDOW_ONLY, NULL, NULL, 0, 0 },
	{ "SAVEFILE",			STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX  },
	{ "SCREEN_OPTIONS",		STR_TYPE_VAR,	0, NULL, NULL, 0, VF_NODAEMON },
	{ "SCRIPT_HELP",		STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX  },
	{ "SCROLL",			BOOL_TYPE_VAR,	DEFAULT_SCROLL, NULL, set_scroll, 0, 0 },
	{ "SCROLL_LINES",		INT_TYPE_VAR,	DEFAULT_SCROLL_LINES, NULL, set_scroll_lines, 0, 0 },
	{ "SEND_AWAY_MSG",		BOOL_TYPE_VAR,	1, NULL, NULL, 0, 0 },
	{ "SEND_IGNORE_MSG",		BOOL_TYPE_VAR,	DEFAULT_SEND_IGNORE_MSG, NULL, NULL, 0, 0 },
	{ "SERVER_PROMPT",		STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "SHELL",			STR_TYPE_VAR,	0, NULL, NULL, 0, VF_NODAEMON },
	{ "SHELL_FLAGS",		STR_TYPE_VAR,	0, NULL, NULL, 0, VF_NODAEMON },
	{ "SHELL_LIMIT",		INT_TYPE_VAR,	DEFAULT_SHELL_LIMIT, NULL, NULL, 0, VF_NODAEMON },
	{ "SHITLIST",			BOOL_TYPE_VAR,  DEFAULT_SHITLIST, NULL, NULL, 0, VIF_BITCHX  },
	{ "SHITLIST_REASON",		STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX  },
	{ "SHOW_AWAY_ONCE",		BOOL_TYPE_VAR,	DEFAULT_SHOW_AWAY_ONCE, NULL, NULL, 0, 0 },
	{ "SHOW_CHANNEL_NAMES",		BOOL_TYPE_VAR,	DEFAULT_SHOW_CHANNEL_NAMES, NULL, NULL, 0, 0 },
	{ "SHOW_CTCP_IDLE",		BOOL_TYPE_VAR,	DEFAULT_SHOW_CTCP_IDLE, NULL, NULL, 0, 0 },
	{ "SHOW_END_OF_MSGS",		BOOL_TYPE_VAR,	DEFAULT_SHOW_END_OF_MSGS, NULL, NULL, 0, 0 },
	{ "SHOW_NUMERICS",		BOOL_TYPE_VAR,	DEFAULT_SHOW_NUMERICS, NULL, NULL, 0, 0 },
	{ "SHOW_NUMERICS_STR",		STR_TYPE_VAR,	0, NULL, set_numeric_string, 0, 0 },
	{ "SHOW_STATUS_ALL",		BOOL_TYPE_VAR,	DEFAULT_SHOW_STATUS_ALL, NULL, update_all_status, 0, 0 },
	{ "SHOW_WHO_HOPCOUNT", 		BOOL_TYPE_VAR,	DEFAULT_SHOW_WHO_HOPCOUNT, NULL, NULL, 0, 0 },
	{ "STATUS_AWAY",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_CDCCCOUNT",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_CHANNEL",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_CHANOP",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_CLOCK",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_CPU_SAVER",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_DCCCOUNT",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_FORMAT",              STR_TYPE_VAR,   0, NULL, build_status, 0, 0 },
	{ "STATUS_FORMAT1",             STR_TYPE_VAR,   0, NULL, build_status, 0, 0 },
	{ "STATUS_FORMAT2",             STR_TYPE_VAR,   0, NULL, build_status, 0, 0 },
	{ "STATUS_FORMAT3",             STR_TYPE_VAR,   0, NULL, build_status, 0, 0 },
	{ "STATUS_HOLD",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_HOLD_LINES",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_INSERT",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_LAG",			STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_MAIL",		STR_TYPE_VAR,	0, NULL, build_status, 0, VF_NODAEMON },
	{ "STATUS_MODE",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_MSGCOUNT",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_NOTIFY",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_NO_REPEAT",		BOOL_TYPE_VAR,	DEFAULT_STATUS_NO_REPEAT, NULL, NULL, 0, 0 },
	{ "STATUS_OPER",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_OPER_KILLS",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_OVERWRITE",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_QUERY",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_SERVER",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_TOPIC",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_UMODE",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER1",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER10",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER11",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER12",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER13",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER14",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER15",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER16",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER17",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER18",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER19",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER2",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER3",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER4",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER5",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER6",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER7",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER8",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USER9",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_USERS",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_VOICE",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "STATUS_WINDOW",		STR_TYPE_VAR,	0, NULL, build_status, 0, 0 },
	{ "SUPPRESS_SERVER_MOTD",	BOOL_TYPE_VAR,	DEFAULT_SUPPRESS_SERVER_MOTD, NULL, NULL, 0, VF_NODAEMON },
	{ "TAB",			BOOL_TYPE_VAR,	DEFAULT_TAB, NULL, NULL, 0, 0 },
	{ "TAB_MAX",			INT_TYPE_VAR,	DEFAULT_TAB_MAX, NULL, NULL, 0, 0 },

#ifdef TRANSLATE
	{ "TRANSLATION",		STR_TYPE_VAR,	0, NULL, set_translation, 0, 0 },
#else
	{ "TRANSLATION",		STR_TYPE_VAR,	0, NULL, NULL, 0, 0 },
#endif

	{ "UNDERLINE_VIDEO",		BOOL_TYPE_VAR,	DEFAULT_UNDERLINE_VIDEO, NULL, NULL, 0, 0 },
	{ "USERLIST",			BOOL_TYPE_VAR,  DEFAULT_USERLIST, NULL, NULL, 0, VIF_BITCHX },
	{ "USERMODE",			STR_TYPE_VAR,	0, NULL, set_user_mode, 0, VIF_BITCHX},
	{ "USER_INFORMATION", 		STR_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ "WINDOW_QUIET",		BOOL_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "XTERM",			STR_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "XTERM_OPTIONS",		STR_TYPE_VAR,	0, NULL, NULL, 0, VF_NODAEMON },
	{ "_CDCC_CLOSE_IDLE_SENDS_TIME",INT_TYPE_VAR,	55,NULL, NULL, 0, VIF_BITCHX },
	{ "_CDCC_MINSPEED_TIME",	INT_TYPE_VAR,	0, NULL, NULL, 0, VIF_BITCHX },
	{ "_CDCC_PACKS_OFFERED",	INT_TYPE_VAR,	0, NULL, NULL, 0, 0 },
	{ NULL, 			0, 		0, NULL, NULL, 0, 0 }
};

#ifdef WINNT
char *convert_dos(char *str)
{
register char *p;
	for (p = str; *p; p++)
		if (*p == '/')
			*p = '\\';
	return str;
}
#endif

/*
 * get_string_var: returns the value of the string variable given as an index
 * into the variable table.  Does no checking of variable types, etc 
 */
char	*	get_string_var(enum VAR_TYPES var)
{
	return (irc_variable[var].string);
}

/*
 * get_int_var: returns the value of the integer string given as an index
 * into the variable table.  Does no checking of variable types, etc 
 */
int get_int_var(enum VAR_TYPES var)
{
	return (irc_variable[var].integer);
}

/*
 * set_string_var: sets the string variable given as an index into the
 * variable table to the given string.  If string is null, the current value
 * of the string variable is freed and set to null 
 */
void set_string_var(enum VAR_TYPES var, char *string)
{
	if (string)
		malloc_strcpy(&(irc_variable[var].string), string);
	else
		new_free(&(irc_variable[var].string));
}

/*
 * set_int_var: sets the integer value of the variable given as an index into
 * the variable table to the given value 
 */
void set_int_var(enum VAR_TYPES var, unsigned int value)
{
	irc_variable[var].integer = value;
}

/*
 * init_variables: initializes the string variables that can't really be
 * initialized properly above 
 */
void init_variables()
{
#ifdef WINNT
	char *shell;
#endif
	int old_display = window_display;
#ifdef VAR_DEBUG
 	int i;

	for (i = 1; i < NUMBER_OF_VARIABLES - 1; i++)
		if (strcmp(irc_variable[i-1].name, irc_variable[i].name) >= 0)
			ircpanic("Variable [%d] (%s) is out of order.", i, irc_variable[i].name);
#endif

	window_display = 0;

	set_string_var(SCRIPT_HELP_VAR, DEFAULT_SCRIPT_HELP_FILE);
	set_string_var(BITCHX_HELP_VAR, DEFAULT_BITCHX_HELP_FILE);
	set_string_var(IDENT_HACK_VAR, DEFAULT_IDENT_HACK);
	set_string_var(AUTO_RESPONSE_VAR, nickname);
	set_string_var(XTERM_OPTIONS_VAR, DEFAULT_XTERM);
        set_string_var(XTERM_OPTIONS_VAR, DEFAULT_XTERM_OPTIONS);
        
#ifndef ONLY_STD_CHARS
	set_string_var(SHOW_NUMERICS_STR_VAR, "[1;31mů[0m[1;37mí[1;31mů[0m");
	set_numeric_string(curr_scr_win, "[1;31mů[0m[1;37mí[1;31mů[0m", 0);
#else
#ifndef LATIN1
	set_string_var(SHOW_NUMERICS_STR_VAR, "***");
	set_numeric_string(curr_scr_win, "***", 0);
#else
/*
 * 	Just a hack, but when a display has latin1 characters, 
 *	we assume it can cope with color codes too.
 */
	set_string_var(SHOW_NUMERICS_STR_VAR, "[1;31m-[0m[1;37m:[1;31m-[0m");
	set_numeric_string(curr_scr_win, "[1;31m-[0m[1;37m:[1;31m-[0m", 0);
#endif
#endif
	reinit_autoresponse(curr_scr_win, nickname, 0);
	set_string_var(MSGLOGFILE_VAR, DEFAULT_MSGLOGFILE);

	set_string_var(MSGLOG_LEVEL_VAR, DEFAULT_MSGLOG_LEVEL);
	set_string_var(CTOOLZ_DIR_VAR, DEFAULT_CTOOLZ_DIR);
	set_int_var(LLOOK_DELAY_VAR, DEFAULT_LLOOK_DELAY);
	set_int_var(MSGCOUNT_VAR, 0);

	set_string_var(SHITLIST_REASON_VAR, DEFAULT_SHITLIST_REASON);
	set_string_var(PROTECT_CHANNELS_VAR, DEFAULT_PROTECT_CHANNELS);
	set_string_var(DEFAULT_REASON_VAR, DEFAULT_KICK_REASON);
	set_string_var(DCC_DLDIR_VAR, DEFAULT_DCC_DLDIR);
	set_string_var(DCC_ULDIR_VAR, DEFAULT_DCC_DLDIR);	

	set_string_var(CMDCHARS_VAR, DEFAULT_CMDCHARS);
	set_string_var(LOGFILE_VAR, DEFAULT_LOGFILE);
#ifdef WINNT
	if (getenv("SHELL"))
	{
		shell = getenv("SHELL");
		set_string_var(SHELL_VAR, path_search(shell, getenv("PATH")));
        	if (getenv("SHELL_FLAGS"))
        		set_string_var(SHELL_FLAGS_VAR, getenv("SHELL_FLAGS"));
	}
 	else if (gdwPlatform == VER_PLATFORM_WIN32_WINDOWS)
	{
		shell = "command.com";
        	set_string_var(SHELL_FLAGS_VAR, "/c");
		set_string_var(SHELL_VAR, convert_dos(path_search(shell, getenv("PATH"))));
	}
	else
	{
	        shell = "cmd.exe";
        	set_string_var(SHELL_FLAGS_VAR, "/c");
		set_string_var(SHELL_VAR, convert_dos(path_search(shell, getenv("PATH"))));
	}
#else
	set_string_var(SHELL_VAR, DEFAULT_SHELL);
	set_string_var(SHELL_FLAGS_VAR, DEFAULT_SHELL_FLAGS);
#endif
	set_string_var(CONTINUED_LINE_VAR, DEFAULT_CONTINUED_LINE);
	set_string_var(INPUT_PROMPT_VAR, DEFAULT_INPUT_PROMPT);
	set_string_var(HIGHLIGHT_CHAR_VAR, DEFAULT_HIGHLIGHT_CHAR);
	set_string_var(LASTLOG_LEVEL_VAR, DEFAULT_LASTLOG_LEVEL);
	set_string_var(NOTIFY_HANDLER_VAR, DEFAULT_NOTIFY_HANDLER);
	set_string_var(NOTIFY_LEVEL_VAR, DEFAULT_NOTIFY_LEVEL);
	set_string_var(REALNAME_VAR, realname);

	set_string_var(STATUS_FORMAT_VAR, DEFAULT_STATUS_FORMAT);
	set_string_var(STATUS_FORMAT1_VAR, DEFAULT_STATUS_FORMAT1);
	set_string_var(STATUS_FORMAT2_VAR, DEFAULT_STATUS_FORMAT2);
	set_string_var(STATUS_FORMAT3_VAR, DEFAULT_STATUS_FORMAT3);

	set_string_var(STATUS_DCCCOUNT_VAR, DEFAULT_STATUS_DCCCOUNT);
	set_string_var(STATUS_CDCCCOUNT_VAR, DEFAULT_STATUS_CDCCCOUNT);

	set_string_var(STATUS_AWAY_VAR, DEFAULT_STATUS_AWAY);
	set_string_var(STATUS_CHANNEL_VAR, DEFAULT_STATUS_CHANNEL);
	set_string_var(STATUS_CHANOP_VAR, DEFAULT_STATUS_CHANOP);
	set_string_var(STATUS_CLOCK_VAR, DEFAULT_STATUS_CLOCK);
	set_string_var(STATUS_CPU_SAVER_VAR, DEFAULT_STATUS_CPU_SAVER);
	set_string_var(STATUS_HOLD_VAR, DEFAULT_STATUS_HOLD);
	set_string_var(STATUS_HOLD_LINES_VAR, DEFAULT_STATUS_HOLD_LINES);
	set_string_var(STATUS_INSERT_VAR, DEFAULT_STATUS_INSERT);
	set_string_var(STATUS_LAG_VAR, DEFAULT_STATUS_LAG);
	set_string_var(STATUS_MAIL_VAR, DEFAULT_STATUS_MAIL);
	set_string_var(STATUS_MODE_VAR, DEFAULT_STATUS_MODE);
	set_string_var(STATUS_MSGCOUNT_VAR, DEFAULT_STATUS_MSGCOUNT);
	set_string_var(STATUS_OPER_VAR, DEFAULT_STATUS_OPER);
	set_string_var(STATUS_VOICE_VAR, DEFAULT_STATUS_VOICE);
	set_string_var(STATUS_NOTIFY_VAR, DEFAULT_STATUS_NOTIFY);
	set_string_var(STATUS_OPER_KILLS_VAR, DEFAULT_STATUS_OPER_KILLS);
	set_string_var(STATUS_OVERWRITE_VAR, DEFAULT_STATUS_OVERWRITE);
	set_string_var(STATUS_QUERY_VAR, DEFAULT_STATUS_QUERY);
	set_string_var(STATUS_SERVER_VAR, DEFAULT_STATUS_SERVER);
	set_string_var(STATUS_TOPIC_VAR, DEFAULT_STATUS_TOPIC);
	set_string_var(STATUS_UMODE_VAR, DEFAULT_STATUS_UMODE);
	set_string_var(STATUS_USER_VAR, DEFAULT_STATUS_USER);
	set_string_var(STATUS_USERS_VAR, DEFAULT_STATUS_USERS);
	set_string_var(STATUS_USER1_VAR, DEFAULT_STATUS_USER1);
	set_string_var(STATUS_USER2_VAR, DEFAULT_STATUS_USER2);
	set_string_var(STATUS_USER3_VAR, DEFAULT_STATUS_USER3);
	set_string_var(STATUS_USER4_VAR, DEFAULT_STATUS_USER4);
	set_string_var(STATUS_USER5_VAR, DEFAULT_STATUS_USER5);
	set_string_var(STATUS_USER6_VAR, DEFAULT_STATUS_USER6);
	set_string_var(STATUS_USER7_VAR, DEFAULT_STATUS_USER7);
	set_string_var(STATUS_USER8_VAR, DEFAULT_STATUS_USER8);
	set_string_var(STATUS_USER9_VAR, DEFAULT_STATUS_USER9);
	set_string_var(STATUS_USER10_VAR, DEFAULT_STATUS_USER10);
	set_string_var(STATUS_USER11_VAR, DEFAULT_STATUS_USER11);
	set_string_var(STATUS_USER12_VAR, DEFAULT_STATUS_USER12);
	set_string_var(STATUS_USER13_VAR, DEFAULT_STATUS_USER13);
	set_string_var(STATUS_USER14_VAR, DEFAULT_STATUS_USER14);
	set_string_var(STATUS_USER15_VAR, DEFAULT_STATUS_USER15);
	set_string_var(STATUS_USER16_VAR, DEFAULT_STATUS_USER16);
	set_string_var(STATUS_USER17_VAR, DEFAULT_STATUS_USER17);
	set_string_var(STATUS_USER18_VAR, DEFAULT_STATUS_USER18);
	set_string_var(STATUS_USER19_VAR, DEFAULT_STATUS_USER19);
	set_string_var(STATUS_WINDOW_VAR, DEFAULT_STATUS_WINDOW);

	set_string_var(USERINFO_VAR, DEFAULT_USERINFO);

	set_string_var(USERMODE_VAR, !send_umode ? DEFAULT_USERMODE : send_umode);
	set_user_mode(curr_scr_win, !send_umode? DEFAULT_USERMODE : send_umode, 0);

	set_beep_on_msg(curr_scr_win, DEFAULT_BEEP_ON_MSG, 0);
	set_string_var(CLIENTINFO_VAR, IRCII_COMMENT);
	set_string_var(FAKE_SPLIT_PATS_VAR, "*fuck* *shit* *suck* *dick* *penis* *cunt* *haha* *fake* *split* *ass* *hehe* *bogus* *yawn* *leet* *blow* *screw* *dumb* *fbi*");

	set_string_var(CDCC_PROMPT_VAR, "%GC%gDCC");
	set_string_var(SERVER_PROMPT_VAR, "[1;32m[%s][0m");
	set_string_var(BOT_LOGFILE_VAR, "tcl.log");

	set_string_var(HELP_PATH_VAR, DEFAULT_HELP_PATH);

#ifdef WANT_CD
	set_cd_device(curr_scr_win, "/dev/cdrom", 0);
#endif
	set_string_var(OPER_MODES_VAR, DEFAULT_OPERMODE);	

	set_lastlog_size(curr_scr_win, NULL, irc_variable[LASTLOG_VAR].integer);
	set_history_size(curr_scr_win, NULL, irc_variable[HISTORY_VAR].integer);

	set_highlight_char(curr_scr_win, irc_variable[HIGHLIGHT_CHAR_VAR].string, 0);
	set_lastlog_level(curr_scr_win, irc_variable[LASTLOG_LEVEL_VAR].string, 0);
	set_notify_level(curr_scr_win, irc_variable[NOTIFY_LEVEL_VAR].string, 0);
	set_msglog_level(curr_scr_win, irc_variable[MSGLOG_LEVEL_VAR].string, 0);

#ifdef TRANSLATE
	set_string_var(TRANSLATION_VAR, "LATIN1");
	set_translation(curr_scr_win, "LATIN1", 0);
#endif
	create_fsets(curr_scr_win);
	set_input_prompt(curr_scr_win, DEFAULT_INPUT_PROMPT, 0);
	if (curr_scr_win->wset)
		remove_wsets_for_window(curr_scr_win);
	curr_scr_win->wset = create_wsets_for_window(curr_scr_win);
	build_status(curr_scr_win, NULL, 0);
	window_display = old_display;
}

BUILT_IN_COMMAND(init_vars)
{
	init_variables();
	if (curr_scr_win->wset)
		remove_wsets_for_window(curr_scr_win);
	curr_scr_win->wset = create_wsets_for_window(curr_scr_win);
	update_all_status(curr_scr_win, NULL, 0);
	update_all_windows();
}

BUILT_IN_COMMAND(init_window_vars)
{
	if (curr_scr_win->wset)
		remove_wsets_for_window(curr_scr_win);
	curr_scr_win->wset = create_wsets_for_window(curr_scr_win);
	update_all_status(curr_scr_win, NULL, 0);
	update_all_windows();
}

/*
 * do_boolean: just a handy thing.  Returns 1 if the str is not ON, OFF, or
 * TOGGLE 
 */
int do_boolean(str, value)
	char	*str;
	int	*value;
{
	upper(str);
	if (strcmp(str, var_settings[ON]) == 0)
		*value = 1;
	else if (strcmp(str, var_settings[OFF]) == 0)
		*value = 0;
	else if (strcmp(str, "TOGGLE") == 0)
	{
		if (*value)
			*value = 0;
		else
			*value = 1;
	}
	else
		return (1);
	return (0);
}

/*
 * set_var_value: Given the variable structure and the string representation
 * of the value, this sets the value in the most verbose and error checking
 * of manors.  It displays the results of the set and executes the function
 * defined in the var structure 
 */

#ifdef WANT_DLL
void set_var_value(int var_index, char *value, IrcVariableDll *dll)
#else
void set_var_value(int var_index, char *value)
#endif
{
	char	*rest;
	IrcVariable *var;
	int	old;
#ifdef WANT_DLL
	if (dll)
	{
		var = (IrcVariable *) new_malloc(sizeof(IrcVariable));
		var->type = dll->type;
		var->string = dll->string;
		var->integer = dll->integer;
		var->int_flags = dll->int_flags;
		var->flags = dll->flags;
		var->name = dll->name;
		var->func = dll->func;
	}
	else
#endif
		var = &(irc_variable[var_index]);
	switch (var->type)
	{
	case BOOL_TYPE_VAR:
		if (value && *value && (value = next_arg(value, &rest)))
		{
			old = var->integer;
			if (do_boolean(value, &(var->integer)))
			{
				say("Value must be either ON, OFF, or TOGGLE");
				break;
			}
			if (!(var->int_flags & VIF_CHANGED))
			{
				if (old != var->integer)
					var->int_flags |= VIF_CHANGED;
			}
			if (loading_global)
				var->int_flags |= VIF_GLOBAL;
			if (var->func)
				(var->func) (curr_scr_win, NULL, var->integer);
			say("Value of %s set to %s", var->name,
				var->integer ? var_settings[ON]
					     : var_settings[OFF]);
		}
		else
			put_it("%s", convert_output_format(fget_string_var(FORMAT_SET_FSET), "%s %s", var->name, var->integer?var_settings[ON] : var_settings[OFF]));
		break;
	case CHAR_TYPE_VAR:
		if (!value)
		{
			if (!(var->int_flags & VIF_CHANGED))
			{
				if (var->integer)
					var->int_flags |= VIF_CHANGED;
			}
			if (loading_global)
				var->int_flags |= VIF_GLOBAL;
			var->integer = ' ';
			if (var->func)
				(var->func) (curr_scr_win, NULL, var->integer);
			say("Value of %s set to '%c'", var->name, var->integer);
		}

		else if (value && *value && (value = next_arg(value, &rest)))
		{
			if (strlen(value) > 1)
				say("Value of %s must be a single character",
					var->name);
			else
			{
				if (!(var->int_flags & VIF_CHANGED))
				{
					if (var->integer != *value)
						var->int_flags |= VIF_CHANGED;
				}
				if (loading_global)
					var->int_flags |= VIF_GLOBAL;
				var->integer = *value;
				if (var->func)
					(var->func) (curr_scr_win, NULL, var->integer);
				say("Value of %s set to '%c'", var->name,
					var->integer);
			}
		}
		else
			put_it("%s", convert_output_format(fget_string_var(FORMAT_SET_FSET), "%s %c", var->name, var->integer));
		break;
	case INT_TYPE_VAR:
		if (value && *value && (value = next_arg(value, &rest)))
		{
			int	val;

			if (!is_number(value))
			{
				say("Value of %s must be numeric!", var->name);
				break;
			}
			if ((val = my_atol(value)) < 0)
			{
				say("Value of %s must be greater than 0", var->name);
				break;
			}
			if (!(var->int_flags & VIF_CHANGED))
			{
				if (var->integer != val)
					var->int_flags |= VIF_CHANGED;
			}
			if (loading_global)
				var->int_flags |= VIF_GLOBAL;
			var->integer = val;
			if (var->func)
				(var->func) (curr_scr_win, NULL, var->integer);
			say("Value of %s set to %d", var->name, var->integer);
		}
		else
			put_it("%s", convert_output_format(fget_string_var(FORMAT_SET_FSET), "%s %d", var->name, var->integer));
		break;
	case STR_TYPE_VAR:
		if (value)
		{
			if (*value)
			{
				char	*temp = NULL;

				if (var->flags & VF_EXPAND_PATH)
				{
					temp = expand_twiddle(value);
					if (temp)
						value = temp;
					else
						say("SET: no such user");
				}
				if ((!var->int_flags & VIF_CHANGED))
				{
					if ((var->string && ! value) ||
					    (! var->string && value) ||
					    my_stricmp(var->string, value))
						var->int_flags |= VIF_CHANGED;
				}
				if (loading_global)
					var->int_flags |= VIF_GLOBAL;
				malloc_strcpy(&(var->string), value);
				if (temp)
					new_free(&temp);
			}
			else
			{
				put_it("%s", convert_output_format(fget_string_var(var->string?FORMAT_SET_FSET:FORMAT_SET_NOVALUE_FSET), "%s %s", var->name, var->string));
				return;
			}
		}
		else
			new_free(&(var->string));
		if (var->func && !(var->int_flags & VIF_PENDING))
		{
			var->int_flags |= VIF_PENDING;
			(var->func) (curr_scr_win, var->string, 0);
			var->int_flags &= ~VIF_PENDING;
		}
		say("Value of %s set to %s", var->name, var->string ?
			var->string : "<EMPTY>");
		break;
	}
#ifdef WANT_DLL
	if (dll)
	{
		dll->integer = var->integer;
		if (var->string)
			dll->string = m_strdup(var->string);
		else
			dll->string = NULL;
		new_free(&var->string);
		new_free((char **)&var);
	}
#endif

}

#if 0
static void do_dop_reset(ChannelList *tmp)
{
NickList *nick;
	if (tmp)
	{
		for (nick = next_nicklist(tmp, NULL); nick; nick = next_nicklist(tmp, nick))
		{
			nick->dopcount = 0;
			nick->doptime = 0;
		}
	}
}
 
static void do_nick_reset(ChannelList *tmp)
{
NickList *nick;
	if (tmp)
	{
		for (nick = next_nicklist(tmp, NULL); nick; nick = next_nicklist(tmp, nick))
		{
			nick->nickcount = 0;
			nick->nicktime = 0;
		}
	}
}
 
static void do_kick_reset(ChannelList *tmp)
{
NickList *nick;
	if (tmp)
	{
		for (nick = next_nicklist(tmp, NULL); nick; nick = next_nicklist(tmp, nick))
		{
			nick->kickcount = 0;
			nick->kicktime = 0;
		}
	}
}
 
static void do_pubflood_reset(ChannelList *tmp)
{
NickList *nick;
	if (tmp)
	{
		for (nick = next_nicklist(tmp, NULL); nick; nick = next_nicklist(tmp, nick))
		{
			nick->floodcount = 0;
			nick->floodtime = 0;
		}
	}
}
 
static void do_join_reset(ChannelList *tmp)
{
NickList *nick;
	if (tmp)
	{
		for (nick = next_nicklist(tmp, NULL); nick; nick = next_nicklist(tmp, nick))
		{
			nick->joincount = 0;
			nick->jointime = 0;
		}
	}
}
#endif

extern AliasStack1 *set_stack;
void do_stack_set(int type, char *args)
{
	AliasStack1 *aptr = set_stack;
	AliasStack1 **aptrptr = &set_stack;
		
	if (!*aptrptr && (type == STACK_POP || type == STACK_LIST))
	{
		say("Set stack is empty!");
		return;
	}

	if (STACK_PUSH == type)
	{
		enum VAR_TYPES var_index;
		int cnt = 0;
		/* Dont need to unstub it, we're not actually using it. */
		upper(args);
		find_fixed_array_item(irc_variable, sizeof(IrcVariable), NUMBER_OF_VARIABLES, args, &cnt, (int *)&var_index);
		if (cnt < 0)
		{	
				aptr = (AliasStack1 *)new_malloc(sizeof(AliasStack1));
				aptr->next = aptrptr ? *aptrptr : NULL;
				*aptrptr = aptr;
				aptr->set = (IrcVariable *) new_malloc(sizeof(IrcVariable));
				memcpy(aptr->set, &irc_variable[var_index], sizeof(IrcVariable));
				aptr->name = m_strdup(irc_variable[var_index].name);
				aptr->set->string = m_strdup(irc_variable[var_index].string);
				aptr->var_index = var_index;
		}
		else if ((cnt == 0))
			say("No such Set [%s]", args);
		else
			say("Set is ambiguous %s", args);
		return;
	}

	if (STACK_POP == type)
	{
		AliasStack1 *prev = NULL;
		for (aptr = *aptrptr; aptr; prev = aptr, aptr = aptr->next)
		{
			/* have we found it on the stack? */
			if (!my_stricmp(args, aptr->name))
			{
				/* remove it from the list */
				if (prev == NULL)
					*aptrptr = aptr->next;
				else
					prev->next = aptr->next;

				new_free(&(irc_variable[aptr->var_index].string));
				memcpy(&irc_variable[aptr->var_index], aptr->set, sizeof(IrcVariable));
				/* free it */
				new_free((char **)&aptr->name);
				new_free((char **)&aptr);
				return;
			}
		}
		say("%s is not on the %s stack!", args, "Set");
		return;
	}
	if (STACK_LIST == type)
	{
		AliasStack1 *prev = NULL;
		for (aptr = *aptrptr; aptr; prev = aptr, aptr = aptr->next)
		{
			switch(aptr->set->type)
			{
				case BOOL_TYPE_VAR:
					say("Variable [%s] = %s", aptr->set->name, on_off(aptr->set->integer));
					break;
				case INT_TYPE_VAR:
					say("Variable [%s] = %d", aptr->set->name, aptr->set->integer);
					break;
				case CHAR_TYPE_VAR:
					say("Variable [%s] = %c", aptr->set->name, aptr->set->integer);
					break;
				case STR_TYPE_VAR:
					say("Variable [%s] = %s", aptr->set->name, aptr->set->string?aptr->set->string:"<Empty String>");
					break;
				default:
					bitchsay("Error in do_stack_set: unknown set type");
			}
		}
		return;
	}
	say("Unknown STACK type ??");
}


/*
 * set_variable: The SET command sets one of the irc variables.  The args
 * should consist of "variable-name setting", where variable name can be
 * partial, but non-ambbiguous, and setting depends on the variable being set 
 */
BUILT_IN_COMMAND(setcmd)
{
	char	*var;
	int	cnt = 0;
	int	hook = 0;

enum VAR_TYPES	var_index;

#ifdef WANT_DLL
	IrcVariableDll *dll = NULL;
#endif	
	if ((var = next_arg(args, &args)) != NULL)
	{
		if (!my_strnicmp(var, "FORMAT", 2) || !my_strnicmp(var, "-FORMAT", 3))
		{
			char *t = NULL;
			malloc_sprintf(&t, "%s%s%s", var, args&&*args?" ":empty_string, args&&*args?args:empty_string);
			fset_variable(NULL, t, NULL, NULL);
			new_free(&t);
			return;
		}
		if (*var == '-')
		{
			var++;
			args = NULL;
		}
#ifdef WANT_DLL
		if (dll_variable)
		{
			int dll_cnt = 0;
			if ((dll = (IrcVariableDll *) find_in_list_ext((List **)&dll_variable, var, 0, list_strnicmp)))
			{
				IrcVariableDll *tmp;
				for (tmp = dll; tmp; tmp = tmp->next)
				{
					if (!my_strnicmp(tmp->name, var, strlen(var)))
						dll_cnt++;
				}
				if (my_stricmp(dll->name, var))
				{
					cnt = dll_cnt;
					if (cnt == 1)
						cnt = -1;
				}
				else
					cnt = -1;
			}
		}
		if (cnt == 0)
#endif
		{
			upper(var);
			find_fixed_array_item (irc_variable, sizeof(IrcVariable), NUMBER_OF_VARIABLES, var, &cnt, (int *)&var_index);
		}

		if (cnt == 1)
			cnt = -1;
#ifdef WANT_DLL
		if ((cnt >= 0) || (!dll && !(irc_variable[var_index].int_flags & VIF_PENDING)) || (dll && !(dll->int_flags & VIF_PENDING)))
			hook = 1;
#else
		if ((cnt >= 0) || (!(irc_variable[var_index].int_flags & VIF_PENDING)))
			hook = 1;
#endif
		if (cnt < 0)
		{
#ifdef WANT_DLL
			if (dll)
				dll->int_flags |= VIF_PENDING;
			else
#endif
				irc_variable[var_index].int_flags |= VIF_PENDING;
		}

		if (hook)
			hook = do_hook(SET_LIST, "%s %s", var, args ? args : empty_string);
		else
			hook = 1;
		if (cnt < 0)
		{
#ifdef WANT_DLL
			if (dll)
				dll->int_flags |= VIF_PENDING;
			else
#endif
				irc_variable[var_index].int_flags &= ~VIF_PENDING;
		}
		if (hook)
		{
			if (cnt < 0)
#ifdef WANT_DLL
				set_var_value(var_index, args, dll);
#else
				set_var_value(var_index, args);
#endif
			else if (cnt == 0)
#ifdef WANT_DLL
				if (!dll)
					say("No such variable \"%s\"", var);
				else
					set_var_value(-1, args, dll);
#else
				say("No such variable \"%s\"", var);
#endif
			else
			{
				say("%s is ambiguous", var);
#ifdef WANT_DLL
			if (dll)
			{
				IrcVariableDll *tmp;
				for (tmp = dll; tmp; tmp = tmp->next)
				{
					if (!my_strnicmp(tmp->name, var, strlen(var)))
						set_var_value(-1, empty_string, tmp);
					else
						break;
				}
			}
			else
#endif
				for (cnt += var_index; var_index < cnt; var_index++)
#ifdef WANT_DLL
					set_var_value(var_index, empty_string, dll);
#else
					set_var_value(var_index, empty_string);
#endif
			}
		}	
	}
	else
        {
		int var_index;
		for (var_index = 0; var_index < NUMBER_OF_VARIABLES; var_index++)
#ifdef WANT_DLL
			set_var_value(var_index, empty_string, NULL);
		for (dll = dll_variable; dll; dll = dll->next)
			set_var_value(-1, empty_string, dll);
#else
			set_var_value(var_index, empty_string);  
#endif
	}
}

/*
 * save_variables: this writes all of the IRCII variables to the given FILE
 * pointer in such a way that they can be loaded in using LOAD or the -l switch 
 */
void save_variables(FILE *fp, int do_all)
{
	IrcVariable *var;

	for (var = irc_variable; var->name; var++)
	{
		if (!(var->int_flags & VIF_CHANGED))
			continue;
		if ((do_all == 1) || !(var->int_flags & VIF_GLOBAL))
		{
			if (strcmp(var->name, "DISPLAY") == 0 || strcmp(var->name, "CLIENT_INFORMATION") == 0)
				continue;
			fprintf(fp, "SET ");
			switch (var->type)
			{
			case BOOL_TYPE_VAR:
				fprintf(fp, "%s %s\n", var->name, var->integer ?
					var_settings[ON] : var_settings[OFF]);
				break;
			case CHAR_TYPE_VAR:
				fprintf(fp, "%s %c\n", var->name, var->integer);
				break;
			case INT_TYPE_VAR:
				fprintf(fp, "%s %u\n", var->name, var->integer);
				break;
			case STR_TYPE_VAR:
				if (var->string)
					fprintf(fp, "%s %s\n", var->name,
						var->string);
				else
					fprintf(fp, "-%s\n", var->name);
				break;
			}
		}
	}
}

void savebitchx_variables(FILE *fp)
{
	IrcVariable *var;
	int count = 0;
	for (var = irc_variable; var->name; var++)
	{
		if (!(var->flags & VIF_BITCHX))
			continue;
		count++;
		fprintf(fp, "SET ");
		switch (var->type)
		{
		case BOOL_TYPE_VAR:
			fprintf(fp, "%s %s\n", var->name, var->integer ?
				var_settings[ON] : var_settings[OFF]);
			break;
		case CHAR_TYPE_VAR:
			fprintf(fp, "%s %c\n", var->name, var->integer);
			break;
		case INT_TYPE_VAR:
			fprintf(fp, "%s %u\n", var->name, var->integer);
			break;
		case STR_TYPE_VAR:
			if (var->string)
				fprintf(fp, "%s %s\n", var->name,
					var->string);
			else
				fprintf(fp, "-%s\n", var->name);
			break;
		}
	}
	bitchsay("Saved %d variables", count);
}

char	*make_string_var(char *var_name)
{
	int	cnt,
		msv_index;
	char	*ret = NULL;

	upper(var_name);
	if ((find_fixed_array_item (irc_variable, sizeof(IrcVariable), NUMBER_OF_VARIABLES, var_name, &cnt, &msv_index) == NULL))
		return NULL;
	if (cnt >= 0)
		return NULL;
	switch (irc_variable[msv_index].type)
	{
		case STR_TYPE_VAR:
			ret = m_strdup(irc_variable[msv_index].string);
			break;
		case INT_TYPE_VAR:
			ret = m_strdup(ltoa(irc_variable[msv_index].integer));
			break;
		case BOOL_TYPE_VAR:
			ret = m_strdup(var_settings[irc_variable[msv_index].integer]);
			break;
		case CHAR_TYPE_VAR:
			ret = m_dupchar(irc_variable[msv_index].integer);
			break;
	}
	return ret;
}

/* exec_warning: a warning message displayed whenever EXEC_PROTECTION is turned off.  */
static	void exec_warning(Window *win, char *unused, int value)
{
	if (value == OFF)
	{
		bitchsay("Warning!  You have turned EXEC_PROTECTION off");
		bitchsay("Please read the /HELP SET EXEC_PROTECTION documentation");
	}
}

static	void input_warning(Window *win, char *unused, int value)
{
	if (value == OFF)
	{
		bitchsay("Warning!  You have turned INPUT_PROTECTION off");
		bitchsay("Please read the /HELP ON INPUT, and /HELP SET INPUT_PROTECTION documentation");
	}
}

/* returns the size of the character set */
int charset_size(void)
{
	return get_int_var(EIGHT_BIT_CHARACTERS_VAR) ? 256 : 128;
}

static	void eight_bit_characters(Window *win, char *unused, int value)
{
	if (value == ON && !term_eight_bit())
		say("Warning!  Your terminal says it does not support eight bit characters");
	set_term_eight_bit(value);
}


static void update_max_recursions (Window *win, char *unused, int value)
{
	extern int max_recursions;
	if (value < 0)
		set_int_var(MAX_RECURSIONS_VAR, 1);
	max_recursions = get_int_var(MAX_RECURSIONS_VAR);
}

static	void set_realname(Window *win, char *value, int unused)
{
	if (value)
		strmcpy(realname, value, REALNAME_LEN);
	else
		strmcpy(realname, empty_string, REALNAME_LEN);
}

void reinit_autoresponse(Window *win, char *value, int unused)
{
int old_window = window_display;
	window_display = 1;
	if (value)
		malloc_strcpy(&auto_str, value);
	else 
		bitchsay("Auto Response is set to - %s", auto_str);
	window_display = old_window;
}

static void set_numeric_string(Window *win, char *value, int unused)
{
	malloc_strcpy(&thing_ansi, value);
}

static void set_user_mode(Window *win, char *value, int unused)
{
	malloc_strcpy(&send_umode, value);
}

int old_ov_mode = -1;

static void set_ov_mode (Window *win, char *value, int unused)
{
int old_window_display = window_display;
	if (!curr_scr_win)
		return;
	window_display = 0;
	if (old_ov_mode == -1)
		setup_ov_mode(unused ? 0 : 1, 0);
	else if (old_ov_mode != unused)
		setup_ov_mode(unused ? 0 : 1, 0);
	old_ov_mode = unused;
	window_display = old_window_display;
}

static void set_away_time(Window *win, char *unused, int value)
{
	if (value == 0)
		set_int_var(AUTO_AWAY_TIME_VAR, 0);
	else if ((value / 60) == 0)		
		set_int_var(AUTO_AWAY_TIME_VAR, value * 60);
	else if (value < 60 * 10)
		set_int_var(AUTO_AWAY_TIME_VAR, 60 * 10);
	else
		set_int_var(AUTO_AWAY_TIME_VAR, value);
}

void clear_sets(void)
{
int i = 0;
	for(i = 0; irc_variable[i].name; i++)
		new_free(&irc_variable->string);
}

static void reinit_screen(Window *win, char *unused, int value)
{
	set_input_prompt(curr_scr_win, NULL, 0);
	set_input_prompt(curr_scr_win, get_string_var(INPUT_PROMPT_VAR), 0);
	update_all_windows();
	update_all_status(curr_scr_win, NULL, 0);
	update_input(UPDATE_ALL);
}

void reinit_status(Window *win, char *unused, int value)
{
	update_all_windows();
	update_all_status(curr_scr_win, NULL, 0);
}


#ifdef WANT_TCL
void add_tcl_vars(void)
{
int i = 0;
	for(i = 0; irc_variable[i].name; i++)
	{
#if 0
		if (i >= FORMAT_381_VAR && i <= FORMAT_WINDOW_SET_VAR)
			continue;
#endif
		switch(irc_variable[i].type)
		{
			case INT_TYPE_VAR:
				Tcl_SetVar(interp, irc_variable[i].name, ltoa(irc_variable[i].integer), TCL_GLOBAL_ONLY);
				break;
			case STR_TYPE_VAR:
				if (irc_variable[i].string)
					Tcl_SetVar(interp, irc_variable[i].name, irc_variable[i].string, TCL_GLOBAL_ONLY);
				break;
			case BOOL_TYPE_VAR:
				Tcl_SetVar(interp, irc_variable[i].name, irc_variable[i].integer?var_settings[ON]:var_settings[OFF], TCL_GLOBAL_ONLY);
				break;
			default:
				break;
		}
	}
}
#endif

static void set_clock_format (Window *win, char *value, int unused)
{
	extern char *time_format; /* XXXX bogus XXXX */
	malloc_strcpy(&time_format, value);
	update_clock(RESET_TIME);
	update_all_status(curr_scr_win, NULL, 0);
}
