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

            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 Building, 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"

   Copyright 1989, 1990, 1991, 1992  University of Washington

    Permission to use, copy, modify, and distribute this software and its
   documentation for any purpose and without fee is hereby granted, provided
   that the above copyright notice appears in all copies and that both the
   above copyright notice and this permission notice appear in supporting
   documentation, and that the name of the University of Washington not be
   used in advertising or publicity pertaining to distribution of the software
   without specific, written prior permission.  This software is made
   available "as is", and
   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  

   Pine is in part based on The Elm Mail System:
    ***********************************************************************
    *  The Elm Mail System  -  $Revision: 2.13 $   $State: Exp $          *
    *                                                                     *
    * 			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 changes for local preferences such as
  default directories and other name. Changes might be needed here for
  porting pine to a new machine

   Includes
     - Various convenience definitions and macros
     - macros for debug printfs
     - data structures used by Pine
     - declarations of all Pine functions

  ====*/


#define BREAK		'\0'  		/* default interrupt    */
#define BACKSPACE	'\b'     	/* backspace character  */
#define TAB		'\t'            /* tab character        */
#define RETURN		'\r'     	/* carriage return char */
#define LINE_FEED	'\n'     	/* line feed character  */
#define FORMFEED	'\f'     	/* form feed (^L) char  */
#define COMMA		','		/* comma character      */
#define SPACE		' '		/* space character      */
#define DOT		'.'		/* period/dot character */
#define BANG		'!'		/* exclaimation mark!   */
#define AT_SIGN		'@'		/* at-sign character    */
#define PERCENT		'%'		/* percent sign char.   */
#define COLON		':'		/* the colon ..		*/
#define BACKQUOTE	'`'		/* backquote character  */
#define TILDE_ESCAPE	'~'		/* escape character~    */
#define ESCAPE		'\033'		/* the escape		*/


#ifndef TRUE
#define TRUE		1
#define FALSE		0
#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 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() */


#define equal(s,w)	(strcmp(s,w) == 0)
#undef  min
#define min(a,b)	((a) < (b) ? (a) : (b))
#undef  max
#define max(a,b)	((a) > (b) ? (a) : (b))
#define ctrl(c)	        ((c) - 'A' + 1)	/* control character mapping */
#define plural(n)	((n) == 1 ? "" : "s")
#define lastch(s)	s[strlen(s)-1]
#define no_ret(s)	{ register int xyz; /* varname is for lint */	      \
		          for (xyz=strlen(s)-1; xyz >= 0 && 		      \
				(s[xyz] == '\r' || s[xyz] == '\n'); )	      \
			     s[xyz--] = '\0';                                 \
			}
#define first_word(s,w) (strncmp(s,w, strlen(w)) == 0)
#define ClearLine(n)	MoveCursor(n,0) ; CleartoEOLN()
#define whitespace(c)	((c) == ' ' || (c) == '\t')
#define ok_char(c)	(isalnum(c) || (c) == '-' || (c) == '_')
#define quote(c)	((c) == '"' || (c) == '\'') 
#define onoff(n)	(n == 0 ? "OFF" : "ON")
/* find tab stops preceding or following a given column position 'a', where
 * the column position starts counting from 1, NOT 0!
 * The external integer "tabspacing" must be declared to use this. */
#define prev_tab(a,tb)	(((((a-1)/(tb)))*(tb))+1)
#define next_tab(a,tb)	(((((a-1)/(tb))+1)*(tb))+1)




/*======================================================================
        Key code definitions
  ===*/
#define PF1           0x0100
#define PF2           0x0101
#define PF3           0x0102
#define PF4           0x0103
#define PF5           0x0104
#define PF6           0x0105
#define PF7           0x0106
#define PF8           0x0107
#define PF9           0x0108
#define PF10          0x0109
#define PF11          0x010A
#define PF12          0x010B
      
