/* 
 * w3m: WWW wo Miru utility
 * 
 * by A.ITO  Feb. 1995
 * 
 * You can use,copy,modify and distribute this program without any permission.
 */

#ifndef FM_H
#define FM_H

#ifndef _GNU_SOURCE
#define _GNU_SOURCE	/* strcasestr() */
#endif /* not defined(_GNU_SOURCE) */

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <limits.h>
#include <sys/stat.h>
#ifndef PIPE_BUF
#ifdef _POSIX_PIPE_BUF
#define PIPE_BUF (_POSIX_PIPE_BUF)
#else
#define PIPE_BUF (512)
#endif
#endif
#include <btri.h>
#include "config.h"
#include "history.h"

#ifndef USE_MENU
#define USE_MENU
#endif

#ifdef USE_MENU
#define MENU_SELECT
#define MENU_MAP
#endif				/* USE_MENU */

#ifndef USE_COLOR
#undef USE_ANSI_COLOR
#endif

#include "ctrlcode.h"
#ifdef HAVE_MOE
#include <mb.h>
#endif
#include "html.h"
#include "gc.h"
#include "Str.h"
#include "form.h"
#include "frame.h"
#include "parsetag.h"
#include "parsetagx.h"
#include "func.h"
#include "menu.h"
#include "textlist.h"
#include "funcname1.h"
#include "terms.h"
#include "regex.h"

#ifndef HAVE_BCOPY
void bcopy(const void *, void *, int);
void bzero(void *, int);
#endif				/* HAVE_BCOPY */
#ifdef __EMX__
#include <strings.h>	/* for bzero() and bcopy() */
#endif

#ifdef MAINPROGRAM
#define global
#define init(x) = x
#else				/* not MAINPROGRAM */
#define global extern
#define init(x)
#endif				/* not MAINPROGRAM */

#if LANG == JA

#define JP_CHARSET

#elif LANG == MANY

#define MANY_CHARSET

#ifdef LOCALE_DIR

#include <locale.h>
#include <libintl.h>

extern char *message_noconv(const char *message);
global char *(*message_conv)(const char *) init(message_noconv);
#define _(String) (message_conv((String)))
#define N_(String) (String)

#else

#define _(String) (String)
#define N_(String) (String)

#endif

typedef struct conv_Str_write_st {
    mb_info_t info;
    Str d;
} conv_Str_write_t;

typedef struct tty_char_conv_st {
    unsigned int *tab;
    mb_wchar_t *pool;
} tty_char_conv_t;

typedef struct process_charsets_st {
    struct process_charsets_st *prev;
    Regex *re;
    const char *cs;
} process_charsets_t;

#elif defined(LOCALE_DIR)

#include <locale.h>
#include <libintl.h>

#define _(String) (gettext((String)))
#define N_(String) (String)

#else

#define _(String) (String)
#define N_(String) (String)

#endif

#ifndef STARTUP_PAGE_TITLE
#define STARTUP_PAGE_TITLE "W3M startup page"
#endif

#ifndef FALLBACK_PAGE_TITLE
#define FALLBACK_PAGE_TITLE "W3M fallback page"
#endif

/* 
 * Constants.
 */
#define PAGER_MAX_LINE	10000	/* Maximum line kept as pager */
#define FNLEN 80

#ifdef USE_IMAGE
#define MAX_IMAGE_SIZE 2048
#define DEFAULT_PIXEL_PER_CHAR  7.0
#define DEFAULT_PIXEL_PER_LINE  14.0
#else
#define DEFAULT_PIXEL_PER_CHAR  8.0	/* arbitrary */
#define DEFAULT_PIXEL_PER_LINE  16.0	/* arbitrary */
#endif
#define MINIMUM_PIXEL_PER_CHAR  4.0
#define MAXIMUM_PIXEL_PER_CHAR  32.0

#ifdef FALSE
#undef FALSE
#endif

#ifdef TRUE
#undef TRUE
#endif

#define FALSE 0
#define TRUE   1

#define SHELLBUFFERNAME	"*Shellout*"
#define PIPEBUFFERNAME	"*stream*"
#define CPIPEBUFFERNAME	"*stream(closed)*"
#ifdef USE_DICT
#define DICTBUFFERNAME "*dictionary*"
#endif				/* USE_DICT */

/* 
 * Line Property
 */
/* Character type */
#define PC_ASCII	0x0000
#define PC_CTRL		0x2000

#ifdef JP_CHARSET
#define PC_KANJI1	0x4000
#define PC_KANJI2	0x8000
#define PC_KANJI	(PC_KANJI1|PC_KANJI2)
#define P_CHARTYPE	(PC_ASCII|PC_CTRL|PC_KANJI)
#else				/* ISO-8859-1 charset (not JP_CHARSET) */
#define P_CHARTYPE	(PC_ASCII|PC_CTRL)
#endif				/* not JP_CHARSET */
#if 0
#define GET_PCTYPE(c)   ((GET_MYCTYPE(c)&MYCTYPE_CNTRL)<<13)
#else
#define GET_PCTYPE(c)   ((GET_MYCTYPE(c)&MYCTYPE_CNTRL)?PC_CTRL:PC_ASCII)
#endif

#ifndef KANJI_SYMBOLS
#define PC_RULE         0x1000
#endif				/* not KANJI_SYMBOLS */

/* Effect ( standout/underline ) */
#define P_EFFECT	0x01ff
#define PE_NORMAL	0x00
#define PE_MARK		0x01
#define PE_UNDER	0x02
#define PE_STAND	0x04
#define PE_BOLD		0x08
#define PE_ANCHOR       0x10
#define PE_EMPH         0x08
#define PE_IMAGE        0x20
#define PE_FORM         0x40
#define PE_ACTIVE	0x80
#define PE_VISITED	0x0100

#define CharType(c)	((c)&P_CHARTYPE)
#ifdef KANJI_SYMBOLS
#define CharEffect(c)	((c)&P_EFFECT)
#else				/* not KANJI_SYMBOLS */
#define CharEffect(c)	((c)&(P_EFFECT|PC_RULE))
#endif				/* not KANJI_SYMBOLS */
#define SetCharType(v,c)	((v)=(((v)&~P_CHARTYPE)|(c)))


#define COLPOS(l,c)	calcPosition(l->lineBuf,l->propBuf,l->len,c,0,CP_AUTO)
#define IS_UNPRINTABLE_CONTROL(c,m) (CharType(m)==PC_CTRL&&(c)!=CTRL_I&&(c)!=CTRL_J)
#ifdef JP_CHARSET
#define IS_UNPRINTABLE_ASCII(c,m) (!IS_ASCII(c)&&CharType(m)==PC_ASCII)
#else
#define IS_UNPRINTABLE_ASCII(c,m) (!IS_LATIN1(c))
#endif

/* Flags for displayBuffer() */
enum {
    B_NORMAL,
    B_FORCE_REDRAW,
    B_REDRAW,
    B_SCROLL,
    B_REDRAW_IMAGE,
};

