/*----------------------------------------------------------------------
  $Id: pine.h,v 4.741 1999/01/29 00:51:43 hubert Exp $

            T H E    P I N E    M A I L   S Y S T E M

   Laurence Lundblade and Mike Seibel
   Networks and Distributed Computing
   Computing and Communications
   University of Washington
   Administration Builiding, AG-44
   Seattle, Washington, 98195, USA
   Internet: lgl@CAC.Washington.EDU
             mikes@CAC.Washington.EDU

   Please address all bugs and comments to "pine-bugs@cac.washington.edu"


   Pine and Pico are registered trademarks of the University of Washington.
   No commercial use of these trademarks may be made without prior written
   permission of the University of Washington.

   Pine, Pico, and Pilot software and its included text are Copyright
   1989-1999 by the University of Washington.

   The full text of our legal notices is contained in the file called
   CPYRIGHT, included with this distribution.


   USENET News reading additions in part by L Lundblade / NorthWestNet, 1993
   lgl@nwnet.net

   Pine is in part based on The Elm Mail System:
    ***********************************************************************
    *  The Elm Mail System  -  Revision: 2.13                             *
    *                                                                     *
    * 			Copyright (c) 1986, 1987 Dave Taylor              *
    * 			Copyright (c) 1988, 1989 USENET Community Trust   *
    ***********************************************************************
 

  ----------------------------------------------------------------------*/

/*======================================================================

     pine.h 

     Definitions here are fundamental to pine. 

    No changes should need to be made here to configure pine for one
  site or another.  That is, no changes for local preferences such as
  default directories and other parameters.  Changes might be needed here
  for porting pine to a new machine, but we hope not.

   Includes
     - Various convenience definitions and macros
     - macros for debug printfs
     - data structures used by Pine
     - declarations of all Pine functions

  ====*/


#ifndef _PINE_INCLUDED
#define _PINE_INCLUDED

#define PINE_VERSION		"4.10"
#define	PHONE_HOME_VERSION	"-count"
#define	PHONE_HOME_HOST		"docserver.cac.washington.edu"

#define UNKNOWN_CHARSET		"X-UNKNOWN"


#if defined(DOS) || defined(OS2)
#define	NEWLINE		"\r\n"		/* local EOL convention...  */
#else
#define	NEWLINE		"\n"		/* necessary for gf_* funcs */
#endif


#define EXECUTE_ACCESS	01		/* These five are 	   */
#define WRITE_ACCESS	02		/*    for the calls	   */
#define READ_ACCESS	04		/*       to access()       */
#define ACCESS_EXISTS	00		/*           <etc>         */
#define EDIT_ACCESS	06		/*  (this is r+w access)   */
#define OWNER_ONLY	010		/* open with mode 0600     */

#define	FEX_NOENT	0x0000		/* file_exists: doesn't exist  */
#define	FEX_ISFILE	0x0001		/* file_exists: name is a file */
#define	FEX_ISDIR	0x0002		/* file_exists: name is a dir  */
#define	FEX_ISMARKED	0x0004		/* file_exists: name is a dir  */
#define	FEX_ERROR	0x1000		/* file_exists: error occured  */

#define	BFL_NONE	0x00		/* build_folder_list: no flag */
#define	BFL_FLDRONLY	0x01		/* ignore directories	      */
#define	BFL_LSUB	0x02		/* use mail_lsub vs mail_list */
#define	BFL_SCAN	0x04		/* use mail_scan vs mail_list */

#define	FM_DISPLAY	0x01		/* flag for format_message */
#define	FM_NEW_MESS	0x02		/* ditto		   */
#define	FM_DO_PGP	0x04		/* ditto		   */
#define	FM_HANDLES	0x08		/* ditto		   */
#define	FM_NOWRAP	0x10		/* ditto		   */

#define SEQ_EXCEPTION   (-3)		/* returned when seq # change and no
					   on_ctrl_C available.          */
#define	RB_NORM		0x00		/* flags modifying radio_buttons */
#define	RB_ONE_TRY	0x01		/* one shot answer, else default */
#define	RB_FLUSH_IN	0x02		/* discard pending input	 */
#define	RB_NO_NEWMAIL	0x04		/* Quell new mail check		 */
#define	RB_SEQ_SENSITIVE 0x08		/* Sensitive to seq # changes    */

#define	WT_NORM		RB_NORM		/* flags modifying want_to       */
#define	WT_FLUSH_IN	RB_FLUSH_IN	/* discard pending input         */
#define	WT_SEQ_SENSITIVE RB_SEQ_SENSITIVE /* Sensitive to seq # changes  */

#define	GF_NOOP		0x01		/* flags used by generalized */
#define GF_EOD		0x02		/* filters                   */
#define GF_DATA		0x04		/* See filter.c for more     */
#define GF_ERROR	0x08		/* details                   */
#define GF_RESET	0x10

#define	DA_SAVE		0x01		/* flags used by display_attachment */
#define	DA_FROM_VIEW	0x02		/* see mailpart.c		    */
#define	DA_RESIZE	0x04

#define OE_NONE			0x00	/* optionally_enter flags	*/
#define OE_USER_MODIFIED	0x08	/* set on return if user input	*/
#define OE_DISALLOW_CANCEL	0x01	/* Turn off Cancel menu item	*/
#define	OE_DISALLOW_HELP	0x02	/* Turn off Help menu item	*/
#define OE_KEEP_TRAILING_SPACE  0x10	/* Allow trailing white-space	*/
#define OE_SEQ_SENSITIVE  	0x20	/* Sensitive to seq # changes   */
#define OE_APPEND_CURRENT  	0x40	/* append, don't truncate       */
#define OE_PASSWD	  	0x80	/* Don't echo user input        */

#define GE_NONE			0x00	/* get_export_filename flags    */
#define GE_IS_EXPORT		0x01	/* include EXPORT: in prompt    */
#define GE_SEQ_SENSITIVE	0x02	/* Sensitive to seq # changes   */

#define GFHP_STRIPPED		0x01
#define GFHP_HANDLES		0x02
#define GFHP_LOCAL_HANDLES	0x04

#define	GFW_HANDLES		0x01
#define	GFW_ONCOMMA		0x02

#define	NSF_TRUST_FLAGS	0x01
#define	NSF_SEEN	0x02

#define	FI_FOLDER		0x01
#define	FI_DIR			0x02
#define	FI_ANY			(FI_FOLDER | FI_DIR)


/*
 * Size of generic filter's input/output queue
 */
#define	GF_MAXBUF		256


#define KEY_HELP_LEN   (2 * MAX_SCREEN_COLS)
                          /*When saving escape sequences, etc length of string
                                for the usual key menu at the bottom. used with
                                begin_output_store(), end_output_store() */


#undef  min
#define min(a,b)	((a) < (b) ? (a) : (b))
#undef  max
#define max(a,b)	((a) > (b) ? (a) : (b))
#define plural(n)	((n) == 1 ? "" : "s")

/*
 * Macro to simplify clearing body portion of pine's display
 */
#define ClearBody()	ClearLines(1, ps_global->ttyo->screen_rows 	      \
						  - FOOTER_ROWS(ps_global) - 1)

/*
 * Macro to reveal horizontal scroll margin.  It can be no greater than
 * half the number of lines on the display...
 */
#define	HS_MAX_MARGIN(p)	(((p)->ttyo->screen_rows-FOOTER_ROWS(p)-3)/2)
#define	HS_MARGIN(p)		min((p)->scroll_margin, HS_MAX_MARGIN(p))


/*
 * Macros to support anything you'd ever want to do with a message
 * number...
 */
#define	mn_init(P, m)		msgno_init((P), (m))

#define	mn_get_cur(p)		(((p) && (p)->select) 			      \
				  ? (p)->select[(p)->sel_cur] : -1)

#define	mn_set_cur(p, m)	{					      \
				  if(p){				      \
				    (p)->select[(p)->sel_cur] = (m);	      \
				  }					      \
				}

#define	mn_inc_cur(s, p)	msgno_inc(s, p)

#define	mn_dec_cur(s, p)	msgno_dec(s, p)

#define	mn_add_cur(p, m)	{					      \
				  if(p){				      \
				      if((p)->sel_cnt+1L > (p)->sel_size){    \
					  (p)->sel_size += 10L;		      \
					  fs_resize((void **)&((p)->select),  \
						    (size_t)(p)->sel_size     \
						             * sizeof(long)); \
				      }					      \
				      (p)->select[((p)->sel_cnt)++] = (m);    \
				  }					      \
				}

#define	mn_total_cur(p)		((p) ? (p)->sel_cnt : 0L)

#define	mn_first_cur(p)		(((p) && (p)->sel_cnt > 0L)		      \
				  ? (p)->select[(p)->sel_cur = 0] : 0L)

#define	mn_next_cur(p)		(((p) && ((p)->sel_cur + 1) < (p)->sel_cnt)   \
				  ? (p)->select[++((p)->sel_cur)] : -1L)

#define	mn_is_cur(p, m)		msgno_in_select((p), (m))

#define	mn_reset_cur(p, m)	{					      \
				  if(p){				      \
				      (p)->sel_cur  = 0L;		      \
				      (p)->sel_cnt  = 1L;		      \
				      (p)->sel_size = 8L;		      \
				      fs_resize((void **)&((p)->select),      \
					(size_t)(p)->sel_size * sizeof(long));\
				      (p)->select[0] = (m);		      \
				  }					      \
			        }

#define	mn_m2raw(p, m)		(((p) && (p)->sort && (m) > 0 		      \
				  && (m) <= mn_get_total(p)) 		      \
				   ? (p)->sort[m] : 0L)

#define	mn_raw2m(p, m)		msgno_in_sort((p), (m))

#define	mn_get_total(p)		((p) ? (p)->max_msgno : 0L)

#define	mn_set_total(p, m)	{					      \
				  if(p)					      \
				    (p)->max_msgno = (m);		      \
			        }

#define	mn_add_raw(p, m)	msgno_add_raw((p), (m))

#define	mn_flush_raw(p, m)	msgno_flush_raw((p), (m))

#define	mn_get_sort(p)		((p) ? (p)->sort_order : SortArrival)

#define	mn_set_sort(p, t)	{					      \
				  if(p)					      \
				    (p)->sort_order = (t);		      \
				}

#define	mn_get_revsort(p)	((p) ? (p)->reverse_sort : 0)

#define	mn_set_revsort(p, t)	{					      \
				  if(p)					      \
				    (p)->reverse_sort = (t);		      \
				}

#define	mn_give(P)		msgno_give(P)

/*
 * This searchs for lines beginning with From<space> so that we can QP-encode
 * them.  It also searches for lines consisting of only a dot.  Some mailers
 * will mangle these lines.  The reason it is ifdef'd is because most people
 * seem to prefer the >From style escape provided by a lot of mail software
 * to the QP-encoding.
 * Froms, dots, bmap, and dmap may be any integer type.  C is the next char.
 * bmap and dmap should be initialized to 1.
 * froms is incremented by 1 whenever a line beginning From_ is found.
 * dots is incremented by 1 whenever a line with only a dot is found.
 */
#define Find_Froms(froms,dots,bmap,dmap,c) { int x,y;			\
				switch (c) {				\
				  case '\n': case '\r':			\
				    x = 0x1;				\
				    y = 0x7;				\
				    bmap = 0;				\
				    break;				\
				  case 'F':				\
				    x = 0x3;				\
				    y = 0;				\
				    break;				\
				  case 'r':				\
				    x = 0x7;				\
				    y = 0;				\
				    break;				\
				  case 'o':				\
				    x = 0xf;				\
				    y = 0;				\
				    break;				\
				  case 'm':				\
				    x = 0x1f;				\
				    y = 0;				\
				    break;				\
				  case ' ':				\
				    x = 0x3f;				\
				    y = 0;				\
				    break;				\
				  case '.':				\
				    x = 0;				\
				    y = 0x3;				\
				    break;				\
				  default:				\
				    x = 0;				\
				    y = 0;				\
				    break;				\
				}					\
				bmap = ((x >> 1) == bmap) ? x : 0;	\
				froms += (bmap == 0x3f ? 1 : 0);	\
				if(y == 0x7 && dmap != 0x3){		\
				    y = 0x1;				\
				    dmap = 0;				\
				}					\
				dmap = ((y >> 1) == dmap) ? y : 0;	\
				dots += (dmap == 0x7 ? 1 : 0);		\
			     }

/*
 * Useful macro to test if current folder is a bboard type (meaning
 * netnews for now) collection...
 */
#define	IS_NEWS(S)	((S) ? ns_test((S)->mailbox, "news") : 0)

#define	READONLY_FOLDER  (ps_global->mail_stream 			     \
			  && ((ps_global->mail_stream->rdonly		     \
			       && !IS_NEWS(ps_global->mail_stream))	     \
			      || ps_global->mail_stream->anonymous))

/*
 * Simple, handy macro to determine if folder name is remote 
 * (on an imap server)
 */
#define	IS_REMOTE(X)	(*(X) == '{' && *((X) + 1) && *((X) + 1) != '}' \
			 && strchr(((X) + 2), '}'))


/* Is this a vCard attachment? */
#define	MIME_VCARD(t,s)	((((t) == TYPETEXT || (t) == TYPEAPPLICATION) \
	                   && (s) && !strucmp((s),"DIRECTORY"))       \
			 || ((t) == TYPETEXT                          \
			   && (s) && !strucmp((s),"X-VCARD")))
#define	MIME_VCARD_A(a)	MIME_VCARD((a)->body->type, (a)->body->subtype)

#define STYLE_NAME(a)   ((a)->text.desc ? (a)->text.desc : "text")


/*
 * Macros to help fetch specific fields
 */
#define	pine_fetchheader_lines(S,N,M,F)		fetch_header(S,N,M,F,0L)
#define	pine_fetchheader_lines_not(S,N,M,F)	fetch_header(S,N,M,F,FT_NOT)


/*
 * Macro to help with new mail check timing...
 */
#define	NM_TIMING(X)	(((X)==NO_OP_IDLE) ? 0 : ((X)==NO_OP_COMMAND) ? 1 : 2)
#define	NM_NONE		0x00
#define	NM_STATUS_MSG	0x01
#define	NM_DEFER_SORT	0x02


/*
 * Macro to help compare two chars without regard to case
 */
#define	CMPNOCASE(x, y)	((isupper((unsigned char) (x))			     \
			    ? tolower((unsigned char) (x))		     \
			    : (unsigned char) (x))			     \
					    == (isupper((unsigned char) (y)) \
				? tolower((unsigned char) (y))		     \
				: (unsigned char) (y)))



/*
 * The array is initialized in init.c so the order of that initialization
 * must correspond to the order of the values here.  The order is
 * significant in that it determines the order that the variables
 * are written into the pinerc file and the order they show up in in the
 * config screen.
 */
typedef	enum {    V_PERSONAL_NAME = 0
		, V_USER_ID
		, V_USER_DOMAIN
		, V_SMTP_SERVER
		, V_NNTP_SERVER
		, V_INBOX_PATH
		, V_INCOMING_FOLDERS
		, V_FOLDER_SPEC
		, V_NEWS_SPEC
		, V_ARCHIVED_FOLDERS
		, V_PRUNED_FOLDERS
		, V_DEFAULT_FCC
		, V_DEFAULT_SAVE_FOLDER
		, V_POSTPONED_FOLDER
		, V_MAIL_DIRECTORY
		, V_READ_MESSAGE_FOLDER
		, V_FORM_FOLDER
		, V_SIGNATURE_FILE
		, V_GLOB_ADDRBOOK
		, V_ADDRESSBOOK
		, V_FEATURE_LIST
		, V_INIT_CMD_LIST
		, V_COMP_HDRS
		, V_CUSTOM_HDRS
		, V_VIEW_HEADERS
		, V_SAVED_MSG_NAME_RULE
		, V_FCC_RULE
		, V_SORT_KEY
		, V_AB_SORT_RULE
		, V_FLD_SORT_RULE
		, V_GOTO_DEFAULT_RULE
		, V_INCOMING_STARTUP
		, V_CHAR_SET
		, V_EDITOR
		, V_SPELLER
		, V_FILLCOL
		, V_REPLY_STRING
		, V_REPLY_INTRO
		, V_EMPTY_HDR_MSG
		, V_IMAGE_VIEWER
		, V_USE_ONLY_DOMAIN_NAME
		, V_PRINTER
		, V_PERSONAL_PRINT_COMMAND
		, V_PERSONAL_PRINT_CATEGORY
		, V_STANDARD_PRINTER
		, V_LAST_TIME_PRUNE_QUESTION
		, V_LAST_VERS_USED
		, V_BUGS_FULLNAME
		, V_BUGS_ADDRESS
		, V_BUGS_EXTRAS
		, V_SUGGEST_FULLNAME
		, V_SUGGEST_ADDRESS
		, V_LOCAL_FULLNAME
		, V_LOCAL_ADDRESS
		, V_FORCED_ABOOK_ENTRY
		, V_KBLOCK_PASSWD_COUNT
		, V_SENDMAIL_PATH
		, V_OPER_DIR
		, V_DISPLAY_FILTERS
		, V_SEND_FILTER
		, V_ALT_ADDRS
		, V_ABOOK_FORMATS
		, V_INDEX_FORMAT
		, V_OVERLAP
		, V_MARGIN
		, V_STATUS_MSG_DELAY
		, V_MAILCHECK
		, V_NEWSRC_PATH
		, V_NEWS_ACTIVE_PATH
		, V_NEWS_SPOOL_DIR
		, V_UPLOAD_CMD
		, V_UPLOAD_CMD_PREFIX
		, V_DOWNLOAD_CMD
		, V_DOWNLOAD_CMD_PREFIX
		, V_MAILCAP_PATH
		, V_MIMETYPE_PATH
		, V_USERINPUTTIMEO
		, V_TCPOPENTIMEO
		, V_RSHOPENTIMEO
		, V_RSHPATH
		, V_RSHCMD
		, V_NEW_VER_QUELL
		, V_BROWSER
		, V_DISABLE_DRIVERS
		, V_REMOTE_ABOOK_METADATA
		, V_REMOTE_ABOOK_HISTORY
		, V_PATTERNS
#ifdef	NEWBB
		, V_NNTP_NEW_GROUP_TIME
#endif
		, V_ELM_STYLE_SAVE	/* obsolete */
		, V_HEADER_IN_REPLY	/* obsolete */
		, V_FEATURE_LEVEL	/* obsolete */
		, V_OLD_STYLE_REPLY	/* obsolete */
		, V_COMPOSE_MIME	/* obsolete */
		, V_SHOW_ALL_CHARACTERS	/* obsolete */
		, V_SAVE_BY_SENDER	/* obsolete */
#if defined(DOS) || defined(OS2)
		, V_FILE_DIR
		, V_FOLDER_EXTENSION
		, V_NORM_FORE_COLOR
		, V_NORM_BACK_COLOR
		, V_REV_FORE_COLOR
		, V_REV_BACK_COLOR
#ifdef	_WINDOWS
		, V_FONT_NAME
		, V_FONT_SIZE
		, V_FONT_STYLE
		, V_PRINT_FONT_NAME
		, V_PRINT_FONT_SIZE
		, V_PRINT_FONT_STYLE
		, V_WINDOW_POSITION
#endif
#endif
#ifdef	ENABLE_LDAP
		, V_LDAP_SERVERS  /* should be last so make will work right */
#endif
		, V_DUMMY
} VariableIndex;