#define OPF1          0x0110
#define OPF2          0x0111
#define OPF3          0x0112
#define OPF4          0x0113
#define OPF5          0x0114
#define OPF6          0x0115
#define OPF7          0x0116
#define OPF8          0x0117
#define OPF9          0x0118
#define OPF10         0x0119
#define OPF11         0x011A
#define OPF12         0x011B

#define OOPF1          0x0120
#define OOPF2          0x0121
#define OOPF3          0x0122
#define OOPF4          0x0123
#define OOPF5          0x0124
#define OOPF6          0x0125
#define OOPF7          0x0126
#define OOPF8          0x0127
#define OOPF9          0x0128
#define OOPF10         0x0129
#define OOPF11         0x012A
#define OOPF12         0x012B

#define PF2OPF(x)      (x + 0x10)
#define PF2OOPF(x)     (x + 0x20)


/*-- some control codes for arrow keys.. see read_char */
#define KEY_UP        0x0130
#define KEY_DOWN      0x0131
#define KEY_RIGHT     0x0132
#define KEY_LEFT      0x0133
#define KEY_JUNK      0x0134
#define KEY_RESIZE    0x135  /* Fake key to cause resize */

#define NO_OP_COMMAND '\0'    /* no-op for short timeouts   */
#define NO_OP_IDLE    0x200   /* no-op for timeouts longer than 25 seconds  */



#define V_USER_ID                  0
#define V_PERSONAL_NAME            1        
#define V_PRINTER                  2        
#define V_PERSONAL_PRINT_COMMAND   3        
#define V_STANDARD_PRINTER         4       
#define V_LAST_TIME_PRUNE_QUESTION 5       
#define V_USER_DOMAIN              6       
#define V_USE_ONLY_DOMAIN_NAME     7
#define V_INBOX_PATH               8       
#define V_ELM_STYLE_SAVE           9       
#define V_HEADER_IN_REPLY          10       
#define V_DEFAULT_FCC              11       
#define V_BUGS_NICKNAME            12
#define V_BUGS_FULLNAME            13
#define V_BUGS_ADDRESS             14       
#define V_SMTP_SERVER              15
#define V_EDITOR                   16
#define V_IMAGE_VIEWER             17
#define V_FEATURE_LEVEL            18
#define V_OLD_STYLE_REPLY          19
#define V_SIGNATURE_FILE           20
#define V_MAIL_DIRECTORY           21
#define V_COMPOSE_MIME             22
#define V_CHAR_SET                 23
#define V_SHOW_ALL_CHARACTERS      24
#define V_NEW_VERSION              25


#define VAR_USER_ID                  vars[V_USER_ID].current_val
#define VAR_PERSONAL_NAME            vars[V_PERSONAL_NAME].current_val
#define VAR_PRINTER                  vars[V_PRINTER].current_val
#define VAR_PERSONAL_PRINT_COMMAND   vars[V_PERSONAL_PRINT_COMMAND].current_val
#define VAR_STANDARD_PRINTER         vars[V_STANDARD_PRINTER].current_val
#define VAR_LAST_TIME_PRUNE_QUESTION vars[V_LAST_TIME_PRUNE_QUESTION].current_val
#define VAR_USER_DOMAIN              vars[V_USER_DOMAIN].current_val
#define VAR_USE_ONLY_DOMAIN_NAME     vars[V_USE_ONLY_DOMAIN_NAME].current_val
#define VAR_INBOX_PATH               vars[V_INBOX_PATH].current_val
#define VAR_ELM_STYLE_SAVE           vars[V_ELM_STYLE_SAVE].current_val
#define VAR_HEADER_IN_REPLY          vars[V_HEADER_IN_REPLY].current_val
#define VAR_DEFAULT_FCC              vars[V_DEFAULT_FCC].current_val
#define VAR_BUGS_NICKNAME            vars[V_BUGS_NICKNAME].current_val
#define VAR_BUGS_FULLNAME            vars[V_BUGS_FULLNAME].current_val
#define VAR_BUGS_ADDRESS             vars[V_BUGS_ADDRESS].current_val
#define VAR_SMTP_SERVER              vars[V_SMTP_SERVER].current_val
#define VAR_EDITOR                   vars[V_EDITOR].current_val
#define VAR_IMAGE_VIEWER             vars[V_IMAGE_VIEWER].current_val
#define VAR_FEATURE_LEVEL            vars[V_FEATURE_LEVEL].current_val
#define VAR_OLD_STYLE_REPLY          vars[V_OLD_STYLE_REPLY].current_val
#define VAR_SIGNATURE_FILE           vars[V_SIGNATURE_FILE].current_val
#define VAR_MAIL_DIRECTORY           vars[V_MAIL_DIRECTORY].current_val
#define VAR_COMPOSE_MIME             vars[V_COMPOSE_MIME].current_val
#define VAR_CHAR_SET                 vars[V_CHAR_SET].current_val
#define VAR_SHOW_ALL_CHARACTERS      vars[V_SHOW_ALL_CHARACTERS].current_val
#define VAR_NEW_VERSION              vars[V_NEW_VERSION].current_val


