/*
 * 
 *
 * Copyright(c) 1997-2000 - All Rights Reserved
 *
 * See the COPYRIGHT file.
 */

#include "format.h"

#define ctrl(c) ((c)-'@')

#define set_option(x, y)	x[(y)/8] |= (1 << ((y) % 8))
#define unset_option(x, y)	x[(y)/8] &= ~(1 << ((y) % 8))
#define option(x, y)		(x[(y)/8] & (1 << ((y) % 8)))

		/* customizable variables */
enum /* boolean options */
{
  Z_SHOWALL = 0, /* DEBUG: display everything which goes to the log */
  Z_REJOIN,	/* automaticallly rejoin channels (available at t&s levels) */
  Z_RECONNECT,	/* automatically reconnect servers (idem) */
  Z_RSTATUS,	/* use reverse for status bar instead of bold */
  Z_ETABKEY,	/* enhanced tabkey (not available at the channel level) */
  Z_UNDEL,	/* undelete mode: shows LOG_DEL entries (see ESC-u) */
  Z_HOLD,	/* ircii like holdmode: don't automatically scroll */
  Z_VCOUNT,	/* verbose counters: underlines the static part of the match */
  Z_VCTCP,	/* verbose CTCPs */
  Z_URL,	/* grab URLs */
  Z_IRCII,	/* use ircii style attributes */
  Z_NOCOLOR,	/* hide ^C color junk */
  ZMAX
};

/* must match TERM_* */
#define	K_UNDERLINE	0x00001
#define	K_STANDOUT	0x00002
#define	K_BOLD		0x00004
#define	K_CHIDE		0x00008
#define	K_BEEP		0x00010	/* beep when matching */
#define	K_NOTIFY	0x00020	/* sets W_KEYWORD for window */
#define	K_SPACE		0x00040

#define	K_OHIGHLIGHT	0x00100	/* highlight origin (origin matching) */
#define	K_OIGNORE	0x00200	/* set LOG_IGNORE (origin matching) */

#define	K_HIDE		0x01000	/* set LOG_HIDE on message */
#define	K_IGNORE	0x02000	/* set LOG_IGNORE on message */

#define	K_REGEXP	0x10000	/* keyword is a regexp */

struct keyword_
{
  char			*kword;
#if defined(HAVE_REGEXP)
  regex_t		rword;
#endif
  unsigned int		kflag;

  struct keyword_	*nextk;
};

struct rewrite_
{
  char			type;	/* 0: stop on match, 1: keep going */
  unsigned int		fmt;
  char			*match;
  char			*new;

#if defined(HAVE_REGEXP)
  regex_t		preg;
#endif

  struct rewrite_	*nextr;
};
      
struct custom_
{
  unsigned char		zopt_on[(ZMAX + 7)/8];
  unsigned char		zopt_off[(ZMAX + 7)/8];

  char			**format;	/* format strings */
  char			**numerics;	/* format strings for numerics */
  unsigned int		mask_on[11], mask_off[11];	/* filter masks */

  struct keyword_	*keywords;
  struct rewrite_	*rules;

  FILE			*log;
  char			logfilter;
};

		/* different log levels */
/* junk, typically not logged by other clients */
#define	LOG_DEBUG	0x00000001	/* debug messages */
#define	LOG_ISNIF	0x00000002	/* incoming traffic */
#define	LOG_OSNIF	0x00000004	/* outgoing traffic */
#define	LOG_INPUT	0x00000008	/* typed by the user */
/* source */
#define	LOG_SERVER	0x00000010	/* sent by a server */
#define	LOG_SERVICE	0x00000020	/* sent by a service */
#define	LOG_USER	0x00000040	/* sent by a user */
#define	LOG_CLIENT	0x00000080	/* junk displayed by the client */
/* destination scope */
#define	LOG_PUBLIC	0x00000100	/* public */
#define	LOG_BROADCAST	0x00000200	/* broadcast */
#define	LOG_PRIVATE	0x00000400	/* private */
#define	LOG_MULTICAST	0x00000800	/* QUIT/NICK type of message
					   used internally ONLY */
/* type */
#define	LOG_MSG		0x00001000	/* message */
#define	LOG_NOTICE	0x00002000	/* notice */
#define	LOG_DCC		0x00004000	/* dcc chat messages */
#define	LOG_CRAP	0x00008000	/* what's left */
/* join part quit topic mode hmm */

#define	LOG_UQUIT	0x00010000	/* regular user quit */
#define	LOG_SQUIT	0x00020000	/* user splitting */
#define	LOG_SPLIT	0x00040000	/* smart split handling */

#define	LOG_HIGHLIGHT	0x01000000	/* origin based highlight */
#define	LOG_KEYWORD	0x02000000	/* contains a keyword */