#define	V_LAST_VAR	(V_DUMMY - 1)


#define VAR_PERSONAL_NAME	     vars[V_PERSONAL_NAME].current_val.p
#define GLO_PERSONAL_NAME	     vars[V_PERSONAL_NAME].global_val.p
#define USR_PERSONAL_NAME	     vars[V_PERSONAL_NAME].user_val.p
#define FIX_PERSONAL_NAME	     vars[V_PERSONAL_NAME].fixed_val.p
#define COM_PERSONAL_NAME	     vars[V_PERSONAL_NAME].cmdline_val.p
#define VAR_USER_ID		     vars[V_USER_ID].current_val.p
#define GLO_USER_ID		     vars[V_USER_ID].global_val.p
#define USR_USER_ID		     vars[V_USER_ID].user_val.p
#define COM_USER_ID		     vars[V_USER_ID].cmdline_val.p
#define VAR_USER_DOMAIN		     vars[V_USER_DOMAIN].current_val.p
#define GLO_USER_DOMAIN		     vars[V_USER_DOMAIN].global_val.p
#define USR_USER_DOMAIN		     vars[V_USER_DOMAIN].user_val.p
#define VAR_SMTP_SERVER		     vars[V_SMTP_SERVER].current_val.l
#define GLO_SMTP_SERVER		     vars[V_SMTP_SERVER].global_val.l
#define USR_SMTP_SERVER		     vars[V_SMTP_SERVER].user_val.l
#define FIX_SMTP_SERVER		     vars[V_SMTP_SERVER].fixed_val.l
#define COM_SMTP_SERVER		     vars[V_SMTP_SERVER].cmdline_val.l
#define VAR_INBOX_PATH		     vars[V_INBOX_PATH].current_val.p
#define GLO_INBOX_PATH		     vars[V_INBOX_PATH].global_val.p
#define VAR_INCOMING_FOLDERS	     vars[V_INCOMING_FOLDERS].current_val.l
#define GLO_INCOMING_FOLDERS	     vars[V_INCOMING_FOLDERS].global_val.l
#define USR_INCOMING_FOLDERS	     vars[V_INCOMING_FOLDERS].user_val.l
#define VAR_FOLDER_SPEC		     vars[V_FOLDER_SPEC].current_val.l
#define GLO_FOLDER_SPEC		     vars[V_FOLDER_SPEC].global_val.l
#define VAR_NEWS_SPEC		     vars[V_NEWS_SPEC].current_val.l
#define GLO_NEWS_SPEC		     vars[V_NEWS_SPEC].global_val.l
#define VAR_ARCHIVED_FOLDERS	     vars[V_ARCHIVED_FOLDERS].current_val.l
#define GLO_ARCHIVED_FOLDERS	     vars[V_ARCHIVED_FOLDERS].global_val.l
#define VAR_PRUNED_FOLDERS	     vars[V_PRUNED_FOLDERS].current_val.l
#define GLO_PRUNED_FOLDERS	     vars[V_PRUNED_FOLDERS].global_val.l
#define VAR_DEFAULT_FCC		     vars[V_DEFAULT_FCC].current_val.p
#define GLO_DEFAULT_FCC		     vars[V_DEFAULT_FCC].global_val.p
#define VAR_DEFAULT_SAVE_FOLDER	     vars[V_DEFAULT_SAVE_FOLDER].current_val.p
#define GLO_DEFAULT_SAVE_FOLDER	     vars[V_DEFAULT_SAVE_FOLDER].global_val.p
#define VAR_POSTPONED_FOLDER	     vars[V_POSTPONED_FOLDER].current_val.p
#define GLO_POSTPONED_FOLDER	     vars[V_POSTPONED_FOLDER].global_val.p
#define VAR_MAIL_DIRECTORY	     vars[V_MAIL_DIRECTORY].current_val.p
#define GLO_MAIL_DIRECTORY	     vars[V_MAIL_DIRECTORY].global_val.p
#define VAR_READ_MESSAGE_FOLDER	     vars[V_READ_MESSAGE_FOLDER].current_val.p
#define GLO_READ_MESSAGE_FOLDER	     vars[V_READ_MESSAGE_FOLDER].global_val.p
#define VAR_FORM_FOLDER		     vars[V_FORM_FOLDER].current_val.p
#define GLO_FORM_FOLDER		     vars[V_FORM_FOLDER].global_val.p
#define VAR_SIGNATURE_FILE	     vars[V_SIGNATURE_FILE].current_val.p
#define GLO_SIGNATURE_FILE	     vars[V_SIGNATURE_FILE].global_val.p
#define VAR_GLOB_ADDRBOOK	     vars[V_GLOB_ADDRBOOK].current_val.l
#define GLO_GLOB_ADDRBOOK	     vars[V_GLOB_ADDRBOOK].global_val.l
#define USR_GLOB_ADDRBOOK	     vars[V_GLOB_ADDRBOOK].user_val.l
#define VAR_ADDRESSBOOK		     vars[V_ADDRESSBOOK].current_val.l
#define GLO_ADDRESSBOOK		     vars[V_ADDRESSBOOK].global_val.l
#define USR_ADDRESSBOOK		     vars[V_ADDRESSBOOK].user_val.l
#define FIX_ADDRESSBOOK		     vars[V_ADDRESSBOOK].fixed_val.l
#define VAR_FEATURE_LIST	     vars[V_FEATURE_LIST].current_val.l
#define GLO_FEATURE_LIST	     vars[V_FEATURE_LIST].global_val.l
#define USR_FEATURE_LIST	     vars[V_FEATURE_LIST].user_val.l
#define VAR_INIT_CMD_LIST	     vars[V_INIT_CMD_LIST].current_val.l
#define GLO_INIT_CMD_LIST	     vars[V_INIT_CMD_LIST].global_val.l
#define COM_INIT_CMD_LIST	     vars[V_INIT_CMD_LIST].cmdline_val.l
#define VAR_COMP_HDRS		     vars[V_COMP_HDRS].current_val.l
#define GLO_COMP_HDRS		     vars[V_COMP_HDRS].global_val.l
#define USR_COMP_HDRS		     vars[V_COMP_HDRS].user_val.l
#define VAR_CUSTOM_HDRS		     vars[V_CUSTOM_HDRS].current_val.l
#define GLO_CUSTOM_HDRS		     vars[V_CUSTOM_HDRS].global_val.l
#define USR_CUSTOM_HDRS		     vars[V_CUSTOM_HDRS].user_val.l
#define VAR_VIEW_HEADERS	     vars[V_VIEW_HEADERS].current_val.l
#define GLO_VIEW_HEADERS	     vars[V_VIEW_HEADERS].global_val.l
#define VAR_SAVED_MSG_NAME_RULE	     vars[V_SAVED_MSG_NAME_RULE].current_val.p
#define GLO_SAVED_MSG_NAME_RULE	     vars[V_SAVED_MSG_NAME_RULE].global_val.p
#define USR_SAVED_MSG_NAME_RULE	     vars[V_SAVED_MSG_NAME_RULE].user_val.p
#define VAR_FCC_RULE		     vars[V_FCC_RULE].current_val.p
#define GLO_FCC_RULE		     vars[V_FCC_RULE].global_val.p
#define VAR_SORT_KEY		     vars[V_SORT_KEY].current_val.p
#define GLO_SORT_KEY		     vars[V_SORT_KEY].global_val.p
#define COM_SORT_KEY		     vars[V_SORT_KEY].cmdline_val.p
#define VAR_AB_SORT_RULE	     vars[V_AB_SORT_RULE].current_val.p
#define GLO_AB_SORT_RULE	     vars[V_AB_SORT_RULE].global_val.p
#define VAR_FLD_SORT_RULE	     vars[V_FLD_SORT_RULE].current_val.p
#define GLO_FLD_SORT_RULE	     vars[V_FLD_SORT_RULE].global_val.p
#define VAR_CHAR_SET		     vars[V_CHAR_SET].current_val.p
#define GLO_CHAR_SET		     vars[V_CHAR_SET].global_val.p
#define VAR_EDITOR		     vars[V_EDITOR].current_val.l
#define GLO_EDITOR		     vars[V_EDITOR].global_val.l
#define VAR_SPELLER		     vars[V_SPELLER].current_val.p
#define GLO_SPELLER		     vars[V_SPELLER].global_val.p
#define VAR_FILLCOL		     vars[V_FILLCOL].current_val.p
#define GLO_FILLCOL		     vars[V_FILLCOL].global_val.p
#define VAR_REPLY_STRING	     vars[V_REPLY_STRING].current_val.p
#define GLO_REPLY_STRING	     vars[V_REPLY_STRING].global_val.p
#define VAR_REPLY_INTRO		     vars[V_REPLY_INTRO].current_val.p
#define GLO_REPLY_INTRO		     vars[V_REPLY_INTRO].global_val.p
#define VAR_EMPTY_HDR_MSG	     vars[V_EMPTY_HDR_MSG].current_val.p
#define GLO_EMPTY_HDR_MSG	     vars[V_EMPTY_HDR_MSG].global_val.p
#define VAR_IMAGE_VIEWER	     vars[V_IMAGE_VIEWER].current_val.p
#define GLO_IMAGE_VIEWER	     vars[V_IMAGE_VIEWER].global_val.p
#define VAR_USE_ONLY_DOMAIN_NAME     vars[V_USE_ONLY_DOMAIN_NAME].current_val.p
#define GLO_USE_ONLY_DOMAIN_NAME     vars[V_USE_ONLY_DOMAIN_NAME].global_val.p
#define VAR_PRINTER		     vars[V_PRINTER].current_val.p
#define GLO_PRINTER		     vars[V_PRINTER].global_val.p
#define VAR_PERSONAL_PRINT_COMMAND   vars[V_PERSONAL_PRINT_COMMAND].current_val.l
#define GLO_PERSONAL_PRINT_COMMAND   vars[V_PERSONAL_PRINT_COMMAND].global_val.l
#define VAR_PERSONAL_PRINT_CATEGORY  vars[V_PERSONAL_PRINT_CATEGORY].current_val.p
#define GLO_PERSONAL_PRINT_CATEGORY  vars[V_PERSONAL_PRINT_CATEGORY].global_val.p
#define VAR_STANDARD_PRINTER	     vars[V_STANDARD_PRINTER].current_val.l
#define GLO_STANDARD_PRINTER	     vars[V_STANDARD_PRINTER].global_val.l
#define FIX_STANDARD_PRINTER	     vars[V_STANDARD_PRINTER].fixed_val.l
#define VAR_LAST_TIME_PRUNE_QUESTION vars[V_LAST_TIME_PRUNE_QUESTION].current_val.p
#define VAR_LAST_VERS_USED	     vars[V_LAST_VERS_USED].current_val.p
#define GLO_LAST_VERS_USED	     vars[V_LAST_VERS_USED].global_val.p
#define VAR_BUGS_FULLNAME	     vars[V_BUGS_FULLNAME].current_val.p
#define GLO_BUGS_FULLNAME	     vars[V_BUGS_FULLNAME].global_val.p
#define VAR_BUGS_ADDRESS	     vars[V_BUGS_ADDRESS].current_val.p
#define GLO_BUGS_ADDRESS	     vars[V_BUGS_ADDRESS].global_val.p
#define VAR_BUGS_EXTRAS		     vars[V_BUGS_EXTRAS].current_val.p
#define GLO_BUGS_EXTRAS		     vars[V_BUGS_EXTRAS].global_val.p
#define VAR_SUGGEST_FULLNAME	     vars[V_SUGGEST_FULLNAME].current_val.p
#define GLO_SUGGEST_FULLNAME	     vars[V_SUGGEST_FULLNAME].global_val.p
#define VAR_SUGGEST_ADDRESS	     vars[V_SUGGEST_ADDRESS].current_val.p
#define GLO_SUGGEST_ADDRESS	     vars[V_SUGGEST_ADDRESS].global_val.p
#define VAR_LOCAL_FULLNAME	     vars[V_LOCAL_FULLNAME].current_val.p
#define GLO_LOCAL_FULLNAME	     vars[V_LOCAL_FULLNAME].global_val.p
#define VAR_LOCAL_ADDRESS	     vars[V_LOCAL_ADDRESS].current_val.p
#define GLO_LOCAL_ADDRESS	     vars[V_LOCAL_ADDRESS].global_val.p
#define VAR_FORCED_ABOOK_ENTRY	     vars[V_FORCED_ABOOK_ENTRY].current_val.l
#define USR_FORCED_ABOOK_ENTRY	     vars[V_FORCED_ABOOK_ENTRY].user_val.l
#define VAR_KBLOCK_PASSWD_COUNT	     vars[V_KBLOCK_PASSWD_COUNT].current_val.p
#define GLO_KBLOCK_PASSWD_COUNT	     vars[V_KBLOCK_PASSWD_COUNT].global_val.p
#define VAR_STATUS_MSG_DELAY	     vars[V_STATUS_MSG_DELAY].current_val.p
#define GLO_STATUS_MSG_DELAY	     vars[V_STATUS_MSG_DELAY].global_val.p
#define VAR_SENDMAIL_PATH	     vars[V_SENDMAIL_PATH].current_val.p
#define GLO_SENDMAIL_PATH	     vars[V_SENDMAIL_PATH].global_val.p
#define USR_SENDMAIL_PATH	     vars[V_SENDMAIL_PATH].user_val.p
#define FIX_SENDMAIL_PATH	     vars[V_SENDMAIL_PATH].fixed_val.p
#define COM_SENDMAIL_PATH	     vars[V_SENDMAIL_PATH].cmdline_val.p
#define VAR_OPER_DIR		     vars[V_OPER_DIR].current_val.p
#define GLO_OPER_DIR		     vars[V_OPER_DIR].global_val.p
#define USR_OPER_DIR		     vars[V_OPER_DIR].user_val.p
#define FIX_OPER_DIR		     vars[V_OPER_DIR].fixed_val.p
#define COM_OPER_DIR		     vars[V_OPER_DIR].cmdline_val.p
#define VAR_DISPLAY_FILTERS	     vars[V_DISPLAY_FILTERS].current_val.l
#define GLO_DISPLAY_FILTERS	     vars[V_DISPLAY_FILTERS].global_val.l
#define USR_DISPLAY_FILTERS	     vars[V_DISPLAY_FILTERS].user_val.l
#define VAR_SEND_FILTER		     vars[V_SEND_FILTER].current_val.l
#define GLO_SEND_FILTER		     vars[V_SEND_FILTER].global_val.l
#define VAR_ALT_ADDRS		     vars[V_ALT_ADDRS].current_val.l
#define GLO_ALT_ADDRS		     vars[V_ALT_ADDRS].global_val.l
#define USR_ALT_ADDRS		     vars[V_ALT_ADDRS].user_val.l
#define VAR_ABOOK_FORMATS	     vars[V_ABOOK_FORMATS].current_val.l
#define GLO_ABOOK_FORMATS	     vars[V_ABOOK_FORMATS].global_val.l
#define USR_ABOOK_FORMATS	     vars[V_ABOOK_FORMATS].user_val.l
#define VAR_INDEX_FORMAT	     vars[V_INDEX_FORMAT].current_val.p
#define GLO_INDEX_FORMAT	     vars[V_INDEX_FORMAT].global_val.p
#define VAR_OVERLAP		     vars[V_OVERLAP].current_val.p
#define GLO_OVERLAP		     vars[V_OVERLAP].global_val.p
#define VAR_MARGIN		     vars[V_MARGIN].current_val.p
#define GLO_MARGIN		     vars[V_MARGIN].global_val.p
#define VAR_MAILCHECK		     vars[V_MAILCHECK].current_val.p
#define GLO_MAILCHECK		     vars[V_MAILCHECK].global_val.p
#define VAR_NEWSRC_PATH		     vars[V_NEWSRC_PATH].current_val.p
#define GLO_NEWSRC_PATH		     vars[V_NEWSRC_PATH].global_val.p
#define VAR_NEWS_ACTIVE_PATH	     vars[V_NEWS_ACTIVE_PATH].current_val.p
#define GLO_NEWS_ACTIVE_PATH	     vars[V_NEWS_ACTIVE_PATH].global_val.p
#define VAR_NEWS_SPOOL_DIR	     vars[V_NEWS_SPOOL_DIR].current_val.p
#define GLO_NEWS_SPOOL_DIR	     vars[V_NEWS_SPOOL_DIR].global_val.p
#define VAR_DISABLE_DRIVERS	     vars[V_DISABLE_DRIVERS].current_val.l
#define VAR_REMOTE_ABOOK_METADATA    vars[V_REMOTE_ABOOK_METADATA].current_val.p
#define VAR_REMOTE_ABOOK_HISTORY     vars[V_REMOTE_ABOOK_HISTORY].current_val.p
#define GLO_REMOTE_ABOOK_HISTORY     vars[V_REMOTE_ABOOK_HISTORY].global_val.p
#define VAR_PATTERNS		     vars[V_PATTERNS].current_val.l
  /* Elm style save is obsolete in Pine 3.81 (see saved msg name rule) */
#define VAR_ELM_STYLE_SAVE           vars[V_ELM_STYLE_SAVE].current_val.p
#define GLO_ELM_STYLE_SAVE           vars[V_ELM_STYLE_SAVE].global_val.p
  /* Header in reply is obsolete in Pine 3.83 (see feature list) */
#define VAR_HEADER_IN_REPLY          vars[V_HEADER_IN_REPLY].current_val.p
#define GLO_HEADER_IN_REPLY          vars[V_HEADER_IN_REPLY].global_val.p
  /* Feature level is obsolete in Pine 3.83 (see feature list) */
#define VAR_FEATURE_LEVEL            vars[V_FEATURE_LEVEL].current_val.p
#define GLO_FEATURE_LEVEL            vars[V_FEATURE_LEVEL].global_val.p
  /* Old style reply is obsolete in Pine 3.83 (see feature list) */
#define VAR_OLD_STYLE_REPLY          vars[V_OLD_STYLE_REPLY].current_val.p
#define GLO_OLD_STYLE_REPLY          vars[V_OLD_STYLE_REPLY].global_val.p
  /* Compose MIME is obsolete in Pine 3.81 */
#define VAR_COMPOSE_MIME             vars[V_COMPOSE_MIME].current_val.p
#define GLO_COMPOSE_MIME             vars[V_COMPOSE_MIME].global_val.p
  /* Show all characters is obsolete in Pine 3.83 */
#define VAR_SHOW_ALL_CHARACTERS      vars[V_SHOW_ALL_CHARACTERS].current_val.p
#define GLO_SHOW_ALL_CHARACTERS      vars[V_SHOW_ALL_CHARACTERS].global_val.p
  /* Save by sender is obsolete in Pine 3.83 (see saved msg name rule) */