/* Buffer Property */
#define BP_NORMAL	0x0
#define BP_FRAMESET	0x1
#define BP_VISIBLE	0x2
#define BP_ON_VIEW	0x4
#define BP_INTERNAL	0x8
#define BP_NO_URL	0x10
#define BP_REDIRECTED   0x20
#define BP_PAGER        0x40
#define BP_ASYNC_MASK	0x180
#define BP_ASYNC_ABORT	0x080
#define BP_ASYNC_WAIT	0x100
#define BP_ASYNC_DONE	0x180
#define BP_ASYNC_STOP	(BP_ASYNC_DONE)
#define BP_ASYNC_GET(prop) ((prop) & BP_ASYNC_MASK)
#define BP_ASYNC_SET(old, prop) (((old) & ~BP_ASYNC_MASK) | BP_ASYNC_GET((prop)))
#define BP_LINKED	0x200
#define BP_DISCARDED	0x400
#define BP_LINKNUM_A	0x800
#define BP_LINKNUM_IMG	0x1000
#define BP_LINKNUM_MASK	(BP_LINKNUM_A | BP_LINKNUM_IMG)
#define BP_NOBUFFER	0x2000
#define BP_NONL		0x4000
#define BP_FOREVER	0x8000

/* Link Buffer */
#define LB_NOLINK	-1
#define LB_INFO		0	/* pginfo() */
#define LB_N_INFO	1
#define LB_SOURCE	2	/* vwSrc() */
#define LB_N_SOURCE	LB_SOURCE
#define MAX_LB		3

/* Search Result */
#define SR_FOUND	0x1
#define SR_NOTFOUND	0x2
#define SR_WRAPPED	0x4

#ifdef MAINPROGRAM
int REV_LB[MAX_LB] = {
    LB_N_INFO, LB_INFO, LB_N_SOURCE,
};
#else				/* not MAINPROGRAM */
extern int REV_LB[];
#endif				/* not MAINPROGRAM */

/* mark URL, Message-ID */
#define CHK_URL                1
#define CHK_NMID       2

/* Flags for calcPosition() */
#define CP_AUTO		0
#define CP_FORCE	1

/* Completion status. */
enum {
    CPL_OK,
    CPL_AMBIG,
    CPL_FAIL,
    CPL_MENU,
};

#define CPL_IMMUTABLE	(1U << 0)
#define CPL_OFF		(0U << 1)
#define CPL_ON		(1U << 1)
#define CPL_URL		(1U << 2)
#define CPL_COMMAND	(1U << 3)
#define CPL_WORDS	(1U << 4)
#define CPL_ALWAYS(mode) ((mode && (CPL_IMMUTABLE | CPL_ON)) == (CPL_IMMUTABLE | CPL_ON))

/* Flags for inputLine() */
#define IN_STRING	0x10
#define IN_FILENAME	0x20
#define IN_PASSWORD	0x40
#define IN_COMMAND	0x80
#define IN_URL		0x100
#define IN_CHAR		0x200
#define IN_CASE		0x400
#define IN_WORDS	0x800

/* Flags for mySystem() */
#define MYSYSTEM_BACKGROUND (1 << 0)
#define MYSYSTEM_NULLSTDIN (1 << 1)
#define MYSYSTEM_NULLSTDOUT (1 << 2)
#define MYSYSTEM_TTYSTDIN (1 << 3)
#define MYSYSTEM_TTYSTDOUT (1 << 4)

enum {
    IMG_FLAG_SKIP = 1,
    IMG_FLAG_AUTO,
    IMG_FLAG_FORCE,
};

enum {
    IMG_FLAG_UNLOADED,
    IMG_FLAG_LOADED,
    IMG_FLAG_ERROR,
    IMG_FLAG_FATAL_ERROR,
};

#ifndef IMG_ERROR_EXPIRE
#define IMG_ERROR_EXPIRE (180)
#endif

#ifndef IMG_ERROR_RETRY
#define IMG_ERROR_RETRY (3)
#endif

/* 
 * Macros.
 */

#define inputLineHist(p,d,f,h)	inputLineHistSearch(p,d,f,h,NULL)
#define inputLine(p,d,f)	inputLineHist(p,d,f,NULL)
#define inputStr(p,d)		inputLine(p,d,IN_STRING)
#define inputStrHist(p,d,h)	inputLineHist(p,d,IN_STRING,h)
#define inputStrHistTab(p,d,h,t)	inputLineHistTabSearch(p,d,IN_STRING,h,t,NULL)
#define inputWordsHistTab(p,d,h,t)	inputLineHistTabSearch(p,d,IN_STRING|IN_WORDS,h,t,NULL)
#define inputFilename(p,d)	inputLine(p,d,IN_FILENAME)
#define inputFilenameHist(p,d,h)	inputLineHist(p,d,IN_FILENAME,h)
#define inputChar(p)		inputLine(p,"",IN_CHAR)

#define free(x)  GC_free(x)	/* let GC do it. */

#ifdef __EMX__
#define HAVE_STRCASECMP
#define strcasecmp	stricmp
#define strncasecmp	strnicmp
#endif				/* __EMX__ */


#define SKIP_BLANKS(p) {while(*(p)&&IS_SPACE(*(p)))(p)++;}
#define SKIP_NON_BLANKS(p) {while(*(p)&&!IS_SPACE(*(p)))(p)++;}
#define IS_ENDL(c) ((c)=='\0'||(c)=='\r'||(c)=='\n')
#define IS_ENDT(c) (IS_ENDL(c)||(c)==';')

#define bpcmp(a,b) \
  (((a).line - (b).line) ? ((a).line - (b).line) : ((a).pos - (b).pos))

#define RELATIVE_WIDTH(w)   (((w)>=0)?(int)((w)/pixel_per_char):(w))
#define REAL_WIDTH(w,limit) (((w)>=0)?(int)((w)/pixel_per_char):(-(w))*(limit)/100)

#ifdef KANJI_SYMBOLS
#ifdef MANY_CHARSET
extern int RULE_WIDTH;
#else
#define RULE_WIDTH 2
#endif
#else				/* not KANJI_SYMBOLS */
#define RULE_WIDTH 1
#endif				/* not KANJI_SYMBOLS */

#define EOL(l) (&(l)->ptr[(l)->length])
#define IS_EOL(p,l) ((p)==&(l)->ptr[(l)->length])

/* 
 * Types.
 */

typedef unsigned short Lineprop;
#ifdef USE_ANSI_COLOR
typedef unsigned char Linecolor;
#endif

#define CHECKTYPE_EOL (1U << 0)
#define CHECKTYPE_NL (1U << 1)

#ifndef FOREVER_INTERVAL
#define FOREVER_INTERVAL (1)
#endif

typedef struct _CheckTypeEnv {
    char *from, *from_end, *to_beg, *to;
    int eol_p, col, width, to_size, logi_lno, logi_len, prev_len;
    Lineprop *to_prop_beg, *to_prop, effect;
#ifdef USE_ANSI_COLOR
    int use_color;
    Linecolor *to_color_beg, *to_color, cmode;
    Lineprop ceffect;
#endif
} CheckTypeEnv;

typedef struct _MapArea {
    char *url;
    char *target;
    char *alt;
#ifdef USE_IMAGE
    char shape;
    short *coords;
    int ncoords;
    short center_x;
    short center_y;
#endif
} MapArea;

typedef struct _MapList {
    Str name;
    GeneralList *area;
    struct _MapList *next;
} MapList;

typedef struct _Line {
    char *lineBuf;
    Lineprop *propBuf;
#ifdef USE_ANSI_COLOR
    Linecolor *colorBuf;
#endif
    struct _Line *next;
    struct _Line *prev;
    int len;
    int width;
    long linenumber;		/* on buffer */
    long real_linenumber;	/* on file */
    unsigned short usrflags;
#if defined(USE_MENU) && defined(USE_MENU_BUFFER)
    struct _MenuItem *menu_item;
#endif
} Line;

typedef struct {
    int line;
    int pos;
} BufferPoint;

