/*
 * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
 * 
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 * 
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */ 

#define FOREVER while (1)

#ifdef DEBUG
#define dprint(N,X) if(debuglevel>=N) fprintf X
#else
#define dprint(N,X) 
#endif

#define mutt_make_string(A,B,C,D) _mutt_make_string(A,B,C,D,0)
void _mutt_make_string (char *, size_t, char *, HEADER *, int);

const char *mutt_extract_token (char *, size_t, const char *, char *, size_t, int);

#define mutt_system(x) _mutt_system(x,0)
int _mutt_system (const char *, int);

#define mutt_next_thread(x) _mutt_aside_thread(x,1,0)
#define mutt_previous_thread(x) _mutt_aside_thread(x,0,0)
#define mutt_next_subthread(x) _mutt_aside_thread(x,1,1)
#define mutt_previous_subthread(x) _mutt_aside_thread(x,0,1)
int _mutt_aside_thread (HEADER *, short, short);

#define ISSPACE(c) isspace((unsigned char)c)

#define mutt_new_parameter() safe_calloc (1, sizeof (PARAMETER))
#define mutt_new_header() safe_calloc (1, sizeof (HEADER))
#define mutt_new_envelope() safe_calloc (1, sizeof (ENVELOPE))

void set_quadoption (int, int);
int query_quadoption (int, const char *);
int quadoption (int);

ADDRESS *mutt_expand_aliases (ADDRESS *);
BODY *mutt_dup_body (BODY *);
BODY *mutt_new_body (void);
HEADER *mutt_dup_header (HEADER *);

ATTACHPTR **mutt_gen_attach_list (BODY *, short *, short *, int);

char *mutt_expand_path (char *, size_t);
char *mutt_find_hook (int, const char *);
char *mutt_gen_msgid (void);
char *mutt_get_parameter (const char *, PARAMETER *);
char *mutt_strlower (char *);
char *mutt_skip_whitespace (char *);
char *mutt_substrcpy (char *, const char *, const char *, size_t);

void mutt_alias_menu (char *, size_t, ALIAS *);
void mutt_block_signals (void);
void mutt_block_signals_system (void);
void mutt_bounce_message (HEADER *, ADDRESS *);
void mutt_buffy (char *);
void mutt_buffy_notify (void);
void mutt_clear_error (void);
void mutt_create_alias (ENVELOPE *);
#if (defined(USE_SLANG_CURSES) || defined(HAVE_CURS_SET))
void mutt_curs_set (int);
#else
#define mutt_curs_set(x)
#endif
void mutt_default_save (char *, size_t, ENVELOPE *);
void mutt_display_address (ADDRESS *);
void mutt_error (const char *, ...);
void mutt_enter_command (void);
void mutt_exit (int);
void mutt_expand_fmt (char *, size_t, const char *, const char *);
void mutt_expand_link (char *, const char *, const char *);
void mutt_fetchPopMail (void);
void mutt_folder_hook (char *);
void mutt_free_address (ADDRESS **);
void mutt_free_alias (ALIAS **);
void mutt_free_body (BODY **);
void mutt_free_color (int fg, int bg);
void mutt_free_envelope (ENVELOPE **);
void mutt_free_header (HEADER **);
void mutt_free_parameter (PARAMETER **);
void mutt_generate_header (char *, size_t, HEADER *, int);
void mutt_help (int);
void mutt_index_menu (void);
void mutt_init (int);
void mutt_init_history (void);
void mutt_make_help (char *, size_t, char *, int, int);
void mutt_message (const char *, ...);
void mutt_message_to_7bit (BODY *, FILE *);
void mutt_mktemp (char *);
void mutt_parse_adrlist (ADDRESS **, const char *, const char *);
void mutt_parse_mime_message (HEADER *);
void mutt_pipe_message_to_state (HEADER *, STATE *);
void mutt_perror (const char *);
void mutt_pretty_mailbox (char *);
void mutt_pretty_size (char *, size_t, long);
void mutt_print_message (HEADER *);
void mutt_remove_trailing_ws (char *);
void mutt_query_exit (void);
void mutt_safe_path (char *s, size_t l, ADDRESS *a);
void mutt_select_fcc (char *, size_t, ENVELOPE *);
void mutt_select_file (char *, size_t, int);
void mutt_send_hook (ADDRESS *);
void mutt_set_flag (CONTEXT *, HEADER *, int, int);
void mutt_shell_escape (void);
void mutt_show_error (void);
void mutt_signal_init (void);
void mutt_simple_address (char *, size_t, ADDRESS *);
void mutt_status_line (char *, size_t, const char *);
void mutt_tabs_to_spaces (char *);
void mutt_tag_set_flag (int, int);
void mutt_unblock_signals (void);
void mutt_unblock_signals_system (int);
void mutt_unlink (const char *);
void mutt_update_encoding (BODY *a);
void mutt_update_tree (ATTACHPTR **, short);
void mutt_view_attachments (HEADER *);