#define VAR_SAVE_BY_SENDER           vars[V_SAVE_BY_SENDER].current_val.p
#define GLO_SAVE_BY_SENDER           vars[V_SAVE_BY_SENDER].global_val.p
#define VAR_NNTP_SERVER              vars[V_NNTP_SERVER].current_val.l
#define GLO_NNTP_SERVER              vars[V_NNTP_SERVER].global_val.l
#define USR_NNTP_SERVER              vars[V_NNTP_SERVER].user_val.l
#define FIX_NNTP_SERVER	             vars[V_NNTP_SERVER].fixed_val.l
#ifdef	ENABLE_LDAP
#define VAR_LDAP_SERVERS             vars[V_LDAP_SERVERS].current_val.l
#endif
#define VAR_UPLOAD_CMD		     vars[V_UPLOAD_CMD].current_val.p
#define VAR_UPLOAD_CMD_PREFIX	     vars[V_UPLOAD_CMD_PREFIX].current_val.p
#define VAR_DOWNLOAD_CMD	     vars[V_DOWNLOAD_CMD].current_val.p
#define VAR_DOWNLOAD_CMD_PREFIX	     vars[V_DOWNLOAD_CMD_PREFIX].current_val.p
#define VAR_GOTO_DEFAULT_RULE	     vars[V_GOTO_DEFAULT_RULE].current_val.p
#define VAR_MAILCAP_PATH	     vars[V_MAILCAP_PATH].current_val.p
#define VAR_MIMETYPE_PATH	     vars[V_MIMETYPE_PATH].current_val.p
#define VAR_USERINPUTTIMEO     	     vars[V_USERINPUTTIMEO].current_val.p
#define GLO_USERINPUTTIMEO     	     vars[V_USERINPUTTIMEO].global_val.p
#define VAR_TCPOPENTIMEO	     vars[V_TCPOPENTIMEO].current_val.p
#define VAR_RSHOPENTIMEO	     vars[V_RSHOPENTIMEO].current_val.p
#define VAR_RSHPATH		     vars[V_RSHPATH].current_val.p
#define VAR_RSHCMD		     vars[V_RSHCMD].current_val.p
#define VAR_NEW_VER_QUELL	     vars[V_NEW_VER_QUELL].current_val.p
#define VAR_BROWSER		     vars[V_BROWSER].current_val.l
#define VAR_INCOMING_STARTUP	     vars[V_INCOMING_STARTUP].current_val.p

#ifdef	NEWBB
#define VAR_NNTP_NEW_GROUP_TIME      vars[V_NNTP_NEW_GROUP_TIME].current_val.p
#define GLO_NNTP_NEW_GROUP_TIME      vars[V_NNTP_NEW_GROUP_TIME].global_val.p
#endif

#if defined(DOS) || defined(OS2)
#define	VAR_FILE_DIR		     vars[V_FILE_DIR].current_val.p
#define	GLO_FILE_DIR		     vars[V_FILE_DIR].current_val.p
#define VAR_FOLDER_EXTENSION	     vars[V_FOLDER_EXTENSION].current_val.p
#define GLO_FOLDER_EXTENSION	     vars[V_FOLDER_EXTENSION].global_val.p
#define VAR_NORM_FORE_COLOR	     vars[V_NORM_FORE_COLOR].current_val.p
#define GLO_NORM_FORE_COLOR	     vars[V_NORM_FORE_COLOR].global_val.p
#define VAR_NORM_BACK_COLOR	     vars[V_NORM_BACK_COLOR].current_val.p
#define GLO_NORM_BACK_COLOR	     vars[V_NORM_BACK_COLOR].global_val.p
#define VAR_REV_FORE_COLOR	     vars[V_REV_FORE_COLOR].current_val.p
#define GLO_REV_FORE_COLOR	     vars[V_REV_FORE_COLOR].global_val.p
#define VAR_REV_BACK_COLOR	     vars[V_REV_BACK_COLOR].current_val.p
#define GLO_REV_BACK_COLOR	     vars[V_REV_BACK_COLOR].global_val.p

#ifdef	_WINDOWS
#define VAR_FONT_NAME		     vars[V_FONT_NAME].current_val.p
#define GLO_FONT_NAME		     vars[V_FONT_NAME].global_val.p
#define VAR_FONT_SIZE		     vars[V_FONT_SIZE].current_val.p
#define GLO_FONT_SIZE		     vars[V_FONT_SIZE].global_val.p
#define VAR_FONT_STYLE		     vars[V_FONT_STYLE].current_val.p
#define GLO_FONT_STYLE		     vars[V_FONT_STYLE].global_val.p
#define VAR_PRINT_FONT_NAME	     vars[V_PRINT_FONT_NAME].current_val.p
#define GLO_PRINT_FONT_NAME	     vars[V_PRINT_FONT_NAME].global_val.p
#define VAR_PRINT_FONT_SIZE	     vars[V_PRINT_FONT_SIZE].current_val.p
#define GLO_PRINT_FONT_SIZE	     vars[V_PRINT_FONT_SIZE].global_val.p
#define VAR_PRINT_FONT_STYLE	     vars[V_PRINT_FONT_STYLE].current_val.p
#define GLO_PRINT_FONT_STYLE	     vars[V_PRINT_FONT_STYLE].global_val.p
#define VAR_WINDOW_POSITION	     vars[V_WINDOW_POSITION].current_val.p
#define GLO_WINDOW_POSITION	     vars[V_WINDOW_POSITION].global_val.p
#endif	/* _WINDOWS */
#endif	/* DOS or OS2 */


/*
 * list of feature numbers (which bit goes with which feature)
 */
typedef enum {
	F_OLD_GROWTH = 0,
	F_ENABLE_FULL_HDR,
	F_ENABLE_PIPE,
	F_ENABLE_TAB_COMPLETE,
	F_QUIT_WO_CONFIRM,
	F_ENABLE_JUMP,
	F_ENABLE_ALT_ED,
	F_ENABLE_BOUNCE,
	F_ENABLE_AGG_OPS,
	F_ENABLE_FLAG,
	F_CAN_SUSPEND,
	F_USE_FK,
	F_INCLUDE_HEADER,
	F_SIG_AT_BOTTOM,
	F_DEL_SKIPS_DEL,
	F_AUTO_EXPUNGE,
	F_FULL_AUTO_EXPUNGE,
	F_AUTO_READ_MSGS,
	F_AUTO_FCC_ONLY,
	F_READ_IN_NEWSRC_ORDER,
	F_SELECT_WO_CONFIRM,
	F_USE_CURRENT_DIR,
	F_SAVE_WONT_DELETE,
	F_SAVE_ADVANCES,
	F_FORCE_LOW_SPEED,
	F_ALT_ED_NOW,
	F_SHOW_DELAY_CUE,
	F_AUTO_OPEN_NEXT_UNREAD,
	F_SELECTED_SHOWN_BOLD,
	F_QUOTE_ALL_FROMS,
	F_AUTO_INCLUDE_IN_REPLY,
	F_DISABLE_CONFIG_SCREEN,
	F_DISABLE_PASSWORD_CMD,
	F_DISABLE_UPDATE_CMD,
	F_DISABLE_KBLOCK_CMD,
	F_DISABLE_SIGEDIT_CMD,
	F_DISABLE_ROLES_SETUP,
	F_DISABLE_ROLES_SIGEDIT,
	F_DISABLE_ROLES_TEMPLEDIT,
	F_ATTACHMENTS_IN_REPLY,
	F_ENABLE_INCOMING,
	F_NO_NEWS_VALIDATION,
	F_DISABLE_TAKE_LASTFIRST,
	F_QUELL_LOCAL_LOOKUP,
	F_COMPOSE_TO_NEWSGRP,
	F_PRESERVE_START_STOP,
	F_COMPOSE_REJECTS_UNQUAL,
	F_FAKE_NEW_IN_NEWS,
	F_SUSPEND_SPAWNS,
	F_ENABLE_8BIT,
	F_COMPOSE_MAPS_DEL,
	F_ENABLE_8BIT_NNTP,
	F_ENABLE_MOUSE,
	F_SHOW_CURSOR,
	F_PASS_CONTROL_CHARS,
	F_SINGLE_FOLDER_LIST,
	F_VERTICAL_FOLDER_LIST,
	F_AUTO_REPLY_TO,
	F_VERBOSE_POST,
	F_FCC_ON_BOUNCE,
	F_USE_SENDER_NOT_X,
	F_BLANK_KEYMENU,
	F_CUSTOM_PRINT,
	F_DEL_FROM_DOT,
	F_AUTO_ZOOM,
	F_AUTO_UNZOOM,
	F_PRINT_INDEX,
	F_ALLOW_TALK,
	F_AGG_PRINT_FF,
	F_ENABLE_DOT_FILES,
	F_ENABLE_DOT_FOLDERS,
	F_FIRST_SEND_FILTER_DFLT,
	F_ALWAYS_LAST_FLDR_DFLT,
	F_TAB_TO_NEW,
	F_QUELL_DEAD_LETTER,
	F_QUELL_BEEPS,
	F_QUELL_LOCK_FAILURE_MSGS,
	F_ENABLE_SPACE_AS_TAB,
	F_ENABLE_TAB_DELETES,
	F_FLAG_SCREEN_DFLT,
	F_ENABLE_XTERM_NEWMAIL,
	F_EXPANDED_DISTLISTS,
	F_AGG_SEQ_COPY,
	F_DISABLE_ALARM,
	F_FROM_DELIM_IN_PRINT,
	F_BACKGROUND_POST,
	F_ALLOW_GOTO,
	F_DSN,
	F_ENABLE_SEARCH_AND_REPL,
	F_ARROW_NAV,
	F_RELAXED_ARROW_NAV,
	F_TCAP_WINS,
	F_ENABLE_SIGDASHES,
	F_ENABLE_STRIP_SIGDASHES,
	F_QUELL_PARTIAL_FETCH,
	F_VIEW_SEL_ATTACH,
	F_VIEW_SEL_URL,
	F_VIEW_SEL_URL_HOST,
	F_SCAN_ADDR,
	F_FORCE_ARROWS,
	F_ENABLE_EDIT_REPLY_INDENT,
	F_ENABLE_PRYNT,
	F_ALLOW_CHANGING_FROM,
	F_ENABLE_SUB_LISTS,
	F_ENABLE_LESSTHAN_EXIT,
	F_ENABLE_FAST_RECENT,
	F_FIX_BROKEN_LIST,
	F_NEWS_CROSS_DELETE,
	F_QUELL_INTERNAL_MSG,
	F_QUELL_IMAP_ENV_CB,
	F_SEPARATE_FLDR_AS_DIR,
	F_CMBND_ABOOK_DISP,
	F_CMBND_FOLDER_DISP,
	F_CMBND_SUBDIR_DISP,
	F_EXPANDED_ADDRBOOKS,
	F_EXPANDED_FOLDERS,
	F_QUELL_EMPTY_DIRS,
	F_SHOW_TEXTPLAIN_INT,
	F_ROLE_CONFIRM_DEFAULT,
	F_NO_FCC_ATTACH,
#ifdef	ENABLE_LDAP
	F_ADD_LDAP_TO_ABOOK,
#endif
	F_FEATURE_LIST_COUNT	/* Number of features */
} FeatureList;


/* Feature list support */
/* Is feature "feature" turned on? */
#define F_ON(feature,ps)	(bitnset((feature),(ps)->feature_list))
#define F_OFF(feature,ps)	(!F_ON(feature,ps))
#define F_TURN_ON(feature,ps)   (setbitn((feature),(ps)->feature_list))
#define F_TURN_OFF(feature,ps)  (clrbitn((feature),(ps)->feature_list))
/* turn off or on depending on value */
#define F_SET(feature,ps,value) ((value) ? F_TURN_ON((feature),(ps))       \
					 : F_TURN_OFF((feature),(ps)))



/*======================================================================
       Macros for debug printfs 
   n is debugging level:
       1 logs only highest level events and errors
       2 logs events like file writes
       3
       4 logs each command
       5
       6 
       7 logs details of command execution (7 is highest to run any production)
         allows core dumps without cleaning up terminal modes
       8
       9 logs gross details of command execution
    
    This is sort of dumb.  The first argument in x is always debugfile, and
    we're sort of assuming that to be the case below.  However, we don't
    want to go back and change all of the dprint calls now.
  ====*/
#ifdef DEBUG
#define   dprint(n,x) {							\
	       if(debugfile && debug >= (n) && do_debug(debugfile))	\
		  fprintf x ;						\
	      }
#else
#define   dprint(n,x)
#endif


/*
 * Status message types
 */
#define	SM_DING		0x01			/* ring bell when displayed  */
#define	SM_ASYNC	0x02			/* display any time	     */
#define	SM_ORDER	0x04			/* ordered, flush on prompt  */
#define	SM_MODAL	0x08			/* display, wait for user    */
#define	SM_INFO		0x10			/* Handy, but discardable    */

/*
 * Which header fields should format_envelope output?
 */
#define	FE_FROM		0x0001
#define	FE_SENDER	0x0002
#define	FE_DATE		0x0004
#define	FE_TO		0x0008
#define	FE_CC		0x0010
#define	FE_BCC		0x0020
#define	FE_NEWSGROUPS	0x0040
#define	FE_SUBJECT	0x0080
#define	FE_MESSAGEID	0x0100
#define	FE_REPLYTO	0x0200
#define	FE_FOLLOWUPTO	0x0400
#define	FE_INREPLYTO	0x0800
#define	FE_RETURNPATH	0x1000
#define	FE_REFERENCES	0x2000
#define	FE_DEFAULT	(FE_FROM | FE_DATE | FE_TO | FE_CC | FE_BCC \
			 | FE_NEWSGROUPS | FE_SUBJECT | FE_REPLYTO \
			 | FE_FOLLOWUPTO)

#define ALL_EXCEPT	"all-except"

/*
 * Flags to indicate how much index border to paint
 */
#define	INDX_CLEAR	0x01
#define	INDX_HEADER	0x02
#define	INDX_FOOTER	0x04


/*
 * Flags to indicate context (i.e., folder collection) use
 */
#define	CNTXT_PSEUDO	0x0001			/* fake folder entry exists  */
#define	CNTXT_INCMNG	0x0002			/* inbox collection	     */
#define	CNTXT_SAVEDFLT	0x0004			/* default save collection   */
#define	CNTXT_PARTFIND	0x0008			/* partial find done         */
#define	CNTXT_NOFIND	0x0010			/* no find done in context   */
#define	CNTXT_FINDALL   0x0020			/* Do a find_all on context  */
#define	CNTXT_NEWS	0x0040			/* News namespace collection */
#define	CNTXT_SUBDIR	0x0080			/* subdirectory within col'n */
#define	CNTXT_PRESRV	0x0100			/* preserve/restore selected */
#define	CNTXT_ZOOM	0x0200			/* context display narrowed  */
#ifdef	NEWBB
#define	CNTXT_NEWBB     0x0400			/* New bboards - NNTP only  */
#endif

/*
 * Useful def's to specify interesting flags
 */
#define	F_SEEN		0x00000001
#define	F_UNSEEN	0x00000002
#define	F_DEL		0x00000004
#define	F_UNDEL		0x00000008
#define	F_FLAG		0x00000010
#define	F_UNFLAG	0x00000020
#define	F_ANS		0x00000040
#define	F_UNANS		0x00000080
#define	F_RECENT	0x00000100
#define	F_UNRECENT	0x00000200
#define	F_DRAFT		0x00000400
#define	F_UNDRAFT	0x00000800

#define	F_OR_SEEN	0x00010000
#define	F_OR_UNSEEN	0x00020000
#define	F_OR_DEL	0x00040000
#define	F_OR_UNDEL	0x00080000
#define	F_OR_FLAG	0x00100000
#define	F_OR_UNFLAG	0x00200000
#define	F_OR_ANS	0x00400000
#define	F_OR_UNANS	0x00800000
#define	F_OR_RECENT	0x01000000
#define	F_OR_UNRECENT	0x02000000


/*
 * Save message rules.  if these grow, widen pine
 * struct's save_msg_rule...
 */
#define	MSG_RULE_DEFLT			0x00
#define	MSG_RULE_SENDER			0x01
#define	MSG_RULE_FROM			0x02
#define	MSG_RULE_RECIP			0x03
#define	MSG_RULE_LAST			0x04
#define	MSG_RULE_NICK_SENDER		0x05
#define	MSG_RULE_NICK_FROM		0x06
#define	MSG_RULE_NICK_RECIP		0x07
#define	MSG_RULE_NICK_SENDER_DEF	0x08
#define	MSG_RULE_NICK_FROM_DEF		0x09
#define	MSG_RULE_NICK_RECIP_DEF		0x0A
#define	MSG_RULE_FCC_SENDER		0x0B
#define	MSG_RULE_FCC_FROM		0x0C
#define	MSG_RULE_FCC_RECIP		0x0D
#define	MSG_RULE_FCC_SENDER_DEF		0x0E
#define	MSG_RULE_FCC_FROM_DEF		0x0F
#define	MSG_RULE_FCC_RECIP_DEF		0x10

/*
 * Fcc rules.  if these grow, widen pine
 * struct's fcc_rule...
 */
#define	FCC_RULE_DEFLT		0x00
#define	FCC_RULE_RECIP		0x01
#define	FCC_RULE_LAST		0x02
#define	FCC_RULE_NICK		0x03
#define	FCC_RULE_NICK_RECIP	0x04
#define	FCC_RULE_CURRENT	0x05

/*
 * Addrbook sorting rules.  if these grow, widen pine
 * struct's ab_sort_rule...
 */
#define	AB_SORT_RULE_FULL_LISTS		0x00
#define	AB_SORT_RULE_FULL  		0x01
#define	AB_SORT_RULE_NICK_LISTS         0x02
#define	AB_SORT_RULE_NICK 		0x03
#define	AB_SORT_RULE_NONE		0x04

#define AB_COMMENT_STR			"Comment   : "

/*
 * Incoming startup rules.  if these grow, widen pine
 * struct's inc_startup_rule...
 */
#define	IS_FIRST_UNSEEN			0x00
#define	IS_FIRST_RECENT  		0x01
#define	IS_FIRST         		0x02
#define	IS_LAST 			0x03

/*
 * Goto default rules.
 */
#define	GOTO_INBOX_RECENT_CLCTN		0x00
#define	GOTO_INBOX_FIRST_CLCTN		0x01
#define	GOTO_LAST_FLDR			0x02
#define	GOTO_FIRST_CLCTN		0x03
#define	GOTO_FIRST_CLCTN_DEF_INBOX	0x04


/*
 * Folder list sort rules
 */
#define	FLD_SORT_ALPHA			0
#define	FLD_SORT_ALPHA_DIR_LAST		1
#define	FLD_SORT_ALPHA_DIR_FIRST	2


/*
 * These are def's to help manage local, private flags pine uses
 * to maintain it's mapping table (see MSGNO_S def).  The local flags
 * are actually stored in spare bits in c-client's pre-message
 * MESSAGECACHE struct.  But they're private, you ask.  Since the flags
 * are tied to the actual message (independent of the mapping), storing
 * them in the c-client means we don't have to worry about them during
 * sorting and such.  See {set,get}_lflags for more on local flags.
 */
#define	MN_NONE		0x0000			/* No Pine specific flags  */
#define	MN_HIDE		0x0001			/* Pine specific hidden    */
#define	MN_EXLD		0x0002			/* Pine specific excluded  */
#define	MN_SLCT		0x0004			/* Pine specific selected  */


/*
 * Macro's to help sort out how we display MIME types
 */
#define	MCD_NONE	0x00
#define	MCD_INTERNAL	0x01
#define	MCD_EXTERNAL	0x02


/*
 * display_output_file mode flags
 */