typedef struct _Href {
    char *url, *target, *referer;
    int hseq;
} Href;

#ifdef USE_IMAGE
typedef struct _imageCache {
    char *url;
    ParsedURL *current;
    char *file;
    char loaded;
    char displayed;
    int index;
    short width;
    short height;
    long time;
    int retry;
} ImageCache;
#endif

typedef struct _image {
    int hseq;
    char *url;
#ifdef USE_IMAGE
    char *ext;
    short width;
    short height;
    short xoffset;
    short yoffset;
    short y;
    short rows;
    char *map;
    char ismap;
    ImageCache *cache;
#endif
} Image;

typedef union _anchorlink {
    Href *href;
    Image *img;
    struct form_item_list *fi;
    char *id;
} AnchorLink;

typedef struct _AnchorKey {
    char s[sizeof(int) * 2];
} AnchorKey;

typedef struct _anchor {
    int hseq;
    BufferPoint start;
    BufferPoint end;
    AnchorLink *link;
} Anchor;

global char NO_REFERER[] init("[ NO REFERER ]");

typedef struct _anchorList {
    btri_string_tab_t *anchors;
    void *urls;
    AnchorLink *alv;
    int nlink, nlink_max;
} AnchorList;

typedef struct _BufferPointLink {
    BufferPoint origin, po, corner;
    int prev, next;
} BufferPointLink;

typedef struct {
    BufferPointLink *marks;
    int nmark;
    int markmax;
    int prevhseq;
    int firstseq, lastseq;
} HmarkerList;

typedef struct {
    int *v;
    int n, n_max, last;
} SeqMap;

#define BV_LINKED (1U << 0)

typedef struct _BufferViewList {
    struct _BufferView *top, *bot;
} BufferViewList;

typedef struct _BufferView {
    struct _BufferView *root, *sup, *up, *down, **cviewv;
    BufferViewList *subv;
    unsigned char flag;
#ifdef USE_IMAGE
    unsigned char draw_image_flag;
#endif
    short x, y, ncols, nrows, *colv, *rowv;
    short rootX, rootY, width, height, ccolumn;
    struct _Buffer *top, *bot;
    Line *cline, *cbot;
    struct frameset *frameset;
} BufferView;

#define BV_LINKED (1U << 0)

typedef struct _Buffer {
    char *filename;
    char *buffername;
    Line *firstLine;
    Line *topLine;
    Line *currentLine;
    Line *lastLine;
    struct _Buffer *prev, *next, *posHist, *up, *down;
    struct _Buffer *linkBuffer[MAX_LB];
    BufferView *view;
    short lmargin, rmargin;
    char *type;
    char *real_type;
    int allLine;
    int bufferprop;
    int currentColumn;
    short cursorX, cursorY;
    int pos;
    int visualpos;
    struct _AsyncRWBuf *async_buf;
    TextList *events;
    SeqMap hseqmap, iseqmap;
    AnchorList *href;
    AnchorList *name;
    AnchorList *img;
    AnchorList *formitem;
    MapList *maplist;
    HmarkerList *hmarklist;
    HmarkerList *imarklist;
    ParsedURL currentURL;
    ParsedURL *baseURL;
    char *baseTarget;
    int real_scheme;
    char *sourcefile;
    struct frameset *frameset;
    clen_t linelen;
    clen_t trbyte;
    char check_url;
#ifdef MANY_CHARSET
    const char *document_charset;
    const char *document_encoding;
#else
#ifdef JP_CHARSET
    char document_code;
    char document_encoding;
#endif				/* JP_CHARSET */
#endif
    TextList *document_header;
    btri_string_tab_t *document_header_table;
    FormItemList *form_submit;
    char *savecache;
    char *saveindex;
    struct mailcap *mailcap;
    char search_header;
    char *boundary, *name_by_header;
#ifdef USE_SSL
    char *ssl_certificate;
#endif
#ifdef USE_IMAGE
    char image_flag;
    char image_unloaded;
#endif
    char redraw_mode;
    char reshape_failure;
    char need_reshape;
    char http_request_method;
    int http_response_code;
#if defined(USE_MENU) && defined(USE_MENU_BUFFER)
    struct _Menu *menu;
#endif
} Buffer;

#define COPY_BUFPOSITION(dstbuf, srcbuf) {\
 (dstbuf)->topLine = (srcbuf)->topLine; \
 (dstbuf)->currentLine = (srcbuf)->currentLine; \
 (dstbuf)->pos = (srcbuf)->pos; \
 (dstbuf)->cursorX = (srcbuf)->cursorX; \
 (dstbuf)->cursorY = (srcbuf)->cursorY; \
 (dstbuf)->visualpos = (srcbuf)->visualpos; \
 (dstbuf)->currentColumn = (srcbuf)->currentColumn; \
}
#define SAVE_BUFPOSITION(sbufp) COPY_BUFPOSITION(sbufp, Currentbuf)
#if defined(USE_MENU) && defined(USE_MENU_BUFFER)
#define RESTORE_BUFPOSITION(sbufp) { \
  Line *RESTORE_BUFPOSITION_old_current_line; \
  RESTORE_BUFPOSITION_old_current_line = Currentbuf->currentLine; \
  COPY_BUFPOSITION(Currentbuf, sbufp); \
  select_menu_line(Currentbuf, RESTORE_BUFPOSITION_old_current_line); \
}
#else
#define RESTORE_BUFPOSITION(sbufp) COPY_BUFPOSITION(Currentbuf, sbufp)
#endif
#define TOP_LINENUMBER(buf) ((buf)->topLine ? (buf)->topLine->linenumber : 1)
#define CUR_LINENUMBER(buf) ((buf)->currentLine ? (buf)->currentLine->linenumber : 1)

#define NO_BUFFER ((Buffer*)1)

#define RB_STACK_SIZE 10

#define TAG_STACK_SIZE 10

#define FONT_STACK_SIZE 5

#define FONTSTAT_SIZE 4

#define INIT_BUFFER_WIDTH (COLS)

typedef struct {
    int pos;
    int len;
    int tlen;
    long flag;
    Str anchor;
    Str anchor_target;
    short anchor_hseq;
    Str img_alt;
    char fontstat[FONTSTAT_SIZE];
    short nobr_level;
    Lineprop prev_ctype;
    char init_flag;
    short top_margin;
    short bottom_margin;
} Breakpoint;

struct readbuffer {
    Str tokbuf, line;
    Lineprop cprop;
    int pos;
    int prevchar;
#ifdef MANY_CHARSET
    int prev_ns_char;
#endif
    long flag;
    long flag_stack[RB_STACK_SIZE];
    int flag_sp;
    int status;
    Str ignore_tag;
    short table_level;
    short nobr_level;
    Str anchor;
    Str anchor_target;
    short anchor_hseq;
    Str img_alt;
    char fontstat[FONTSTAT_SIZE];
    char fontstat_stack[FONT_STACK_SIZE][FONTSTAT_SIZE];
    int fontstat_sp;
    Lineprop prev_ctype;
    Breakpoint bp;
    struct cmdtable *tag_stack[TAG_STACK_SIZE];
    int tag_sp;
    short top_margin;
    short bottom_margin;
    struct _Phase1Env *p1env;
};

#define in_bold fontstat[0]
#define in_under fontstat[1]
#define in_stand fontstat[2]