#define	LOG_HIDE	0x10000000	/* hide */
#define	LOG_IGNORE	0x20000000	/* origin based ignore */
#define	LOG_LASTLOG	0x40000000	/* output from /lastlog */
#define	LOG_DEL		0x80000000	/* entry was /clear'ed */

#define	LOG_ALL		0x0003F7FF
#define	LOG_DEFAULT	0x0003F7F0
#define	LOG_QUICKDEL	0x0000000F

struct log_
{
  struct log_	*nextl;
  struct log_	*prevl;
  /* window???? */
  unsigned int	flags;
  char		*origin;	/* NULL if self */
  char		*cmd;
  signed char	fmt;
  char		*dest;		/* NULL if self -- hmm is this wise?
				   it eventually screws up formatting? */
  char		*para;
  time_t	ts;		/* time stamp */
  time_t	delts;		/* when /clear'ed */
  char		*prefix;	/* optional prefix for the string */
  int		plen;		/* length of the prefix string */
  int		len;		/* length of the formatted string */
  char		*formatted;	/* string as it should appear */
  u_char	*attributes;	/* character attriibutes (optional) */
};

enum /* windows options */
{
  W_DEFAULT = 0,	/* hmpf */
  W_DCC,		/* where all DCC go */
  W_MCAST,		/* QUIT/NICK */
  W_ACTIVITY,		/* activity */
  W_KEYWORD,		/* keyword */
  W_NOPREFIX,		/* hide prefix */
  WMAX
};

struct window_
{
  unsigned char		ref;

  unsigned char		wopt[(WMAX + 7)/8];

  struct custom_	custw;
  unsigned char		fnb; /* filter number 0-9 */
  char			*searchstr; /* current search string */

  struct channel_	*defchan; /* default channel */
  char			query[10];

  struct server_	*via, *lasts; /* current and last server */

  struct log_		*llog, /* last logged line */
			*flog, /* first logged line */
  			*ldisp; /* last line displayed */
  unsigned char		ltrunc; /* truncation: how many lines not displayed */

  char			*split;
  time_t		split_t;

  struct window_	*nextw;
};

enum /* server options */
{
  S_DEFAULT = 0,
  S_CONFIG,		/* configuration file read */
  S_DNS,		/* waiting for DNS lookup to give IP address */
  S_NOTCONNECTED,	/* not connected (irc wise: tcp conn might be up) */
  S_CONNECTING,		/* connecting (tcp wise) */
  S_CONNECTED,		/* connected (tcp wise) */
  S_RECONNECT,		/* reconnect after timer expires */
  S_QUIT,		/* user initiated quit -> don't reconnect */
  S_DCC,		/* DCC */
  S_SEND,		/* DCC send */
  S_LISTEN,		/* waiting for DCC */
  S_MOTD,		/* set upon 001, removed when receiving motd */
  S_PING,		/* PING sent */
  SMAX
};

#define P_IRC	1	/* IRC */
#define P_E	2	/* EFnet */
#define P_U	3	/* Undernet */
#define P_D	4	/* Dalnet */

#define P_MAX	4

struct server_
{
  char			*sname;
  char			*ip;
#if defined(HAVE_GETADDRINFO)
  struct addrinfo	*address;
#endif
  char			*pass;		/* also used for DCC filenames */
  int			port;
  char			*nick;
  char			*uname;		/* user name */
  char			*rname;		/* real name */
  unsigned char		protocol;	/* protocol type */
  char			umode[32];
  int			fd;
  char			readbuf[520];
  unsigned long		size, read, sent;	/* DCC file size */
  int			readf; /* incoming file */
  int			sendf; /* outgoing file */
  unsigned char		sopt[(SMAX + 7)/8];

  time_t		lastr, ts;

  struct custom_	custs;

  struct server_	*nexts;
};

enum /* channel options */
{
  C_DEFAULT = 0,	/* default channel for the window */
  C_JOINING,		/* JOIN sent to server: one and one only
			 * can't issue a PART when this is set
			 */
  C_JOINED,		/* on channel
			 * can't issue a JOIN when this is set
			 */
  C_REJOIN,		/* auto rejoin */
  C_REJOINED,		/* rejoined (already attempted) */
  C_CHOP,		/* channel operator status */
  C_PART,		/* user requested part: won't try to rejoin */
  C_DEL,		/* marked for deletion */
  C_NAMES,		/* got a complete RPL_NAMES */
  CMAX
};

struct member_
{
  char			*nick;
  struct member_	*next;
};

struct channel_
{
  char			*chname;
  struct window_	*on;
  unsigned char		copt[(CMAX + 7)/8];

  struct custom_	custc;

  time_t		rejoin;

  struct member_	*members;
  unsigned int		member_cnt;

  struct channel_	*nextc;
};