#define	DOF_NONE	0
#define	DOF_EMPTY	1
#define	DOF_BRIEF	2


/*
 * Macros to aid hack to turn off talk permission.
 * Bit 020 is usually used to turn off talk permission, we turn off
 * 002 also for good measure, since some mesg commands seem to do that.
 */
#define	TALK_BIT		020		/* mode bits */
#define	GM_BIT			002
#define	TMD_CLEAR		0		/* functions */
#define	TMD_SET			1
#define	TMD_RESET		2
#define	allow_talk(p)		tty_chmod((p), TALK_BIT, TMD_SET)
#define	disallow_talk(p)	tty_chmod((p), TALK_BIT|GM_BIT, TMD_CLEAR)


/*
 * Macros to help set numeric pinerc variables.  Defined here are the 
 * allowed min and max values as well as the name of the var as it
 * should be displayed in error messages.
 */
#define	SVAR_OVERLAP(ps, n, e)	strtoval((ps)->VAR_OVERLAP,		  \
					 &(n), 0, 20, (e),		  \
					 "Viewer-overlap")
#define	SVAR_MARGIN(ps, n, e)	strtoval((ps)->VAR_MARGIN,		  \
					 &(n), 0, 20, (e),		  \
					 "Scroll-margin")
#define	SVAR_FILLCOL(ps, n, e)	strtoval((ps)->VAR_FILLCOL,		  \
					 &(n), 0, MAX_FILLCOL, (e),	  \
					 "Composer-wrap-column")
#define	SVAR_MSGDLAY(ps, n, e)	strtoval((ps)->VAR_STATUS_MSG_DELAY,	  \
					 &(n), 0, 30, (e),		  \
					"Status-message-delay")
#define	SVAR_MAILCHK(ps, n, e)	strtoval((ps)->VAR_MAILCHECK,		  \
					 &(n), 14, 1, (e),		  \
					"Mail-check-interval")
#define	SVAR_AB_HIST(ps, n, e)	strtoval((ps)->VAR_REMOTE_ABOOK_HISTORY,  \
					 &(n), 0, 100, (e),		  \
					"Remote-abook-history")
#define	SVAR_USER_INPUT(ps, n, e) strtoval((ps)->VAR_USERINPUTTIMEO,	  \
					 &(n), 0, 1000, (e),		  \
					"user-input-timeout")


/*======================================================================
            Various structures that Pine uses
 ====*/

/*
 * Keeps track of selected folders between instances of
 * the folder list screen.
 */
typedef	struct _name_list {
    char		*name;
    struct _name_list	*next;
} STRLIST_S;


/*
 * Keeps track of display dimensions
 */
struct ttyo {
    int	screen_rows,
	screen_cols,
	header_rows,	/* number of rows for titlebar and whitespace */
	footer_rows;	/* number of rows for status and keymenu      */
};

/*
 * HEADER_ROWS is always 2.  1 for the titlebar and 1 for the
 * blank line after the titlebar.  We should probably make it go down
 * to 0 when the screen shrinks but instead we're just figuring out
 * if there is enough room by looking at screen_rows.
 * FOOTER_ROWS is either 3 or 1.  Normally it is 3, 2 for the keymenu plus 1
 * for the status line.  If the NoKeyMenu command has been given, then it is 1.
 */
#define HEADER_ROWS(X) ((X)->ttyo->header_rows)
#define FOOTER_ROWS(X) ((X)->ttyo->footer_rows)


/* (0,0) is upper left */
typedef struct screen_position {
    int row;
    int col;
} Pos;

typedef struct _screen_position_list {
    Pos				  where;
    struct _screen_position_list *next;
} POSLIST_S;


/*
 * Code exists that is sensitive to this order.  Don't change
 * it unless you know what you're doing.
 */
typedef enum {SortSubject = 0, SortArrival, SortFrom, SortTo, 
              SortCc, SortDate, SortSize,
	      SortSubject2, EndofList}   SortOrder;

#define	refresh_sort(M,S)	sort_folder((M), mn_get_sort(M), \
					    mn_get_revsort(M), (S))

/*
 * The two structs below hold all knowledge regarding
 * messages requiring special handling
 */
typedef	struct _part_exception_s {
    char		     *partno;
    int			      handling;
    struct _part_exception_s *next;
} PARTEX_S;

#define	MSG_EX_DELETE	0x01


/*
 * This is *the* struct that keeps track of the pine message number to
 * raw c-client sequence number mappings.  The mapping is necessary
 * because pine may re-sort or even hide (exclude) c-client numbers
 * from the displayed list of messages.  See mailindx.c:msgno_* and
 * the mn_* macros above for how this things gets used.  See
 * mailcmd.c:pseudo_selected for an explanation of the funny business
 * going on with the "hilited" field...
 */
typedef struct msg_nos {
    long      *select,				/* selected message array  */
	       sel_cur,				/* current interesting msg */
	       sel_cnt,				/* its size		   */
	       sel_size,			/* its size		   */
              *sort,				/* sorted array of msgno's */
               sort_size,			/* its size		   */
	       max_msgno,			/* total messages	   */
	       hilited,				/* holder for "current" msg*/
	       top;				/* message at top of screen*/
    SortOrder  sort_order;			/* list's current sort     */
    unsigned   reverse_sort:1;			/* whether that's reversed */
    long       flagged_hid,			/* hidden count		   */
	       flagged_exld,			/* excluded count	   */
	       flagged_tmp;			/* tmp flagged count	   */
} MSGNO_S;


/*
 * Used by pine_args to tell caller what was found;
 */
typedef struct _argdata {
    enum	{aaFolder = 0, aaMore, aaURL, aaMail} action;
    union {
	char	  *folder;
	char	  *file;
	char	  *url;
	struct {
	    STRLIST_S *addrlist;
	    PATMT     *attachlist;
	} mail;
    } data;
} ARGDATA_S;


/*
 * Flags for the pipe command routines...
 */
#define	PIPE_WRITE	0x0001			/* set up pipe for reading */
#define	PIPE_READ	0x0002			/* set up pipe for reading */
#define	PIPE_NOSHELL	0x0004			/* don't exec in shell     */
#define	PIPE_USER	0x0008			/* user mode		   */
#define	PIPE_STDERR	0x0010			/* stderr to child output  */
#define	PIPE_PROT	0x0020			/* protected mode	   */
#define	PIPE_RESET	0x0040			/* reset terminal mode     */
#define	PIPE_DESC	0x0080			/* no stdio desc wrapping  */
#define	PIPE_SILENT	0x0100			/* no screen clear, etc	   */

/*
 * stucture required for the pipe commands...
 */
typedef struct pipe_s {
    int      pid,				/* child's process id       */
	     mode,				/* mode flags used to open  */
	     timeout,				/* wait this long for child */
	     old_timeo;				/* previous active alarm    */
    SigType  (*hsig)(),				/* previously installed...  */
	     (*isig)(),				/* handlers		    */
	     (*qsig)(),
	     (*alrm)();
    union {
	FILE *f;
	int   d;
    }	     in;				/* input data handle	    */
    union {
	FILE *f;
	int   d;
    }	     out;				/* output data handle	    */
    char   **argv,				/* any necessary args	    */
	    *args,
	    *tmp;				/* pointer to stuff	    */
#ifdef	_WINDOWS
    char    *command;				/* command to execute */
#endif
} PIPE_S;


/*
 * digested form of context including pointer to the parent
 * level of hierarchy...
 */
typedef struct folder_dir {
    char	   *ref,			/* collection location     */
		   *desc,			/* Optional description	   */
		    delim,			/* dir/file delimiter      */
		    status;			/* folder data's status    */
    struct {
	char	   *user,
		   *internal;
    } view;					/* file's within dir	   */
    void           *folders;			/* folder data             */
    struct folder_dir *prev;			/* parent directory	   */
} FDIR_S;


/*------------------------------
    Stucture to keep track of the various folder collections being
    dealt with.
  ----*/
typedef struct context {
    FDIR_S	    *dir;			/* directory stack	   */
    char	    *context,			/* raw context string	   */
		    *server,			/* server name/parms	   */
		    *nickname,			/* user provided nickname  */
		    *label,			/* Description		   */
		    *comment,			/* Optional comment	   */
		     last_folder[MAXFOLDER+1];	/* last folder used        */
    struct {
	struct variable *v;			/* variable where defined  */
	short		 i;			/* index into list	   */
    } var;
    unsigned short   use,			/* use flags for context   */
		     d_line;			/* display line for labels */
    struct {
	char	    *reference;			/* location of selected	   */
	STRLIST_S   *folders;			/* list of selected	   */
	unsigned     zoomed:1;			/* zoomed state		   */
    } selected;
    struct context  *next,			/* next context struct	   */
		    *prev;			/* previous context struct */
} CONTEXT_S;


/*
 * struct to help manage mail_list calls/callbacks
 */
typedef	struct _mm_list_s {
    MAILSTREAM	*stream;
    void       (*filter) PROTO((MAILSTREAM *, char *, int, long, void *));
    void	*data;
} MM_LIST_S;

extern MM_LIST_S *mm_list_info;


/*
 * Macros to help users of above two structures...
 */
#define	NEWS_TEST(c)	((c) && ((c)->use & CNTXT_NEWS))
			 
#define	FOLDERS(c)	((c)->dir->folders)


/*------------------------------
   Used for displaying as well as
   keeping track of folders. 
  ----*/
typedef struct folder {
    unsigned char   name_len;			/* name length		     */
    unsigned	    isfolder:1;			/* is it a folder?	     */
    unsigned	    isdir:1;			/* is it a directory?	     */
    unsigned	    scanned:1;			/* scanned by c-client	     */
    unsigned	    parent:1;			/* visit parent		     */
    unsigned	    selected:1;			/* selected by user	     */
    unsigned	    subscribed:1;		/* selected by user	     */
    char	   *nickname;			/* folder's short name       */
    char	    name[1];			/* folder's name             */
} FOLDER_S;



/*------------------------------
   Used for index display
   formatting.
  ----*/
typedef enum {iNothing, iStatus, iFStatus, iIStatus,
	      iDate, iLDate, iS1Date, iS2Date, iS3Date, iS4Date, iSDate,
	      iRDate,
	      iTime24, iTime12,
	      iCurDate, iCurTime24, iCurTime12,
	      iMessNo, iAtt, iMsgID, iSubject,
	      iSize, iDescripSize,
	      iNewsAndTo, iToAndNews, iNewsAndRecips, iRecipsAndNews,
	      iFromTo, iFrom, iTo, iSender, iCc, iNews, iRecips,
	      iMailbox, iAddress, iCursorPos,
	      iDay, iMonAbb, iMonLong, iMon, iYear} IndexColType;
typedef enum {AllAuto, Fixed, Percent, WeCalculate, Special} WidthType;
typedef enum {Left, Right} ColAdj;

typedef struct index_parse_tokens {
    char        *name;
    IndexColType ctype;
    int          what_for;
} INDEX_PARSE_T;

/* these are flags for the what_for field in INDEX_PARSE_T */
#define FOR_NOTHING	0x00
#define FOR_INDEX	0x01
#define FOR_REPLY_INTRO	0x02
#define FOR_TEMPLATE	0x04

#define DEFAULT_REPLY_INTRO "default"

typedef struct col_description {
    IndexColType ctype;
    WidthType    wtype;
    int		 req_width;
    int		 width;
    char	*string;
    int		 actual_length;
    ColAdj	 adjustment;
} INDEX_COL_S;


typedef long MsgNo;

struct variable {
    char *name;
    unsigned  is_obsolete:1;	/* variable read in, not written unless set */
    unsigned  is_used:1;	/* Some variables are disabled              */
    unsigned  been_written:1;
    unsigned  is_user:1;
    unsigned  is_global:1;
    unsigned  is_list:1;	/* flag indicating variable is a list       */
    unsigned  is_fixed:1;	/* sys mgr has fixed this variable          */
    char     *descrip;		/* description                              */
    union {
	char *p;		/* pointer to single string value           */
	char **l;		/* pointer to list of string values         */
    } current_val;
    union {
	char *p;		/* pointer to single string value           */
	char **l;		/* pointer to list of string values         */
    } user_val;			/* from pinerc                              */
    union {
	char *p;		/* pointer to single string value           */
	char **l;		/* pointer to list of string values         */
    } global_val;		/* from default or pine.conf                */
    union {
	char *p;		/* pointer to single string value           */
	char **l;		/* pointer to list of string values         */
    } fixed_val;		/* fixed value assigned in pine.conf.fixed  */
    union {
	char *p;		/* pointer to single string value           */
	char **l;		/* pointer to list of string values         */
    } cmdline_val;		/* user typed as cmdline arg                */
};



/*
 * Generic name/value pair structure
 */
typedef struct nameval {
    char *name;			/* the name that goes in the config file */
    int   value;		/* the internal bit number */
} NAMEVAL_S;			/* available features in init.c:feat_list */


typedef struct _feature_entry {
    char       *name;
    int		id;
    HelpType	help;
    int		section;
} FEATURE_S;


typedef struct attachment {
    char       *description;
    BODY       *body;
    unsigned	test_deferred:1;
    unsigned	can_display:4;
    unsigned	shown:1;
    char       *number;
    char	size[25];
} ATTACH_S;



/*
 * Struct to help manage embedded urls (and anythin' else we might embed)
 */
typedef	struct handle_s {
    int		     key;		/* tag number embedded in text */
    enum	     {URL, Attach, Folder} type;
    unsigned	     force_display:1;	/* Don't ask before launching */
    union {
	struct {			/* URL corresponding to this handle */
	    char *path,			/* Actual url string */
		 *tool,			/* displaying application */
		 *name;			/* URL's NAME attribute */
	} url;				/* stuff to describe URL handle */
	ATTACH_S    *attach;		/* Attachment struct for this handle */
	struct {
	    int	       index;		/* folder's place in context's list */
	    CONTEXT_S *context;		/* description of folders */
	} f;				/* stuff to describe Folder handle */
    } h;
    POSLIST_S	    *loc;		/* list of places it exists in text */
    struct handle_s *next, *prev;	/* next and previous in the list */
} HANDLE_S ;



/*
 * Function used to dispatch locally handled URL's
 */
typedef	int	(*url_tool_t) PROTO((char *));



/*------
   A key menu has two ways to turn on and off individual items in the menu.
   If there is a null entry in the key_menu structure for that key, then
   it is off.  Also, if the passed bitmap has a zero in the position for
   that key, then it is off.  This means you can usually set all of the
   bitmaps and only turn them off if you want to kill a key that is normally
   there otherwise.
   Each key_menu is an array of keys with a multiple of 12 number of keys.
  ------*/

/*
 * Max size of a bitmap based on largest customer: feature list count
 * Problems if a screen's keymenu bitmap ever gets wider than feature list.
 */
#define BM_SIZE			((F_FEATURE_LIST_COUNT / 8)		   \
				      + ((F_FEATURE_LIST_COUNT % 8) ? 1 : 0))
#define _BITCHAR(bit)		((bit) / 8)
#define _BITBIT(bit)		(1 << ((bit) % 8))
typedef unsigned char bitmap_t[BM_SIZE];
/* is bit set? */
#define bitnset(bit,map)	(((map)[_BITCHAR(bit)] & _BITBIT(bit)) ? 1 : 0)
/* set bit */
#define setbitn(bit,map)	((map)[_BITCHAR(bit)] |= _BITBIT(bit))
/* clear bit */
#define clrbitn(bit,map)	((map)[_BITCHAR(bit)] &= ~_BITBIT(bit))
/* clear entire bitmap */
#define clrbitmap(map)		memset((void *)(map), 0, (size_t)BM_SIZE)
/* set entire bitmap */
#define setbitmap(map)		memset((void *)(map), 0xff, (size_t)BM_SIZE)
/*------
  Argument to draw_keymenu().  These are to identify which of the possibly
  multiple sets of twelve keys should be shown in the keymenu.  That is,
  a keymenu may have 24 or 36 keys, so that there are 2 or 3 different
  screens of key menus for that keymenu.  FirstMenu means to use the
  first twelve, NextTwelve uses the one after the previous one, SameTwelve
  uses the same one.
  ------*/
typedef enum {MenuNotSet = 0, FirstMenu, NextMenu, SameMenu,
	      SecondMenu, ThirdMenu, FourthMenu} OtherMenu;


struct key {
    char   *name;			/* the short name */
    char   *label;			/* the descriptive label */
    struct {
	short  cmd;
	short  nch;
	int    ch[11];
    } bind;
    KS_OSDATAVAR			/* slot for port-specific data */
    short  column;			/* menu col after formatting */
};


struct key_menu {
    unsigned int  how_many:4;		/* how many separate sets of 12      */
    unsigned int  which:4;		/* which of the sets are we using    */
    unsigned int  width:8;		/* screen width when formatting done */
    struct key	 *keys;			/* array of how_many*12 size structs */
    unsigned int  formatted_hm:4;	/* how_many when formatting done     */
    bitmap_t      bitmap;
};

/*
 * Macro to simplify instantiation of key_menu structs from key structs
 */
#define	INST_KEY_MENU(X, Y)	static struct key_menu X = \
					{sizeof(Y)/(sizeof(Y[0])*12), 0, 0, Y}

/*
 * Definitions for the various Menu Commands...
 */
#define	MC_NONE		0		/* NO command defined */
#define	MC_UNKNOWN	-1

/* Cursor/page Motion */
#define	MC_CHARUP	100
#define	MC_CHARDOWN	101
#define	MC_CHARRIGHT	102
#define	MC_CHARLEFT	103
#define	MC_GOTOBOL	104
#define	MC_GOTOEOL	105
#define	MC_GOTOSOP	106
#define	MC_GOTOEOP	107
#define	MC_PAGEUP	108
#define	MC_PAGEDN	109
#define	MC_MOUSE	110

/* New Screen Commands */
#define	MC_HELP		500
#define	MC_QUIT		501
#define	MC_OTHER	502
#define	MC_MAIN		503
#define	MC_INDEX	504
#define	MC_VIEW_TEXT	505
#define	MC_VIEW_ATCH	506
#define	MC_FOLDERS	507
#define	MC_ADDRBOOK	508
#define	MC_RELNOTES	509
#define	MC_KBLOCK	510
#define	MC_JOURNAL	511
#define	MC_SETUP	512
#define	MC_COLLECTIONS	513
#define	MC_PARENT	514
#define	MC_ROLE		515