#define RB_PRE		0x01
#define RB_XMPMODE	0x02
#define RB_LSTMODE	0x04
#define RB_PLAIN	0x08
#define RB_NOALIGN	0x00
#define RB_CENTER	0x10
#define RB_RIGHT	0x20
#define RB_LEFT		0x30
#define RB_ALIGN	0x30
#define RB_NOBR		0x40
#define RB_P		0x80
#define RB_PRE_INT	0x100
#define RB_PREMODE	(RB_PRE | RB_PRE_INT)
#define RB_SPECIAL	(RB_PRE|RB_XMPMODE|RB_LSTMODE|RB_PLAIN|RB_NOBR|RB_PRE_INT)
#define RB_PLAINMODE	(RB_XMPMODE|RB_LSTMODE|RB_PLAIN)

#define RB_IN_DT	0x200
#define RB_INTXTA	0x400
#define RB_INSELECT	0x800
#define RB_IGNORE	0x1000
#define RB_INSEL	0x2000
#define RB_IGNORE_P	0x4000
#define RB_TITLE	0x8000
#define RB_NFLUSHED	0x10000
#define RB_NOFRAMES	0x20000
#define RB_DIV_INT	0x40000

#ifdef FORMAT_NICE
#define RB_FILL		0x200000
#endif				/* FORMAT_NICE */

#define RB_GET_ALIGN(obuf) ((obuf)->flag&RB_ALIGN)
#define RB_SET_ALIGN(obuf,align) {(obuf)->flag &= ~RB_ALIGN; (obuf)->flag |= (align); }
#define RB_SAVE_FLAG(obuf) { \
    if ((obuf)->flag_sp < RB_STACK_SIZE) \
	(obuf)->flag_stack[(obuf)->flag_sp++] = RB_GET_ALIGN(obuf); \
}
#define RB_RESTORE_FLAG(obuf) { \
    if ((obuf)->flag_sp > 0) \
	RB_SET_ALIGN(obuf,(obuf)->flag_stack[--(obuf)->flag_sp]); \
}

/* status flags */
enum {
    R_ST_NORMAL,	/* normal */
    R_ST_TAG0,	/* within tag, just after < */
    R_ST_TAG,	/* within tag */
    R_ST_QUOTE,	/* within single quote */
    R_ST_DQUOTE,	/* within double quote */
    R_ST_EQL,	/* = */
    R_ST_AMP,	/* within ampersand quote */
    R_ST_CMNT1,	/* <!  */
    R_ST_CMNT2,	/* <!- */
    R_ST_CMNT,	/* within comment */
    R_ST_NCMNT1,	/* comment - */
    R_ST_NCMNT2,	/* comment -- */
    R_ST_NCMNT3,	/* comment -- space */
    R_ST_IRRTAG,	/* within irregular tag */
};

#define ST_IS_REAL_TAG(s)   ((s)==R_ST_TAG||(s)==R_ST_TAG0||(s)==R_ST_EQL)
#define ST_IS_COMMENT(s)    ((s)>=R_ST_CMNT1)
#define ST_IS_TAG(s)        ((s)!=R_ST_NORMAL&&(s)!=R_ST_AMP&&!ST_IS_COMMENT(s))

/* is this '<' really means the beginning of a tag? */
#define REALLY_THE_BEGINNING_OF_A_TAG(p) \
	  (IS_ALPHA(p[1]) || p[1] == '/' || p[1] == '!' || p[1] == '?' || p[1] == '_')

/* processing mode of HTMLlineproc0 */
#define HLP_INTERNAL (1 << 0)
#define HLP_EOL (1 << 1)

/* read_token flag */
#define RT_PRE (1 << 0)
#define RT_OLDPRE (1 << 1)
#define RT_APPEND (1 << 2)
#define RT_WANTAMP (1 << 3)
#define RT_EOL (1 << 4)

/* flags for loadGeneralFile */
#define RG_NOCACHE   (1 << 0)
#define RG_PROC_POS (1)
#define RG_PROC_MASK_LEN (2)
#define RG_PROC_MASK (~(~0 << RG_PROC_MASK_LEN) << RG_PROC_POS)
#define RG_PROC_FORK (1 << RG_PROC_POS)
#define RG_PROC_SUP (2 << RG_PROC_POS)
#define RG_PROC_SUB (3 << RG_PROC_POS)
#define RG_HALFDUMP_POS (RG_PROC_POS + RG_PROC_MASK_LEN)
#define RG_HALFDUMP_OUT_POS (RG_HALFDUMP_POS)
#define RG_HALFDUMP_OUT_MASK_LEN (2)
#define RG_HALFDUMP_OUT_MASK ((~(~0 << RG_HALFDUMP_OUT_MASK_LEN)) << RG_HALFDUMP_OUT_POS)
#define RG_HALFDUMP_OUT_PERLINE (1 << RG_HALFDUMP_OUT_POS)
#define RG_HALFDUMP_OUT_SAVEBUF (2 << RG_HALFDUMP_OUT_POS)
#define RG_HALFDUMP_CODECONV (1 << (RG_HALFDUMP_OUT_POS + RG_HALFDUMP_OUT_MASK_LEN))
#define RG_HALFDUMP_BUFFER (1 << (RG_HALFDUMP_OUT_POS + RG_HALFDUMP_OUT_MASK_LEN + 1))
#define RG_HALFDUMP_MASK (RG_HALFDUMP_OUT_MASK | RG_HALFDUMP_CODECONV | RG_HALFDUMP_BUFFER)
#define RG_DUMP_POS (RG_HALFDUMP_OUT_POS + RG_HALFDUMP_OUT_MASK_LEN + 2)
#define RG_DUMP_HEAD (1 << RG_DUMP_POS)
#define RG_DUMP_FRAME (1 << (RG_DUMP_POS + 1))
#define RG_DUMP_BODY_POS (RG_DUMP_POS + 2)
#define RG_DUMP_BODY_MASK_LEN (2)
#define RG_DUMP_BODY_MASK ((~(~0 << RG_DUMP_BODY_MASK_LEN)) << RG_DUMP_BODY_POS)
#define RG_DUMP_BODY_BUFFER (1 << RG_DUMP_BODY_POS)
#define RG_DUMP_BODY_SOURCE (2 << RG_DUMP_BODY_POS)
#define RG_DUMP_BODY_DECODED (3 << RG_DUMP_BODY_POS)
#define RG_DUMP_EXTRA (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN))
#define RG_DUMP_MASK (RG_DUMP_HEAD | RG_DUMP_BODY_MASK | RG_DUMP_EXTRA)
#define RG_NOPROP (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 1))
#define RG_LINKNUM_A (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 2))
#define RG_LINKNUM_IMG (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 3))
#define RG_LINKNUM_MASK (RG_LINKNUM_A | RG_LINKNUM_IMG)
#define RG_REPBUF (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 4))
#define RG_STRSRC (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 5))
#define RG_HIST (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 6))
#define RG_IMAGE (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 7))
#define RG_DO_DOWNLOAD (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 8))
#define RG_ON_TARGET (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 9))
#define RG_IMPLICIT (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 10))
#define RG_SINGLE_ROW_IMAGE (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 11))
#define RG_DONT_RESET_FORM (1 << (RG_DUMP_BODY_POS + RG_DUMP_BODY_MASK_LEN + 12))

struct html_feed_environ {
    struct readbuffer *obuf;
    TextLineList *buf;
    FILE *f;
#ifdef MANY_CHARSET
    mb_info_t *f_info;
#endif
    Str tagbuf;
    int limit;
    int maxlimit;
    struct environment *envs;
    int nenv;
    int envc;
    int envc_real;
    char *title;
    int blank_lines;
};