int mutt_addr_is_user (ADDRESS *);
int mutt_alias_complete (char *, size_t);
int mutt_alloc_color (int fg, int bg);
int mutt_any_key_to_continue (const char *);
int mutt_buffy_check (void);
int mutt_can_decode (BODY *);
int mutt_change_flag (HEADER *, int);
int mutt_check_encoding (const char *);
int mutt_check_key (const char *);
int mutt_check_menu (const char *);
int mutt_check_mime_type (const char *);
int mutt_check_month (const char *);
int mutt_check_overwrite (const char *, const char *, char *, size_t, int);
int mutt_complete (char *);
int mutt_confirm_func (const char *);
int mutt_copy_bytes (FILE *, FILE *, size_t);
int mutt_copy_hdr (FILE *, FILE *, long, long, int);
int mutt_copy_header (FILE *, HEADER *, FILE *, int);
int mutt_copy_stream (FILE *, FILE *);
int mutt_decode_save_attachment (FILE *, BODY *, char *, int, int);
int mutt_display_message (HEADER *h);
int mutt_do_pager (char *, char *, int);
int mutt_edit_attachment(BODY *, int);
int mutt_enter_fname (const char *, char *, size_t, int *);
int mutt_enter_string (unsigned char *, size_t, int, int, int);
int mutt_get_field (char *, char *, size_t, int);
int mutt_get_password (char *, char *, size_t);
int mutt_is_autoview (char *);
int mutt_is_mail_list (ADDRESS *);
int mutt_is_text_type (int, char *);
int mutt_is_valid_mailbox (const char *);
int mutt_needs_mailcap (BODY *);
int mutt_num_postponed (void);
int mutt_pager (const char *, const char *, HEADER *, int);
int mutt_parse_bind (const char *, void *, char *, size_t);
int mutt_parse_color (const char *, void *, char *, size_t);
int mutt_parse_hook (const char *, void *, char *, size_t);
int mutt_parse_macro (const char *, void *, char *, size_t);
int mutt_parse_mailboxes (const char *s, void *, char *, size_t);
int mutt_parse_mono (const char *, void *, char *, size_t);
int mutt_parse_push (const char *, void *, char *, size_t);
int mutt_parse_rc_line (const char *, char *, int);
int mutt_pattern_func (int, char *, HEADER *);
int mutt_pipe_attachment (FILE *, BODY *, const char *, char *); 
int mutt_pipe_message (HEADER *);
int mutt_print_attachment (FILE *, BODY *);
int mutt_save_attachment (FILE *, BODY *, char *, int);
int mutt_save_message (HEADER *, int, int, int *);
int mutt_search_command (int, int);
int mutt_strcmp (const char *, const char *);
int mutt_thread_set_flag (HEADER *, int, int, int);
int mutt_view_attachment (FILE*, BODY *, int);
int mutt_wait_filter (pid_t);
int mutt_which_case (const char *);
int mutt_write_rfc822_header (FILE *, ENVELOPE *, BODY *, int);
int mutt_yesorno (const char *, int);

int mh_valid_message (const char *);