/* Commands within Screens */
#define	MC_NEXTITEM	700
#define	MC_PREVITEM	701
#define	MC_DELETE	702
#define	MC_UNDELETE	703
#define	MC_COMPOSE	704
#define	MC_REPLY	705
#define	MC_FORWARD	706
#define	MC_GOTO		707
#define	MC_TAB		708
#define	MC_WHEREIS	709
#define	MC_ZOOM		710
#define	MC_PRINTMSG	711
#define	MC_PRINTTXT	712
#define	MC_TAKE		713
#define	MC_SAVE		714
#define	MC_EXPORT	715
#define	MC_EXPUNGE	717
#define	MC_UNEXCLUDE	718
#define	MC_CHOICE	719
#define	MC_SELECT	720
#define	MC_SELCUR	721
#define	MC_SELALL	722
#define	MC_UNSELALL	723
#define	MC_APPLY	724
#define	MC_SORT		725
#define	MC_FULLHDR	726
#define	MC_BOUNCE	727
#define	MC_FLAG		728
#define	MC_PIPE		729
#define	MC_EXIT		730
#define	MC_PRINTALL	731
#define	MC_REPAINT	732
#define	MC_JUMP		733
#define	MC_RESIZE	734
#define	MC_FWDTEXT	735
#define	MC_SAVETEXT	736
#define	MC_ABOUTATCH	737
#define	MC_LISTMODE	738
#define	MC_RENAMEFLDR	739
#define	MC_ADDFLDR	740
#define	MC_SUBSCRIBE	741
#define	MC_UNSUBSCRIBE	742
#define	MC_ADD		743
#define	MC_TOGGLE	744
#define	MC_EDIT		745
#define	MC_ADDABOOK	746
#define	MC_DELABOOK	747
#define	MC_VIEW_ENTRY	748
#define	MC_EDITABOOK	750
#define	MC_OPENABOOK	751
#define	MC_POPUP	752
#define	MC_EXPAND	753
#define	MC_UNEXPAND	754
#define	MC_COPY		755
#define	MC_SHUFFLE	756
#define	MC_VIEW_HANDLE	757
#define	MC_NEXT_HANDLE	758
#define	MC_PREV_HANDLE	759
#define	MC_QUERY_SERV	760
#define MC_GRIPE_LOCAL  761
#define MC_GRIPE_PIC    762
#define MC_GRIPE_READ   763
#define MC_GRIPE_POST   764
#define	MC_FINISH	765
#define	MC_PRINTFLDR	766
#define	MC_OPENFLDR	767
#define	MC_EDITFILE	768
#define	MC_ADDFILE	769
#define	MC_DELFILE	770
#define	MC_CHOICEB	771
#define	MC_CHOICEC	772


/*
 * Some standard Key/Command Bindings 
 */
#define	NULL_MENU	{NULL, NULL, {MC_NONE}, KS_NONE}
#define	HELP_MENU	{"?", "Help", \
			 {MC_HELP, 2, {'?',ctrl('G')}}, \
			 KS_SCREENHELP}
#define	OTHER_MENU	{"O", "OTHER CMDS", \
			 {MC_OTHER, 1, {'o'}}, \
			 KS_NONE}
#define	WHEREIS_MENU	{"W", "WhereIs", \
			 {MC_WHEREIS, 2, {'w',ctrl('W')}}, \
			 KS_WHEREIS}
#define	MAIN_MENU	{"M", "Main Menu", \
			 {MC_MAIN, 1, {'m'}}, \
			 KS_MAINMENU}
#define	QUIT_MENU	{"Q", "Quit Pine", \
			 {MC_QUIT, 1, {'q'}}, \
			 KS_EXIT}
#define	PREVMSG_MENU	{"P", "PrevMsg", \
			 {MC_PREVITEM, 1, {'p'}}, \
			 KS_PREVMSG}
#define	NEXTMSG_MENU	{"N", "NextMsg", \
			 {MC_NEXTITEM, 1, {'n'}}, \
			 KS_NEXTMSG}
#define	PREVPAGE_MENU	{"-", "PrevPage", \
			 {MC_PAGEUP, 3, {'-',ctrl('Y'),KEY_PGUP}}, \
			 KS_PREVPAGE}
#define	NEXTPAGE_MENU	{"Spc", "NextPage", \
			 {MC_PAGEDN, 4, {'+',' ',ctrl('V'),KEY_PGDN}}, \
			 KS_NEXTPAGE}
#define	JUMP_MENU	{"J", "Jump", \
			 {MC_JUMP, 1, {'j'}}, \
			 KS_JUMPTOMSG}
#define	FWDEMAIL_MENU	{"F", "Fwd Email", \
			{MC_FWDTEXT,1,{'f'}}, \
			 KS_FORWARD}
#define	PRYNTMSG_MENU	{"%", "Print", \
			 {MC_PRINTMSG,1,{'%'}}, \
			 KS_PRINT}
#define	PRYNTTXT_MENU	{"%", "Print", \
			 {MC_PRINTTXT,1,{'%'}}, \
			 KS_PRINT}
#define	SAVE_MENU	{"S", "Save", \
			 {MC_SAVE,1,{'s'}}, \
			 KS_SAVE}
#define	EXPORT_MENU	{"E", "Export", \
			 {MC_EXPORT, 1, {'e'}}, \
			 KS_EXPORT}
#define	COMPOSE_MENU	{"C", "Compose", \
			 {MC_COMPOSE,1,{'c'}}, \
			 KS_COMPOSER}
#define	DELETE_MENU	{"D", "Delete", \
			 {MC_DELETE,2,{'d',KEY_DEL}}, \
			 KS_DELETE}
#define	UNDELETE_MENU	{"U", "Undelete", \
			 {MC_UNDELETE,1,{'u'}}, \
			 KS_UNDELETE}
#define	REPLY_MENU	{"R", "Reply", \
			 {MC_REPLY,1,{'r'}}, \
			 KS_REPLY}
#define	FORWARD_MENU	{"F", "Forward", \
			 {MC_FORWARD,1,{'f'}}, \
			 KS_FORWARD}
#define	LISTFLD_MENU	{"L", "ListFldrs", \
			 {MC_COLLECTIONS,1,{'l'}}, \
			 KS_FLDRLIST}
#define	INDEX_MENU	{"I", "Index", \
			 {MC_INDEX,1,{'i'}}, \
			 KS_FLDRINDEX}
#define	GOTO_MENU	{"G", "GotoFldr", \
			 {MC_GOTO,1,{'g'}}, \
			 KS_GOTOFLDR}
#define	TAKE_MENU	{"T", "TakeAddr", \
			 {MC_TAKE,1,{'t'}}, \
			 KS_TAKEADDR}
#define	FLAG_MENU	{"*", "Flag", \
			 {MC_FLAG,1,{'*'}}, \
			 KS_FLAG}
#define	PIPE_MENU	{"|", "Pipe", \
			 {MC_PIPE,1,{'|'}}, \
			 KS_NONE}
#define	BOUNCE_MENU	{"B", "Bounce", \
			 {MC_BOUNCE,1,{'b'}}, \
			 KS_BOUNCE}
#define	HDRMODE_MENU	{"H", "HdrMode", \
			 {MC_FULLHDR,1,{'h'}}, \
			 KS_HDRMODE}
#define	TAB_MENU	{"Tab", "NextNew", \
			 {MC_TAB,1,{TAB}}, \
			 KS_NONE}

#define USER_INPUT_TIMEOUT(ps) ((ps->hours_to_timeout > 0) && \
  ((time((time_t *)0) - ps->time_of_last_input) > 60*60*(ps->hours_to_timeout)))


#ifdef	ENABLE_LDAP
/*
 * This is used to consolidate related information about a server. This
 * information is all stored in the ldap-servers variable, per server.
 */
typedef struct _ldap_serv {
    char	*serv,		/* Server name			*/
		*base,		/* Search base			*/
		*cust,		/* Custom search filter		*/
		*nick,		/* Nickname			*/
		*mail,		/* Backup email address		*/
		*mailattr,	/* "Mail" attribute name	*/
		*snattr,	/* "Surname" attribute name	*/
		*gnattr,	/* "Givenname" attribute name	*/
		*cnattr;	/* "CommonName" attribute name	*/
    int		 port,		/* Port number			*/
		 time,		/* Time limit			*/
		 size,		/* Size limit			*/
		 impl,		/* Use implicitly feature	*/
		 rhs,		/* Lookup contents feature	*/
		 ref,		/* Save by reference feature	*/
		 nosub,		/* Disable space sub feature	*/
		 type,		/* Search type (surname...)	*/
		 srch,		/* Search rule (contains...)	*/
		 scope;		/* Scope of search (base...)	*/
} LDAP_SERV_S;

/*
 * Structures to control the LDAP address selection screen
 */
typedef struct _ldap_serv_results {
    LDAP                      *ld;		/* LDAP handle */
    LDAPMessage               *res;		/* LDAP search result */
    LDAP_SERV_S               *info_used;
    char                      *serv;
    struct _ldap_serv_results *next;
} LDAP_SERV_RES_S;

typedef struct _addr_choose {
    LDAP_SERV_RES_S *res_head;
    char            *title;
    LDAP            *selected_ld;	/* from which ld was entry selected */
    LDAPMessage     *selected_entry;	/* which entry was selected */
    LDAP_SERV_S     *info_used;
    char            *selected_serv;
} ADDR_CHOOSE_S;

/*
 * How the LDAP lookup should work.
 */
typedef	enum {AlwaysDisplay,
	      AlwaysDisplayAndMailRequired,
    	      DisplayIfTwo,
	      DisplayIfOne,
	      DisplayForURL
	      } LDAPLookupStyle;

#define	LDAP_TYPE_CN		0
#define	LDAP_TYPE_SUR		1
#define	LDAP_TYPE_GIVEN		2
#define	LDAP_TYPE_EMAIL		3
#define	LDAP_TYPE_CN_EMAIL	4
#define	LDAP_TYPE_SUR_GIVEN	5
#define	LDAP_TYPE_SEVERAL	6


#define	LDAP_SRCH_CONTAINS	0
#define	LDAP_SRCH_EQUALS	1
#define	LDAP_SRCH_BEGINS	2
#define	LDAP_SRCH_ENDS		3

#define	DEF_LDAP_TYPE		6
#define	DEF_LDAP_SRCH		2
#define	DEF_LDAP_TIME		30
#define	DEF_LDAP_SIZE		0
#define	DEF_LDAP_SCOPE		LDAP_SCOPE_SUBTREE
#define	DEF_LDAP_MAILATTR	"mail"
#define	DEF_LDAP_SNATTR		"sn"
#define	DEF_LDAP_GNATTR		"givenname"
#define	DEF_LDAP_CNATTR		"cn"

#endif	/* ENABLE_LDAP */


/*
 * used to store system derived user info
 */
typedef struct user_info {
    char *homedir;
    char *login;
    char *fullname;
} USER_S;

typedef int (*percent_done_t)();    /* returns %done for progress status msg */

/* used to fake alarm syscall on systems without it */
#ifndef	ALARM_BLIP
#define ALARM_BLIP()
#endif


/*
 * Printing control structure
 */
typedef struct print_ctrl {
#ifndef	DOS
    PIPE_S	*pipe;		/* control struct for pipe to write text */
    FILE	*fp;		/* file pointer to write printed text into */
    char	*result;	/* file containing print command's output */
#endif
#ifdef	OS2
    int		ispipe;
#endif
    int		err;		/* bit indicating something went awry */
} PRINT_S;


/*
 * Child posting control structure
 */
typedef struct _post_s {
    int		pid;		/* proc id of child doing posting */
    int		status;		/* child's exit status */
    char       *fcc;		/* fcc we may have copied */
} POST_S;


/*
 * This structure is used to contain strings which are matched against
 * header fields. The match is a simple substring match. The match is
 * an OR of all the patterns in the PATTERN_S list.
 */
typedef struct pattern_s {
    char             *substring;
    struct pattern_s *next;
} PATTERN_S;

/*
 * A pattern gives characteristics of an envelope to match against. Any of
 * the characteristics (to, from, ...) which is non-null must match for the
 * whole thing to be considered a match. That is, it is an AND of all the
 * non-null members.
 */
typedef struct patgrp_s {
    char      *nick;
    PATTERN_S *to,
	      *from,
	      *sender,
	      *cc,
	      *news,
	      *subj;
} PATGRP_S;

/*
 * This type of action is used to set a role.
 */
typedef struct role_action_s {
    ADDRESS	*from;		/* value to set for From		*/
    char	*fcc;		/* value to set for Fcc			*/
    char	*sig;		/* value to set for Sig File		*/
    char	*template;	/* value to set for Template		*/
    char	*nick;		/* value to set for Nickname		*/
    int		 repl_type;
    int		 forw_type;
    char	*inherit_nick;	/* pattern we inherit actions from	*/
} ROLE_ACTION_S;

/* flags for confirm_role() */
#define ROLE_COMPOSE	0x1
#define ROLE_ANY	0x1	/* same as compose for now */
#define ROLE_REPLY	0x2
#define ROLE_FORWARD	0x4
#define ROLE_DEFAULTOK	0x8

#define	ROLE_REPL_NO		0
#define	ROLE_REPL_YES		1
#define	ROLE_REPL_NOCONF	2
#define	ROLE_FORW_NO		0
#define	ROLE_FORW_YES		1
#define	ROLE_FORW_NOCONF	2

#define	ROLE_REPL_DEFL		ROLE_REPL_YES
#define	ROLE_FORW_DEFL		ROLE_FORW_YES

/*
 * This gives the details of an action. Each pattern may have more than
 * one type of action associated with it. If an action in the list below
 * is non-NULL then this pattern is being used for that type of action.
 * (So far role is the only type of action.)
 */
typedef struct action_s {
    ROLE_ACTION_S *role;
} ACTION_S;

/*
 * An message is compared with a pattern to see if it matches.
 * If it does match, then there is an action which is taken.
 */
typedef struct pat_s {
    PATGRP_S          *patgrp;
    ACTION_S          *action;
    struct pat_line_s *patline;	/* pat_line that goes with this pat */
    struct pat_s      *next;
    struct pat_s      *prev;
} PAT_S;

typedef	enum {TypeNotSet = 0, Literal, File} PAT_TYPE;

/* There's one of these for each line in the pinerc variable */
typedef struct pat_line_s {
    PAT_TYPE           type;
    PAT_S             *first;	/* 1st pattern in list belonging to this line */
    PAT_S             *last;
    char              *filename; /* If type File, the filename */
    char              *filepath;
    unsigned	       readonly:1;
    unsigned	       dirty:1;	/* needs to be written back to storage */
    struct pat_line_s *next;
    struct pat_line_s *prev;
} PAT_LINE_S;

typedef struct pat_handle {
    PAT_LINE_S *patlinehead;	/* list of in-core, parsed pat lines */
    PAT_LINE_S *patlinecurrent;
    PAT_S      *patcurrent;	/* current pat within patline */
    unsigned    dirtypinerc:1;	/* needs to be written */
} PAT_HANDLE;

typedef struct role_nameval {
    char *name;			/* the name that goes on the screen      */
    char *shortname;		/* the name that goes in the config file */
    int   value;		/* the internal bit number */
} ROLE_NAMEVAL_S;

#define PATTERN_MAGIC     "P#Pats"
#define PATTERN_FILE_VERS "01"


/*
 * Message Reply control structure
 */
typedef struct _reply_s {
    unsigned int   flags:4;	/* how to interpret handle field */
    char	  *mailbox;	/* mailbox handles are valid in */
    char	  *prefix;	/* string to prepend reply-to text */
    union {
	long	   pico_flags;	/* Flags to manage pico initialization */
	struct {		/* UID information */
	    unsigned long  validity;	/* validity token */
	    unsigned long *msgs;	/* array of reply'd to msgs */
	} uid;
    } data;
} REPLY_S;

#define	REPLY_PSEUDO	1
#define	REPLY_MSGNO	2
#define	REPLY_UID	3

/*
 * Flag definitions to help control reply header building
 */
#define	RSF_NONE		0x00
#define	RSF_FORCE_REPLY_TO	0x01
#define	RSF_QUERY_REPLY_ALL	0x02
#define	RSF_FORCE_REPLY_ALL	0x04

/*
 * Flag definitions to help build forwarded bodies
 */
#define	FWD_NONE	0
#define	FWD_ANON	1

/*
 * Flag definitions to control composition of forwarded subject
 */
#define FS_NONE           0
#define FS_CONVERT_QUOTES 1

/*
 * Cursor position when resuming postponed message.
 */
typedef struct _redraft_pos_s {
    char	  *hdrname;	/* header field name, : if in body */
    long	   offset;	/* offset into header or body */
} REDRAFT_POS_S;




/*----------------------------------------------------------------------
   This structure sort of takes the place of global variables or perhaps
is the global variable.  (It can be accessed globally as ps_global.  One
advantage to this is that as soon as you see a reference to the structure
you know it is a global variable. 
   In general it is treated as global by the lower level and utility
routines, but it is not treated so by the main screen driving routines.
Each of them receives it as an argument and then sets ps_global to the
argument they received.  This is sort of with the thought that things
might be coupled more loosely one day and that Pine might run where there
is more than one window and more than one instance.  But we haven't kept
up with this convention very well.
 ----*/
  
struct pine {
    void       (*next_screen)();	/* See loop at end of main() for how */
    void       (*prev_screen)();	/* these are used...		     */
    void       (*redrawer)();		/* NULL means stay in current screen */

    CONTEXT_S   *context_list;		/* list of user defined contexts */
    CONTEXT_S   *context_current;	/* default open context          */
    CONTEXT_S   *context_last;		/* most recently open context    */

    char         inbox_name[MAXFOLDER+1];
    MAILSTREAM  *inbox_stream;		/* these used when current folder */
    long         inbox_new_mail_count;	/* is *not* inbox...		  */
    long         inbox_expunge_count;
    int          inbox_changed;
    MSGNO_S	*inbox_msgmap;		/* pointer to inbox mapping struct  */
    
    MAILSTREAM  *mail_stream;		/* c-client's current folder stream */

    MSGNO_S	 *msgmap;		/* message num mapping into stream  */

    long	 new_mail_count;
    long	 expunge_count;
    long	 first_unseen;

    unsigned     mail_box_changed:1;
    unsigned     unsorted_newmail:1;

    char         cur_folder[MAXPATH+1];
    ATTACH_S    *atmts;
    int          atmts_allocated;

    INDEX_COL_S *index_disp_format;

    char        *folders_dir;

    unsigned     mangled_footer:1; 	/* footer needs repainting */
    unsigned     mangled_header:1;	/* header needs repainting */
    unsigned     mangled_body:1;	/* body of screen needs repainting */
    unsigned     mangled_screen:1;	/* whole screen needs repainting */
    unsigned     in_init_seq:1;		/* executing initial cmd list */
    unsigned     save_in_init_seq:1;
    unsigned     dont_use_init_cmds:1;	/* use keyboard input when true */
    unsigned     give_fixed_warning:1;	/* warn user about "fixed" vars */

    unsigned     fix_fixed_warning:1;	/* offer to fix it              */
    unsigned     unseen_in_view:1;
    unsigned     start_in_context:1;	/* start fldr_scrn in current cntxt */
    unsigned     io_error_on_stream:1;	/* last write on mail_stream failed */
    unsigned     def_sort_rev:1;	/* true if reverse sort is default  */ 
    unsigned     restricted:1;
    unsigned	 show_dot_names:1;
    unsigned     nr_mode:1;

    unsigned     anonymous:1;           /* for now implys nr_mode */
    unsigned	 save_msg_rule:4;
    unsigned	 fcc_rule:3;

    unsigned	 ab_sort_rule:3;
    unsigned	 fld_sort_rule:3;
    unsigned	 inc_startup_rule:2;
    unsigned	 goto_default_rule:3;

    unsigned     full_header:1;         /* display full headers */
    unsigned     orig_use_fkeys:1;
    unsigned     try_to_create:1;	/* Save should try mail_create */
    unsigned     low_speed:1;		/* various opt's 4 low connect speed */
    unsigned     dead_inbox:1;
    unsigned     dead_stream:1;
    unsigned     noticed_dead_inbox:1;
    unsigned     noticed_dead_stream:1;