struct auth_cookie {
    Str host;
    int port;
    Str file;
    Str realm;
    Str cookie;
    struct auth_cookie *next;
};

#ifdef USE_COOKIE
struct portlist {
    unsigned short port;
    struct portlist *next;
};

struct cookie {
    ParsedURL url;
    Str name;
    Str value;
    time_t expires;
    Str path;
    Str domain;
    Str comment;
    Str commentURL;
    struct portlist *portl;
    char version;
    char flag;
    struct cookie *next;
};
#define COO_USE		1
#define COO_SECURE	2
#define COO_DOMAIN	4
#define COO_PATH	8
#define COO_DISCARD	16
#define COO_OVERRIDE	32			/* user chose to override security checks */

#define COO_OVERRIDE_OK	32			/* flag to specify that an error is overridable */
						/* version 0 refers to the original cookie_spec.html */
						/* version 1 refers to RFC 2109 */
						/* version 1' refers to the Internet draft to obsolete RFC 2109 */
#define COO_EINTERNAL	(1)			/* unknown error; probably forgot to convert "return 1" in cookie.c */
#define COO_ETAIL	(2 | COO_OVERRIDE_OK)	/* tail match failed (version 0) */
#define COO_ESPECIAL	(3)			/* special domain check failed (version 0) */
#define COO_EPATH	(4)			/* Path attribute mismatch (version 1 case 1) */
#define COO_ENODOT	(5 | COO_OVERRIDE_OK)	/* no embedded dots in Domain (version 1 case 2.1) */
#define COO_ENOTV1DOM	(6 | COO_OVERRIDE_OK)	/* Domain does not start with a dot (version 1 case 2.2) */
#define COO_EDOM	(7 | COO_OVERRIDE_OK)	/* domain-match failed (version 1 case 3) */
#define COO_EBADHOST	(8 | COO_OVERRIDE_OK)	/* dot in matched host name in FQDN (version 1 case 4) */
#define COO_EPORT	(9)			/* Port match failed (version 1' case 5) */
#define COO_EMAX	COO_EPORT
#endif				/* USE_COOKIE */

/* modes for align() */

#define ALIGN_CENTER 0
#define ALIGN_LEFT   1
#define ALIGN_RIGHT  2
#define ALIGN_MIDDLE 4
#define ALIGN_TOP    5
#define ALIGN_BOTTOM 6

#define VALIGN_MIDDLE 0
#define VALIGN_TOP    1
#define VALIGN_BOTTOM 2

typedef struct http_request {
    char command;
    char flag;
    char *referer;
    FormList *request;
} HRequest;

enum {
    HR_COMMAND_GET,
    HR_COMMAND_POST,
    HR_COMMAND_CONNECT,
    HR_COMMAND_HEAD,
    HR_COMMAND_BY_USER,
};

#define HR_FLAG_LOCAL		1

enum {
    HTST_NORMAL,
    HTST_CONNECT,
    HTST_MISSING,
    HTST_UNKNOWN,
};

#define TMPF_DFL	0
#define TMPF_SRC	1
#define TMPF_FRAME	2
#define TMPF_CACHE	3
#define TMPF_INDEX	4
#define MAX_TMPF_TYPE	5

#define set_no_proxy(domains) (NO_proxy_domains=make_domain_list(domains))

/* 
 * Globals.
 */

extern int LINES, COLS, LASTLINE, INPUTLINE;

global int MessageIndent init(0);
global int Tabstop init(8);
global int ShowEffect init(TRUE);
global int PagerMax init(PAGER_MAX_LINE);
#ifdef JP_CHARSET
global char InnerCode init(CODE_INNER_EUC);	/* use EUC-JP internally; do not change */
#endif				/* JP_CHARSET */

global char TargetSelf init(FALSE);
global char PermitSaveToPipe init(FALSE);
global char DecodeCTE init(FALSE);
global char ArgvIsURL init(FALSE);

global char fmInitialized init(FALSE);
global char QuietMessage init(FALSE);

#ifdef __EMX__
extern char	PcKeymap[];
#endif
extern FuncList w3mFuncList[];
extern KeyTabList w3mDefaultFuncKeyTabList;
extern KeyTabList *w3mFuncKeyTabList;
extern KeyTabList w3mDefaultEditKeyTabList;
extern KeyTabList *w3mEditKeyTabList;
#ifdef USE_MENU
extern KeyTabList w3mDefaultMenuKeyTabList;
extern KeyTabList *w3mMenuKeyTabList;
#endif

global char *HTTP_proxy init(NULL);
#ifdef USE_SSL
global char *HTTPS_proxy init(NULL);
#endif				/* USE_SSL */
#ifdef USE_GOPHER
global char *GOPHER_proxy init(NULL);
#endif				/* USE_GOPHER */
global char *FTP_proxy init(NULL);
global ParsedURL HTTP_proxy_parsed;
#ifdef USE_SSL
global ParsedURL HTTPS_proxy_parsed;
#endif				/* USE_SSL */
#ifdef USE_GOPHER
global ParsedURL GOPHER_proxy_parsed;
#endif				/* USE_GOPHER */
global ParsedURL FTP_proxy_parsed;
global char *NO_proxy init(NULL);
global int NOproxy_netaddr init(TRUE);
#ifdef INET6
enum {
    DNS_ORDER_UNSPEC,
    DNS_ORDER_INET_INET6,
    DNS_ORDER_INET6_INET,
};
global int DNS_order init(DNS_ORDER_UNSPEC);
extern int ai_family_order_table[3][3];		/* XXX */
#endif				/* INET6 */
#ifndef KEPT_SOCK_MAX
#define KEPT_SOCK_MAX (20)
#endif
global int concurrent init(KEPT_SOCK_MAX);
#ifndef KEPT_SOCK_MAX_PER_SERVER
#define KEPT_SOCK_MAX_PER_SERVER (5)
#endif
global int concurrent_per_server init(KEPT_SOCK_MAX_PER_SERVER);
#ifndef KEPT_SOCK_EXPIRE
#define KEPT_SOCK_EXPIRE (30)
#endif
#ifndef KEPT_SOCK_EXPIRE_ANYWAY
#define KEPT_SOCK_EXPIRE_ANYWAY (2)
#endif
global int kept_nsocks init(0);
global int kept_sock init(-1);
global int dont_keep_alive init(FALSE);
global int FollowRedirection init(10);
global TextList *NO_proxy_domains;
global int NoCache init(FALSE);
global int Do_not_use_proxy init(FALSE);
global int Do_not_use_ti_te init(FALSE);

global char *document_root init(NULL);
global char *personal_document_root init(NULL);
global char *cgi_bin init(NULL);
global char *index_file init(NULL);

global char *CurrentDir;
global BufferViewList TopViewList;
global Buffer *Firstbuf;
global int CurrentKey init(0);
global int NStroke init(0);
global int TargetX init(-1);
global int TargetY init(-1);
global int PrevTargetX init(-1);
global int PrevTargetY init(-1);
global char *CurrentKeyData;
global char *ForcedKeyData init(NULL);
global Buffer *Argumentbuf init(NULL);
#ifdef USE_MENU
global int CurrentMenuPopup init(0);
global Menu *CurrentMenu init(NULL);
#endif
global char *CurrentCmdData;
#ifndef MANY_CHARSET
extern char *ullevel[];
#endif

extern char *w3m_version;

global int w3m_debug;
global int w3m_halfload init(FALSE);
global char *UserSpecifiedContentType init(NULL);
global char *UserSpecifiedExtraContentType init(NULL);