time_t mutt_mktime (struct tm *);

pid_t mutt_create_filter (const char *, FILE **, FILE **, FILE **);
pid_t mutt_create_filter_fd (const char *, FILE **, FILE **, FILE **, int, int, int);

char *safe_strdup (const char *);

void *safe_calloc (size_t, size_t);
void *safe_malloc (unsigned int);
void safe_realloc (void **, size_t);
void safe_free (void **);

FILE *safe_fopen (const char *, const char *);

ADDRESS *alias_reverse_lookup (ADDRESS *);

#define strfcpy(A,B,C) strncpy(A,B,C), *(A+(C)-1)=0

#define SKIPWS(c) while (*(c) && isspace ((unsigned char) *(c))) c++;

#ifdef LOCALES_HACK
#define IsPrint(c) (isprint((unsigned char)(c)) || \
	((unsigned char)(c) >= 0xa0))
#else
#define IsPrint(c) (isprint((unsigned char)(c)) || \
	(option (OPTLOCALES) ? 0 : \
	((unsigned char)(c) >= 0xa0)))
#endif

/* ----------------------------------------------------------------------------
 * Prototypes for broken systems
 */

#ifdef HAVE_SRAND48
#define LRAND lrand48
#define SRAND srand48
#define DRAND drand48
#else
#define LRAND rand
#define SRAND srand
#define DRAND (double)rand
#endif /* HAVE_SRAND48 */

#ifdef HAVE_SETEGID
#define SETEGID setegid
#else
#define SETEGID setgid
#endif

int getdnsdomainname (char *, size_t);

/* According to SCO support, this is how to detect SCO */
#if defined (_M_UNIX) || defined (M_OS)
#define SCO
#endif

/* SCO Unix uses chsize() instead of ftruncate() */
#ifndef HAVE_FTRUNCATE
#define ftruncate chsize
#endif

#ifndef HAVE_SNPRINTF
extern int snprintf (char *, size_t, const char *, ...);
extern int vsnprintf (char *, size_t, const char *, va_list);
#endif

#ifndef HAVE_STRERROR
#ifndef STDC_HEADERS
extern int sys_nerr;
extern char *sys_errlist[];
#endif

#define strerror(x) ((x) > 0 && (x) < sys_nerr) ? sys_errlist[(x)] : 0
#endif /* !HAVE_STRERROR */

/* AIX doesn't define these in any headers (sigh) */
int strcasecmp (const char *, const char *);
int strncasecmp (const char *, const char *, size_t);

#ifdef _AIX
int setegid (gid_t);
#endif /* _AIX */

#ifndef STDC_HEADERS
extern FILE *fdopen ();
extern int system ();
extern int puts ();
extern int fputs ();
extern int fputc ();
extern int fseek ();
extern char *strchr ();
extern int getopt ();
extern int fputs ();
extern int fputc ();
extern int fclose ();
extern int fprintf();
extern int printf ();
extern int fgetc ();
extern int tolower ();
extern int toupper ();
extern int sscanf ();
extern size_t fread ();
extern size_t fwrite ();
extern int system ();
extern int rename ();
extern time_t time ();
extern struct tm *localtime ();
extern char *asctime ();
extern char *strpbrk ();
extern int fflush ();
extern long lrand48 ();
extern void srand48 ();
extern time_t mktime ();
extern int vsprintf ();
extern int ungetc ();
extern char *mktemp ();
extern int ftruncate ();
extern char *re_comp ();
extern int re_exec ();
extern void *memset ();
extern int pclose ();
extern int socket ();
extern int connect ();
extern size_t strftime ();
extern int lstat ();
extern void rewind ();
extern int readlink ();

/* IRIX barfs on empty var decls because the system include file uses elipsis
 * in the declaration.  So declare all the args to avoid compiler errors.  This
 * should be harmless on other systems.
 */
int ioctl (int, int, ...);

#endif

/* unsorted */
void ci_bounce_message (HEADER *, int *);
void ci_send_message (int, HEADER *, char *, HEADER *);
void ci_attach (BODY *);