    unsigned     mm_log_error:1;
    unsigned     compose_mime:1;
    unsigned     show_new_version:1;
    unsigned     pre390:1;		/** temporary!!!! right. **/
    unsigned     first_time_user:1;
    unsigned	 outstanding_pinerc_changes:1;
    unsigned	 intr_pending:1;	/* received SIGINT and haven't acted */
    unsigned	 expunge_in_progress:1;	/* don't want to re-enter c-client   */
    unsigned	 never_allow_changing_from:1;	/* not even for roles */

    unsigned	 readonly_pinerc:1;
    unsigned	 view_all_except:1;
    unsigned     start_in_index:1;	/* cmd line flag modified on startup */
    unsigned     noshow_error:1;	/* c-client error callback controls */
    unsigned     noshow_warn:1;
    unsigned	 noshow_timeout:1;

    unsigned	 phone_home:1;
    unsigned     painted_body_on_startup:1;
    unsigned     painted_footer_on_startup:1;
    unsigned     open_readonly_on_startup:1;

    unsigned 	 viewer_overlap:8;
    unsigned	 scroll_margin:8;
    unsigned 	 remote_abook_history:8;

#if defined(DOS) || defined(OS2)
    unsigned     blank_user_id:1;
    unsigned     blank_personal_name:1;
    unsigned     blank_user_domain:1;
    unsigned	 permit_isolated_post:1;
#endif

#ifdef DEBUG
    unsigned 	 debug_malloc:6;
    unsigned 	 debug_timestamp:1;
    unsigned 	 debug_flush:1;
    unsigned 	 debug_imap:3;
    unsigned 	 debug_nfiles:5;
#endif

    unsigned     start_entry;		/* cmd line arg: msg # to start on */

    bitmap_t     feature_list;		/* a bitmap of all the features */
    char       **feat_list_back_compat;


    short	 init_context;

    int         *initial_cmds;         /* cmds to execute on startup */
    int         *free_initial_cmds;    /* used to free when done */

    char         c_client_error[300];  /* when nowhow_error is set and PARSE */

    struct ttyo *ttyo;

    USER_S	 ui;		/* system derived user info */

    POST_S      *post;

    char	*home_dir,
                *hostname,	/* Fully qualified hostname */
                *localdomain,	/* The (DNS) domain this host resides in */
                *userdomain,	/* The per user domain from .pinerc or */
                *maildomain,	/* Domain name for most uses */
#if defined(DOS) || defined(OS2)
                *pine_dir,	/* argv[0] as provided by DOS */
#endif
                *pine_conf,	/* Location of global pine.conf */
                *pinerc,	/* Location of user's pinerc */
		*pine_name;	/* name we were invoked under */

    time_t	 pinerc_written;

    SortOrder    def_sort,	/* Default sort type */
		 sort_types[20];

    int          last_expire_year, last_expire_month;

    int		 printer_category;

    int		 status_msg_delay;

    int		 composer_fillcol;

    time_t	 time_of_last_input;
    int          hours_to_timeout;

    char	 last_error[500],
	       **init_errs;

    PRINT_S	*print;

    struct variable *vars;
};


/*------------------------------
  Structure to pass optionally_enter to tell it what keystrokes
  are special
  ----*/

typedef struct esckey {
    int  ch;
    int  rval;
    char *name;
    char *label;
} ESCKEY_S;


struct date {
    int	 sec, minute, hour, day, month, 
	 year, hours_off_gmt, min_off_gmt, wkday;
};


/*------------------------------
  Structures and enum used to expand the envelope structure to
  support user defined headers.
  ----*/

typedef enum {FreeText, Address, Fcc,
	      Attachment, Subject, TypeUnknown} FieldType;

typedef struct pine_field {
    char     *name;			/* field's literal name		    */
    FieldType type;			/* field's type			    */
    unsigned  canedit:1;		/* allow editing of this field	    */
    unsigned  writehdr:1;		/* write rfc822 header for field    */
    unsigned  localcopy:1;		/* copy to fcc or postponed	    */
    unsigned  rcptto:1;			/* send to this if type Address	    */
    ADDRESS **addr;			/* used if type is Address	    */
    char     *scratch;			/* scratch pointer for Address type */
    char    **text;			/* field's free text form	    */
    char     *textbuf;			/* need to free this when done	    */
    struct headerentry *he;		/* he that goes with this field, a  */
					/*   pointer into headerentry array */
    struct pine_field *next;		/* next pine field		    */
} PINEFIELD;


typedef struct {
    ENVELOPE   *env;		/* standard c-client envelope		*/
    PINEFIELD  *local;		/* this is all of the headers		*/
    PINEFIELD  *custom;		/* ptr to start of custom headers	*/
    PINEFIELD **sending_order;	/* array giving writing order of hdrs	*/
} METAENV;

/*
 * Return values for check_address()
 */
#define CA_OK	  0		/* Address is OK                           */
#define CA_EMPTY  1		/* Address is OK, but no deliverable addrs */
#define CA_BAD   -1		/* Address is bogus                        */

/*
 * This is the structure that the builders impose on the private data
 * that is pointed to by the bldr_private pointer in each header entry.
 *
 * The bldr_private pointer points to a PrivateTop which consists of two
 * parts, whose purposes are independent:
 *   encoded -- This is used to preserve the charset information for
 *                addresses in this entry. For example, if the user types
 *                in a nickname which has a charset in it, the encoded
 *                version containing the charset information is saved here
 *                along with a checksum of the text that created it (the
 *                line containing the nickname).
 *         etext -- Pointer to the encoded text.
 *     chksumlen -- Length of string that produced the etext.
 *     chksumval -- Checksum of that string.
 *         The string that produced the etext is just the displayed
 *         value of the entry, not the nickname before it was expanded.
 *         That's so we can check on the next builder call to see if it
 *         was changed or not. Appending or prepending more addresses to
 *         what's there will work, the etext from the old contents will
 *         be combined with the etext from the appended stuff. (The check
 *         is for appending or prepending so appending AND prepending all
 *         at once won't work, charset will be lost.) If the middle of the
 *         text is edited the charset is lost. If text is removed, the
 *         charset is lost.
 *
 *  affector -- This is for entries which affect the contents of other
 *                fields. For example, the Lcc field affects what goes in
 *                the To and Fcc fields, and the To field affects what goes
 *                in the Fcc field.
 *           who -- Who caused this field to be set last.
 *     chksumlen -- Length of string in the "who" field that caused the effect.
 *     chksumval -- Checksum of that string.
 *         The string that is being checksummed is the one that is displayed
 *         in the field doing the affecting. So, for the affector in the
 *         Fcc headerentry, the who might point to either To or Lcc and
 *         then the checksummed string would be either the To or Lcc displayed
 *         string. The purpose of the affector is to remember that the
 *         affected field was set from an address book entry that is no
 *         longer identifiable once it is expanded. For example, if a list
 *         is entered into the Lcc field, then the To field gets the list
 *         fullname and the fcc field gets the fcc entry for the list. If
 *         we move out of the Lcc field and back in and call the builder
 *         again, the list has been expanded and we can't tell (except for
 *         the affector) that the same list is what caused the results.
 *         Same for the To field. A nickname entered there will cause the
 *         fcc of that nickname to go in the Fcc field and the affector
 *         will cause it to stick as long as the To field is only appended to.
 *
 * It may seem a little strange that the PrivateAffector doesn't have a text
 * field. The reason is that the text is actually displayed in that field
 * and so is contained in the entry itself, unlike the PrivateEncoded
 * which has etext which is not displayed and is only used when we go to
 * send the mail.
 */

typedef enum {BP_Unset, BP_To, BP_Lcc} WhoSetUs;

typedef struct private_affector {
    WhoSetUs who;
    int      cksumlen;
    long     cksumval;
} PrivateAffector;

typedef struct private_encoded {
    char    *etext;
    int      cksumlen;
    long     cksumval;
} PrivateEncoded;

typedef struct private_top {
    PrivateEncoded  *encoded;
    PrivateAffector *affector;
} PrivateTop;


typedef enum {OpenFolder, SaveMessage, FolderMaint, GetFcc,
		Subscribe, PostNews} FolderFun;
typedef enum {MsgIndex, MultiMsgIndex, ZoomIndex} IndexType;
typedef enum {TitleBarNone = 0, FolderName, MessageNumber, MsgTextPercent,
		TextPercent, FileTextPercent} TitleBarType;
typedef enum {CharStarStar, CharStar, FileStar,
		TmpFileStar, PicoText} SourceType;
typedef enum {GoodTime, BadTime, VeryBadTime, DoItNow} CheckPointTime;
typedef enum {InLine, QStatus} DetachErrStyle;

/*
 * Flags to help manage help display
 */
#define	HLPD_NONE	0x00
#define	HLPD_NEWWIN	0x01
#define	HLPD_SECONDWIN	0x02
#define	HLPD_SIMPLE	0x04
#define	HLPD_FROMHELP	0x08



/*
 * Struct defining scrolltool operating parameters.
 * 
 */
typedef	struct _scrolltool_s {
    struct {			/* Data and its attributes to scroll	 */
	void	   *text;	/* what to scroll			 */
	SourceType  src;	/* it's form (char **,char *,FILE *)	 */
	char	   *desc;	/* Description of "type" of data shown	 */
	HANDLE_S   *handles;	/* embedded data descriptions		 */
    } text;
    struct {			/* titlebar state			 */
	char	     *title;	/* screen's title			 */
	TitleBarType  style;	/* it's type				 */
    } bar;
    struct {			/* screen's keymenu/command bindings	 */
	struct key_menu	 *menu;
	bitmap_t	  bitmap;
	OtherMenu	  what;
	void		(*each_cmd) PROTO((struct _scrolltool_s *, int));
    } keys;
    struct {			/* help for this attachment		 */
	HelpType  text;		/* help text				 */
	char	 *title;	/* title for help screen		 */
    } help;
    struct {
	int (*click) PROTO((struct _scrolltool_s *));
	int (*clickclick) PROTO((struct _scrolltool_s *));
#ifdef	_WINDOWS
	/*
	 * For systems that support it, allow caller to do popup menu
	 */
	int (*popup) PROTO((struct _scrolltool_s *, int));
#endif
    } mouse;
    struct {			/* where to start paging from		 */
	enum {FirstPage = 0, LastPage, Fragment, Handle} on;
	char	*frag;		/* fragment in html text to start on	 */
    } start;
    struct {			/* Non-default Command Processor	 */
	int (*tool) PROTO((int, MSGNO_S *, struct _scrolltool_s *));
	/* The union below is opaque as far as scrolltool itself is
	 * concerned, but is provided as a container to pass data
	 * between the scrolltool caller and the given "handler"
	 * callback (or any other callback that takes a _scrolltool_s *).
	 */
	union {
	    void *p;
	    int	  i;
	} data;
    } proc;
				/* End of page processing		 */
    int	       (*end_scroll) PROTO((struct _scrolltool_s *));
				/* Handler for invalid command input	 */
    int	       (*bogus_input) PROTO((int));
    unsigned	 resize_exit:1;	/* Return from scrolltool if resized	 */
    unsigned	 body_valid:1;	/* Screen's body already displayed	 */
    unsigned	 no_stat_msg:1;	/* Don't display status messages	 */
    unsigned	 vert_handle:1;	/* hunt up and down on arrows/ctrl-[np]  */
    unsigned	 quell_help:1;	/* Don't show handle nav help message    */
} SCROLL_S;



/*
 * typedefs of generalized filters used by gf_pipe
 */
typedef struct filter_s {	/* type to hold data for filter function */
    void (*f) PROTO((struct filter_s *, int));
    struct filter_s *next;	/* next filter to call                   */
    long     n;			/* number of chars seen                  */
    short    f1;		/* flags                                 */
    int	     f2;		/* second place for flags                */
    unsigned char t;		/* temporary char                        */
    char     *line;		/* place for temporary storage           */
    char     *linep;		/* pointer into storage space            */
    void     *opt;		/* optional per instance data		 */
    void     *data;		/* misc internal data pointer		 */
    unsigned char queue[1 + GF_MAXBUF];
    short	  queuein, queueout;
} FILTER_S;

typedef struct filter_insert_s {
    char *where;
    char *text;
    int   len;
    struct filter_insert_s *next;
} LT_INS_S;

typedef int  (*gf_io_t)();	/* type of get and put char function     */
typedef void (*filter_t) PROTO((FILTER_S *, int));
typedef	int  (*linetest_t) PROTO((long, char *, LT_INS_S **, void *));

typedef	struct filtlist_s {
    filter_t  filter;
    void     *data;
} FILTLIST_S;


/*
 * typedef used by storage object routines
 */

typedef struct store_object {
    unsigned char *dp;		/* current position in data		 */
    unsigned char *eod;		/* end of current data			 */
    void	  *txt;		/* container's data			 */
    unsigned char *eot;		/* end of space alloc'd for data	 */
    int  (*writec) PROTO((int, struct store_object *));
    int  (*readc) PROTO((unsigned char *, struct store_object *));
    int  (*puts) PROTO((struct store_object *, char *));
    fpos_t	   used;	/* amount of object in use		 */
    char          *name;	/* optional object name			 */
    SourceType     src;		/* what we're copying into		 */
    short          flags;	/* flags relating to object use		 */
} STORE_S;

#define	so_writec(c, so)	((*(so)->writec)((c), (so)))
#define	so_readc(c, so)		((*(so)->readc)((c), (so)))
#define	so_puts(so, s)		((*(so)->puts)((so), (s)))


/*
 * Attribute table where information on embedded formatting and such
 * is really stored.
 */

typedef	enum {Link, LinkTarget} EmbedActions;

typedef struct atable_s {	/* a stands for either "anchor" or "action" */
    short	 handle;	/* handle for this action */
    EmbedActions action;	/* type of action indicated */
    short	 len;		/* number of characters in label */
    unsigned     wasuline:1;	/* previously underlined (not standard bold) */
    char	*name;		/* pointer to name of action */
    PARAMETER	*parms;		/* pointer to  necessary data */
    struct atable_s *next;
} ATABLE_S;


#define TAG_EMBED	'\377'	/* Announces embedded data in text string */
#define	TAG_INVON	'\001'	/* Supported character attributes	  */
#define	TAG_INVOFF	'\002'
#define	TAG_BOLDON	'\003'
#define	TAG_BOLDOFF	'\004'
#define	TAG_ULINEON	'\005'
#define	TAG_ULINEOFF	'\006'
#define	TAG_HANDLE	'\020'	/* indicate's a handle to an action	  */
#define	TAG_HANDLEOFF	'\030'	/* indicate's end of handle text	  */


/*
 * This is just like a struct timeval. We need it for portability to systems
 * that don't have a struct timeval.
 */
typedef struct our_time_val {
    long sec;
    long usec;
} TIMEVAL_S;


/*
 * Structures to control flag maintenance screen
 */
struct flag_table {
    char     *name;		/* flag's name string */
    HelpType  help;		/* help text */
    long      flag;		/* flag tag (i.e., F_DEL above) */
    unsigned  set:2;		/* its state (set, unset, unknown) */
    unsigned  ukn:1;		/* allow unknown state */
};

struct flag_screen {
    char	      **explanation;
    struct flag_table  *flag_table;
};

/*
 * Some defs to help keep flag setting straight...
 */
#define	CMD_FLAG_CLEAR	FALSE
#define	CMD_FLAG_SET	TRUE
#define	CMD_FLAG_UNKN	2


/*
 * Error handling argument for white pages lookups.
 */
typedef struct _wp_err {
    char	*error;
    int		 wp_err_occurred;
    int		*mangled;
    int		 ldap_errno;
} WP_ERR_S;


/*
 * Structures to control the collection list screen
 */
typedef struct _context_screen {
    unsigned	      edit:1;
    char	     *title, *print_string;
    CONTEXT_S	     *start,
		     *selected,
		    **contexts;
    struct {
	HelpType  text;
	char	 *title;
    } help;
    struct key_menu  *keymenu;
} CONT_SCR_S;

 
/*
 * Structure and macros to help control format_header_text
 */
typedef struct header_s {
    unsigned type:4;
    unsigned except:1;
    union {
	char **l;		/* list of char *'s */
	long   b;		/* bit field of header fields (FE_* above) */
    } h;
} HEADER_S;

#define	HD_LIST		1
#define	HD_BFIELD	2
#define	HD_INIT(H, L, E, B)	if((L) && (L)[0]){			\
				    (H)->type = HD_LIST;		\
				    (H)->except = (E);			\
				    (H)->h.l = (L);			\
				}					\
				else{					\
				    (H)->type = HD_BFIELD;		\
				    (H)->h.b = (B);			\
				}


/*
 * struct to help peruse a, possibly fragmented ala RFC 2231, parm list
 */
typedef	struct _parmlist {
    PARAMETER *list,
	      *seen;
    char       attrib[32],
	      *value;
} PARMLIST_S;


/*
 * Macro to help determine when we need to filter out naughty chars
 * from message index or headers...
 */
#define	CAN_DISPLAY(c)	(iscntrl((c) & 0x7f)				\
			 && !(isspace((unsigned char) (c))		\
			      || (c) == '\016'				\
			      || (c) == '\017'))

/*
 * return values for IMAP URL parser
 */
#define	URL_IMAP_MASK		0x0007
#define	URL_IMAP_ERROR		0
#define	URL_IMAP_IMAILBOXLIST	0x0001
#define	URL_IMAP_IMESSAGELIST	0x0002
#define	URL_IMAP_IMESSAGEPART	0x0004
#define	URL_IMAP_IMBXLSTLSUB	0x0010




/*======================================================================
    Declarations of all the Pine functions.
 ====*/
  
/*-- addrbook.c --*/
char	   *addr_book_bounce PROTO((void));
char	   *addr_book_compose PROTO((char **));
char	   *addr_book_compose_lcc PROTO((char **));
char	   *addr_book_oneaddr PROTO((void));
void	    addr_book_screen PROTO((struct pine *));
void	    addr_book_config PROTO((struct pine *));

/*-- adrbkcmd.c --*/
#ifdef	ENABLE_LDAP
void        view_ldap_entry PROTO((struct pine *, LDAP_SERV_RES_S *));
void        free_saved_query_parameters PROTO((void));
int         url_local_ldap PROTO((char *));
#endif

/*-- adrbklib.c --*/
char	    *tempfile_in_same_dir PROTO((char *, char *, char **));

/*-- args.c --*/
void	    pine_args PROTO((struct pine *, int, char **, ARGDATA_S *));

/*-- bldaddr.c --*/
void	    addrbook_reset PROTO((void));
int	    address_is_us PROTO((ADDRESS *, struct pine *));
int	    address_is_same PROTO((ADDRESS *, ADDRESS *));
char	   *addr_list_string PROTO((ADDRESS *,
				  char *(*f) PROTO((ADDRESS *, char *)),
				  int, int));