#ifdef USE_COLOR
global int useColor init(TRUE);
global int basic_color init(8);	/* don't change */
global int anchor_color init(4);	/* blue  */
global int image_color init(2);	/* green */
global int form_color init(1);	/* red   */
#ifdef USE_BG_COLOR
global int bg_color init(8);	/* don't change */
global int mark_color init(6);	/* cyan */
#endif				/* USE_BG_COLOR */
global int useActiveColor init(FALSE);
global int active_color init(6);	/* cyan */
global int useVisitedColor init(FALSE);
global int visited_color init(5);	/* magenta  */
global int frame_color init(6);	/* cyan  */
#endif				/* USE_COLOR */
global int confirm_on_quit init(TRUE);
#ifdef USE_MARK
global int use_mark init(TRUE);
#endif
#ifdef EMACS_LIKE_LINEEDIT
global int emacs_like_lineedit init(TRUE);
#endif
#ifdef VI_PREC_NUM
global int vi_prec_num init(TRUE);
#endif
global char *displayTitleTerm init(NULL);
global int displayLink init(FALSE);
global int displayLineInfo init(FALSE);
global int retryAsHttp init(TRUE);
global int showLineNum init(FALSE);
global int show_srch_str init(TRUE);
#ifdef USE_IMAGE
global char *Imgdisplay init(IMGDISPLAY);
global char *Imgsize init(NULL); /* Obsolete, never used */
global int activeImage init(FALSE);
global int image_map_list init(TRUE);
#endif
global char *ExtBrowser init(DEF_EXT_BROWSER);
global char *ExtBrowser2 init(NULL);
global char *ExtBrowser3 init(NULL);
global int BackgroundExtViewer init(TRUE);
global int disable_secret_security_check init(FALSE);
global char *passwd_file init(PASSWD_FILE);
global char *ftppasswd init(NULL);
#ifdef FTPPASS_HOSTNAMEGEN
global int ftppass_hostnamegen init(TRUE);
#endif
global char *UserAgent init(NULL);
global int NoSendReferer init(FALSE);
global char *UserSpecifiedReferer init(NULL);
global char *AcceptLang init(NULL);
global char *AcceptMedia init(NULL);
global char *DecoderSearchPath init(NULL);
global Str AllAcceptEncodings init(NULL);
global char *AcceptEncoding init(NULL);
extern TextList HTTPRequestHeaderList;
global char *LangExt init(NULL);
global int WrapDefault init(FALSE);
global int IgnoreCase init(TRUE);
global int AcrossLines init(TRUE);
global int WrapSearch init(FALSE);
global int squeezeBlankLine init(FALSE);
global char *BookmarkFile init(NULL);
global char *pauth init(NULL);
global Str proxy_auth_cookie init(NULL);
global int UseExternalDirBuffer init(TRUE);
global char *DirBufferCommand init("file:///$LIB/dirlist" CGI_EXTENSION);
#ifdef USE_DICT
global int UseDictCommand init(FALSE);
global char *DictCommand init("file:///$LIB/w3mdict" CGI_EXTENSION);
#endif				/* USE_DICT */
global int ignore_null_img_alt init(TRUE);
global char *anchor_num_style init(NULL);
global int FoldTextarea init(FALSE);
enum {
    DEFAULT_URL_EMPTY,
    DEFAULT_URL_CURRENT,
    DEFAULT_URL_LINK,
};
global int DefaultURLString init(DEFAULT_URL_EMPTY);
global int MarkAllPages init(TRUE);
global char *img_num_style init(NULL);
global char *label_withinpage_style init(NULL);
global char *link_num_url init(NULL);
global int scroll_amount init(0);
global int WrapLine init(FALSE);
global char *LineTruncated init("$");
global char *LineContinued init("");
#define HTTP_DEFAULT_VERSION "1.1"
global char *HTTPVersion init(HTTP_DEFAULT_VERSION);

global struct auth_cookie *Auth_cookie init(NULL);
global char *Local_cookie init(NULL);
#ifdef USE_COOKIE
global struct cookie *First_cookie init(NULL);
#endif				/* USE_COOKIE */

extern struct mailcap *DefaultMailcaps[];
global struct mailcap **UserMailcap init(DefaultMailcaps);
global btri_string_tab_t **UserMimeTypes;
global TextList *mailcap_list;
global TextList *mimetypes_list;
global char *mailcap_files init("0, " USER_MAILCAP ", 0, " SYS_MAILCAP ", 1, " GLOBAL_MAILCAP);
global char *mimetypes_files init(USER_MIMETYPES ", " SYS_MIMETYPES);
global TextList mailcap_entries;

global struct mailcap **UserBrowsecap init(NULL);
global TextList *browsecap_list;
global char *browsecap_files init(USER_BROWSECAP ", " SYS_BROWSECAP);
global TextList browsecap_entries;

global TextList *fileToDelete;

enum {
    LoadHist_i,
    SaveHist_i,
    URLHist_i,
    ShellHist_i,
    TextHist_i,
    FuncHist_i,
    DirectoryHist_i,
    HistV_size,
};

extern Hist HistV[HistV_size];;
#define LoadHist (&HistV[LoadHist_i])
#define SaveHist (&HistV[SaveHist_i])
#define URLHist (&HistV[URLHist_i])
#define ShellHist (&HistV[ShellHist_i])
#define TextHist (&HistV[TextHist_i])
#define FuncHist (&HistV[FuncHist_i])
#define DirectoryHist (&HistV[DirectoryHist_i])
#ifdef USE_HISTORY
global int URLHistSize init(100);
global int SaveURLHist init(TRUE);
#endif				/* USE_HISTORY */
global int multicolList init(FALSE);

global char DisplayCode init(DISPLAY_CODE);
#ifdef JP_CHARSET
global char SystemCode init(SYSTEM_CODE);
global char DocumentCode init(0);
global char UseContentCharset init(TRUE);
global char UseAutoDetect init(TRUE);
#define Str_conv_from_system(x) conv_str((x), SystemCode, InnerCode)
#define Str_conv_to_system(x) conv_str((x), InnerCode, SystemCode)
#define conv_from_system(x) conv((x), SystemCode, InnerCode)->ptr
#define conv_to_system(x) conv((x), InnerCode, SystemCode)->ptr
#define url_quote_conv(x,c) url_quote(conv((x), InnerCode, (c))->ptr)
#define url_quote_conv_for_buf(x,b) url_quote_conv((x), (b)->document_encoding)
#elif defined(MANY_CHARSET)
#define Str_conv_from_system(x) conv_Str2mbStr((x), NULL, "@", lookup_process_charset(myname))
#define Str_conv_to_system(x) \
conv_str2isoStr((x)->ptr, "@|", lookup_process_charset(myname), MB_FLAG_ASCIIATCTL | MB_FLAG_DISCARD_NOTPREFERED_CHAR)
#define conv_from_system(x) conv_str2mbStr((x), NULL, "@", lookup_process_charset(myname))->ptr
#define conv_to_system(x) \
conv_str2isoStr((x), "@|", lookup_process_charset(myname), MB_FLAG_ASCIIATCTL | MB_FLAG_DISCARD_NOTPREFERED_CHAR)->ptr
#define url_quote_conv(x,c) url_quote(conv_str2isoStr((x), "@|", (c), MB_FLAG_ASCIIATCTL | MB_FLAG_DISCARD_NOTPREFERED_CHAR)->ptr)
#define url_quote_conv_for_buf(x,b) url_quote_conv((x), (b)->document_encoding)
#else
#define Str_conv_from_system(x) (x)
#define Str_conv_to_system(x) (x)
#define conv_from_system(x) (x)
#define conv_to_system(x) (x)
#define url_quote_conv(x,c) url_quote(x)
#define url_quote_conv_for_buf(x,b) url_quote((x))
#endif				/* JP_CHARSET */
#ifndef KANJI_SYMBOLS
global int no_graphic_char init(FALSE);
extern char alt_rule[];
#endif				/* not KANJI_SYMBOLS */
extern char UseAltEntity;
global const char *myname init("w3m");
global char *rc_dir;
global char *tmp_dir;
global int rc_dir_is_tmp init(FALSE);