/*======================================================================
       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

 the following macro is as suggested by Larry McVoy.  Thanks! *
  ====*/
# ifdef DEBUG
#  define   dprint(n,x)		{ 				\
				   if (debugfile != NULL && debug >= n)  { \
				     fprintf x ; 		\
                                     if(debug > 7)              \
                                       fflush(debugfile);       \
				   }				\
				}
# else
#  define   dprint(n,x)
# endif





/*======================================================================
            Various structures that Pine uses
 ====*/
struct text_line {
    char *text;
    unsigned char  length;  /* Never longer than 255 */
};


struct ttyo {
    int  screen_rows,
         screen_cols;
};

typedef short MsgNo;

struct variable {
    char *name;
    unsigned  is_used:1;   /* Some variables are disabled */
    unsigned  been_written:1;
    unsigned  is_user:1;
  /*unsigned  is_group:1; */
    unsigned  is_global:1;
    char     *current_val;
    char     *user_val;
  /*char     *group_val;*/
    char     *global_val;
    char     *description;
};


typedef enum {ShowAll, ShowParts, ShowNone} MimeShow;

struct attachment {
    char           *description;
    BODY           *body;
    unsigned int    can_display:1;
    unsigned int    shown:1;
    MimeShow        show;
    char            number[20];
    char            size[25];
};


typedef enum {SortDate, SortArrival, SortFrom, SortSubject,
                SortTo, SortCc, SortSize, EndofList}   SortOrder;
typedef enum {Sapling, Seedling, Seasoned} FeatureLevel;
/*----------------------------------------------------------------------
   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 is soon as you see a reference to the structure
you know it sort of 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 couple more loosely one day.
 ----*/
  
struct pine {
    /*-- see the loop at the end of main() for how these are used --*/
    void       (*next_screen)();   /* NULL means stay in current screen */
    void       (*prev_screen)();
    void       (*redrawer)();

    char        *return_string;
    char        *error_message;

    char         inbox_name[MAXFOLDER+1];
    MAILSTREAM  *inbox_stream;
    long         inbox_sorted_msgno;/* These counters only are changed if the*/
    long         inbox_max_msgno;  /* current folder is *not* the inbox      */
    long         inbox_new_mail_count;
    long         inbox_expunge_count;
    int          inbox_changed;
    
    MAILSTREAM  *mail_stream;
    long         current_sorted_msgno;
    long         new_current_sorted_msgno;
    long         max_msgno;
    long         new_mail_count;
    long         expunge_count;
    int          mail_box_changed;
    long         top_of_screen_sorted_msgno;
    char         cur_folder[MAXFOLDER+1];
    char         last_folder[MAXFOLDER+1];
    struct attachment
                *atmts;
    int          atmts_allocated;

    long        *sort;
    long         sort_allocated;