char	   *addr_string PROTO((ADDRESS *, char *));
void	    adrbk_maintenance PROTO((void));
int	    build_address PROTO((char *, char **,char **,BUILDER_ARG *,int *));
int	    build_addr_lcc PROTO((char *, char **,char **,BUILDER_ARG *,int *));
void	    completely_done_with_adrbks PROTO((void));
void        free_privatetop PROTO((PrivateTop *));
char	   *get_fcc PROTO((char *));
char	   *get_fcc_based_on_to PROTO((ADDRESS *));
char	   *get_fcc_from_addr PROTO((ADDRESS *, char *));
char	   *get_nickname_from_addr PROTO((ADDRESS *, char *));
void	    just_update_lookup_file PROTO((char *, char *));
void	    set_last_fcc PROTO((char *));
char	   *simple_addr_string PROTO((ADDRESS *, char *));
#ifdef	ENABLE_LDAP
LDAP_SERV_S *break_up_ldap_server PROTO((char *));
void	     free_ldap_server_info PROTO((LDAP_SERV_S **));
int          ldap_v3_is_supported PROTO((LDAP *));
void	     our_ldap_memfree PROTO((void *));
void	     our_ldap_dn_memfree PROTO((void *));
int	     our_ldap_set_option PROTO((LDAP *, int, void *));
#endif

/*--- filter.c ---*/
STORE_S	   *so_get PROTO((SourceType, char *, int));
void	    so_give PROTO((STORE_S **));
int	    so_seek PROTO((STORE_S *, long, int));
int	    so_truncate PROTO((STORE_S *, long));
int	    so_release PROTO((STORE_S *));
int	    so_nputs PROTO((STORE_S *, char *, long));
void	   *so_text PROTO((STORE_S *));
void	    gf_filter_init PROTO((void));
char	   *gf_pipe PROTO((gf_io_t, gf_io_t));
long	    gf_bytes_piped PROTO(());
char	   *gf_filter PROTO((char *, char *, STORE_S *,
			     gf_io_t, FILTLIST_S *));
void	    gf_set_so_readc PROTO((gf_io_t *, STORE_S *));
void	    gf_clear_so_readc PROTO((STORE_S *));
void	    gf_set_so_writec PROTO((gf_io_t *, STORE_S *));
void	    gf_clear_so_writec PROTO((STORE_S *));
void	    gf_set_readc PROTO((gf_io_t *, void *, unsigned long, SourceType));
void	    gf_set_writec PROTO((gf_io_t *, void *, unsigned long, \
				 SourceType));
int	    gf_puts PROTO((char *, gf_io_t));
int	    gf_nputs PROTO((char *, long, gf_io_t));
void	    gf_set_terminal PROTO((gf_io_t));
void	    gf_binary_b64 PROTO((FILTER_S *, int));
void	    gf_b64_binary PROTO((FILTER_S *, int));
void	    gf_qp_8bit PROTO((FILTER_S *, int));
void	    gf_8bit_qp PROTO((FILTER_S *, int));
void	    gf_rich2plain PROTO((FILTER_S *, int));
void	   *gf_rich2plain_opt PROTO((int));
void	    gf_enriched2plain PROTO((FILTER_S *, int));
void	   *gf_enriched2plain_opt PROTO((int));
void	    gf_html2plain PROTO((FILTER_S *, int));
void	   *gf_html2plain_opt PROTO((char *, int, int));
void	    gf_escape_filter PROTO((FILTER_S *, int));
void	    gf_control_filter PROTO((FILTER_S *, int));
void	    gf_wrap PROTO((FILTER_S *, int));
void	   *gf_wrap_filter_opt PROTO((int, int, int, int));
void	    gf_busy PROTO((FILTER_S *, int));
void	    gf_nvtnl_local PROTO((FILTER_S *, int));
void	    gf_local_nvtnl PROTO((FILTER_S *, int));
void	    gf_line_test PROTO((FILTER_S *, int));
void	   *gf_line_test_opt PROTO((linetest_t, void *));
LT_INS_S  **gf_line_test_new_ins PROTO((LT_INS_S **, char *, char *, int));
void	    gf_line_test_free_ins PROTO((LT_INS_S **));
void	    gf_prefix PROTO((FILTER_S *, int));
void	   *gf_prefix_opt PROTO((char *));
#if defined(DOS) || defined(OS2)
void	    gf_translate PROTO((FILTER_S *, int));
void	   *gf_translate_opt PROTO((unsigned char *, unsigned));
#endif

/*--- folder.c ---*/
void	    folder_screen PROTO((struct pine *));
void	    folder_config_screen PROTO((struct pine *));
char	   *folders_for_fcc PROTO((char **));
int	    folders_for_goto PROTO((struct pine *, CONTEXT_S **, char *, int));
int	    folders_for_save PROTO((struct pine *, CONTEXT_S **, char *, int));

#ifdef	NEWBB
void	    mark_folder_as_new PROTO((char *));
#endif
char	   *pretty_fn PROTO((char *));
int	    folder_exists PROTO((CONTEXT_S *, char *));
int	    folder_name_exists PROTO((CONTEXT_S *, char *, char **));
int	    folder_create PROTO((char *, CONTEXT_S *));
int	    folder_complete PROTO((CONTEXT_S *, char *, int *));
char	   *folder_as_breakout PROTO((CONTEXT_S *, char *));
void	    init_folders PROTO((struct pine *));
CONTEXT_S  *new_context PROTO((char *, int *));
void	    free_contexts PROTO((CONTEXT_S **));
void	    free_context PROTO((CONTEXT_S **));
void	    build_folder_list PROTO((MAILSTREAM **, CONTEXT_S *,
				     char *, char *, int));
void	    free_folder_list PROTO((CONTEXT_S *));
CONTEXT_S  *default_save_context PROTO((CONTEXT_S *));
FOLDER_S   *folder_entry PROTO((int, void *));
FOLDER_S   *new_folder PROTO((char *));
int	    folder_insert PROTO((int, FOLDER_S *, void *));
int	    folder_index PROTO((char *, CONTEXT_S *, int));
char	   *folder_is_nick PROTO((char *, void *));
char	   *next_folder PROTO((MAILSTREAM **, char *, char *,CONTEXT_S *,
			       long *));
void	    init_inbox_mapping PROTO((char *, CONTEXT_S *));
int	    news_build PROTO((char *, char **, char **, BUILDER_ARG *, int *));
char	   *news_group_selector PROTO((char **));
void	    free_newsgrp_cache PROTO(());
char	   *context_edit_screen PROTO((struct pine *, char *, char *,
				       char *, char *, char *));

/*-- help.c --*/
int	    helper PROTO((HelpType, char *, int));
int	    url_local_helper PROTO((char *));
void	    review_messages PROTO((char *));
void	    add_review_message PROTO((char *));
void	    end_status_review PROTO((void));
int	    gripe_gripe_to PROTO((char *));
int	    init_helper_getc PROTO((char **));
int	    helper_getc PROTO((char *));
void	    print_help PROTO((char **));
#if defined(DOS) || defined(HELPFILE)
char	  **get_help_text PROTO((HelpType)); 
#endif

/*-- imap.c --*/
char	   *cached_user_name PROTO((char *));
void	    imap_flush_passwd_cache PROTO(());
long	    pine_tcptimeout PROTO((long, long));
char	   *imap_referral PROTO((MAILSTREAM *, char *, long));
long	    imap_proxycopy PROTO((MAILSTREAM *, char *, char *, long));

/*-- init.c --*/
void	    init_error PROTO((struct pine *, char *));
void	    init_vars PROTO((struct pine *));
void	    free_vars PROTO((struct pine *));
char	   *expand_variables PROTO((char *, char *));
void	    set_current_val PROTO((struct variable *, int, int));
int	    init_username PROTO((struct pine *));
int	    init_hostname PROTO((struct pine *));  
int	    write_pinerc PROTO((struct pine *));
int	    var_in_pinerc PROTO((char *));
void	    free_pinerc_lines PROTO((void));
void	    dump_global_conf PROTO((void));
void	    dump_new_pinerc PROTO((char *));
int	    set_variable PROTO((int, char *, int));
int	    set_variable_list PROTO((int, char **, int));
int	    init_mail_dir PROTO((struct pine *));
void	    init_save_defaults PROTO(());
int	    expire_sent_mail PROTO((void));
char	  **parse_list PROTO((char *, int, char **));
char      **copy_list_array PROTO((char **));
void        free_list_array PROTO((char ***));
FEATURE_S  *feature_list PROTO((int));
char	   *feature_list_name PROTO((int));
char	   *feature_list_section PROTO((FEATURE_S *));
HelpType    feature_list_help PROTO((int));
NAMEVAL_S  *save_msg_rules PROTO((int));
NAMEVAL_S  *fcc_rules PROTO((int));
NAMEVAL_S  *ab_sort_rules PROTO((int));
NAMEVAL_S  *fld_sort_rules PROTO((int));
NAMEVAL_S  *incoming_startup_rules PROTO((int));
NAMEVAL_S  *goto_rules PROTO((int));
void	    set_old_growth_bits PROTO((struct pine *, int));
int	    test_old_growth_bits PROTO((struct pine *, int));
void	    dump_config PROTO((struct pine *, gf_io_t, int));
void	    dump_pine_struct PROTO((struct pine *, gf_io_t));

/*---- mailcap.c ----*/
char	   *mailcap_build_command PROTO((int, char *, PARAMETER *,
					 char *, int *));
int	    mailcap_can_display PROTO((int, char *, PARAMETER *));
void	    mailcap_free PROTO((void));
int	    set_mime_type_by_extension PROTO((BODY *, char *));
int	    set_mime_extension_by_type PROTO((char *, char *));

/*---- mailcmd.c ----*/
int	    process_cmd PROTO((struct pine *, MAILSTREAM *, MSGNO_S *,
			       int, int, int *));
int	    menu_command PROTO((int, struct key_menu *));
void	    menu_init_binding PROTO((struct key_menu *, int, int,
				     char *, char *, int));
void	    menu_add_binding PROTO((struct key_menu *, int, int));
int	    menu_clear_binding PROTO((struct key_menu *, int));
int	    menu_binding_index PROTO((struct key_menu *, int));
int	    individual_select PROTO((struct pine *, MSGNO_S *, int, int));
void	    bogus_command PROTO((int, char *));
void	    cmd_cancelled PROTO((char *));
char	   *broach_folder PROTO((int, int, CONTEXT_S **));
int	    do_broach_folder PROTO((char *, CONTEXT_S *));
void	    visit_folder PROTO((struct pine *, char *, CONTEXT_S *));
int	    jump_to PROTO((MSGNO_S *, int, int));
long	    zoom_index PROTO((struct pine *, MSGNO_S *));
int	    unzoom_index PROTO((struct pine *, MSGNO_S *));
int	    save_prompt PROTO((struct pine *, CONTEXT_S **, char *, char *,
			       ENVELOPE *, long, char *));
int	    save_fetch_append PROTO((MAILSTREAM *, long, char *, MAILSTREAM *,
				     char *, CONTEXT_S *, unsigned long,
				     char *, char *, STORE_S *));
void	    flag_string PROTO((MESSAGECACHE *, long, char *));
void	    expunge_and_close PROTO((MAILSTREAM *, CONTEXT_S *, char *,
				     char **));
char	   *get_uname PROTO((char *, char *, int));
char	   *build_updown_cmd PROTO((char *, char *, char *, char*));
int	    file_lister PROTO((char *, char *, int, char *, int, int, int));
int	    display_folder_list PROTO((CONTEXT_S **, char *, int,
				       int (*) PROTO((struct pine *,
						      CONTEXT_S **,
						      char *, int))));
int	    pseudo_selected PROTO((MSGNO_S *));
void	    restore_selected PROTO((MSGNO_S *));
int         simple_export PROTO((struct pine *, void *, SourceType, char *,
				       char *));
int         get_export_filename PROTO((struct pine *, char *, char *, char *,
				       char *, ESCKEY_S *,
				       int *, int, int));
char	   *build_sequence PROTO((MAILSTREAM *, MSGNO_S *, long *));
#ifdef	_WINDOWS
int	    header_mode_callback PROTO((int, long));
int	    any_selected_callback PROTO((int, long));
int	    zoom_mode_callback PROTO((int, long));
int	    flag_callback PROTO((int, long));
MPopup	   *flag_submenu PROTO((MESSAGECACHE *));
#endif

/*--- mailindx.c ---*/
void	    mail_index_screen PROTO((struct pine *));
int	    index_lister PROTO((struct pine *, CONTEXT_S *, char *, \
				MAILSTREAM *, MSGNO_S *));
int	    print_index PROTO((struct pine *, MSGNO_S *, int));
void	    clear_index_cache PROTO((void));
void	    clear_index_cache_ent PROTO((long));
int	    build_index_cache PROTO((long));
#ifdef	DOS
void	    flush_index_cache PROTO((void));
#endif
long	    line_hash PROTO((char *));
void	    init_index_format PROTO((char *, INDEX_COL_S **));
void	    pine_imap_envelope PROTO((MAILSTREAM *, unsigned long, ENVELOPE *));
void	    build_header_cache PROTO((void));
void	    redraw_index_body PROTO((void));
struct key_menu *
	    do_index_border PROTO((CONTEXT_S *, char *, MAILSTREAM *, \
				   MSGNO_S *, IndexType, int *, int));
char	   *sort_name PROTO((SortOrder));
void	    sort_folder PROTO((MSGNO_S *, SortOrder, int, int));
int	    percent_sorted PROTO((void));
void	    msgno_init PROTO((MSGNO_S **, long));
void	    msgno_give PROTO((MSGNO_S **));
void	    msgno_add_raw PROTO((MSGNO_S *, long));
void	    msgno_flush_raw PROTO((MSGNO_S *, long));
int	    msgno_in_select PROTO((MSGNO_S *, long));
long	    msgno_in_sort PROTO((MSGNO_S *, long));
void	    msgno_inc PROTO((MAILSTREAM *, MSGNO_S *));
void	    msgno_dec PROTO((MAILSTREAM *, MSGNO_S *));
void	    msgno_include PROTO((MAILSTREAM *, MSGNO_S *));
void	    msgno_exclude PROTO((MAILSTREAM *, MSGNO_S *));
int	    msgno_exceptions PROTO((MAILSTREAM *, long, char *, int *, int));
int	    msgno_any_exceptions PROTO((MAILSTREAM *, MSGNO_S *));
int	    msgno_part_deleted PROTO((MAILSTREAM *, long, char *));
void	    msgno_free_exceptions PROTO((PARTEX_S **));
#ifdef	_WINDOWS
int	    header_mode_callback PROTO((int, long));
int	    index_sort_callback PROTO((int, long));
#endif

/*---- mailpart.c ----*/
void	    attachment_screen PROTO((struct pine *));
char	   *detach PROTO((MAILSTREAM *, long, char *,
			  long *, gf_io_t, FILTLIST_S *));
int	    display_attachment PROTO((long, ATTACH_S *, int));
MAILSTREAM *save_msg_stream PROTO((CONTEXT_S *, char *, int *));
int	    valid_filter_command PROTO((char **));
char	   *expand_filter_tokens PROTO((char *, ENVELOPE *, char **,
					char **, char **, int *, int *));
char	   *filter_session_key PROTO(());
char	   *filter_data_file PROTO((int));
char	   *dfilter PROTO((char *, STORE_S *, gf_io_t, FILTLIST_S *));
char	   *df_static_trigger PROTO((BODY *, char *));
char	   *detach_raw PROTO((MAILSTREAM *, long, char *, gf_io_t, int));
void        date_str PROTO((char *, IndexColType, int, char *));

/*--- mailview.c ---*/
void	    mail_view_screen PROTO((struct pine *));
int	    scrolltool PROTO((SCROLL_S *));
char	   *body_type_names PROTO((int));
char	   *type_desc PROTO((int, char *, PARAMETER *, int));
char	   *part_desc PROTO((char *, BODY *, int, int, gf_io_t));
int	    format_message PROTO((long, ENVELOPE *, BODY *, int, gf_io_t));
char	   *format_editorial PROTO((char *, int, gf_io_t));
int	    match_escapes PROTO((char *));
int	    decode_text PROTO((ATTACH_S *, long, gf_io_t, DetachErrStyle,int));
char	   *display_parameters PROTO((PARAMETER *));
void	    display_output_file PROTO((char *, char *, char *, int));
char	   *fetch_header PROTO((MAILSTREAM *, long, char *, char **, long));
int	    format_header PROTO((MAILSTREAM *, long, char *, ENVELOPE *,
				 HEADER_S *, char *, int, gf_io_t));
void	    init_handles PROTO((HANDLE_S **));
void	    free_handles PROTO((HANDLE_S **));
HANDLE_S   *new_handle PROTO((void));
HANDLE_S   *get_handle PROTO((HANDLE_S *, int));
url_tool_t  url_local_handler PROTO((char *));
int	    url_local_fragment PROTO((char *));
int	    url_external_specific_handler PROTO((char *, int));
int	    url_imap_folder PROTO((char *, char **, long *,
				   long *, char **, int));
int	    url_hilite PROTO((long, char *, LT_INS_S **, void *));
int         url_hilite_abook PROTO((long, char *, LT_INS_S **, void *));

/*--newmail.c --*/
long	    new_mail PROTO((int, int, int));
void	    check_point_change PROTO(());
void	    reset_check_point PROTO((void));
void	    zero_new_mail_count PROTO((void));

/*-- os.c --*/
int	    can_access PROTO((char *, int));
int	    can_access_in_path PROTO((char *, char *, int));
long	    name_file_size PROTO((char *));
long	    fp_file_size PROTO((FILE *));
time_t	    name_file_mtime PROTO((char *));
time_t	    fp_file_mtime PROTO((FILE *));
void	    file_attrib_copy PROTO((char *, char *));
int	    is_writable_dir PROTO((char *));
int	    create_mail_dir PROTO((char *));
int	    rename_file PROTO((char *, char *));
void	    build_path PROTO((char *, char *, char *));
int	    is_absolute_path PROTO((char *));
char	   *last_cmpnt PROTO((char *));
int	    expand_foldername PROTO((char *));
char	   *fnexpand PROTO((char *, int));
char	   *filter_filename PROTO((char *, int *));
int	    cntxt_allowed PROTO((char *));
long	    disk_quota PROTO((char *, int *));
char	   *read_file PROTO((char *));
FILE	   *create_tmpfile PROTO((void));
void	    coredump PROTO((void));
void	    getdomainnames PROTO((char *, int, char *, int));
int	    have_job_control PROTO((void));
int 	    stop_process PROTO((void));
char	   *error_description PROTO((int));
void	    get_user_info PROTO((struct user_info *));
char	   *local_name_lookup PROTO((char *));
int	    change_passwd PROTO((void));
int	    mime_can_display PROTO((int, char *, PARAMETER *));
int	    fget_pos PROTO((FILE *, fpos_t *));
char	   *canonical_name PROTO((char *));
PIPE_S	   *open_system_pipe PROTO((char *, char **, char **, int, int));
int	    close_system_pipe PROTO((PIPE_S **));
char	   *smtp_command PROTO((char *));
int	    mta_handoff PROTO((METAENV *, BODY *, char *));
char	   *post_handoff PROTO((METAENV *, BODY *, char *));
void	    exec_mailcap_cmd PROTO((char *, char *, int));
int	    exec_mailcap_test_cmd PROTO((char *));
#ifdef DEBUG
void	    init_debug PROTO((void));
void	    save_debug_on_crash PROTO((FILE *));
int	    do_debug PROTO((FILE *));
char	   *debug_time PROTO((int));
#endif
#if defined(DOS) || defined(OS2)
char	   *temp_nam_ext PROTO((char *, char *, char *));
#endif
#ifdef	DOS
void	   *dos_cache PROTO((MAILSTREAM *, long, long));
char	   *dos_gets PROTO((readfn_t, void *, unsigned long));
#endif
#ifdef	_WINDOWS
void	    scroll_setrange PROTO((long page, long max));
void	    scroll_setpos PROTO((long pos));
long	    scroll_getpos PROTO((void));
long	    scroll_getscrollto PROTO((void));
char	   *pcpine_general_help PROTO((char *));
char	   *pcpine_help PROTO((HelpType));
#endif
#ifdef	MOUSE
unsigned long mouse_in_main PROTO((int, int, int));
#endif
int	    open_printer PROTO((char *));
void	    close_printer PROTO((void));
int	    print_char PROTO((int));
void	    print_text PROTO((char *));
void	    print_text1 PROTO((char *, char *));
void	    print_text2 PROTO((char *, char *, char *));
void	    print_text3 PROTO((char *, char *, char *, char *));
int	    get_time PROTO((TIMEVAL_S *));
long        time_diff PROTO((TIMEVAL_S *, TIMEVAL_S *));