#ifdef USE_MOUSE
global int use_mouse init(TRUE);
global int mouseActive init(FALSE);
global int reverse_mouse init(FALSE);
#endif				/* USE_MOUSE */

#ifdef USE_COOKIE
global int default_use_cookie init(TRUE);
global int use_cookie init(FALSE);
global int accept_cookie init(FALSE);
enum {
    ACCEPT_BAD_COOKIE_DISCARD,
    ACCEPT_BAD_COOKIE_ACCEPT,
    ACCEPT_BAD_COOKIE_ASK,
};
global int accept_bad_cookie init(ACCEPT_BAD_COOKIE_DISCARD);
global char *cookie_reject_domains init(NULL);
global char *cookie_accept_domains init(NULL);
global TextList *Cookie_reject_domains;
global TextList *Cookie_accept_domains;
#endif				/* USE_COOKIE */

#ifdef USE_ROMAJI
global int use_romaji_search init(FALSE);
global char *romaji_filter init(DEF_ROMAJI_FILTER);
#endif				/* USE_ROMAJI */

#ifdef USE_IMAGE
global int view_unseenobject init(FALSE);
#else
global int view_unseenobject init(TRUE);
#endif

#if defined(USE_SSL) && defined(USE_SSL_VERIFY)
global int ssl_verify_server init(FALSE);
global char *ssl_cert_file init(NULL);
global char *ssl_key_file init(NULL);
global char *ssl_ca_path init(NULL);
global char *ssl_ca_file init(NULL);
global int ssl_path_modified init(FALSE);
#endif				/* defined(USE_SSL) &&
				 * defined(USE_SSL_VERIFY) */
#ifdef USE_SSL
global char *ssl_forbid_method init(NULL);
#endif

global int is_redisplay init(FALSE);
global int clear_buffer init(TRUE);
global double pixel_per_char init(DEFAULT_PIXEL_PER_CHAR);
global double pixel_per_line init(DEFAULT_PIXEL_PER_LINE);
#ifdef USE_IMAGE
global double image_scale init(100);
global int img_valign init(-1);
global int table_valign init(VALIGN_MIDDLE);
global int preload_image init(FALSE);
global char auto_pixel_per_char init(TRUE);
global char auto_pixel_per_line init(TRUE);
#endif
global int dont_buffername init(FALSE);
global int edit_remote_source init(TRUE);
global int remove_trailing_spaces init(TRUE);

extern int read_nfd;
extern void (**read_hookv)(int, void *);
extern void **read_hook_argv;
global FILE *orig_stderr init(NULL);

global int next_dcompl_next init(-1);
global struct _InputLineEnv *next_dcompl_env init(NULL);
global int next_dcompl_top init(-1);

#ifdef MANY_CHARSET

#undef def_rcsect_begin
#define def_rcsect_begin(n)

#undef def_rcsect_end
#define def_rcsect_end(n)

#undef def_rcitem
#define def_rcitem(name, type, inputtype, varptr, comment, select)

#undef def_rcstr
#define def_rcstr(key, mac, ini, eng) extern char *RCSTR_ ## mac;

#undef def_mbsetup
#define def_mbsetup(key, mac, inputtype, eng)

#include "rc.h"

extern tty_char_conv_t tty_char_conv_tab;
extern char *term_char_repl;

#endif

global int use_lessopen init(FALSE);

global Buffer *loadingBuffer init(NULL);

global char *keymap_file init(KEYMAP_FILE);

#ifdef JP_CHARSET
#define is_kanji(s)    (IS_KANJI1((s)[0])&&IS_KANJI2((s)[1]))
#define get_mctype(s)  (is_kanji(s)?PC_KANJI:GET_PCTYPE(*(s)))
#define get_mclen(m)   (((m)==PC_KANJI)?2:1)
#define mctowc(s,m) \
(((m)==PC_KANJI)?(((unsigned char)(s)[0]<<8)|(unsigned char)(s)[1]): \
 (unsigned char)(s)[0])
#define is_wckanji(wc) ((wc)&~0xff)
#define get_wctype(wc) (is~wckanji(wc)?PC_KANJI:GET_PCTYPE(wc))
#else
#define get_mctype(s)  GET_PCTYPE(*(s))
#define get_mclen(m)   1
#define mctowc(s,m)    ((unsigned char)*(s))
#define is_wckanji(wc) ((wc)&~0xff)
#define get_wctype(wc) (is~wckanji(wc)?PC_ASCII:GET_PCTYPE(wc))
#endif

global TextList HTTPRequestHeaderList init({NULL});
global TextList ExtraHTTPRequestHeaderList init({NULL});

enum {
    FollowWithOriginalMethodWhenRedirected,
    FollowWithGETWhenRedirected,
    IgnoreRedirection,
    QueryWhenReidirected,
};

global int WhenRedirected init(FollowWithGETWhenRedirected);

global char *TryExtensions init(NULL);

enum {
    urgent_output,
    urgent_input,
    urgent_default,
    urgent_bufferinfo,
    urgent_label,
#ifdef USE_COOKIE
    urgent_find_cookie,
    urgent_cookie,
#endif
    urgent_find_auth_cookie,
    urgent_auth_cookie,
    urgent_proxy_auth_cookie,
    urgent_control,
    urgent_record,
    urgent_tmpfile,
    urgent_framebody,
    urgent_frameset,
    urgent_fmsetup,
    urgent_failure,
    urgent_nobuffer,
#ifdef USE_IMAGE
    urgent_image_retrieve,
    urgent_image_register,
    urgent_image_size,
    urgent_cur_baseURL,
#endif
    urgent_keep_alive,
    urgent_redirected,
    urgent_ready,
    urgent_body,
    urgent_echo,
};

enum {
    urgent_bufferinfo_filename,
    urgent_bufferinfo_buffername,
    urgent_bufferinfo_type,
    urgent_bufferinfo_real_type,
    urgent_bufferinfo_bufferprop,
    urgent_bufferinfo_currentURL,
    urgent_bufferinfo_baseURL,
    urgent_bufferinfo_baseTarget,
    urgent_bufferinfo_real_scheme,
    urgent_bufferinfo_sourcefile,
    urgent_bufferinfo_trbyte,
#ifdef MANY_CHARSET
    urgent_bufferinfo_document_charset,
    urgent_bufferinfo_document_encoding,
#elif defined(JP_CHARSET)
    urgent_bufferinfo_document_code,
    urgent_bufferinfo_document_encoding,
#endif
    urgent_bufferinfo_document_header,
    urgent_bufferinfo_mailcap_source,
    urgent_bufferinfo_mailcap,
    urgent_bufferinfo_name_by_header,
#ifdef USE_SSL
    urgent_bufferinfo_ssl_certificate,
#endif
#ifdef USE_IMAGE
    urgent_bufferinfo_image_flag,
    urgent_bufferinfo_image_unloaded,
#endif
    urgent_bufferinfo_http_response_code,
    urgent_bufferinfo_search_header,
};