    char        *folders_dir;
    char        *signature_file;
    FeatureLevel feature_level;
    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     scroll_text_changed:1; /* */
    unsigned     status_changed:1;  /* Let function above know status changed*/
    unsigned     elm_style_save:1;   /* Default save folder to the
                                                   message originator */
    unsigned     header_in_reply:1;  /* Show full header in reply inclusion */
    unsigned     show_folders_dir:1;  /* show folders dir path when showing
                                                 folder names */
    unsigned     io_error_on_stream:1; /* last write on mail_stream failed */
    unsigned     restricted:1;
    unsigned     reverse_sort:1;
    unsigned     current_reverse_sort:1;
    unsigned     nr_mode:1;
    unsigned     full_header:1;
    unsigned     use_full_hostname:1; /* Use full hostname vs just domain */
    unsigned     low_speed:1;         /* Special screen painting 4 low speed */
    unsigned     dead_inbox:1;
    unsigned     dead_stream:1;
    unsigned     noticed_dead_inbox:1;
    unsigned     noticed_dead_stream:1;
    unsigned     compose_mime:1;
    unsigned     show_all_characters:1;
    unsigned     show_new_version:1;
    unsigned     do_local_lookup;  /* look up in passwd even if using
                                           user defined domain */

    /*--- Command line flags, modify only on start up ---*/
    unsigned     can_suspend:1;
    unsigned     use_fkeys:1;
    unsigned     start_in_index:1;

    unsigned     noshow_error:1;

    unsigned     start_entry;

    char         painted_on_startup;

    char         c_client_error[300];  /* when nowhow_error is set and PARSE */

    struct ttyo *ttyo;

    char        *passwd,         /* Encrypted login passwd for keyboard lock */
                *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 */

#ifdef MATCH
    char       **display_header_fields,
               **address_header_fields;
#endif

    SortOrder    sort_order, current_sort_order,
                 sort_types[20];

    int          last_expire_year, last_expire_month;

    char         last_error[500];
    char         addr_field_buf[MAX_ADDR_FIELD+1];
                          /* Buffer for formatting whole address fields.
                             Used in a few different place so it's worth
                             sharing a buffer. No meausre prevent over flow
                             of this buffer.
                           */
    struct variable *vars;
};


struct outgoing_message {
    ADDRESS *to,
            *from,
            *cc,
            *bcc,
            *sender,
            *reply_to,
            *return_path;
    char    *date,
            *subject,
            *message_id,
            **optional_lines;
};


struct key_menu {
    short width;
    struct key {
       char *name;
       char *label;
       short column;
   } keys[12];
};


struct date {
    int  sec, minute, hour, day, month, year, hours_off_gmt, min_off_gmt, wkday;
    char zone_name[15];
};


typedef enum {OpenFolder, SaveMessage, FolderMaint, GetFcc} FolderFun;
typedef enum {FolderName, MessageNumber, TextPercent, PageNumber} TitleBarType;
typedef enum {ComposerHelpText, HelpText, NewsText, MessageText, WhoText,
                NetNewsText} TextType;
typedef enum {GoodTime, BadTime, VeryBadTime} CheckPointTime;
typedef enum {IsText, IsText8, IsBinary} FileTypes;
typedef enum {AppendMessage, AppendFcc, AppendPostpone,
                AppendInterrupted, AppendSendmail} AppendTypes;


/*======================================================================
    Declarations of all the Pine functions.
 ====*/
  
#ifdef ANSI

/*-- standard libraries --*/
FILE *popen(const char *, const char *);

/*-- addrbook.c --*/
char        *addr_book(int);
void         addr_book_screen();
char        *addr_lookup(char *);
int          addr_add(char *, char *, char *);
/*AdrBk       *get_adrbk(); */

/*-- addrutil.c --*/
int  build_address(char *, char *, char **);
char *addr_list_string(ADDRESS *);
char *addr_string(ADDRESS *);
int   addr_is_us(ADDRESS *);

/*-- args.c --*/
char *pine_args(struct pine *, char **);

/*--- folder.c ---*/
void folder_screen();
int  folder_lister(struct pine *, FolderFun, char *);
void folder_screen();
char *pretty_fn(char *);
int  folder_exists(char *, char *);
void add_up_disk_usage(char *, int *, long *);
char *pretty_fn(char *);
int  folders_for_fcc(char *);