/*--- other.c ---*/
int	    lock_keyboard PROTO((void));
char	   *signature_edit PROTO((char *, char *));
void	    redraw_kl_body PROTO(());
void	    redraw_klocked_body PROTO(());
void	    option_screen PROTO((struct pine *));
void	    flag_maintenance_screen PROTO((struct pine *,
					   struct flag_screen *));
CONTEXT_S  *context_select_screen PROTO((struct pine *, CONT_SCR_S *));
void	    parse_printer PROTO ((char *, char **, char **, char **,
				  char **, char **, char **));
#ifdef	ENABLE_LDAP
int         ldap_addr_select PROTO((struct pine *, ADDR_CHOOSE_S *,
				    LDAP_SERV_RES_S **, LDAPLookupStyle,
				    WP_ERR_S *));
void	    directory_config PROTO((struct pine *));
NAMEVAL_S  *ldap_search_rules PROTO((int));
NAMEVAL_S  *ldap_search_types PROTO((int));
NAMEVAL_S  *ldap_search_scope PROTO((int));
#endif
void        role_config_screen PROTO((struct pine *));
int         role_select_screen PROTO((struct pine *, ROLE_ACTION_S **, int));
ROLE_NAMEVAL_S *role_repl_types PROTO((int));
ROLE_NAMEVAL_S *role_forw_types PROTO((int));
void	    set_feature PROTO((char ***, char *, int));
#ifndef DOS
void	    select_printer PROTO((struct pine *));
#endif

/*-- pine.c --*/
void	    main_menu_screen PROTO((struct pine *));
void	    show_main_screen PROTO((struct pine *, int, OtherMenu, \
				    struct key_menu *, int, Pos *));
void	    news_screen PROTO((struct pine *));
void	    quit_screen PROTO((struct pine *));
long	    count_flagged PROTO((MAILSTREAM *, long));
void	    panic PROTO((char *));
void	    panic1 PROTO((char *, char *));
MAILSTREAM *same_stream PROTO((char *, MAILSTREAM *));
MsgNo	    first_sorted_flagged PROTO((unsigned long, MAILSTREAM *, int));
MsgNo	    next_sorted_flagged PROTO((unsigned long, MAILSTREAM *, \
				       long, int *));
long	    any_lflagged PROTO((MSGNO_S *, int));
int	    get_lflag PROTO((MAILSTREAM *, MSGNO_S *, long, int));
int	    set_lflag PROTO((MAILSTREAM *, MSGNO_S *, long, int, int));
void	    warn_other_cmds PROTO(());
void	    pine_close_stream PROTO((MAILSTREAM *));
unsigned long pine_gets_bytes PROTO((int));
int	    is_imap_stream PROTO((MAILSTREAM *));
int	    modern_imap_stream PROTO((MAILSTREAM *));
     
/*-- reply.c --*/
void	    reply PROTO((struct pine *));
void	    reply_seed PROTO((struct pine *, ENVELOPE *, ENVELOPE *,
			      ADDRESS *, ADDRESS *, ADDRESS *, ADDRESS *,
			      BUILDER_ARG *, int));
int	    reply_harvest PROTO((struct pine *, long, char *,
				 ENVELOPE *, ADDRESS **, ADDRESS **,
				 ADDRESS **, ADDRESS **,int *));
int	    reply_news_test PROTO((ENVELOPE *, ENVELOPE *));
int	    reply_text_query PROTO((struct pine *, long, char **));
BODY	   *reply_body PROTO((MAILSTREAM *, ENVELOPE *, BODY *, long,
			      char *, void *, char *, int, char *, char *,
			      REDRAFT_POS_S **));
char	   *reply_subject PROTO((char *, char *));
void	    reply_delimiter PROTO((ENVELOPE *, gf_io_t));
char	   *reply_in_reply_to PROTO((ENVELOPE *));
char	   *reply_quote_str PROTO((ENVELOPE *));
void	    forward PROTO((struct pine *));
char	   *forward_subject PROTO((ENVELOPE *, int));
BODY	   *forward_body PROTO((MAILSTREAM *, ENVELOPE *, BODY *, long,
				char *, void *, int));
int	    forward_mime_msg PROTO((MAILSTREAM *, long, char *,
				    ENVELOPE *, PART **, void *));
int	    fetch_contents PROTO((MAILSTREAM *, long, char *, BODY *));
void	    bounce PROTO((struct pine *));
char	   *bounce_msg PROTO((MAILSTREAM *, long, char *, char **, char *, \
			      char *, char *));
void	    forward_text PROTO((struct pine *, void *, SourceType));
char	   *generate_message_id PROTO((void));
ADDRESS    *first_addr PROTO((ADDRESS *));
char	   *get_signature PROTO((char *, int, int, int));
char	   *signature_path PROTO((char *, char *, size_t));
ENVELOPE   *copy_envelope PROTO((ENVELOPE *));
BODY	   *copy_body PROTO((BODY *, BODY *));
PARAMETER  *copy_parameters PROTO((PARAMETER *));
int	    get_body_part_text PROTO((MAILSTREAM *, BODY *, long, char *, \
				      gf_io_t, char *));
char	   *body_partno PROTO((MAILSTREAM *, long, BODY *));
char	   *partno PROTO((BODY *, BODY *));
ROLE_ACTION_S *set_role_from_msg PROTO((struct pine *, int, PAT_HANDLE *,
					long, char *));
int	    confirm_role PROTO((int, PAT_HANDLE *, ROLE_ACTION_S **));
char	   *detoken_file PROTO((char *, ENVELOPE *, int, int, int,
				REDRAFT_POS_S **, int *));
void	    free_redraft_pos PROTO((REDRAFT_POS_S **));

/*-- screen.c --*/
void	    draw_keymenu PROTO((struct key_menu *, bitmap_t, int, int, \
				int, OtherMenu));
void	    blank_keymenu PROTO((int, int));
void	    draw_cancel_keymenu PROTO((void));
void	    redraw_keymenu PROTO((void));
void	    mark_keymenu_dirty PROTO((void));
void	    mark_titlebar_dirty PROTO((void));
char	   *status_string PROTO((MAILSTREAM *, MESSAGECACHE *));
char	   *format_titlebar PROTO((int *));
char	   *set_titlebar PROTO((char *, MAILSTREAM *, CONTEXT_S *, char *, \
				MSGNO_S *, int, TitleBarType, long, long));
void	    push_titlebar_state PROTO(());
void	    pop_titlebar_state PROTO(());
void	    redraw_titlebar PROTO((void));
void	    update_titlebar_message PROTO((void));
void	    update_titlebar_status PROTO((void));
void	    update_titlebar_percent PROTO((long));
void	    update_titlebar_lpercent PROTO((long));
void	    clearfooter PROTO((struct pine *));
void	    end_titlebar PROTO((void));
void	    end_keymenu PROTO((void));

/*-- send.c --*/
void	    compose_screen PROTO((struct pine *)); 
void	    alt_compose_screen PROTO((struct pine *)); 
void	    compose_mail PROTO((char *, char *, ROLE_ACTION_S *,
				PATMT *, gf_io_t));
void	    pine_send PROTO((ENVELOPE *, BODY **, char *, ROLE_ACTION_S *,
			     char *, REPLY_S *, REDRAFT_POS_S *, char *,
			     void *, int));
int	    pine_simple_send PROTO((ENVELOPE *, BODY **, char *, char *,
				    char **, int));
char	   *pine_send_status PROTO((int, char *, char *, int *));
void	    phone_home PROTO((char *));
void	    pine_free_body PROTO((BODY **));
void	    simple_header_parse PROTO((char *, char **, char **));
int	    valid_subject PROTO((char *, char **, char **,BUILDER_ARG *,int *));
long	    flags_for_pico PROTO((struct pine *));
long	    new_mail_for_pico PROTO((int, int));
int	    display_message_for_pico PROTO((int));
void	    cmd_input_for_pico PROTO((void));
int	    upload_msg_to_pico PROTO((char *, long *));
char	   *checkpoint_dir_for_pico PROTO((char *, int));
void	    set_mime_type_by_grope PROTO((BODY *, char *));
void	    resize_for_pico PROTO((void));
STORE_S	   *open_fcc PROTO((char *, CONTEXT_S **, int, char *, char *));
int	    write_fcc PROTO((char *, CONTEXT_S *, STORE_S *, MAILSTREAM *,
			     char *));
void	    free_headents PROTO((struct headerentry **));
void	    free_attachment_list PROTO((PATMT **));
FieldType   pine_header_standard PROTO((char *));
ADDRESS    *generate_from PROTO((void));

/*-- signals.c --*/
int	    busy_alarm PROTO((unsigned, char *, percent_done_t, int));
void	    suspend_busy_alarm PROTO((void));
void	    resume_busy_alarm PROTO((unsigned));
void	    cancel_busy_alarm PROTO((int)); 
void	    fake_alarm_blip PROTO((void));
void	    init_signals PROTO((void));
void	    init_sighup PROTO((void));
void	    end_sighup PROTO((void));
void	    init_sigwinch PROTO((void));
int	    ttyfix PROTO((int));
int	    do_suspend PROTO((void));
void	    fix_windsize PROTO((struct pine *));
void	    winch_cleanup PROTO((void));
void	    end_signals PROTO((int));
SigType	    hup_signal PROTO(());
SigType	    term_signal PROTO(());
SigType	    child_signal PROTO(());
void	    intr_allow PROTO((void));
void	    intr_disallow PROTO((void));
void	    intr_handling_on PROTO((void));
void	    intr_handling_off PROTO((void));
void	    user_input_timeout_exit PROTO((int));

/*-- status.c --*/
int	    display_message PROTO((int));
void	    d_q_status_message PROTO((void));
void	    q_status_message PROTO(( int, int, int, char *));
void	    q_status_message1 PROTO((int, int, int, char *, void *));
void	    q_status_message2 PROTO((int, int, int, char *, void *, void *));
void	    q_status_message3 PROTO((int, int, int, char *, void *, void *, \
				     void *));
void	    q_status_message4 PROTO((int, int, int, char *, void *, void *, \
				     void *, void *));
void	    q_status_message7 PROTO((int, int, int, char *, void *, void *, \
				     void *, void *, void *, void *, void *));
int	    messages_queued PROTO((long *));
char	   *last_message_queued PROTO((void));
int	    status_message_remaining PROTO((void));
int	    status_message_write PROTO((char *, int));
void	    flush_status_messages PROTO((int));
void	    flush_ordered_messages PROTO((void));
void	    mark_status_dirty PROTO((void));
void	    mark_status_unknown PROTO((void));
int	    want_to PROTO((char *, int, int, HelpType, int));
int	    one_try_want_to PROTO((char *, int, int, HelpType, int));
int	    radio_buttons PROTO((char *, int, ESCKEY_S *, int, int, HelpType,
				 int));

/*-- strings.c --*/
char	   *rplstr PROTO((char *, int, char *));
void	    sqzspaces PROTO((char *));
void	    sqznewlines PROTO((char *));
void	    removing_trailing_white_space PROTO((char *));
void	    removing_leading_white_space PROTO((char *));
void	    removing_leading_and_trailing_white_space PROTO((char *));
void	    removing_double_quotes PROTO((char *));
char	   *skip_white_space PROTO((char *));
char	   *skip_to_white_space PROTO((char *));
char	   *removing_quotes PROTO((char *));
char	   *strclean PROTO((char *));
int	    in_dir PROTO((char *, char *));
char	   *srchstr PROTO((char *, char *));
char	   *srchrstr PROTO((char *, char *));
char	   *strindex PROTO((char *, int));
char	   *strrindex PROTO((char *, int));
void	    sstrcpy PROTO((char **, char *));
char	   *istrncpy PROTO((char *, char *, int));
char	   *month_abbrev PROTO((int));
char	   *month_name PROTO((int));
char	   *week_abbrev PROTO((int));
int	    month_num PROTO((char *));
void	    parse_date PROTO((char *, struct date *));
int	    compare_dates PROTO((MESSAGECACHE *, MESSAGECACHE *));
void	    convert_to_gmt PROTO((MESSAGECACHE *));
char	   *pretty_command PROTO((int));
char	   *repeat_char PROTO((int, int));
char	   *comatose PROTO((long));
char	   *byte_string PROTO((long));
char	   *enth_string PROTO((int));
char       *fold PROTO((char *, int, int, int, int, char *, char *));
char	   *strsquish PROTO((char *, char *, int));
char	   *long2string PROTO((long));
char	   *int2string PROTO((int));
char	   *strtoval PROTO((char *, int *, int, int, char *, char *));
void	    get_pair PROTO((char *, char **, char **, int));
int	    read_hex PROTO((char *));
char	   *string_to_cstring PROTO((char *));
char	   *cstring_to_hexstring PROTO((char *));
char	   *add_backslash_escapes PROTO((char *));
char	   *remove_backslash_escapes PROTO((char *));
char	   *vcard_escape PROTO((char *));
char	   *vcard_unescape PROTO((char *));
void	    vcard_unfold PROTO((char *));
int	    isxpair PROTO((char *));
STRLIST_S  *new_strlist PROTO((void));
void	    free_strlist PROTO((STRLIST_S **));
unsigned char *rfc1522_decode PROTO((unsigned char *, char *, char **));
char	   *rfc1522_encode PROTO((char *, unsigned char *, char *));
char	   *rfc1738_scan PROTO((char *, int *));
char	   *rfc1738_str PROTO((char *));
long	    rfc1738_num PROTO((char **));
int	    rfc1738_group PROTO((char *));
char	   *rfc1738_encode_mailto PROTO((char *));
int	    rfc1808_tokens PROTO((char *, char **, char **, char **,
				  char **, char **, char **));
char	   *web_host_scan PROTO((char *, int *));
char	   *mail_addr_scan PROTO((char *, int *));
char	   *rfc2231_get_param PROTO((PARAMETER *, char *, char **, char **));
int	    rfc2231_output PROTO((STORE_S *, char *, char *, char *, char *));
PARMLIST_S *rfc2231_newparmlist PROTO((PARAMETER *));
void	    rfc2231_free_parmlist PROTO((PARMLIST_S **));
int	    rfc2231_list_params PROTO((PARMLIST_S *));
PAT_HANDLE *open_patterns PROTO((void));
PAT_HANDLE *open_nonempty_patterns PROTO((void));
int         write_patterns PROTO((PAT_HANDLE *));
void        close_patterns PROTO((PAT_HANDLE **));
int         match_pattern PROTO((PATGRP_S *, MAILSTREAM *, long, char *));
PAT_S      *first_pattern PROTO((PAT_HANDLE *, int));
PAT_S      *last_pattern PROTO((PAT_HANDLE *, int));
PAT_S      *prev_pattern PROTO((PAT_HANDLE *, int));
PAT_S      *next_pattern PROTO((PAT_HANDLE *, int));
PAT_LINE_S *parse_pat_file PROTO((char *));
void        free_pat PROTO((PAT_S **));
void        free_role PROTO((ROLE_ACTION_S **));
char	   *pattern_to_string PROTO((PATTERN_S *));
PATTERN_S  *string_to_pattern PROTO((char *));
ROLE_ACTION_S *copy_role PROTO((ROLE_ACTION_S *));
ROLE_ACTION_S *combine_inherited_role PROTO((ROLE_ACTION_S *, PAT_HANDLE *));

/*-- takeaddr.c --*/
char	  **detach_vcard_att PROTO ((MAILSTREAM *, long, BODY *, char *));
void	    cmd_take_addr PROTO((struct pine *, MSGNO_S *, int));
void	    save_vcard_att PROTO((struct pine *, int, long, ATTACH_S *));
ADDRESS    *copyaddr PROTO((ADDRESS *));
#ifdef	ENABLE_LDAP
void        save_ldap_entry PROTO((struct pine *, LDAP_SERV_RES_S *, int));
#endif

/*-- ttyin.c--*/
int	    read_char PROTO((int));
int	    read_command PROTO(());
int	    optionally_enter PROTO((char *, int, int, int, char *, \
				    ESCKEY_S *, HelpType, int *));
int	    init_tty_driver PROTO((struct pine *));
void	    tty_chmod PROTO((struct pine *, int, int));
void	    end_tty_driver PROTO((struct pine *));
int	    PineRaw PROTO((int));
void	    end_keyboard PROTO((int));
void	    init_keyboard PROTO((int));
int	    validatekeys PROTO((int));
int	    key_recorder PROTO((int));
int	    key_playback PROTO((int));

/*-- ttyout.c --*/
int	    get_windsize PROTO((struct ttyo *));
int	    BeginScroll PROTO((int, int));
void	    EndScroll PROTO((void));
int	    ScrollRegion PROTO(( int));
void	    Writechar PROTO((unsigned int, int));
void	    Write_to_screen PROTO((char *));
void	    PutLine0 PROTO((int, int, char *));
void	    PutLine0n8b PROTO((int, int, char *, int, HANDLE_S *));
void	    PutLine1 PROTO((int, int, char *, void *));
void	    PutLine2 PROTO((int, int, char *, void *, void *));
void	    PutLine3 PROTO((int, int, char *, void *, void *, void *));
void	    PutLine4 PROTO((int, int, char *, void *, void *, void *, void *));
void	    PutLine5 PROTO((int, int, char *, void *, void *, void *, void *, \
			    void *));
void	    CleartoEOLN PROTO((void));
int	    CleartoEOS PROTO((void));
void	    ClearScreen PROTO((void));
void	    ClearLine PROTO((int));
void	    ClearLines PROTO((int, int));
void	    MoveCursor PROTO((int, int));
void	    NewLine PROTO((void));
int	    StartInverse PROTO((void));
void	    EndInverse PROTO((void));
int	    InverseState PROTO((void));
int	    StartUnderline PROTO((void));
void	    EndUnderline PROTO((void));
int	    StartBold PROTO((void));
void	    EndBold PROTO((void));
int	    config_screen PROTO((struct ttyo **));
void	    init_screen PROTO((void));
void	    end_screen PROTO((char *));
void	    outchar PROTO((int));
void	    icon_text PROTO((char *));
void	    clear_cursor_pos PROTO((void));
int	    InsertChar PROTO((int));
int	    DeleteChar PROTO((int));

#define SCREEN_FUN_NULL ((void (*) PROTO((void *)))NULL)

#endif /* _PINE_INCLUDED */