global FILE *urgent_out init(NULL);
#define BACKEND_QUIET (1)
#define BACKEND_VERBOSE (2)
#define BACKEND_VERY_VERBOSE (3)
global int w3m_backend init(0);
extern void backend_message(char *msg, int urgent);
char *backend_inputLine(char *prompt, char *def_str, int flag, Hist *hist);
extern void deleteFiles(void);
void w3m_exit(int i);

/* 
 * Externals
 */

#include "table.h"

#define FRAMESTACK_SIZE 10
#define FORMSTACK_SIZE 10

struct link_stack {
    int cmd;
    int offset;
    int pos;
    struct link_stack *next;
};

#define SEARCH_HEADER_CHECK (1 << 0)
#define SEARCH_HEADER_NOVIEW (1 << 1)
#define SEARCH_HEADER_RESHAPE (1 << 2)

typedef struct _RedirectHistory {
    ParsedURL *v;
    int n, n_max;
} RedirectHistory;

typedef struct _Phase0Env {
    void (*receiver)(Buffer *buf, int nlines);
    void *receiver_arg;
    int flag;
    char *DefaultType;
#ifdef JP_CHARSET
    char DocumentCode;
    char content_charset;
#ifdef USE_IMAGE
    char cur_document_code;
#endif
#endif
#ifdef MANY_CHARSET
    const char *default_content_charset;
    const char *content_charset;
#ifdef USE_IMAGE
    const char *cur_content_charset;
#endif
#endif
    clen_t current_content_length;
    Buffer *curbuf;
    ParsedURL *URL;
    RedirectHistory *redir_hist;
#ifdef USE_IMAGE
    char *current_source;
    ParsedURL *cur_baseURL;
#endif
    InputStream is;
    BufferView *view;
    char SearchHeader;
    char RenderFrame;
    char displayImage;
} Phase0Env;

extern Phase0Env main_p0env;
#define Currentbuf (main_p0env.curbuf)

typedef struct _Phase1Env {
    Phase0Env *p0env;
    Buffer *buf;
    struct table *tables[MAX_TABLE];
    struct table_mode table_mode[MAX_TABLE];
    Str cur_select;
    Str select_str;
    int select_is_multiple;
    int n_selectitem;
    Str cur_option;
    Str cur_option_value;
    Str cur_option_label;
    int cur_option_selected;
    int cur_status;
#ifdef MENU_SELECT
    /* menu based <select>  */
    FormSelectOption *select_option;
    int max_select;
    int n_select;
    int cur_option_maxwidth;
#endif				/* MENU_SELECT */
    Str cur_textarea;
    Str *textarea_str;
    int textarea_visible;
    int cur_textarea_size;
    int cur_textarea_rows;
    int cur_textarea_readonly;
    int n_textarea;
    int max_textarea;
    char *button_type;
    char *button_value;
    char *button_name;
    Str save_line;
#ifdef MANY_CHARSET
    int save_prevchar;
    int save_prev_ns_char;
#else
    int save_prevchar;
#endif
    struct link_stack *link_stack;
#define INITIAL_FORM_SIZE 10
    FormList **forms;
    int *form_stack;
    int form_max;
    int forms_size;
#define cur_form_id(arg) (((arg)->form_sp >= 0)? (arg)->form_stack[(arg)->form_sp] : -1)
    int form_sp;
    int cur_hseq;
#ifdef USE_IMAGE
    int cur_iseq;
#endif
    TextList *links;
    btri_string_tab_t *link_tab;
    ParsedURL *link_base;
} Phase1Env;

typedef struct _Phase2Env {
    Phase1Env *p1env;
    int llimit;
    Anchor *a_href, *a_img, *a_form;
    Lineprop effect;
    int nlines;
    FILE *debug;
    struct frameset *frameset_s[FRAMESTACK_SIZE];
    int frameset_sp;
    CheckTypeEnv *ctenv;
    Anchor **a_form_v;
    int a_form_n, a_form_n_max;
#ifdef USE_IMAGE
    Anchor **a_img_v;
    int a_img_n, a_img_n_max;
#endif
} Phase2Env;

#define ASYNC_FLAG_MAYREAD (1 << 0)
#define ASYNC_FLAG_REDRAW (1 << 1)
#define ASYNC_FLAG_COMPLETED (1 << 2)
#define ASYNC_FLAG_KEEP_ALIVE (1 << 3)
#define ASYNC_FLAG_USED (1 << 4)
#define ASYNC_FLAG_DONT_KEEP_ALIVE (1 << 3)

#define ASYNC_EOHTML "</html>"

typedef struct _AsyncRWBuf {
    int flag;
    pid_t pid;
    int rfd, ufd;
    FILE *w;
    Str rbuf, ubuf;
    int rprocessed, chunk_size, uprocessed;
    Phase2Env *p2env;
    char *label;
    char *path;
    Str urgent_title;
} AsyncRWBuf;

enum {
    async_body_unknown,
    async_body_html,
    async_body_plain,
    async_body_chunked,
};

enum {
    fgets_async_error = -1,
    fgets_async_eof,
    fgets_async_eol_and_eof,
    fgets_async_eol_without_read,
    fgets_async_eol_with_read,
    fgets_async_no_eol,
};

#define STR_LEN	(BUFSIZ)

typedef struct _ComplFileNameEnv {
    Str CFileName;
    Str CDirBuf;
} ComplFileNameEnv;

typedef struct _InputLineEnv {
    Str strBuf;
    Lineprop strProp[STR_LEN];
    Str CompleteBuf;
    Str CBeforeBuf;
    Str CAfterBuf;
    Str (*do_complete)(Str, int *, int, struct _InputLineEnv *);
    char **CandBuf;
    void *ComplPrivate;
    int NCandBuf;
    int NCandOffset;
    int CPos, CLen, offset;
    int i_cont, i_broken, i_quote;
#ifdef MANY_CHARSET
    int i_wchar;
#endif
    int cm_mode, cm_next, cm_clear, cm_disp_next, cm_disp_clear;
    int need_redraw, is_passwd;
    int (*same_type_char_p)(
#ifdef MANY_CHARSET
			    mb_wchar_t x, mb_wchar_t y
#else
			    int x, int y
#endif
			    );
    int prev_stroke, nstroke;
    Hist *CurrentHist;
    Str strCurrentBuf;
    int use_hist;
#ifdef JP_CHARSET
    int in_kanji;
#endif
    struct {
	int col, row, len;
	Str d;
    } dcompl_env;
} InputLineEnv;

typedef struct _UrgentInputQueueElement {
    char *prompt, *def_str;
    int flag;
    Hist *hist;
    FILE **pfp;
} UrgentInputQueueElement;

typedef struct _UrgentInputQueue {
    int n, n_max;
    UrgentInputQueueElement *v;
} UrgentInputQueue;

enum {
    cooked_event_char,
#if defined(USE_MOUSE) && (defined(USE_GPM) || defined(USE_SYSMOUSE))
    cooked_event_mouse,
#endif
};

typedef struct _RawEvent {
    fd_set rfds;
#if defined(USE_MOUSE) && defined(USE_SYSMOUSE)
    int sigmouse;
#endif
} RawEvent;

typedef struct _CookedEvent {
    unsigned char type, what;
    int x, y;
} CookedEvent;

#include "proto.h"

#endif				/* not FM_H */

/* Local Variables:    */
/* c-basic-offset: 4   */
/* tab-width: 8        */
/* End:                */