/*-- help.c --*/
void helper(char *text[], char *title, int); 
void print_all_help();

/*-- init.c --*/
void init_vars(struct pine *);
char *expand_variables(char *, char *);
int  init_username(struct pine *);  
int  init_hostname(struct pine *);  
int  write_pinerc(struct pine *);
void dump_global_conf();
int  set_variable(int, char *);
int  init_mail_dir(char *); 
int  expire_sent_mail();
#ifdef DEBUG
void init_debug();
#endif

/*---- mailcmd.c ----*/
int append_message(char *, char *, char *, char *, long *, long, long, char *);
int process_cmd(int, int, int);
int save_msg(int, MESSAGECACHE *, int *, long);
int grab_addr_cmd(MESSAGECACHE *, int);
long jump_to(int);
char *broach_folder(int, int);
int do_broach_folder(char *);
void expunge_and_close(MAILSTREAM *, char *);
int  export_message(int, long);
int  print_messag(int);
int  process_cmd(int, int, int);
long search_headers(int, long, long);

/*--- mailindex.c ---*/
void  mail_index_screen();
void  clear_index_cache();
void  clear_index_cache_ent(int);
char *build_header_line(long, int);
void  redraw_index_body();
void  do_index_border(int, int, int);
char *sort_name(SortOrder);


/*--- mailview.c ---*/
void mail_view_screen();
int  match_fields(char *, char **);
void scrolltool(char **,char *,char *,char **,char **,char *,int *,TextType);
void end_scroll_text();
void format_scroll_text();
int  get_scroll_text_lines();
void  redraw_scroll_text();
void  scroll_scroll_text(int, int);
int   search_scroll_text(int, char *);
int   search_text(int, int);
void  set_scroll_text(char **, char *, char *, char **, char **,int, int, int);
void  rich2plain(char *, int, int);
char *body_type_names(int);
char *type_desc(int, char *, PARAMETER *, int);
char *format_envelope();
char *format_message(MESSAGECACHE *, int, int);



/*--newmail.c --*/
long new_mail(int *, int, int);
int  check_point(int, CheckPointTime);
void reset_check_point();
void zero_new_mail_count();

/*-- os.c --*/
int can_access(char *, int);
long file_size(char *);
int is_writable_dir(char *);
int create_mail_dir(char *);
int create_folder(char *, char *);
int rename_file(char *, char *);
void build_path(char *, char *, char *);
char *last_cmpnt(char *);
int   expand_filename(char *);
char *fnexpand(char *, int);
char *filter_filename(char *);
int   disk_space(char *);
long  disk_quota(char *, int *);
int   simple_opendir(char *);
char *simple_readdir();
void  simple_closedir();
void  coredump();
void  getdomainnames(char *, int, char *, int);
int   have_job_control();
int   stop_process();
char *error_name(int);
char *error_description(int);
char *get_system_login();
char *get_system_fullname();
char *get_system_homedir();
char *get_system_passwd();
char *local_name_lookup(char *);
int   change_passwd();

/*--- other.c ---*/
void other_screen();
int  lock_keyboard();

/*-- pine.c --*/
void main_menu_screen(struct pine *);
void news_screen(struct pine *);
void quit_screen(struct pine *);
int  count_deleted(MAILSTREAM *);
void who_screen(struct pine *);
void panic(char *);
void panic1(char *, char *);

/*-- print.c --*/
int  open_printer(char *);
void close_printer();
void print_char(int);
void print_text(char *);
void print_text1(char *, char *);
void print_text2(char *, char *, char *);
void print_text3(char *, char *, char *, char *);
     
/*-- reply.c --*/
void  reply(struct pine *, MESSAGECACHE *);
void  forward(struct pine *, MESSAGECACHE *);
char *generate_message_id(struct pine *);
char *pretty_addr_string(char *, ADDRESS *, char *);
PARAMETER *copy_parameters(PARAMETER *);

/*-- screen.c --*/
void output_keymenu(struct key_menu *, int, int);
void format_keymenu(struct key_menu *, int);
void blank_keymenu(int, int);
void redraw_keymenu();
char *status_string(MESSAGECACHE *);
char *set_titlebar(char *, int, TitleBarType, long, int, int);
void redraw_titlebar();
void update_titlebar_message(int);
void update_titlebar_percent(int);
void update_titlebar_page(int);
int  update_del(int, int);

/*-- send.c --*/
void  compose_screen(struct pine *); 
void  pine_send(ENVELOPE *, BODY **, char *, char *, int, void *, int);
void  compose_mail(char *);
int   append_message2(char *, ENVELOPE *, BODY *, char *, long *,
                     AppendTypes, int, int, int, long, char *, void *, char *);

/*-- signals.c --*/
void init_signals(); 
void do_suspend(struct pine *);
void end_signals();
SigType hup_signal();

/*-- status.c --*/
void display_message(int);
int messages_queued();
void d_q_status_message();
void q_status_message( int, int, int, char *);
void q_status_message1(int, int, int, char *, void *);
void q_status_message2(int, int, int, char *, void *, void *);
void q_status_message3(int, int, int, char *, void *, void *, void *);
void q_status_message4(int, int, int, char *, void *, void *, void *, void *);
void q_status_message7(int, int, int, char *, void *, void *, void *, void *,
                       void *, void *, void *);
void flush_status_messages();
void mark_status_dirty();
int want_to(char *, int, char **, int);
int want_to2(char *, int, int, int, char **, int);
int radio_buttons(char *, int, int, char *, char **, int, char **, int);


/*-- strings.c --*/
char *rplstr(char *, int, char *);
void sqzspaces(char *);
void removing_trailing_white_space(char *);
void removing_leading_white_space(char *);
int strucmp(char *, char *);
int struncmp(char *, char *, int);
char *srchstr(char *, char *);
char *strindex(char *, int);
char *strrindex(char *, int);
char *strcat_nocr(char *, char *);
void crlf2lf(char *);
char *month_abbrev(int);
char *week_abbrev(int);
int   month_num(char *);
void  parse_date(char *, struct date *);
int   compare_dated(struct date *, struct date *);
void  convert_to_gmt(struct date *);
char *pretty_command(int);
char *repeat_char(int, int);
char *temp_file_name(char *, char *);
char *comatose(long);
char *byte_string(long);
char *enth_string(int);
char *long2string(long);
char *int2string(int);
char *rfc822date_to_ctime(char *);
char *lf2crlf(char *);

/*-- ttyin.c--*/
int read_char(int);
int read_command();
int optionally_enter(char *,int,int,int,int,int,char *, char *, char **, int);
int init_tty_driver(struct pine *);
void end_tty_driver(struct pine *);
int Raw(int);
void end_keyboard(int);
void init_keyboard(int);
int validatekeys(int);

/*-- ttyout.c --*/
void get_windsize(struct ttyo *);
int BeginScroll(int, int);
void EndScroll();
int  ScrollRegion( int);
int  Writechar(int, int);
void Write_to_screen(char *);
void PutLine0(int, int, char *);
void PutLine0n8b(int, int, int, char *, int);
void PutLine1(int, int, char *, char *);
void PutLine2(int, int, char *, char *, char *);
void PutLine3(int, int, char *, char *, char *, char *);
void PutLine4(int, int, char *, char *, char *, char *, char *);
void PutLine5(int, int, char *, char *, char *, char *, char *, char *);
int  CenterLine(int, char *);
void Stripe0(int, int, int,  char *);
void Stripe3(int, int, int, char *, char *, char *, char *);
void CleartoEOLN();
int  CleartoEOS();
void ClearScreen();
void MoveCursor(int, int);
void NewLine();
void StartInverse();
void EndInverse();
void StartUnderline();
void EndUnderline();
void StartBold();
void EndBold();
int  config_screen(struct ttyo **);
void init_screen();
void end_screen();
void outchar(int);
void clear_cursor_pos();
int  InsertChar(int);
int  DeleteChar(int);


/*-- IMAP left out of mail.h --*/
void     rfc822_parse_adrlist(ADDRESS **, char *, char *);
ADDRESS *rfc822_cpy_adr(ADDRESS *);
void     rfc822_write_address(char *, ADDRESS *);
void     rfc822_parse_msg(ENVELOPE **, BODY **, char *, int, char *, int,
                          char *, char *);
void     rfc822_date(char *);
void     rfc822_header(char *, ENVELOPE *, BODY *);

char *cpystr(char *);
char *read_file(char *);
/*----------------------------------------
    These routines map to malloc(), free() and realloc(). They are used
 because they check to be sure malloc didn't return NULL. fs_give() takes
 a pointer to a pointer because it zeros the pointer to the space freed.
 fs_resize assumes you want the new storage in the same variable. These
 are in osdep.c as part of the imap client. They call fatal() with a string
 if malloc fails.
  -------*/
#ifndef MEMLOG
void *fs_get(int);
void fs_give(void **);
void fs_resize(void **, int);
#endif

#define SCREEN_FUN_NULL ((void (*) (void *))NULL)

#else

/*-- addrbook.c --*/
char        *addr_book();
void         addr_book_screen();
char        *addr_lookup();
int          addr_add();
/*AdrBk       *get_adrbk(); */

/*-- addrutil.c --*/
int  build_address();
char *addr_list_string();
char *addr_string();
int   addr_is_us();

/*-- args.c --*/
char *pine_args();

/*--- folder.c ---*/
void folder_screen();
int  folder_lister();
void folder_screen();
char *pretty_fn();
int  folder_exists();
void add_up_disk_usage();
char *pretty_fn();
int  folders_for_fcc();

/*-- help.c --*/
void helper(); 
void print_all_help();

/*-- init.c --*/
void init_vars();
char *expand_variables();
int  init_username();  
int  init_hostname();  
int  write_pinerc();
void dump_global_conf();
int  set_variable();
int  init_mail_dir(); 
int  expire_sent_mail();
#ifdef DEBUG
void init_debug();
#endif

/*---- mailcmd.c ----*/
#ifdef NEVER_X
int append_message();
#endif
int process_cmd();
int save_msg();
int grab_addr_cmd();
long jump_to();
char *broach_folder();
int do_broach_folder();
void expunge_and_close();
int  export_message();
int  print_messag();
int  process_cmd();
int  save_msg();
long search_headers();


/*--- mailindex.c ---*/
void  mail_index_screen();
char *build_header_line();
void  clear_index_cache();
void  clear_index_cache_ent();
char *build_header_line();
void  redraw_index_body();
void  do_index_border();
char *sort_name();


/*--- mailview.c ---*/
void mail_view_screen();
int  match_fields();
void scrolltool();
void end_scroll_text();
void format_scroll_text();
int  get_scroll_text_lines();
void  redraw_scroll_text();
void  scroll_scroll_text();
int   search_scroll_text();
int   search_text();
void  set_scroll_text();
void  rich2plain();
char *body_type_names();
char *type_desc();
char *format_envelope();
char *format_message();


/*--newmail.c --*/
long new_mail();
int check_point();
void reset_check_point();
void zero_new_mail_count();

/*-- os.c --*/
int can_access();
long file_size();
int is_writable_dir();
int create_mail_dir();
int create_folder();
int rename_file();
void build_path();
char *last_cmpnt();
int expand_filename();
char *fnexpand();
char *filter_filename();
int disk_space();
long disk_quota();
int  simple_opendir();
char *simple_readdir();
void  simple_closedir();
void coredump();
void getdomainnames();
int  have_job_control();
int stop_process();
char *error_name();
char *error_description();
char *get_system_login();
char *get_system_fullname();
char *get_system_homedir();
char *get_system_passwd();
char *local_name_lookup();
int change_passwd();

/*--- other.c ---*/
void other_screen();
int  lock_keyboard();

/*-- pine.c --*/
void main_menu_screen();
void news_screen();
void quit_screen();
int  count_deleted();
void who_screen();
void panic();
void panic1();

/*-- print.c --*/
int  open_printer();
void close_printer();
void print_char();
void print_text();
void print_text1();
void print_text2();
void print_text3();
     
/*-- reply.c --*/
void  reply();
void  forward();
char *generate_message_id();
char *pretty_addr_string();
PARAMETER *copy_parameters();

/*-- screen.c --*/
void output_keymenu();
void format_keymenu();
void blank_keymenu();
void redraw_keymenu();
char *status_string();
char *set_titlebar();
void redraw_titlebar();
void update_titlebar_message();
void update_titlebar_percent();
void update_titlebar_page();
int  update_del();

/*-- send.c --*/
void  compose_screen(); 
void  pine_send();
void  compose_mail();

/*-- signals.c --*/
void init_signals(); 
void do_suspend();
void end_signals();
SigType hup_signal();

/*-- status.c --*/
void display_message();
int messages_queued();
void d_q_status_message();
void q_status_message();
void q_status_message1();
void q_status_message2();
void q_status_message3();
void q_status_message4();
void q_status_message7();
void flush_status_messages();
void mark_status_dirty();
int want_to();
int want_to2();
int radio_buttons();

/*-- strings.c --*/
char *rplstr();
void sqzspaces();
void removing_trailing_white_space();
void removing_leading_white_space();
int strucmp();
int struncmp();
char *srchstr();
char *strindex();
char *strrindex();
char *strcat_nocr();
void crlf2lf();
char *month_abbrev();
char *week_abbrev();
int   month_num();
char *pretty_command();
char *repeat_char();
char *temp_file_name();
char *comatose();
char *byte_string();
char *enth_string();
char *long2string();
char *int2string();
char *rfc822date_to_ctime();
char *lf2crlf();

/*-- ttyin.c--*/
int read_char();
int read_command();
int optionally_enter();
int init_tty_driver();
void end_tty_driver();
int Raw();
void end_keyboard();
void init_keyboard();
int validatekeys();

/*-- ttyout.c --*/
void get_windsize();
int BeginScroll();
void EndScroll();
int  ScrollRegion();
int  Writechar();
void Write_to_screen();
void PutLine0();
void PutLine0n8b();
void PutLine1();
void PutLine2();
void PutLine3();
void PutLine4();
void PutLine5();
int  CenterLine();
void Stripe0();
void Stripe3();
void CleartoEOLN();
int  CleartoEOS();
void ClearScreen();
void MoveCursor();
void NewLine();
void StartInverse();
void EndInverse();
void StartUnderline();
void EndUnderline();
void StartBold();
void EndBold();
int  config_screen();
void init_screen();
void end_screen();
void outchar();
void clear_cursor_pos();
int  InsertChar();
int  DeleteChar();




/*-- IMAP left out of mail.h --*/
void rfc822_parse_adrlist();
ADDRESS *rfc822_cpy_adr();
void     rfc822_write_address();
void     rfc822_parse_msg();
void     rfc822_date();
void     rfc822_header();


/*----- our own various library things, some from imap, other from ../lib --*/
char *cpystr();
char *srchstr();
char *read_file();
int strucmp();
int struncmp();

/*----------------------------------------
    These routines map to malloc(), free() and realloc(). They are used
 because they check to be sure malloc didn't return NULL. fs_give() takes
 a pointer to a pointer because it zeros the pointer to the space freed.
 fs_resize assumes you want the new storage in the same variable. These
 are in osdep.c as part of the imap client. They call fatal() with a string
 if malloc fails.
  -------*/
#if defined(DYN) || defined(S53)
char *fs_get();
#else
void *fs_get();
#endif
void fs_give();
void fs_resize(); 

/*-- Standard system libraries that got missed in standard include files ---*/
FILE *popen();

#define SCREEN_FUN_NULL ((void (*) ())NULL)

#endif






