Description: Restrict table and menu borders to ASCII if you use -no-graph Make it possible to restrict table and menu borders to ASCII characters. This is now done with -no-graph and the old meaning of -no-graph is accessible through -o graphic_char=0 The values of graphic_char now have a strange order to be compatible with older configs. It might be better to make the order natural. Origin: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=261174#10 Author: Karsten Schoelzel Bug-Debian: http://bugs.debian.org/261174 diff -urN w3m-0.5.2.orig/fm.h w3m-0.5.2/fm.h --- w3m-0.5.2.orig/fm.h 2007-05-30 13:47:24.000000000 +0900 +++ w3m-0.5.2/fm.h 2010-07-18 08:13:26.000000000 +0900 @@ -1055,7 +1055,10 @@ #define wc_Str_conv_strict(x,charset0,charset1) (x) #endif global char UseAltEntity init(TRUE); -global char UseGraphicChar init(FALSE); +#define GRAPHIC_CHAR_ASCII 2 +#define GRAPHIC_CHAR_CHARSET 0 +#define GRAPHIC_CHAR_ALL 1 +global char UseGraphicChar init(GRAPHIC_CHAR_ASCII); extern char *graph_symbol[]; extern char *graph2_symbol[]; extern int symbol_width; diff -urN w3m-0.5.2.orig/fm.h.orig w3m-0.5.2/fm.h.orig --- w3m-0.5.2.orig/fm.h.orig 1970-01-01 09:00:00.000000000 +0900 +++ w3m-0.5.2/fm.h.orig 2007-05-30 13:47:24.000000000 +0900 @@ -0,0 +1,1191 @@ +/* $Id: fm.h,v 1.138 2007/05/30 04:47:24 inu Exp $ */ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "history.h" + +#ifdef USE_MENU +#define MENU_SELECT +#define MENU_MAP +#endif /* USE_MENU */ + +#ifndef USE_COLOR +#undef USE_ANSI_COLOR +#undef USE_BG_COLOR +#endif + +#include "ctrlcode.h" +#include "html.h" +#include +#include "Str.h" +#ifdef USE_M17N +#include "wc.h" +#include "wtf.h" +#else +typedef int wc_ces; /* XXX: not used */ +#endif + +#ifdef HAVE_LOCALE_H +#include +#endif +#if !HAVE_SETLOCALE +#define setlocale(category, locale) /* empty */ +#endif + +#ifdef ENABLE_NLS +#include +#define _(String) gettext (String) +#define N_(String) (String) +#else +# undef bindtextdomain +# define bindtextdomain(Domain, Directory) /* empty */ +# undef textdomain +# define textdomain(Domain) /* empty */ +# define _(Text) Text +# define N_(Text) Text +# define gettext(Text) Text +#endif + +#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" + +#ifndef HAVE_BCOPY +void bcopy(const void *, void *, int); +void bzero(void *, int); +#endif /* HAVE_BCOPY */ +#ifdef __EMX__ +#include /* 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 */ + +#define DEFUN(funcname, macroname, docstring) void funcname(void) + +/* + * Constants. + */ +#define LINELEN 256 /* Initial line length */ +#define PAGER_MAX_LINE 10000 /* Maximum line kept as pager */ + +#ifdef USE_IMAGE +#define MAX_IMAGE 1000 +#define MAX_IMAGE_SIZE 2048 + +#define DEFAULT_PIXEL_PER_CHAR 7.0 /* arbitrary */ +#define DEFAULT_PIXEL_PER_LINE 14.0 /* arbitrary */ +#else +#define DEFAULT_PIXEL_PER_CHAR 8.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 + */ + +#define P_CHARTYPE 0x3f00 +#ifdef USE_M17N +#define PC_ASCII (WTF_TYPE_ASCII << 8) +#define PC_CTRL (WTF_TYPE_CTRL << 8) +#define PC_WCHAR1 (WTF_TYPE_WCHAR1 << 8) +#define PC_WCHAR2 (WTF_TYPE_WCHAR2 << 8) +#define PC_KANJI (WTF_TYPE_WIDE << 8) +#define PC_KANJI1 (PC_WCHAR1 | PC_KANJI) +#define PC_KANJI2 (PC_WCHAR2 | PC_KANJI) +#define PC_UNKNOWN (WTF_TYPE_UNKNOWN << 8) +#define PC_UNDEF (WTF_TYPE_UNDEF << 8) +#else +#define PC_ASCII 0x0000 +#define PC_CTRL 0x0100 +#endif +#define PC_SYMBOL 0x8000 + +/* Effect ( standout/underline ) */ +#define P_EFFECT 0x40ff +#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 0x4000 + +/* Extra effect */ +#define PE_EX_ITALIC 0x01 +#define PE_EX_INSERT 0x02 +#define PE_EX_STRIKE 0x04 + +#define PE_EX_ITALIC_E PE_UNDER +#define PE_EX_INSERT_E PE_UNDER +#define PE_EX_STRIKE_E PE_STAND + +#define CharType(c) ((c)&P_CHARTYPE) +#define CharEffect(c) ((c)&(P_EFFECT|PC_SYMBOL)) +#define SetCharType(v,c) ((v)=(((v)&~P_CHARTYPE)|(c))) + + +#define COLPOS(l,c) calcPosition(l->lineBuf,l->propBuf,l->len,c,0,CP_AUTO) + +/* Flags for displayBuffer() */ +#define B_NORMAL 0 +#define B_FORCE_REDRAW 1 +#define B_REDRAW 2 +#define B_SCROLL 3 +#define B_REDRAW_IMAGE 4 + +/* Buffer Property */ +#define BP_NORMAL 0x0 +#define BP_PIPE 0x1 +#define BP_FRAME 0x2 +#define BP_INTERNAL 0x8 +#define BP_NO_URL 0x10 +#define BP_REDIRECTED 0x20 +#define BP_CLOSE 0x40 + +/* Link Buffer */ +#define LB_NOLINK -1 +#define LB_FRAME 0 /* rFrame() */ +#define LB_N_FRAME 1 +#define LB_INFO 2 /* pginfo() */ +#define LB_N_INFO 3 +#define LB_SOURCE 4 /* vwSrc() */ +#define LB_N_SOURCE LB_SOURCE +#define MAX_LB 5 + +/* Search Result */ +#define SR_FOUND 0x1 +#define SR_NOTFOUND 0x2 +#define SR_WRAPPED 0x4 + +#ifdef MAINPROGRAM +int REV_LB[MAX_LB] = { + LB_N_FRAME, LB_FRAME, 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. */ +#define CPL_OK 0 +#define CPL_AMBIG 1 +#define CPL_FAIL 2 +#define CPL_MENU 3 + +#define CPL_NEVER 0x0 +#define CPL_OFF 0x1 +#define CPL_ON 0x2 +#define CPL_ALWAYS 0x4 +#define CPL_URL 0x8 + +/* 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 IMG_FLAG_SKIP 1 +#define IMG_FLAG_AUTO 2 + +#define IMG_FLAG_START 0 +#define IMG_FLAG_STOP 1 +#define IMG_FLAG_NEXT 2 + +#define IMG_FLAG_UNLOADED 0 +#define IMG_FLAG_LOADED 1 +#define IMG_FLAG_ERROR 2 +#define IMG_FLAG_DONT_REMOVE 4 + +/* + * 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 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) + +#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 + +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; + int size; + int bpos; + int bwidth; +} Line; + +typedef struct { + int line; + int pos; + int invalid; +} BufferPoint; + +#ifdef USE_IMAGE +typedef struct _imageCache { + char *url; + ParsedURL *current; + char *file; + char *touch; + pid_t pid; + char loaded; + int index; + short width; + short height; +} ImageCache; + +typedef struct _image { + char *url; + char *ext; + short width; + short height; + short xoffset; + short yoffset; + short y; + short rows; + char *map; + char ismap; + int touch; + ImageCache *cache; +} Image; +#endif + +typedef struct _anchor { + char *url; + char *target; + char *referer; + char *title; + unsigned char accesskey; + BufferPoint start; + BufferPoint end; + int hseq; + char slave; + short y; + short rows; +#ifdef USE_IMAGE + Image *image; +#endif +} Anchor; + +#define NO_REFERER ((char*)-1) + +typedef struct _anchorList { + Anchor *anchors; + int nanchor; + int anchormax; + int acache; +} AnchorList; + +typedef struct { + BufferPoint *marks; + int nmark; + int markmax; + int prevhseq; +} HmarkerList; + +#define LINK_TYPE_NONE 0 +#define LINK_TYPE_REL 1 +#define LINK_TYPE_REV 2 +typedef struct _LinkList { + char *url; + char *title; /* Next, Contents, ... */ + char *ctype; /* Content-Type */ + char type; /* Rel, Rev */ + struct _LinkList *next; +} LinkList; + +typedef struct _Buffer { + char *filename; + char *buffername; + Line *firstLine; + Line *topLine; + Line *currentLine; + Line *lastLine; + struct _Buffer *nextBuffer; + struct _Buffer *linkBuffer[MAX_LB]; + short width; + short height; + char *type; + char *real_type; + int allLine; + short bufferprop; + int currentColumn; + short cursorX; + short cursorY; + int pos; + int visualpos; + short rootX; + short rootY; + short COLS; + short LINES; + InputStream pagerSource; + AnchorList *href; + AnchorList *name; + AnchorList *img; + AnchorList *formitem; + LinkList *linklist; + FormList *formlist; + MapList *maplist; + HmarkerList *hmarklist; + HmarkerList *imarklist; + ParsedURL currentURL; + ParsedURL *baseURL; + char *baseTarget; + int real_scheme; + char *sourcefile; + struct frameset *frameset; + struct frameset_queue *frameQ; + int *clone; + size_t trbyte; + char check_url; +#ifdef USE_M17N + wc_ces document_charset; + wc_uint8 auto_detect; +#endif + TextList *document_header; + FormItemList *form_submit; + char *savecache; + char *edit; + struct mailcap *mailcap; + char *mailcap_source; + char *header_source; + char search_header; +#ifdef USE_SSL + char *ssl_certificate; +#endif + char image_flag; + char image_loaded; + char need_reshape; + Anchor *submit; + struct _BufferPos *undo; +#ifdef USE_ALARM + struct _AlarmEvent *event; +#endif +} Buffer; + +typedef struct _BufferPos { + long top_linenumber; + long cur_linenumber; + int currentColumn; + int pos; + int bpos; + struct _BufferPos *next; + struct _BufferPos *prev; +} BufferPos; + +typedef struct _TabBuffer { + struct _TabBuffer *nextTab; + struct _TabBuffer *prevTab; + Buffer *currentBuffer; + Buffer *firstBuffer; + short x1; + short x2; + short y; +} TabBuffer; + +typedef struct _DownloadList { + pid_t pid; + char *url; + char *save; + char *lock; + clen_t size; + time_t time; + int ok; + struct _DownloadList *next; + struct _DownloadList *prev; +} DownloadList; +#define DOWNLOAD_LIST_TITLE "Download List Panel" + +#define COPY_BUFROOT(dstbuf, srcbuf) {\ + (dstbuf)->rootX = (srcbuf)->rootX; \ + (dstbuf)->rootY = (srcbuf)->rootY; \ + (dstbuf)->COLS = (srcbuf)->COLS; \ + (dstbuf)->LINES = (srcbuf)->LINES; \ +} + +#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) +#define RESTORE_BUFPOSITION(sbufp) COPY_BUFPOSITION(Currentbuf, sbufp) +#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 7 + +#define _INIT_BUFFER_WIDTH (COLS - (showLineNum ? 6 : 1)) +#define INIT_BUFFER_WIDTH ((_INIT_BUFFER_WIDTH > 0) ? _INIT_BUFFER_WIDTH : 0) +#define FOLD_BUFFER_WIDTH (FoldLine ? (INIT_BUFFER_WIDTH + 1) : -1) + +typedef struct { + int pos; + int len; + int tlen; + long flag; + Anchor anchor; + 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 line; + Lineprop cprop; + short pos; + Str prevchar; + long flag; + long flag_stack[RB_STACK_SIZE]; + int flag_sp; + int status; + unsigned char end_tag; + short table_level; + short nobr_level; + Anchor anchor; + 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; +}; + +#define in_bold fontstat[0] +#define in_under fontstat[1] +#define in_italic fontstat[2] +#define in_strike fontstat[3] +#define in_ins fontstat[4] +#define in_stand fontstat[5] + +#define RB_PRE 0x01 +#define RB_SCRIPT 0x02 +#define RB_STYLE 0x04 +#define RB_PLAIN 0x08 +#define RB_LEFT 0x10 +#define RB_CENTER 0x20 +#define RB_RIGHT 0x40 +#define RB_ALIGN (RB_LEFT| RB_CENTER | RB_RIGHT) +#define RB_NOBR 0x80 +#define RB_P 0x100 +#define RB_PRE_INT 0x200 +#define RB_IN_DT 0x400 +#define RB_INTXTA 0x800 +#define RB_INSELECT 0x1000 +#define RB_IGNORE_P 0x2000 +#define RB_TITLE 0x4000 +#define RB_NFLUSHED 0x8000 +#define RB_NOFRAMES 0x10000 +#define RB_INTABLE 0x20000 +#define RB_PREMODE (RB_PRE | RB_PRE_INT | RB_SCRIPT | RB_STYLE | RB_PLAIN | RB_INTXTA) +#define RB_SPECIAL (RB_PRE | RB_PRE_INT | RB_SCRIPT | RB_STYLE | RB_PLAIN | RB_NOBR) +#define RB_PLAIN_PRE 0x40000 + +#ifdef FORMAT_NICE +#define RB_FILL 0x80000 +#endif /* FORMAT_NICE */ +#define RB_DEL 0x100000 +#define RB_S 0x200000 + +#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 */ +#define R_ST_NORMAL 0 /* normal */ +#define R_ST_TAG0 1 /* within tag, just after < */ +#define R_ST_TAG 2 /* within tag */ +#define R_ST_QUOTE 3 /* within single quote */ +#define R_ST_DQUOTE 4 /* within double quote */ +#define R_ST_EQL 5 /* = */ +#define R_ST_AMP 6 /* within ampersand quote */ +#define R_ST_EOL 7 /* end of file */ +#define R_ST_CMNT1 8 /* currentBuffer) +#define Firstbuf (CurrentTab->firstBuffer) +global DownloadList *FirstDL init(NULL); +global DownloadList *LastDL init(NULL); +global int CurrentKey; +global char *CurrentKeyData; +global char *CurrentCmdData; +global char *w3m_reqlog; +extern char *w3m_version; + +#define DUMP_BUFFER 0x01 +#define DUMP_HEAD 0x02 +#define DUMP_SOURCE 0x04 +#define DUMP_EXTRA 0x08 +#define DUMP_HALFDUMP 0x10 +#define DUMP_FRAME 0x20 +global int w3m_debug; +global int w3m_dump init(0); +#define w3m_halfdump (w3m_dump & DUMP_HALFDUMP) +global int w3m_halfload init(FALSE); +global Str header_string init(NULL); +global int override_content_type init(FALSE); + +#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 */ +#endif /* USE_COLOR */ +global int confirm_on_quit init(TRUE); +#ifdef USE_MARK +global int use_mark init(FALSE); +#endif +global int emacs_like_lineedit init(FALSE); +global int vi_prec_num init(FALSE); +global int label_topline init(FALSE); +global int nextpage_topline init(FALSE); +global char *displayTitleTerm init(NULL); +global int displayLink init(FALSE); +global int displayLineInfo init(FALSE); +global int DecodeURL 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 int activeImage init(FALSE); +global int displayImage init(TRUE); +global int autoImage init(TRUE); +global int useExtImageViewer init(TRUE); +global int maxLoadImage init(4); +global int image_map_list init(TRUE); +#else +global int displayImage init(FALSE); /* XXX: emacs-w3m use display_image=off */ +#endif +global char *Editor init(DEF_EDITOR); +#ifdef USE_W3MMAILER +global char *Mailer init(NULL); +#else +global char *Mailer init(DEF_MAILER); +#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 *pre_form_file init(PRE_FORM_FILE); +global char *ftppasswd init(NULL); +global int ftppass_hostnamegen init(TRUE); +global int do_download init(FALSE); +#ifdef USE_IMAGE +global char *image_source init(NULL); +#endif +global char *UserAgent init(NULL); +global int NoSendReferer init(FALSE); +global char *AcceptLang init(NULL); +global char *AcceptEncoding init(NULL); +global char *AcceptMedia init(NULL); +global int WrapDefault init(FALSE); +global int IgnoreCase 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); +#define DISPLAY_INS_DEL_SIMPLE 0 +#define DISPLAY_INS_DEL_NORMAL 1 +#define DISPLAY_INS_DEL_FONTIFY 2 +global int displayInsDel init(DISPLAY_INS_DEL_NORMAL); +global int FoldTextarea init(FALSE); +global int FoldLine init(FALSE); +#define DEFAULT_URL_EMPTY 0 +#define DEFAULT_URL_CURRENT 1 +#define DEFAULT_URL_LINK 2 +global int DefaultURLString init(DEFAULT_URL_EMPTY); +global int MarkAllPages init(FALSE); + +#ifdef USE_MIGEMO +global int use_migemo init(FALSE); +global int migemo_active init(0); +global char *migemo_command init(DEF_MIGEMO_COMMAND); +#endif /* USE_MIGEMO */ + +global struct auth_cookie *Auth_cookie init(NULL); +#ifdef USE_COOKIE +global struct cookie *First_cookie init(NULL); +#endif /* USE_COOKIE */ + +global char *mailcap_files init(USER_MAILCAP ", " SYS_MAILCAP); +global char *mimetypes_files init(USER_MIMETYPES ", " SYS_MIMETYPES); +#ifdef USE_EXTERNAL_URI_LOADER +global char *urimethodmap_files init(USER_URIMETHODMAP ", " SYS_URIMETHODMAP); +#endif + +global TextList *fileToDelete; + +extern Hist *LoadHist; +extern Hist *SaveHist; +extern Hist *URLHist; +extern Hist *ShellHist; +extern Hist *TextHist; +#ifdef USE_HISTORY +global int UseHistory init(TRUE); +global int URLHistSize init(100); +global int SaveURLHist init(TRUE); +#endif /* USE_HISTORY */ +global int multicolList init(FALSE); + +#ifdef USE_M17N +global wc_ces InnerCharset init(WC_CES_WTF); /* Don't change */ +global wc_ces DisplayCharset init(DISPLAY_CHARSET); +global wc_ces DocumentCharset init(DOCUMENT_CHARSET); +global wc_ces SystemCharset init(SYSTEM_CHARSET); +global wc_ces BookmarkCharset init(SYSTEM_CHARSET); +global char ExtHalfdump init(FALSE); +global char FollowLocale init(TRUE); +global char UseContentCharset init(TRUE); +global char SearchConv init(TRUE); +#define Str_conv_from_system(x) wc_Str_conv((x), SystemCharset, InnerCharset) +#define Str_conv_to_system(x) wc_Str_conv_strict((x), InnerCharset, SystemCharset) +#define Str_conv_to_halfdump(x) (ExtHalfdump ? wc_Str_conv((x), InnerCharset, DisplayCharset) : (x)) +#define conv_from_system(x) wc_conv((x), SystemCharset, InnerCharset)->ptr +#define conv_to_system(x) wc_conv_strict((x), InnerCharset, SystemCharset)->ptr +#define url_quote_conv(x,c) url_quote(wc_conv_strict((x), InnerCharset, (c))->ptr) +#else +#define Str_conv_from_system(x) (x) +#define Str_conv_to_system(x) (x) +#define Str_conv_to_halfdump(x) (x) +#define conv_from_system(x) (x) +#define conv_to_system(x) (x) +#define url_quote_conv(x,c) url_quote(x) +#define wc_Str_conv(x,charset0,charset1) (x) +#define wc_Str_conv_strict(x,charset0,charset1) (x) +#endif +global char UseAltEntity init(TRUE); +global char UseGraphicChar init(FALSE); +extern char *graph_symbol[]; +extern char *graph2_symbol[]; +extern int symbol_width; +extern int symbol_width0; +#define N_GRAPH_SYMBOL 32 +#define SYMBOL_BASE 0x20 +global int no_rc_dir init(FALSE); +global char *rc_dir init(NULL); +global char *tmp_dir; +global char *config_file init(NULL); + +#ifdef USE_MOUSE +global int use_mouse init(TRUE); +extern int mouseActive; +global int reverse_mouse init(FALSE); +global int relative_wheel_scroll init(FALSE); +global int fixed_wheel_scroll_count init(5); +global int relative_wheel_scroll_ratio init(30); +typedef struct _MouseActionMap { + void (*func) (); + char *data; +} MouseActionMap; +typedef struct _MouseAction { + char *menu_str; + char *lastline_str; + int menu_width; + int lastline_width; + int in_action; + int cursorX; + int cursorY; + MouseActionMap default_map[3]; + MouseActionMap anchor_map[3]; + MouseActionMap active_map[3]; + MouseActionMap tab_map[3]; + MouseActionMap *menu_map[3]; + MouseActionMap *lastline_map[3]; +} MouseAction; +global MouseAction mouse_action; +#define LIMIT_MOUSE_MENU 100 +#endif /* USE_MOUSE */ + +#ifdef USE_COOKIE +global int default_use_cookie init(TRUE); +global int use_cookie init(FALSE); +global int show_cookie init(TRUE); +global int accept_cookie init(FALSE); +#define ACCEPT_BAD_COOKIE_DISCARD 0 +#define ACCEPT_BAD_COOKIE_ACCEPT 1 +#define ACCEPT_BAD_COOKIE_ASK 2 +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_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 int set_pixel_per_char init(FALSE); +#ifdef USE_IMAGE +global double pixel_per_line init(DEFAULT_PIXEL_PER_LINE); +global int set_pixel_per_line init(FALSE); +global double image_scale init(100); +#endif +global int use_lessopen init(FALSE); + +global char *keymap_file init(KEYMAP_FILE); + +#ifdef USE_M17N +#define get_mctype(c) ((Lineprop)wtf_type((wc_uchar *)(c)) << 8) +#define get_mclen(c) wtf_len1((wc_uchar *)(c)) +#define get_mcwidth(c) wtf_width((wc_uchar *)(c)) +#define get_strwidth(c) wtf_strwidth((wc_uchar *)(c)) +#define get_Str_strwidth(c) wtf_strwidth((wc_uchar *)((c)->ptr)) +#else +#define get_mctype(c) (IS_CNTRL(*(c)) ? PC_CTRL : PC_ASCII) +#define get_mclen(c) 1 +#define get_mcwidth(c) 1 +#define get_strwidth(c) strlen(c) +#define get_Str_strwidth(c) ((c)->length) +#endif + +global int FollowRedirection init(10); + +global int w3m_backend init(FALSE); +global TextLineList *backend_halfdump_buf; +global TextList *backend_batch_commands init(NULL); +int backend(void); +extern void deleteFiles(void); +void w3m_exit(int i); + +#ifdef USE_ALARM +#define AL_UNSET 0 +#define AL_EXPLICIT 1 +#define AL_IMPLICIT 2 +#define AL_IMPLICIT_ONCE 3 + +typedef struct _AlarmEvent { + int sec; + short status; + int cmd; + void *data; +} AlarmEvent; +#endif + +/* + * Externals + */ + +#include "table.h" +#include "proto.h" + +#endif /* not FM_H */ diff -urN w3m-0.5.2.orig/main.c w3m-0.5.2/main.c --- w3m-0.5.2.orig/main.c 2007-05-31 10:19:50.000000000 +0900 +++ w3m-0.5.2/main.c 2010-07-18 08:13:26.000000000 +0900 @@ -557,9 +557,9 @@ } #endif else if (!strcmp("-graph", argv[i])) - UseGraphicChar = TRUE; + UseGraphicChar = GRAPHIC_CHAR_ALL; else if (!strcmp("-no-graph", argv[i])) - UseGraphicChar = FALSE; + UseGraphicChar = GRAPHIC_CHAR_ASCII; else if (!strcmp("-T", argv[i])) { if (++i >= argc) usage(); diff -urN w3m-0.5.2.orig/main.c.orig w3m-0.5.2/main.c.orig --- w3m-0.5.2.orig/main.c.orig 1970-01-01 09:00:00.000000000 +0900 +++ w3m-0.5.2/main.c.orig 2007-05-31 10:19:50.000000000 +0900 @@ -0,0 +1,6650 @@ +/* $Id: main.c,v 1.258 2007/05/31 01:19:50 inu Exp $ */ +#define MAINPROGRAM +#include "fm.h" +#include +#include +#include +#include +#include +#include +#if defined(HAVE_WAITPID) || defined(HAVE_WAIT3) +#include +#endif +#include +#include "terms.h" +#include "myctype.h" +#include "regex.h" +#ifdef USE_MOUSE +#ifdef USE_GPM +#include +#endif /* USE_GPM */ +#if defined(USE_GPM) || defined(USE_SYSMOUSE) +extern int do_getch(); +#define getch() do_getch() +#endif /* defined(USE_GPM) || defined(USE_SYSMOUSE) */ +#endif + +#ifdef __MINGW32_VERSION +#include + +WSADATA WSAData; +#endif + +#define DSTR_LEN 256 + +Hist *LoadHist; +Hist *SaveHist; +Hist *URLHist; +Hist *ShellHist; +Hist *TextHist; + +typedef struct _Event { + int cmd; + void *data; + struct _Event *next; +} Event; +static Event *CurrentEvent = NULL; +static Event *LastEvent = NULL; + +#ifdef USE_ALARM +static AlarmEvent DefaultAlarm = { + 0, AL_UNSET, FUNCNAME_nulcmd, NULL +}; +static AlarmEvent *CurrentAlarm = &DefaultAlarm; +static MySignalHandler SigAlarm(SIGNAL_ARG); +#endif + +#ifdef SIGWINCH +static int need_resize_screen = FALSE; +static MySignalHandler resize_hook(SIGNAL_ARG); +static void resize_screen(void); +#endif + +#ifdef SIGPIPE +static MySignalHandler SigPipe(SIGNAL_ARG); +#endif + +#ifdef USE_MARK +static char *MarkString = NULL; +#endif +static char *SearchString = NULL; +int (*searchRoutine) (Buffer *, char *); + +#ifndef __MINGW32_VERSION +JMP_BUF IntReturn; +#else +_JBTYPE IntReturn[_JBLEN]; +#endif /* __MINGW32_VERSION */ + +static void delBuffer(Buffer *buf); +static void cmd_loadfile(char *path); +static void cmd_loadURL(char *url, ParsedURL *current, char *referer, + FormList *request); +static void cmd_loadBuffer(Buffer *buf, int prop, int linkid); +static void keyPressEventProc(int c); +int show_params_p = 0; +void show_params(FILE * fp); + +static char *getCurWord(Buffer *buf, int *spos, int *epos, + const char *badchars); + +static int display_ok = FALSE; +static void do_dump(Buffer *); +int prec_num = 0; +int prev_key = -1; +int on_target = 1; +static int add_download_list = FALSE; + +void set_buffer_environ(Buffer *); +static void save_buffer_position(Buffer *buf); + +static void _followForm(int); +static void _goLine(char *); +static void _newT(void); +static void followTab(TabBuffer * tab); +static void moveTab(TabBuffer * t, TabBuffer * t2, int right); +static void _nextA(int); +static void _prevA(int); +static int check_target = TRUE; +#define PREC_NUM (prec_num ? prec_num : 1) +#define PREC_LIMIT 10000 +static int searchKeyNum(void); + +#define help() fusage(stdout, 0) +#define usage() fusage(stderr, 1) + +static void +fversion(FILE * f) +{ + fprintf(f, "w3m version %s, options %s\n", w3m_version, +#if LANG == JA + "lang=ja" +#else + "lang=en" +#endif +#ifdef USE_M17N + ",m17n" +#endif +#ifdef USE_IMAGE + ",image" +#endif +#ifdef USE_COLOR + ",color" +#ifdef USE_ANSI_COLOR + ",ansi-color" +#endif +#endif +#ifdef USE_MOUSE + ",mouse" +#ifdef USE_GPM + ",gpm" +#endif +#ifdef USE_SYSMOUSE + ",sysmouse" +#endif +#endif +#ifdef USE_MENU + ",menu" +#endif +#ifdef USE_COOKIE + ",cookie" +#endif +#ifdef USE_SSL + ",ssl" +#ifdef USE_SSL_VERIFY + ",ssl-verify" +#endif +#endif +#ifdef USE_EXTERNAL_URI_LOADER + ",external-uri-loader" +#endif +#ifdef USE_W3MMAILER + ",w3mmailer" +#endif +#ifdef USE_NNTP + ",nntp" +#endif +#ifdef USE_GOPHER + ",gopher" +#endif +#ifdef INET6 + ",ipv6" +#endif +#ifdef USE_ALARM + ",alarm" +#endif +#ifdef USE_MARK + ",mark" +#endif +#ifdef USE_MIGEMO + ",migemo" +#endif + ); +} + +static void +fusage(FILE * f, int err) +{ + fversion(f); + /* FIXME: gettextize? */ + fprintf(f, "usage: w3m [options] [URL or filename]\noptions:\n"); + fprintf(f, " -t tab set tab width\n"); + fprintf(f, " -r ignore backspace effect\n"); + fprintf(f, " -l line # of preserved line (default 10000)\n"); +#ifdef USE_M17N + fprintf(f, " -I charset document charset\n"); + fprintf(f, " -O charset display/output charset\n"); +#ifndef DEBIAN /* disabled by ukai: -s is used for squeeze multi lines */ + fprintf(f, " -e EUC-JP\n"); + fprintf(f, " -s Shift_JIS\n"); + fprintf(f, " -j JIS\n"); +#endif +#endif + fprintf(f, " -B load bookmark\n"); + fprintf(f, " -bookmark file specify bookmark file\n"); + fprintf(f, " -T type specify content-type\n"); + fprintf(f, " -m internet message mode\n"); + fprintf(f, " -v visual startup mode\n"); +#ifdef USE_COLOR + fprintf(f, " -M monochrome display\n"); +#endif /* USE_COLOR */ + fprintf(f, + " -N open URL of command line on each new tab\n"); + fprintf(f, " -F automatically render frame\n"); + fprintf(f, + " -cols width specify column width (used with -dump)\n"); + fprintf(f, + " -ppc count specify the number of pixels per character (4.0...32.0)\n"); +#ifdef USE_IMAGE + fprintf(f, + " -ppl count specify the number of pixels per line (4.0...64.0)\n"); +#endif + fprintf(f, " -dump dump formatted page into stdout\n"); + fprintf(f, + " -dump_head dump response of HEAD request into stdout\n"); + fprintf(f, " -dump_source dump page source into stdout\n"); + fprintf(f, " -dump_both dump HEAD and source into stdout\n"); + fprintf(f, + " -dump_extra dump HEAD, source, and extra information into stdout\n"); + fprintf(f, " -post file use POST method with file content\n"); + fprintf(f, " -header string insert string as a header\n"); + fprintf(f, " + goto line\n"); + fprintf(f, " -num show line number\n"); + fprintf(f, " -no-proxy don't use proxy\n"); +#ifdef INET6 + fprintf(f, " -4 IPv4 only (-o dns_order=4)\n"); + fprintf(f, " -6 IPv6 only (-o dns_order=6)\n"); +#endif +#ifdef USE_MOUSE + fprintf(f, " -no-mouse don't use mouse\n"); +#endif /* USE_MOUSE */ +#ifdef USE_COOKIE + fprintf(f, + " -cookie use cookie (-no-cookie: don't use cookie)\n"); +#endif /* USE_COOKIE */ + fprintf(f, " -pauth user:pass proxy authentication\n"); + fprintf(f, " -graph use graphic character\n"); + fprintf(f, " -no-graph don't use graphic character\n"); +#ifdef DEBIAN /* replaced by ukai: pager requires -s */ + fprintf(f, " -s squeeze multiple blank lines\n"); +#else + fprintf(f, " -S squeeze multiple blank lines\n"); +#endif + fprintf(f, " -W toggle wrap search mode\n"); + fprintf(f, " -X don't use termcap init/deinit\n"); + fprintf(f, + " -title[=TERM] set buffer name to terminal title string\n"); + fprintf(f, " -o opt=value assign value to config option\n"); + fprintf(f, " -show-option print all config options\n"); + fprintf(f, " -config file specify config file\n"); + fprintf(f, " -help print this usage message\n"); + fprintf(f, " -version print w3m version\n"); + fprintf(f, " -reqlog write request logfile\n"); + fprintf(f, " -debug DO NOT USE\n"); + if (show_params_p) + show_params(f); + exit(err); +} + +#ifdef USE_M17N +#ifdef __EMX__ +static char *getCodePage(void); +#endif +#endif + +static GC_warn_proc orig_GC_warn_proc = NULL; +#define GC_WARN_KEEP_MAX (20) + +static void +wrap_GC_warn_proc(char *msg, GC_word arg) +{ + if (fmInitialized) { + /* *INDENT-OFF* */ + static struct { + char *msg; + GC_word arg; + } msg_ring[GC_WARN_KEEP_MAX]; + /* *INDENT-ON* */ + static int i = 0; + static int n = 0; + static int lock = 0; + int j; + + j = (i + n) % (sizeof(msg_ring) / sizeof(msg_ring[0])); + msg_ring[j].msg = msg; + msg_ring[j].arg = arg; + + if (n < sizeof(msg_ring) / sizeof(msg_ring[0])) + ++n; + else + ++i; + + if (!lock) { + lock = 1; + + for (; n > 0; --n, ++i) { + i %= sizeof(msg_ring) / sizeof(msg_ring[0]); + + printf(msg_ring[i].msg, (unsigned long)msg_ring[i].arg); + sleep_till_anykey(1, 1); + } + + lock = 0; + } + } + else if (orig_GC_warn_proc) + orig_GC_warn_proc(msg, arg); + else + fprintf(stderr, msg, (unsigned long)arg); +} + +#ifdef SIGCHLD +static void +sig_chld(int signo) +{ + int p_stat; +#ifdef HAVE_WAITPID + pid_t pid; + + while ((pid = waitpid(-1, &p_stat, WNOHANG)) > 0) { + ; + } +#elif HAVE_WAIT3 + int pid; + + while ((pid = wait3(&p_stat, WNOHANG, NULL)) > 0) { + ; + } +#else + wait(&p_stat); +#endif + mySignal(SIGCHLD, sig_chld); + return; +} +#endif + +Str +make_optional_header_string(char *s) +{ + char *p; + Str hs; + + if (strchr(s, '\n') || strchr(s, '\r')) + return NULL; + for (p = s; *p && *p != ':'; p++) ; + if (*p != ':' || p == s) + return NULL; + hs = Strnew_size(strlen(s) + 3); + Strcopy_charp_n(hs, s, p - s); + if (!Strcasecmp_charp(hs, "content-type")) + override_content_type = TRUE; + Strcat_charp(hs, ": "); + if (*(++p)) { /* not null header */ + SKIP_BLANKS(p); /* skip white spaces */ + Strcat_charp(hs, p); + } + Strcat_charp(hs, "\r\n"); + return hs; +} + +int +main(int argc, char **argv, char **envp) +{ + Buffer *newbuf = NULL; + char *p, c; + int i; + InputStream redin; + char *line_str = NULL; + char **load_argv; + FormList *request; + int load_argc = 0; + int load_bookmark = FALSE; + int visual_start = FALSE; + int open_new_tab = FALSE; + char search_header = FALSE; + char *default_type = NULL; + char *post_file = NULL; + Str err_msg; +#ifdef USE_M17N + char *Locale = NULL; + wc_uint8 auto_detect; +#ifdef __EMX__ + wc_ces CodePage; +#endif +#endif + GC_INIT(); +#if defined(ENABLE_NLS) || (defined(USE_M17N) && defined(HAVE_LANGINFO_CODESET)) + setlocale(LC_ALL, ""); +#endif +#ifdef ENABLE_NLS + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); +#endif + +#ifndef HAVE_SYS_ERRLIST + prepare_sys_errlist(); +#endif /* not HAVE_SYS_ERRLIST */ + + NO_proxy_domains = newTextList(); + fileToDelete = newTextList(); + + load_argv = New_N(char *, argc - 1); + load_argc = 0; + + CurrentDir = currentdir(); + CurrentPid = (int)getpid(); + BookmarkFile = NULL; + config_file = NULL; + + /* argument search 1 */ + for (i = 1; i < argc; i++) { + if (*argv[i] == '-') { + if (!strcmp("-config", argv[i])) { + argv[i] = "-dummy"; + if (++i >= argc) + usage(); + config_file = argv[i]; + argv[i] = "-dummy"; + } + else if (!strcmp("-h", argv[i]) || !strcmp("-help", argv[i])) + help(); + else if (!strcmp("-V", argv[i]) || !strcmp("-version", argv[i])) { + fversion(stdout); + exit(0); + } + } + } + +#ifdef USE_M17N + if (non_null(Locale = getenv("LC_ALL")) || + non_null(Locale = getenv("LC_CTYPE")) || + non_null(Locale = getenv("LANG"))) { + DisplayCharset = wc_guess_locale_charset(Locale, DisplayCharset); + DocumentCharset = wc_guess_locale_charset(Locale, DocumentCharset); + SystemCharset = wc_guess_locale_charset(Locale, SystemCharset); + } +#ifdef __EMX__ + CodePage = wc_guess_charset(getCodePage(), 0); + if (CodePage) + DisplayCharset = DocumentCharset = SystemCharset = CodePage; +#endif +#endif + + /* initializations */ + init_rc(); + + LoadHist = newHist(); + SaveHist = newHist(); + ShellHist = newHist(); + TextHist = newHist(); + URLHist = newHist(); + +#ifdef USE_M17N + if (FollowLocale && Locale) { + DisplayCharset = wc_guess_locale_charset(Locale, DisplayCharset); + SystemCharset = wc_guess_locale_charset(Locale, SystemCharset); + } + auto_detect = WcOption.auto_detect; + BookmarkCharset = DocumentCharset; +#endif + + if (!non_null(HTTP_proxy) && + ((p = getenv("HTTP_PROXY")) || + (p = getenv("http_proxy")) || (p = getenv("HTTP_proxy")))) + HTTP_proxy = p; +#ifdef USE_SSL + if (!non_null(HTTPS_proxy) && + ((p = getenv("HTTPS_PROXY")) || + (p = getenv("https_proxy")) || (p = getenv("HTTPS_proxy")))) + HTTPS_proxy = p; + if (HTTPS_proxy == NULL && non_null(HTTP_proxy)) + HTTPS_proxy = HTTP_proxy; +#endif /* USE_SSL */ +#ifdef USE_GOPHER + if (!non_null(GOPHER_proxy) && + ((p = getenv("GOPHER_PROXY")) || + (p = getenv("gopher_proxy")) || (p = getenv("GOPHER_proxy")))) + GOPHER_proxy = p; +#endif /* USE_GOPHER */ + if (!non_null(FTP_proxy) && + ((p = getenv("FTP_PROXY")) || + (p = getenv("ftp_proxy")) || (p = getenv("FTP_proxy")))) + FTP_proxy = p; + if (!non_null(NO_proxy) && + ((p = getenv("NO_PROXY")) || + (p = getenv("no_proxy")) || (p = getenv("NO_proxy")))) + NO_proxy = p; +#ifdef USE_NNTP + if (!non_null(NNTP_server) && (p = getenv("NNTPSERVER")) != NULL) + NNTP_server = p; + if (!non_null(NNTP_mode) && (p = getenv("NNTPMODE")) != NULL) + NNTP_mode = p; +#endif + + if (!non_null(Editor) && (p = getenv("EDITOR")) != NULL) + Editor = p; + if (!non_null(Mailer) && (p = getenv("MAILER")) != NULL) + Mailer = p; + + /* argument search 2 */ + i = 1; + while (i < argc) { + if (*argv[i] == '-') { + if (!strcmp("-t", argv[i])) { + if (++i >= argc) + usage(); + if (atoi(argv[i]) > 0) + Tabstop = atoi(argv[i]); + } + else if (!strcmp("-r", argv[i])) + ShowEffect = FALSE; + else if (!strcmp("-l", argv[i])) { + if (++i >= argc) + usage(); + if (atoi(argv[i]) > 0) + PagerMax = atoi(argv[i]); + } +#ifdef USE_M17N +#ifndef DEBIAN /* XXX: use -o kanjicode={S|J|E} */ + else if (!strcmp("-s", argv[i])) + DisplayCharset = WC_CES_SHIFT_JIS; + else if (!strcmp("-j", argv[i])) + DisplayCharset = WC_CES_ISO_2022_JP; + else if (!strcmp("-e", argv[i])) + DisplayCharset = WC_CES_EUC_JP; +#endif + else if (!strncmp("-I", argv[i], 2)) { + if (argv[i][2] != '\0') + p = argv[i] + 2; + else { + if (++i >= argc) + usage(); + p = argv[i]; + } + DocumentCharset = wc_guess_charset_short(p, DocumentCharset); + WcOption.auto_detect = WC_OPT_DETECT_OFF; + UseContentCharset = FALSE; + } + else if (!strncmp("-O", argv[i], 2)) { + if (argv[i][2] != '\0') + p = argv[i] + 2; + else { + if (++i >= argc) + usage(); + p = argv[i]; + } + DisplayCharset = wc_guess_charset_short(p, DisplayCharset); + } +#endif + else if (!strcmp("-graph", argv[i])) + UseGraphicChar = TRUE; + else if (!strcmp("-no-graph", argv[i])) + UseGraphicChar = FALSE; + else if (!strcmp("-T", argv[i])) { + if (++i >= argc) + usage(); + DefaultType = default_type = argv[i]; + } + else if (!strcmp("-m", argv[i])) + SearchHeader = search_header = TRUE; + else if (!strcmp("-v", argv[i])) + visual_start = TRUE; + else if (!strcmp("-N", argv[i])) + open_new_tab = TRUE; +#ifdef USE_COLOR + else if (!strcmp("-M", argv[i])) + useColor = FALSE; +#endif /* USE_COLOR */ + else if (!strcmp("-B", argv[i])) + load_bookmark = TRUE; + else if (!strcmp("-bookmark", argv[i])) { + if (++i >= argc) + usage(); + BookmarkFile = argv[i]; + if (BookmarkFile[0] != '~' && BookmarkFile[0] != '/') { + Str tmp = Strnew_charp(CurrentDir); + if (Strlastchar(tmp) != '/') + Strcat_char(tmp, '/'); + Strcat_charp(tmp, BookmarkFile); + BookmarkFile = cleanupName(tmp->ptr); + } + } + else if (!strcmp("-F", argv[i])) + RenderFrame = TRUE; + else if (!strcmp("-W", argv[i])) { + if (WrapDefault) + WrapDefault = FALSE; + else + WrapDefault = TRUE; + } + else if (!strcmp("-dump", argv[i])) + w3m_dump = DUMP_BUFFER; + else if (!strcmp("-dump_source", argv[i])) + w3m_dump = DUMP_SOURCE; + else if (!strcmp("-dump_head", argv[i])) + w3m_dump = DUMP_HEAD; + else if (!strcmp("-dump_both", argv[i])) + w3m_dump = (DUMP_HEAD | DUMP_SOURCE); + else if (!strcmp("-dump_extra", argv[i])) + w3m_dump = (DUMP_HEAD | DUMP_SOURCE | DUMP_EXTRA); + else if (!strcmp("-halfdump", argv[i])) + w3m_dump = DUMP_HALFDUMP; + else if (!strcmp("-halfload", argv[i])) { + w3m_dump = 0; + w3m_halfload = TRUE; + DefaultType = default_type = "text/html"; + } + else if (!strcmp("-backend", argv[i])) { + w3m_backend = TRUE; + } + else if (!strcmp("-backend_batch", argv[i])) { + w3m_backend = TRUE; + if (++i >= argc) + usage(); + if (!backend_batch_commands) + backend_batch_commands = newTextList(); + pushText(backend_batch_commands, argv[i]); + } + else if (!strcmp("-cols", argv[i])) { + if (++i >= argc) + usage(); + COLS = atoi(argv[i]); + } + else if (!strcmp("-ppc", argv[i])) { + double ppc; + if (++i >= argc) + usage(); + ppc = atof(argv[i]); + if (ppc >= MINIMUM_PIXEL_PER_CHAR && + ppc <= MAXIMUM_PIXEL_PER_CHAR) { + pixel_per_char = ppc; + set_pixel_per_char = TRUE; + } + } +#ifdef USE_IMAGE + else if (!strcmp("-ppl", argv[i])) { + double ppc; + if (++i >= argc) + usage(); + ppc = atof(argv[i]); + if (ppc >= MINIMUM_PIXEL_PER_CHAR && + ppc <= MAXIMUM_PIXEL_PER_CHAR * 2) { + pixel_per_line = ppc; + set_pixel_per_line = TRUE; + } + } +#endif + else if (!strcmp("-num", argv[i])) + showLineNum = TRUE; + else if (!strcmp("-no-proxy", argv[i])) + use_proxy = FALSE; +#ifdef INET6 + else if (!strcmp("-4", argv[i]) || !strcmp("-6", argv[i])) + set_param_option(Sprintf("dns_order=%c", argv[i][1])->ptr); +#endif + else if (!strcmp("-post", argv[i])) { + if (++i >= argc) + usage(); + post_file = argv[i]; + } + else if (!strcmp("-header", argv[i])) { + Str hs; + if (++i >= argc) + usage(); + if ((hs = make_optional_header_string(argv[i])) != NULL) { + if (header_string == NULL) + header_string = hs; + else + Strcat(header_string, hs); + } + while (argv[i][0]) { + argv[i][0] = '\0'; + argv[i]++; + } + } +#ifdef USE_MOUSE + else if (!strcmp("-no-mouse", argv[i])) { + use_mouse = FALSE; + } +#endif /* USE_MOUSE */ +#ifdef USE_COOKIE + else if (!strcmp("-no-cookie", argv[i])) { + use_cookie = FALSE; + accept_cookie = FALSE; + } + else if (!strcmp("-cookie", argv[i])) { + use_cookie = TRUE; + accept_cookie = TRUE; + } +#endif /* USE_COOKIE */ + else if (!strcmp("-pauth", argv[i])) { + if (++i >= argc) + usage(); + proxy_auth_cookie = Strnew_m_charp("Basic ", + encodeB(argv[i])->ptr, + NULL); + while (argv[i][0]) { + argv[i][0] = '\0'; + argv[i]++; + } + } +#ifdef DEBIAN + else if (!strcmp("-s", argv[i])) +#else + else if (!strcmp("-S", argv[i])) +#endif + squeezeBlankLine = TRUE; + else if (!strcmp("-X", argv[i])) + Do_not_use_ti_te = TRUE; + else if (!strcmp("-title", argv[i])) + displayTitleTerm = getenv("TERM"); + else if (!strncmp("-title=", argv[i], 7)) + displayTitleTerm = argv[i] + 7; + else if (!strcmp("-o", argv[i]) || + !strcmp("-show-option", argv[i])) { + if (!strcmp("-show-option", argv[i]) || ++i >= argc || + !strcmp(argv[i], "?")) { + show_params(stdout); + exit(0); + } + if (!set_param_option(argv[i])) { + /* option set failed */ + /* FIXME: gettextize? */ + fprintf(stderr, "%s: bad option\n", argv[i]); + show_params_p = 1; + usage(); + } + } + else if (!strcmp("-dummy", argv[i])) { + /* do nothing */ + } + else if (!strcmp("-debug", argv[i])) { + w3m_debug = TRUE; + } + else if (!strcmp("-reqlog",argv[i])) { + w3m_reqlog=rcFile("request.log"); + } + else { + usage(); + } + } + else if (*argv[i] == '+') { + line_str = argv[i] + 1; + } + else { + load_argv[load_argc++] = argv[i]; + } + i++; + } + +#ifdef __WATT32__ + if (w3m_debug) + dbug_init(); + sock_init(); +#endif + +#ifdef __MINGW32_VERSION + { + int err; + WORD wVerReq; + + wVerReq = MAKEWORD(1, 1); + + err = WSAStartup(wVerReq, &WSAData); + if (err != 0) + { + fprintf(stderr, "Can't find winsock\n"); + return 1; + } + _fmode = _O_BINARY; + } +#endif + + FirstTab = NULL; + LastTab = NULL; + nTab = 0; + CurrentTab = NULL; + CurrentKey = -1; + if (BookmarkFile == NULL) + BookmarkFile = rcFile(BOOKMARK); + + if (!isatty(1) && !w3m_dump) { + /* redirected output */ + w3m_dump = DUMP_BUFFER; + } + if (w3m_dump) { + if (COLS == 0) + COLS = 80; + } + +#ifdef USE_BINMODE_STREAM + setmode(fileno(stdout), O_BINARY); +#endif + if (!w3m_dump && !w3m_backend) { + fmInit(); +#ifdef SIGWINCH + mySignal(SIGWINCH, resize_hook); +#else /* not SIGWINCH */ + setlinescols(); + setupscreen(); +#endif /* not SIGWINCH */ + } +#ifdef USE_IMAGE + else if (w3m_halfdump && displayImage) + activeImage = TRUE; +#endif + + sync_with_option(); +#ifdef USE_COOKIE + initCookie(); +#endif /* USE_COOKIE */ +#ifdef USE_HISTORY + if (UseHistory) + loadHistory(URLHist); +#endif /* not USE_HISTORY */ + +#ifdef USE_M17N + wtf_init(DocumentCharset, DisplayCharset); + /* if (w3m_dump) + * WcOption.pre_conv = WC_TRUE; + */ +#endif + + if (w3m_backend) + backend(); + + if (w3m_dump) + mySignal(SIGINT, SIG_IGN); +#ifdef SIGCHLD + mySignal(SIGCHLD, sig_chld); +#endif +#ifdef SIGPIPE + mySignal(SIGPIPE, SigPipe); +#endif + + orig_GC_warn_proc = GC_set_warn_proc(wrap_GC_warn_proc); + err_msg = Strnew(); + if (load_argc == 0) { + /* no URL specified */ + if (!isatty(0)) { + redin = newFileStream(fdopen(dup(0), "rb"), (void (*)())pclose); + newbuf = openGeneralPagerBuffer(redin); + dup2(1, 0); + } + else if (load_bookmark) { + newbuf = loadGeneralFile(BookmarkFile, NULL, NO_REFERER, 0, NULL); + if (newbuf == NULL) + Strcat_charp(err_msg, "w3m: Can't load bookmark.\n"); + } + else if (visual_start) { + /* FIXME: gettextize? */ + Str s_page; + s_page = + Strnew_charp + ("W3M startup page
Welcome to "); + Strcat_charp(s_page, ""); + Strcat_m_charp(s_page, + "w3m!

This is w3m version ", + w3m_version, + "
Written by Akinori Ito", + NULL); +#ifdef DEBIAN + Strcat_m_charp(s_page, + "

Debian package is maintained by Fumitoshi UKAI.", + "You can read w3m documents on your local system.", + NULL); +#endif /* DEBIAN */ + newbuf = loadHTMLString(s_page); + if (newbuf == NULL) + Strcat_charp(err_msg, "w3m: Can't load string.\n"); + else if (newbuf != NO_BUFFER) + newbuf->bufferprop |= (BP_INTERNAL | BP_NO_URL); + } + else if ((p = getenv("HTTP_HOME")) != NULL || + (p = getenv("WWW_HOME")) != NULL) { + newbuf = loadGeneralFile(p, NULL, NO_REFERER, 0, NULL); + if (newbuf == NULL) + Strcat(err_msg, Sprintf("w3m: Can't load %s.\n", p)); + else if (newbuf != NO_BUFFER) + pushHashHist(URLHist, parsedURL2Str(&newbuf->currentURL)->ptr); + } + else { + if (fmInitialized) + fmTerm(); + usage(); + } + if (newbuf == NULL) { + if (fmInitialized) + fmTerm(); + if (err_msg->length) + fprintf(stderr, "%s", err_msg->ptr); + w3m_exit(2); + } + i = -1; + } + else { + i = 0; + } + for (; i < load_argc; i++) { + if (i >= 0) { + SearchHeader = search_header; + DefaultType = default_type; + if (w3m_dump == DUMP_HEAD) { + request = New(FormList); + request->method = FORM_METHOD_HEAD; + newbuf = + loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0, + request); + } + else { + if (post_file && i == 0) { + FILE *fp; + Str body; + if (!strcmp(post_file, "-")) + fp = stdin; + else + fp = fopen(post_file, "r"); + if (fp == NULL) { + /* FIXME: gettextize? */ + Strcat(err_msg, + Sprintf("w3m: Can't open %s.\n", post_file)); + continue; + } + body = Strfgetall(fp); + if (fp != stdin) + fclose(fp); + request = + newFormList(NULL, "post", NULL, NULL, NULL, NULL, + NULL); + request->body = body->ptr; + request->boundary = NULL; + request->length = body->length; + } + else { + request = NULL; + } + newbuf = + loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0, + request); + } + if (newbuf == NULL) { + /* FIXME: gettextize? */ + Strcat(err_msg, + Sprintf("w3m: Can't load %s.\n", load_argv[i])); + continue; + } + else if (newbuf == NO_BUFFER) + continue; + switch (newbuf->real_scheme) { + case SCM_MAILTO: + break; + case SCM_LOCAL: + case SCM_LOCAL_CGI: + unshiftHist(LoadHist, conv_from_system(load_argv[i])); + default: + pushHashHist(URLHist, parsedURL2Str(&newbuf->currentURL)->ptr); + break; + } + } + else if (newbuf == NO_BUFFER) + continue; + if (newbuf->pagerSource || + (newbuf->real_scheme == SCM_LOCAL && newbuf->header_source && + newbuf->currentURL.file && strcmp(newbuf->currentURL.file, "-"))) + newbuf->search_header = search_header; + if (CurrentTab == NULL) { + FirstTab = LastTab = CurrentTab = newTab(); + nTab = 1; + Firstbuf = Currentbuf = newbuf; + } + else if (open_new_tab) { + _newT(); + Currentbuf->nextBuffer = newbuf; + delBuffer(Currentbuf); + } + else { + Currentbuf->nextBuffer = newbuf; + Currentbuf = newbuf; + } + if (!w3m_dump || w3m_dump == DUMP_BUFFER) { + if (Currentbuf->frameset != NULL && RenderFrame) + rFrame(); + } + if (w3m_dump) + do_dump(Currentbuf); + else { + Currentbuf = newbuf; +#ifdef USE_BUFINFO + saveBufferInfo(); +#endif + } + } + if (w3m_dump) { + if (err_msg->length) + fprintf(stderr, "%s", err_msg->ptr); +#ifdef USE_COOKIE + save_cookies(); +#endif /* USE_COOKIE */ + w3m_exit(0); + } + + if (add_download_list) { + add_download_list = FALSE; + CurrentTab = LastTab; + if (!FirstTab) { + FirstTab = LastTab = CurrentTab = newTab(); + nTab = 1; + } + if (!Firstbuf || Firstbuf == NO_BUFFER) { + Firstbuf = Currentbuf = newBuffer(INIT_BUFFER_WIDTH); + Currentbuf->bufferprop = BP_INTERNAL | BP_NO_URL; + Currentbuf->buffername = DOWNLOAD_LIST_TITLE; + } + else + Currentbuf = Firstbuf; + ldDL(); + } + else + CurrentTab = FirstTab; + if (!FirstTab || !Firstbuf || Firstbuf == NO_BUFFER) { + if (newbuf == NO_BUFFER) { + if (fmInitialized) + /* FIXME: gettextize? */ + inputChar("Hit any key to quit w3m:"); + } + if (fmInitialized) + fmTerm(); + if (err_msg->length) + fprintf(stderr, "%s", err_msg->ptr); + if (newbuf == NO_BUFFER) { +#ifdef USE_COOKIE + save_cookies(); +#endif /* USE_COOKIE */ + if (!err_msg->length) + w3m_exit(0); + } + w3m_exit(2); + } + if (err_msg->length) + disp_message_nsec(err_msg->ptr, FALSE, 1, TRUE, FALSE); + + SearchHeader = FALSE; + DefaultType = NULL; +#ifdef USE_M17N + UseContentCharset = TRUE; + WcOption.auto_detect = auto_detect; +#endif + + Currentbuf = Firstbuf; + displayBuffer(Currentbuf, B_FORCE_REDRAW); + if (line_str) { + _goLine(line_str); + } + for (;;) { + if (add_download_list) { + add_download_list = FALSE; + ldDL(); + } + if (Currentbuf->submit) { + Anchor *a = Currentbuf->submit; + Currentbuf->submit = NULL; + gotoLine(Currentbuf, a->start.line); + Currentbuf->pos = a->start.pos; + _followForm(TRUE); + continue; + } + /* event processing */ + if (CurrentEvent) { + CurrentKey = -1; + CurrentKeyData = NULL; + CurrentCmdData = (char *)CurrentEvent->data; + w3mFuncList[CurrentEvent->cmd].func(); + CurrentCmdData = NULL; + CurrentEvent = CurrentEvent->next; + continue; + } + /* get keypress event */ +#ifdef USE_ALARM + if (Currentbuf->event) { + if (Currentbuf->event->status != AL_UNSET) { + CurrentAlarm = Currentbuf->event; + if (CurrentAlarm->sec == 0) { /* refresh (0sec) */ + Currentbuf->event = NULL; + CurrentKey = -1; + CurrentKeyData = NULL; + CurrentCmdData = (char *)CurrentAlarm->data; + w3mFuncList[CurrentAlarm->cmd].func(); + CurrentCmdData = NULL; + continue; + } + } + else + Currentbuf->event = NULL; + } + if (!Currentbuf->event) + CurrentAlarm = &DefaultAlarm; +#endif +#ifdef USE_MOUSE + mouse_action.in_action = FALSE; + if (use_mouse) + mouse_active(); +#endif /* USE_MOUSE */ +#ifdef USE_ALARM + if (CurrentAlarm->sec > 0) { + mySignal(SIGALRM, SigAlarm); + alarm(CurrentAlarm->sec); + } +#endif +#ifdef SIGWINCH + mySignal(SIGWINCH, resize_hook); +#endif +#ifdef USE_IMAGE + if (activeImage && displayImage && Currentbuf->img && + !Currentbuf->image_loaded) { + do { +#ifdef SIGWINCH + if (need_resize_screen) + resize_screen(); +#endif + loadImage(Currentbuf, IMG_FLAG_NEXT); + } while (sleep_till_anykey(1, 0) <= 0); + } +#ifdef SIGWINCH + else +#endif +#endif +#ifdef SIGWINCH + { + do { + if (need_resize_screen) + resize_screen(); + } while (sleep_till_anykey(1, 0) <= 0); + } +#endif + c = getch(); +#ifdef USE_ALARM + if (CurrentAlarm->sec > 0) { + alarm(0); + } +#endif +#ifdef USE_MOUSE + if (use_mouse) + mouse_inactive(); +#endif /* USE_MOUSE */ + if (IS_ASCII(c)) { /* Ascii */ + if( vi_prec_num ){ + if(((prec_num && c == '0') || '1' <= c) && (c <= '9')) { + prec_num = prec_num * 10 + (int)(c - '0'); + if (prec_num > PREC_LIMIT) + prec_num = PREC_LIMIT; + } + else { + set_buffer_environ(Currentbuf); + save_buffer_position(Currentbuf); + keyPressEventProc((int)c); + prec_num = 0; + } + } + else { + set_buffer_environ(Currentbuf); + save_buffer_position(Currentbuf); + keyPressEventProc((int)c); + prec_num = 0; + } + } + prev_key = CurrentKey; + CurrentKey = -1; + CurrentKeyData = NULL; + } +} + +static void +keyPressEventProc(int c) +{ + CurrentKey = c; + w3mFuncList[(int)GlobalKeymap[c]].func(); +} + +void +pushEvent(int cmd, void *data) +{ + Event *event; + + event = New(Event); + event->cmd = cmd; + event->data = data; + event->next = NULL; + if (CurrentEvent) + LastEvent->next = event; + else + CurrentEvent = event; + LastEvent = event; +} + +static void +dump_source(Buffer *buf) +{ + FILE *f; + char c; + if (buf->sourcefile == NULL) + return; + f = fopen(buf->sourcefile, "r"); + if (f == NULL) + return; + while (c = fgetc(f), !feof(f)) { + putchar(c); + } + fclose(f); +} + +static void +dump_head(Buffer *buf) +{ + TextListItem *ti; + + if (buf->document_header == NULL) { + if (w3m_dump & DUMP_EXTRA) + printf("\n"); + return; + } + for (ti = buf->document_header->first; ti; ti = ti->next) { +#ifdef USE_M17N + printf("%s", + wc_conv_strict(ti->ptr, InnerCharset, + buf->document_charset)->ptr); +#else + printf("%s", ti->ptr); +#endif + } + puts(""); +} + +static void +dump_extra(Buffer *buf) +{ + printf("W3m-current-url: %s\n", parsedURL2Str(&buf->currentURL)->ptr); + if (buf->baseURL) + printf("W3m-base-url: %s\n", parsedURL2Str(buf->baseURL)->ptr); +#ifdef USE_M17N + printf("W3m-document-charset: %s\n", + wc_ces_to_charset(buf->document_charset)); +#endif +#ifdef USE_SSL + if (buf->ssl_certificate) { + Str tmp = Strnew(); + char *p; + for (p = buf->ssl_certificate; *p; p++) { + Strcat_char(tmp, *p); + if (*p == '\n') { + for (; *(p + 1) == '\n'; p++) ; + if (*(p + 1)) + Strcat_char(tmp, '\t'); + } + } + if (Strlastchar(tmp) != '\n') + Strcat_char(tmp, '\n'); + printf("W3m-ssl-certificate: %s", tmp->ptr); + } +#endif +} + +static void +do_dump(Buffer *buf) +{ + MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL; + + prevtrap = mySignal(SIGINT, intTrap); + if (SETJMP(IntReturn) != 0) { + mySignal(SIGINT, prevtrap); + return; + } + if (w3m_dump & DUMP_EXTRA) + dump_extra(buf); + if (w3m_dump & DUMP_HEAD) + dump_head(buf); + if (w3m_dump & DUMP_SOURCE) + dump_source(buf); + if (w3m_dump == DUMP_BUFFER) + saveBuffer(buf, stdout, FALSE); + mySignal(SIGINT, prevtrap); +} + +DEFUN(nulcmd, NOTHING NULL @@@, "Do nothing") +{ /* do nothing */ +} + +#ifdef __EMX__ +DEFUN(pcmap, PCMAP, "pcmap") +{ + w3mFuncList[(int)PcKeymap[(int)getch()]].func(); +} +#else /* not __EMX__ */ +void +pcmap(void) +{ +} +#endif + +static void +escKeyProc(int c, int esc, unsigned char *map) +{ + if (CurrentKey >= 0 && CurrentKey & K_MULTI) { + unsigned char **mmap; + mmap = (unsigned char **)getKeyData(MULTI_KEY(CurrentKey)); + if (!mmap) + return; + switch (esc) { + case K_ESCD: + map = mmap[3]; + break; + case K_ESCB: + map = mmap[2]; + break; + case K_ESC: + map = mmap[1]; + break; + default: + map = mmap[0]; + break; + } + esc |= (CurrentKey & ~0xFFFF); + } + CurrentKey = esc | c; + w3mFuncList[(int)map[c]].func(); +} + +DEFUN(escmap, ESCMAP, "ESC map") +{ + char c; + c = getch(); + if (IS_ASCII(c)) + escKeyProc((int)c, K_ESC, EscKeymap); +} + +DEFUN(escbmap, ESCBMAP, "ESC [ map") +{ + char c; + c = getch(); + if (IS_DIGIT(c)) { + escdmap(c); + return; + } + if (IS_ASCII(c)) + escKeyProc((int)c, K_ESCB, EscBKeymap); +} + +void +escdmap(char c) +{ + int d; + d = (int)c - (int)'0'; + c = getch(); + if (IS_DIGIT(c)) { + d = d * 10 + (int)c - (int)'0'; + c = getch(); + } + if (c == '~') + escKeyProc((int)d, K_ESCD, EscDKeymap); +} + +DEFUN(multimap, MULTIMAP, "multimap") +{ + char c; + c = getch(); + if (IS_ASCII(c)) { + CurrentKey = K_MULTI | (CurrentKey << 16) | c; + escKeyProc((int)c, 0, NULL); + } +} + +void +tmpClearBuffer(Buffer *buf) +{ + if (buf->pagerSource == NULL && writeBufferCache(buf) == 0) { + buf->firstLine = NULL; + buf->topLine = NULL; + buf->currentLine = NULL; + buf->lastLine = NULL; + } +} + +static Str currentURL(void); + +#ifdef USE_BUFINFO +void +saveBufferInfo() +{ + FILE *fp; + + if (w3m_dump) + return; + if ((fp = fopen(rcFile("bufinfo"), "w")) == NULL) { + return; + } + fprintf(fp, "%s\n", currentURL()->ptr); + fclose(fp); +} +#endif + +static void +pushBuffer(Buffer *buf) +{ + Buffer *b; + +#ifdef USE_IMAGE + deleteImage(Currentbuf); +#endif + if (clear_buffer) + tmpClearBuffer(Currentbuf); + if (Firstbuf == Currentbuf) { + buf->nextBuffer = Firstbuf; + Firstbuf = Currentbuf = buf; + } + else if ((b = prevBuffer(Firstbuf, Currentbuf)) != NULL) { + b->nextBuffer = buf; + buf->nextBuffer = Currentbuf; + Currentbuf = buf; + } +#ifdef USE_BUFINFO + saveBufferInfo(); +#endif + +} + +static void +delBuffer(Buffer *buf) +{ + if (buf == NULL) + return; + if (Currentbuf == buf) + Currentbuf = buf->nextBuffer; + Firstbuf = deleteBuffer(Firstbuf, buf); + if (!Currentbuf) + Currentbuf = Firstbuf; +} + +static void +repBuffer(Buffer *oldbuf, Buffer *buf) +{ + Firstbuf = replaceBuffer(Firstbuf, oldbuf, buf); + Currentbuf = buf; +} + + +MySignalHandler +intTrap(SIGNAL_ARG) +{ /* Interrupt catcher */ + LONGJMP(IntReturn, 0); + SIGNAL_RETURN; +} + +#ifdef SIGWINCH +static MySignalHandler +resize_hook(SIGNAL_ARG) +{ + need_resize_screen = TRUE; + mySignal(SIGWINCH, resize_hook); + SIGNAL_RETURN; +} + +static void +resize_screen(void) +{ + need_resize_screen = FALSE; + setlinescols(); + setupscreen(); + if (CurrentTab) + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} +#endif /* SIGWINCH */ + +#ifdef SIGPIPE +static MySignalHandler +SigPipe(SIGNAL_ARG) +{ +#ifdef USE_MIGEMO + init_migemo(); +#endif + mySignal(SIGPIPE, SigPipe); + SIGNAL_RETURN; +} +#endif + +/* + * Command functions: These functions are called with a keystroke. + */ + +static void +nscroll(int n, int mode) +{ + Buffer *buf = Currentbuf; + Line *top = buf->topLine, *cur = buf->currentLine; + int lnum, tlnum, llnum, diff_n; + + if (buf->firstLine == NULL) + return; + lnum = cur->linenumber; + buf->topLine = lineSkip(buf, top, n, FALSE); + if (buf->topLine == top) { + lnum += n; + if (lnum < buf->topLine->linenumber) + lnum = buf->topLine->linenumber; + else if (lnum > buf->lastLine->linenumber) + lnum = buf->lastLine->linenumber; + } + else { + tlnum = buf->topLine->linenumber; + llnum = buf->topLine->linenumber + buf->LINES - 1; + if (nextpage_topline) + diff_n = 0; + else + diff_n = n - (tlnum - top->linenumber); + if (lnum < tlnum) + lnum = tlnum + diff_n; + if (lnum > llnum) + lnum = llnum + diff_n; + } + gotoLine(buf, lnum); + arrangeLine(buf); + if (n > 0) { + if (buf->currentLine->bpos && + buf->currentLine->bwidth >= buf->currentColumn + buf->visualpos) + cursorDown(buf, 1); + else { + while (buf->currentLine->next && buf->currentLine->next->bpos && + buf->currentLine->bwidth + buf->currentLine->width < + buf->currentColumn + buf->visualpos) + cursorDown0(buf, 1); + } + } + else { + if (buf->currentLine->bwidth + buf->currentLine->width < + buf->currentColumn + buf->visualpos) + cursorUp(buf, 1); + else { + while (buf->currentLine->prev && buf->currentLine->bpos && + buf->currentLine->bwidth >= + buf->currentColumn + buf->visualpos) + cursorUp0(buf, 1); + } + } + displayBuffer(buf, mode); +} + +/* Move page forward */ +DEFUN(pgFore, NEXT_PAGE, "Move to next page") +{ + if (vi_prec_num) + nscroll(searchKeyNum() * (Currentbuf->LINES - 1), B_NORMAL); + else + nscroll(prec_num ? searchKeyNum() : searchKeyNum() + * (Currentbuf->LINES - 1), prec_num ? B_SCROLL : B_NORMAL); +} + +/* Move page backward */ +DEFUN(pgBack, PREV_PAGE, "Move to previous page") +{ + if (vi_prec_num) + nscroll(-searchKeyNum() * (Currentbuf->LINES - 1), B_NORMAL); + else + nscroll(-(prec_num ? searchKeyNum() : searchKeyNum() + * (Currentbuf->LINES - 1)), prec_num ? B_SCROLL : B_NORMAL); +} + +/* 1 line up */ +DEFUN(lup1, UP, "Scroll up one line") +{ + nscroll(searchKeyNum(), B_SCROLL); +} + +/* 1 line down */ +DEFUN(ldown1, DOWN, "Scroll down one line") +{ + nscroll(-searchKeyNum(), B_SCROLL); +} + +/* move cursor position to the center of screen */ +DEFUN(ctrCsrV, CENTER_V, "Move to the center column") +{ + int offsety; + if (Currentbuf->firstLine == NULL) + return; + offsety = Currentbuf->LINES / 2 - Currentbuf->cursorY; + if (offsety != 0) { +#if 0 + Currentbuf->currentLine = lineSkip(Currentbuf, + Currentbuf->currentLine, offsety, + FALSE); +#endif + Currentbuf->topLine = + lineSkip(Currentbuf, Currentbuf->topLine, -offsety, FALSE); + arrangeLine(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); + } +} + +DEFUN(ctrCsrH, CENTER_H, "Move to the center line") +{ + int offsetx; + if (Currentbuf->firstLine == NULL) + return; + offsetx = Currentbuf->cursorX - Currentbuf->COLS / 2; + if (offsetx != 0) { + columnSkip(Currentbuf, offsetx); + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); + } +} + +/* Redraw screen */ +DEFUN(rdrwSc, REDRAW, "Redraw screen") +{ + clear(); + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +static void +clear_mark(Line *l) +{ + int pos; + if (!l) + return; + for (pos = 0; pos < l->size; pos++) + l->propBuf[pos] &= ~PE_MARK; +} + +/* search by regular expression */ +static int +srchcore(char *volatile str, int (*func) (Buffer *, char *)) +{ + MySignalHandler(*prevtrap) (); + volatile int i, result = SR_NOTFOUND; + + if (str != NULL && str != SearchString) + SearchString = str; + if (SearchString == NULL || *SearchString == '\0') + return SR_NOTFOUND; + + str = conv_search_string(SearchString, DisplayCharset); + prevtrap = mySignal(SIGINT, intTrap); + crmode(); + if (SETJMP(IntReturn) == 0) { + for (i = 0; i < PREC_NUM; i++) { + result = func(Currentbuf, str); + if (i < PREC_NUM - 1 && result & SR_FOUND) + clear_mark(Currentbuf->currentLine); + } + } + mySignal(SIGINT, prevtrap); + term_raw(); + return result; +} + +static void +disp_srchresult(int result, char *prompt, char *str) +{ + if (str == NULL) + str = ""; + if (result & SR_NOTFOUND) + disp_message(Sprintf("Not found: %s", str)->ptr, TRUE); + else if (result & SR_WRAPPED) + disp_message(Sprintf("Search wrapped: %s", str)->ptr, TRUE); + else if (show_srch_str) + disp_message(Sprintf("%s%s", prompt, str)->ptr, TRUE); +} + +static int +dispincsrch(int ch, Str buf, Lineprop *prop) +{ + static Buffer sbuf; + static Line *currentLine; + static int pos; + char *str; + int do_next_search = FALSE; + + if (ch == 0 && buf == NULL) { + SAVE_BUFPOSITION(&sbuf); /* search starting point */ + currentLine = sbuf.currentLine; + pos = sbuf.pos; + return -1; + } + + str = buf->ptr; + switch (ch) { + case 022: /* C-r */ + searchRoutine = backwardSearch; + do_next_search = TRUE; + break; + case 023: /* C-s */ + searchRoutine = forwardSearch; + do_next_search = TRUE; + break; + +#ifdef USE_MIGEMO + case 034: + migemo_active = -migemo_active; + goto done; +#endif + + default: + if (ch >= 0) + return ch; /* use InputKeymap */ + } + + if (do_next_search) { + if (*str) { + if (searchRoutine == forwardSearch) + Currentbuf->pos += 1; + SAVE_BUFPOSITION(&sbuf); + if (srchcore(str, searchRoutine) == SR_NOTFOUND + && searchRoutine == forwardSearch) { + Currentbuf->pos -= 1; + SAVE_BUFPOSITION(&sbuf); + } + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_FORCE_REDRAW); + clear_mark(Currentbuf->currentLine); + return -1; + } + else + return 020; /* _prev completion for C-s C-s */ + } + else if (*str) { + RESTORE_BUFPOSITION(&sbuf); + arrangeCursor(Currentbuf); + srchcore(str, searchRoutine); + arrangeCursor(Currentbuf); + currentLine = Currentbuf->currentLine; + pos = Currentbuf->pos; + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); + clear_mark(Currentbuf->currentLine); +#ifdef USE_MIGEMO + done: + while (*str++ != '\0') { + if (migemo_active > 0) + *prop++ |= PE_UNDER; + else + *prop++ &= ~PE_UNDER; + } +#endif + return -1; +} + +void +isrch(int (*func) (Buffer *, char *), char *prompt) +{ + char *str; + Buffer sbuf; + SAVE_BUFPOSITION(&sbuf); + dispincsrch(0, NULL, NULL); /* initialize incremental search state */ + + searchRoutine = func; + str = inputLineHistSearch(prompt, NULL, IN_STRING, TextHist, dispincsrch); + if (str == NULL) { + RESTORE_BUFPOSITION(&sbuf); + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +void +srch(int (*func) (Buffer *, char *), char *prompt) +{ + char *str; + int result; + int disp = FALSE; + int pos; + + str = searchKeyData(); + if (str == NULL || *str == '\0') { + str = inputStrHist(prompt, NULL, TextHist); + if (str != NULL && *str == '\0') + str = SearchString; + if (str == NULL) { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + disp = TRUE; + } + pos = Currentbuf->pos; + if (func == forwardSearch) + Currentbuf->pos += 1; + result = srchcore(str, func); + if (result & SR_FOUND) + clear_mark(Currentbuf->currentLine); + else + Currentbuf->pos = pos; + displayBuffer(Currentbuf, B_NORMAL); + if (disp) + disp_srchresult(result, prompt, str); + searchRoutine = func; +} + +/* Search regular expression forward */ + +DEFUN(srchfor, SEARCH SEARCH_FORE WHEREIS, "Search forward") +{ + srch(forwardSearch, "Forward: "); +} + +DEFUN(isrchfor, ISEARCH, "Incremental search forward") +{ + isrch(forwardSearch, "I-search: "); +} + +/* Search regular expression backward */ + +DEFUN(srchbak, SEARCH_BACK, "Search backward") +{ + srch(backwardSearch, "Backward: "); +} + +DEFUN(isrchbak, ISEARCH_BACK, "Incremental search backward") +{ + isrch(backwardSearch, "I-search backward: "); +} + +static void +srch_nxtprv(int reverse) +{ + int result; + /* *INDENT-OFF* */ + static int (*routine[2]) (Buffer *, char *) = { + forwardSearch, backwardSearch + }; + /* *INDENT-ON* */ + + if (searchRoutine == NULL) { + /* FIXME: gettextize? */ + disp_message("No previous regular expression", TRUE); + return; + } + if (reverse != 0) + reverse = 1; + if (searchRoutine == backwardSearch) + reverse ^= 1; + if (reverse == 0) + Currentbuf->pos += 1; + result = srchcore(SearchString, routine[reverse]); + if (result & SR_FOUND) + clear_mark(Currentbuf->currentLine); + displayBuffer(Currentbuf, B_NORMAL); + disp_srchresult(result, (reverse ? "Backward: " : "Forward: "), + SearchString); +} + +/* Search next matching */ +DEFUN(srchnxt, SEARCH_NEXT, "Search next regexp") +{ + srch_nxtprv(0); +} + +/* Search previous matching */ +DEFUN(srchprv, SEARCH_PREV, "Search previous regexp") +{ + srch_nxtprv(1); +} + +static void +shiftvisualpos(Buffer *buf, int shift) +{ + Line *l = buf->currentLine; + buf->visualpos -= shift; + if (buf->visualpos - l->bwidth >= buf->COLS) + buf->visualpos = l->bwidth + buf->COLS - 1; + else if (buf->visualpos - l->bwidth < 0) + buf->visualpos = l->bwidth; + arrangeLine(buf); + if (buf->visualpos - l->bwidth == -shift && buf->cursorX == 0) + buf->visualpos = l->bwidth; +} + +/* Shift screen left */ +DEFUN(shiftl, SHIFT_LEFT, "Shift screen left") +{ + int column; + + if (Currentbuf->firstLine == NULL) + return; + column = Currentbuf->currentColumn; + columnSkip(Currentbuf, searchKeyNum() * (-Currentbuf->COLS + 1) + 1); + shiftvisualpos(Currentbuf, Currentbuf->currentColumn - column); + displayBuffer(Currentbuf, B_NORMAL); +} + +/* Shift screen right */ +DEFUN(shiftr, SHIFT_RIGHT, "Shift screen right") +{ + int column; + + if (Currentbuf->firstLine == NULL) + return; + column = Currentbuf->currentColumn; + columnSkip(Currentbuf, searchKeyNum() * (Currentbuf->COLS - 1) - 1); + shiftvisualpos(Currentbuf, Currentbuf->currentColumn - column); + displayBuffer(Currentbuf, B_NORMAL); +} + +DEFUN(col1R, RIGHT, "Shift screen one column right") +{ + Buffer *buf = Currentbuf; + Line *l = buf->currentLine; + int j, column, n = searchKeyNum(); + + if (l == NULL) + return; + for (j = 0; j < n; j++) { + column = buf->currentColumn; + columnSkip(Currentbuf, 1); + if (column == buf->currentColumn) + break; + shiftvisualpos(Currentbuf, 1); + } + displayBuffer(Currentbuf, B_NORMAL); +} + +DEFUN(col1L, LEFT, "Shift screen one column") +{ + Buffer *buf = Currentbuf; + Line *l = buf->currentLine; + int j, n = searchKeyNum(); + + if (l == NULL) + return; + for (j = 0; j < n; j++) { + if (buf->currentColumn == 0) + break; + columnSkip(Currentbuf, -1); + shiftvisualpos(Currentbuf, -1); + } + displayBuffer(Currentbuf, B_NORMAL); +} + +DEFUN(setEnv, SETENV, "Set environment variable") +{ + char *env; + char *var, *value; + + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + env = searchKeyData(); + if (env == NULL || *env == '\0' || strchr(env, '=') == NULL) { + if (env != NULL && *env != '\0') + env = Sprintf("%s=", env)->ptr; + env = inputStrHist("Set environ: ", env, TextHist); + if (env == NULL || *env == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + } + if ((value = strchr(env, '=')) != NULL && value > env) { + var = allocStr(env, value - env); + value++; + set_environ(var, value); + } + displayBuffer(Currentbuf, B_NORMAL); +} + +DEFUN(pipeBuf, PIPE_BUF, "Send rendered document to pipe") +{ + Buffer *buf; + char *cmd, *tmpf; + FILE *f; + + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + cmd = searchKeyData(); + if (cmd == NULL || *cmd == '\0') { + /* FIXME: gettextize? */ + cmd = inputLineHist("Pipe buffer to: ", "", IN_COMMAND, ShellHist); + } + if (cmd != NULL) + cmd = conv_to_system(cmd); + if (cmd == NULL || *cmd == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + tmpf = tmpfname(TMPF_DFL, NULL)->ptr; + f = fopen(tmpf, "w"); + if (f == NULL) { + /* FIXME: gettextize? */ + disp_message(Sprintf("Can't save buffer to %s", cmd)->ptr, TRUE); + return; + } + saveBuffer(Currentbuf, f, TRUE); + fclose(f); + buf = getpipe(myExtCommand(cmd, shell_quote(tmpf), TRUE)->ptr); + if (buf == NULL) { + disp_message("Execution failed", TRUE); + return; + } + else { + buf->filename = cmd; + buf->buffername = Sprintf("%s %s", PIPEBUFFERNAME, + conv_from_system(cmd))->ptr; + buf->bufferprop |= (BP_INTERNAL | BP_NO_URL); + if (buf->type == NULL) + buf->type = "text/plain"; + buf->currentURL.file = "-"; + pushBuffer(buf); + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* Execute shell command and read output ac pipe. */ +DEFUN(pipesh, PIPE_SHELL, "Execute shell command and browse") +{ + Buffer *buf; + char *cmd; + + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + cmd = searchKeyData(); + if (cmd == NULL || *cmd == '\0') { + cmd = inputLineHist("(read shell[pipe])!", "", IN_COMMAND, ShellHist); + } + if (cmd != NULL) + cmd = conv_to_system(cmd); + if (cmd == NULL || *cmd == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + buf = getpipe(cmd); + if (buf == NULL) { + disp_message("Execution failed", TRUE); + return; + } + else { + buf->bufferprop |= (BP_INTERNAL | BP_NO_URL); + if (buf->type == NULL) + buf->type = "text/plain"; + pushBuffer(buf); + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* Execute shell command and load entire output to buffer */ +DEFUN(readsh, READ_SHELL, "Execute shell command and load") +{ + Buffer *buf; + MySignalHandler(*prevtrap) (); + char *cmd; + + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + cmd = searchKeyData(); + if (cmd == NULL || *cmd == '\0') { + cmd = inputLineHist("(read shell)!", "", IN_COMMAND, ShellHist); + } + if (cmd != NULL) + cmd = conv_to_system(cmd); + if (cmd == NULL || *cmd == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + prevtrap = mySignal(SIGINT, intTrap); + crmode(); + buf = getshell(cmd); + mySignal(SIGINT, prevtrap); + term_raw(); + if (buf == NULL) { + /* FIXME: gettextize? */ + disp_message("Execution failed", TRUE); + return; + } + else { + buf->bufferprop |= (BP_INTERNAL | BP_NO_URL); + if (buf->type == NULL) + buf->type = "text/plain"; + pushBuffer(buf); + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* Execute shell command */ +DEFUN(execsh, EXEC_SHELL SHELL, "Execute shell command") +{ + char *cmd; + + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + cmd = searchKeyData(); + if (cmd == NULL || *cmd == '\0') { + cmd = inputLineHist("(exec shell)!", "", IN_COMMAND, ShellHist); + } + if (cmd != NULL) + cmd = conv_to_system(cmd); + if (cmd != NULL && *cmd != '\0') { + fmTerm(); + printf("\n"); + system(cmd); + /* FIXME: gettextize? */ + printf("\n[Hit any key]"); + fflush(stdout); + fmInit(); + getch(); + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* Load file */ +DEFUN(ldfile, LOAD, "Load local file") +{ + char *fn; + + fn = searchKeyData(); + if (fn == NULL || *fn == '\0') { + /* FIXME: gettextize? */ + fn = inputFilenameHist("(Load)Filename? ", NULL, LoadHist); + } + if (fn != NULL) + fn = conv_to_system(fn); + if (fn == NULL || *fn == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + cmd_loadfile(fn); +} + +/* Load help file */ +DEFUN(ldhelp, HELP, "View help") +{ +#ifdef USE_HELP_CGI + char *lang; + int n; + Str tmp; + + lang = AcceptLang; + n = strcspn(lang, ";, \t"); + tmp = Sprintf("file:///$LIB/" HELP_CGI CGI_EXTENSION "?version=%s&lang=%s", + Str_form_quote(Strnew_charp(w3m_version))->ptr, + Str_form_quote(Strnew_charp_n(lang, n))->ptr); + cmd_loadURL(tmp->ptr, NULL, NO_REFERER, NULL); +#else + cmd_loadURL(helpFile(HELP_FILE), NULL, NO_REFERER, NULL); +#endif +} + +static void +cmd_loadfile(char *fn) +{ + Buffer *buf; + + buf = loadGeneralFile(file_to_url(fn), NULL, NO_REFERER, 0, NULL); + if (buf == NULL) { + /* FIXME: gettextize? */ + char *emsg = Sprintf("%s not found", conv_from_system(fn))->ptr; + disp_err_message(emsg, FALSE); + } + else if (buf != NO_BUFFER) { + pushBuffer(buf); + if (RenderFrame && Currentbuf->frameset != NULL) + rFrame(); + } + displayBuffer(Currentbuf, B_NORMAL); +} + +/* Move cursor left */ +static void +_movL(int n) +{ + int i, m = searchKeyNum(); + if (Currentbuf->firstLine == NULL) + return; + for (i = 0; i < m; i++) + cursorLeft(Currentbuf, n); + displayBuffer(Currentbuf, B_NORMAL); +} + +DEFUN(movL, MOVE_LEFT, + "Move cursor left (a half screen shift at the left edge)") +{ + _movL(Currentbuf->COLS / 2); +} + +DEFUN(movL1, MOVE_LEFT1, "Move cursor left (1 columns shift at the left edge)") +{ + _movL(1); +} + +/* Move cursor downward */ +static void +_movD(int n) +{ + int i, m = searchKeyNum(); + if (Currentbuf->firstLine == NULL) + return; + for (i = 0; i < m; i++) + cursorDown(Currentbuf, n); + displayBuffer(Currentbuf, B_NORMAL); +} + +DEFUN(movD, MOVE_DOWN, + "Move cursor down (a half screen scroll at the end of screen)") +{ + _movD((Currentbuf->LINES + 1) / 2); +} + +DEFUN(movD1, MOVE_DOWN1, + "Move cursor down (1 line scroll at the end of screen)") +{ + _movD(1); +} + +/* move cursor upward */ +static void +_movU(int n) +{ + int i, m = searchKeyNum(); + if (Currentbuf->firstLine == NULL) + return; + for (i = 0; i < m; i++) + cursorUp(Currentbuf, n); + displayBuffer(Currentbuf, B_NORMAL); +} + +DEFUN(movU, MOVE_UP, + "Move cursor up (a half screen scroll at the top of screen)") +{ + _movU((Currentbuf->LINES + 1) / 2); +} + +DEFUN(movU1, MOVE_UP1, "Move cursor up (1 line scrol at the top of screen)") +{ + _movU(1); +} + +/* Move cursor right */ +static void +_movR(int n) +{ + int i, m = searchKeyNum(); + if (Currentbuf->firstLine == NULL) + return; + for (i = 0; i < m; i++) + cursorRight(Currentbuf, n); + displayBuffer(Currentbuf, B_NORMAL); +} + +DEFUN(movR, MOVE_RIGHT, + "Move cursor right (a half screen shift at the right edge)") +{ + _movR(Currentbuf->COLS / 2); +} + +DEFUN(movR1, MOVE_RIGHT1, + "Move cursor right (1 columns shift at the right edge)") +{ + _movR(1); +} + +/* movLW, movRW */ +/* + * From: Takashi Nishimoto Date: Mon, 14 Jun + * 1999 09:29:56 +0900 + */ +#define IS_WORD_CHAR(c,p) (IS_ALNUM(c) && CharType(p) == PC_ASCII) + +static int +prev_nonnull_line(Line *line) +{ + Line *l; + + for (l = line; l != NULL && l->len == 0; l = l->prev) ; + if (l == NULL || l->len == 0) + return -1; + + Currentbuf->currentLine = l; + if (l != line) + Currentbuf->pos = Currentbuf->currentLine->len; + return 0; +} + +DEFUN(movLW, PREV_WORD, "Move to previous word") +{ + char *lb; + Lineprop *pb; + Line *pline; + int ppos; + int i, n = searchKeyNum(); + + if (Currentbuf->firstLine == NULL) + return; + + for (i = 0; i < n; i++) { + pline = Currentbuf->currentLine; + ppos = Currentbuf->pos; + + if (prev_nonnull_line(Currentbuf->currentLine) < 0) + goto end; + + while (1) { + lb = Currentbuf->currentLine->lineBuf; + pb = Currentbuf->currentLine->propBuf; + while (Currentbuf->pos > 0 && + !IS_WORD_CHAR(lb[Currentbuf->pos - 1], + pb[Currentbuf->pos - 1])) { + Currentbuf->pos--; + } + if (Currentbuf->pos > 0) + break; + if (prev_nonnull_line(Currentbuf->currentLine->prev) < 0) { + Currentbuf->currentLine = pline; + Currentbuf->pos = ppos; + goto end; + } + Currentbuf->pos = Currentbuf->currentLine->len; + } + + lb = Currentbuf->currentLine->lineBuf; + pb = Currentbuf->currentLine->propBuf; + while (Currentbuf->pos > 0 && + IS_WORD_CHAR(lb[Currentbuf->pos - 1], + pb[Currentbuf->pos - 1])) { + Currentbuf->pos--; + } + } + end: + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); +} + +static int +next_nonnull_line(Line *line) +{ + Line *l; + + for (l = line; l != NULL && l->len == 0; l = l->next) ; + + if (l == NULL || l->len == 0) + return -1; + + Currentbuf->currentLine = l; + if (l != line) + Currentbuf->pos = 0; + return 0; +} + +DEFUN(movRW, NEXT_WORD, "Move to next word") +{ + char *lb; + Lineprop *pb; + Line *pline; + int ppos; + int i, n = searchKeyNum(); + + if (Currentbuf->firstLine == NULL) + return; + + for (i = 0; i < n; i++) { + pline = Currentbuf->currentLine; + ppos = Currentbuf->pos; + + if (next_nonnull_line(Currentbuf->currentLine) < 0) + goto end; + + lb = Currentbuf->currentLine->lineBuf; + pb = Currentbuf->currentLine->propBuf; + + while (lb[Currentbuf->pos] && + IS_WORD_CHAR(lb[Currentbuf->pos], pb[Currentbuf->pos])) + Currentbuf->pos++; + + while (1) { + while (lb[Currentbuf->pos] && + !IS_WORD_CHAR(lb[Currentbuf->pos], pb[Currentbuf->pos])) + Currentbuf->pos++; + if (lb[Currentbuf->pos]) + break; + if (next_nonnull_line(Currentbuf->currentLine->next) < 0) { + Currentbuf->currentLine = pline; + Currentbuf->pos = ppos; + goto end; + } + Currentbuf->pos = 0; + lb = Currentbuf->currentLine->lineBuf; + pb = Currentbuf->currentLine->propBuf; + } + } + end: + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); +} + +static void +_quitfm(int confirm) +{ + char *ans = "y"; + + if (checkDownloadList()) + /* FIXME: gettextize? */ + ans = inputChar("Download process retains. " + "Do you want to exit w3m? (y/n)"); + else if (confirm) + /* FIXME: gettextize? */ + ans = inputChar("Do you want to exit w3m? (y/n)"); + if (!(ans && TOLOWER(*ans) == 'y')) { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + + term_title(""); /* XXX */ +#ifdef USE_IMAGE + if (activeImage) + termImage(); +#endif + fmTerm(); +#ifdef USE_COOKIE + save_cookies(); +#endif /* USE_COOKIE */ +#ifdef USE_HISTORY + if (UseHistory && SaveURLHist) + saveHistory(URLHist, URLHistSize); +#endif /* USE_HISTORY */ + w3m_exit(0); +} + +/* Quit */ +DEFUN(quitfm, ABORT EXIT, "Quit w3m without confirmation") +{ + _quitfm(FALSE); +} + +/* Question and Quit */ +DEFUN(qquitfm, QUIT, "Quit w3m") +{ + _quitfm(confirm_on_quit); +} + +/* Select buffer */ +DEFUN(selBuf, SELECT, "Go to buffer selection panel") +{ + Buffer *buf; + int ok; + char cmd; + + ok = FALSE; + do { + buf = selectBuffer(Firstbuf, Currentbuf, &cmd); + switch (cmd) { + case 'B': + ok = TRUE; + break; + case '\n': + case ' ': + Currentbuf = buf; + ok = TRUE; + break; + case 'D': + delBuffer(buf); + if (Firstbuf == NULL) { + /* No more buffer */ + Firstbuf = nullBuffer(); + Currentbuf = Firstbuf; + } + break; + case 'q': + qquitfm(); + break; + case 'Q': + quitfm(); + break; + } + } while (!ok); + + for (buf = Firstbuf; buf != NULL; buf = buf->nextBuffer) { + if (buf == Currentbuf) + continue; +#ifdef USE_IMAGE + deleteImage(buf); +#endif + if (clear_buffer) + tmpClearBuffer(buf); + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* Suspend (on BSD), or run interactive shell (on SysV) */ +DEFUN(susp, INTERRUPT SUSPEND, "Stop loading document") +{ +#ifndef SIGSTOP + char *shell; +#endif /* not SIGSTOP */ + move(LASTLINE, 0); + clrtoeolx(); + refresh(); + fmTerm(); +#ifndef SIGSTOP + shell = getenv("SHELL"); + if (shell == NULL) + shell = "/bin/sh"; + system(shell); +#else /* SIGSTOP */ + kill((pid_t) 0, SIGSTOP); +#endif /* SIGSTOP */ + fmInit(); + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* Go to specified line */ +static void +_goLine(char *l) +{ + if (l == NULL || *l == '\0' || Currentbuf->currentLine == NULL) { + displayBuffer(Currentbuf, B_FORCE_REDRAW); + return; + } + Currentbuf->pos = 0; + if (((*l == '^') || (*l == '$')) && prec_num) { + gotoRealLine(Currentbuf, prec_num); + } + else if (*l == '^') { + Currentbuf->topLine = Currentbuf->currentLine = Currentbuf->firstLine; + } + else if (*l == '$') { + Currentbuf->topLine = + lineSkip(Currentbuf, Currentbuf->lastLine, + -(Currentbuf->LINES + 1) / 2, TRUE); + Currentbuf->currentLine = Currentbuf->lastLine; + } + else + gotoRealLine(Currentbuf, atoi(l)); + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +DEFUN(goLine, GOTO_LINE, "Go to specified line") +{ + + char *str = searchKeyData(); + if (prec_num) + _goLine("^"); + else if (str) + _goLine(str); + else + /* FIXME: gettextize? */ + _goLine(inputStr("Goto line: ", "")); +} + + +DEFUN(goLineF, BEGIN, "Go to the first line") +{ + _goLine("^"); +} + +DEFUN(goLineL, END, "Go to the last line") +{ + _goLine("$"); +} + +/* Go to the beginning of the line */ +DEFUN(linbeg, LINE_BEGIN, "Go to the beginning of line") +{ + if (Currentbuf->firstLine == NULL) + return; + while (Currentbuf->currentLine->prev && Currentbuf->currentLine->bpos) + cursorUp0(Currentbuf, 1); + Currentbuf->pos = 0; + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); +} + +/* Go to the bottom of the line */ +DEFUN(linend, LINE_END, "Go to the end of line") +{ + if (Currentbuf->firstLine == NULL) + return; + while (Currentbuf->currentLine->next + && Currentbuf->currentLine->next->bpos) + cursorDown0(Currentbuf, 1); + Currentbuf->pos = Currentbuf->currentLine->len - 1; + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); +} + +static int +cur_real_linenumber(Buffer *buf) +{ + Line *l, *cur = buf->currentLine; + int n; + + if (!cur) + return 1; + n = cur->real_linenumber ? cur->real_linenumber : 1; + for (l = buf->firstLine; l && l != cur && l->real_linenumber == 0; l = l->next) { /* header */ + if (l->bpos == 0) + n++; + } + return n; +} + +/* Run editor on the current buffer */ +DEFUN(editBf, EDIT, "Edit current document") +{ + char *fn = Currentbuf->filename; + Str cmd; + + if (fn == NULL || Currentbuf->pagerSource != NULL || /* Behaving as a pager */ + (Currentbuf->type == NULL && Currentbuf->edit == NULL) || /* Reading shell */ + Currentbuf->real_scheme != SCM_LOCAL || !strcmp(Currentbuf->currentURL.file, "-") || /* file is std input */ + Currentbuf->bufferprop & BP_FRAME) { /* Frame */ + disp_err_message("Can't edit other than local file", TRUE); + return; + } + if (Currentbuf->edit) + cmd = unquote_mailcap(Currentbuf->edit, Currentbuf->real_type, fn, + checkHeader(Currentbuf, "Content-Type:"), NULL); + else + cmd = myEditor(Editor, shell_quote(fn), + cur_real_linenumber(Currentbuf)); + fmTerm(); + system(cmd->ptr); + fmInit(); + + displayBuffer(Currentbuf, B_FORCE_REDRAW); + reload(); +} + +/* Run editor on the current screen */ +DEFUN(editScr, EDIT_SCREEN, "Edit currently rendered document") +{ + char *tmpf; + FILE *f; + + tmpf = tmpfname(TMPF_DFL, NULL)->ptr; + f = fopen(tmpf, "w"); + if (f == NULL) { + /* FIXME: gettextize? */ + disp_err_message(Sprintf("Can't open %s", tmpf)->ptr, TRUE); + return; + } + saveBuffer(Currentbuf, f, TRUE); + fclose(f); + fmTerm(); + system(myEditor(Editor, shell_quote(tmpf), + cur_real_linenumber(Currentbuf))->ptr); + fmInit(); + unlink(tmpf); + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +#ifdef USE_MARK + +/* Set / unset mark */ +DEFUN(_mark, MARK, "Set/unset mark") +{ + Line *l; + if (!use_mark) + return; + if (Currentbuf->firstLine == NULL) + return; + l = Currentbuf->currentLine; + l->propBuf[Currentbuf->pos] ^= PE_MARK; + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* Go to next mark */ +DEFUN(nextMk, NEXT_MARK, "Move to next word") +{ + Line *l; + int i; + + if (!use_mark) + return; + if (Currentbuf->firstLine == NULL) + return; + i = Currentbuf->pos + 1; + l = Currentbuf->currentLine; + if (i >= l->len) { + i = 0; + l = l->next; + } + while (l != NULL) { + for (; i < l->len; i++) { + if (l->propBuf[i] & PE_MARK) { + Currentbuf->currentLine = l; + Currentbuf->pos = i; + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); + return; + } + } + l = l->next; + i = 0; + } + /* FIXME: gettextize? */ + disp_message("No mark exist after here", TRUE); +} + +/* Go to previous mark */ +DEFUN(prevMk, PREV_MARK, "Move to previous mark") +{ + Line *l; + int i; + + if (!use_mark) + return; + if (Currentbuf->firstLine == NULL) + return; + i = Currentbuf->pos - 1; + l = Currentbuf->currentLine; + if (i < 0) { + l = l->prev; + if (l != NULL) + i = l->len - 1; + } + while (l != NULL) { + for (; i >= 0; i--) { + if (l->propBuf[i] & PE_MARK) { + Currentbuf->currentLine = l; + Currentbuf->pos = i; + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); + return; + } + } + l = l->prev; + if (l != NULL) + i = l->len - 1; + } + /* FIXME: gettextize? */ + disp_message("No mark exist before here", TRUE); +} + +/* Mark place to which the regular expression matches */ +DEFUN(reMark, REG_MARK, "Set mark using regexp") +{ + Line *l; + char *str; + char *p, *p1, *p2; + + if (!use_mark) + return; + str = searchKeyData(); + if (str == NULL || *str == '\0') { + str = inputStrHist("(Mark)Regexp: ", MarkString, TextHist); + if (str == NULL || *str == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + } + str = conv_search_string(str, DisplayCharset); + if ((str = regexCompile(str, 1)) != NULL) { + disp_message(str, TRUE); + return; + } + MarkString = str; + for (l = Currentbuf->firstLine; l != NULL; l = l->next) { + p = l->lineBuf; + for (;;) { + if (regexMatch(p, &l->lineBuf[l->len] - p, p == l->lineBuf) == 1) { + matchedPosition(&p1, &p2); + l->propBuf[p1 - l->lineBuf] |= PE_MARK; + p = p2; + } + else + break; + } + } + + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} +#endif /* USE_MARK */ + +static Buffer * +loadNormalBuf(Buffer *buf, int renderframe) +{ + pushBuffer(buf); + if (renderframe && RenderFrame && Currentbuf->frameset != NULL) + rFrame(); + return buf; +} + +static Buffer * +loadLink(char *url, char *target, char *referer, FormList *request) +{ + Buffer *buf, *nfbuf; + union frameset_element *f_element = NULL; + int flag = 0; + ParsedURL *base, pu; + + message(Sprintf("loading %s", url)->ptr, 0, 0); + refresh(); + + base = baseURL(Currentbuf); + if (base == NULL || + base->scheme == SCM_LOCAL || base->scheme == SCM_LOCAL_CGI) + referer = NO_REFERER; + if (referer == NULL) + referer = parsedURL2Str(&Currentbuf->currentURL)->ptr; + buf = loadGeneralFile(url, baseURL(Currentbuf), referer, flag, request); + if (buf == NULL) { + char *emsg = Sprintf("Can't load %s", url)->ptr; + disp_err_message(emsg, FALSE); + return NULL; + } + + parseURL2(url, &pu, base); + pushHashHist(URLHist, parsedURL2Str(&pu)->ptr); + + if (buf == NO_BUFFER) { + return NULL; + } + if (!on_target) /* open link as an indivisual page */ + return loadNormalBuf(buf, TRUE); + + if (do_download) /* download (thus no need to render frame) */ + return loadNormalBuf(buf, FALSE); + + if (target == NULL || /* no target specified (that means this page is not a frame page) */ + !strcmp(target, "_top") || /* this link is specified to be opened as an indivisual * page */ + !(Currentbuf->bufferprop & BP_FRAME) /* This page is not a frame page */ + ) { + return loadNormalBuf(buf, TRUE); + } + nfbuf = Currentbuf->linkBuffer[LB_N_FRAME]; + if (nfbuf == NULL) { + /* original page (that contains tag) doesn't exist */ + return loadNormalBuf(buf, TRUE); + } + + f_element = search_frame(nfbuf->frameset, target); + if (f_element == NULL) { + /* specified target doesn't exist in this frameset */ + return loadNormalBuf(buf, TRUE); + } + + /* frame page */ + + /* stack current frameset */ + pushFrameTree(&(nfbuf->frameQ), copyFrameSet(nfbuf->frameset), Currentbuf); + /* delete frame view buffer */ + delBuffer(Currentbuf); + Currentbuf = nfbuf; + /* nfbuf->frameset = copyFrameSet(nfbuf->frameset); */ + resetFrameElement(f_element, buf, referer, request); + discardBuffer(buf); + rFrame(); + { + Anchor *al = NULL; + char *label = pu.label; + + if (label && f_element->element->attr == F_BODY) { + al = searchAnchor(f_element->body->nameList, label); + } + if (!al) { + label = Strnew_m_charp("_", target, NULL)->ptr; + al = searchURLLabel(Currentbuf, label); + } + if (al) { + gotoLine(Currentbuf, al->start.line); + if (label_topline) + Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->topLine, + Currentbuf->currentLine-> + linenumber - + Currentbuf->topLine->linenumber, + FALSE); + Currentbuf->pos = al->start.pos; + arrangeCursor(Currentbuf); + } + } + displayBuffer(Currentbuf, B_NORMAL); + return buf; +} + +static void +gotoLabel(char *label) +{ + Buffer *buf; + Anchor *al; + int i; + + al = searchURLLabel(Currentbuf, label); + if (al == NULL) { + /* FIXME: gettextize? */ + disp_message(Sprintf("%s is not found", label)->ptr, TRUE); + return; + } + buf = newBuffer(Currentbuf->width); + copyBuffer(buf, Currentbuf); + for (i = 0; i < MAX_LB; i++) + buf->linkBuffer[i] = NULL; + buf->currentURL.label = allocStr(label, -1); + pushHashHist(URLHist, parsedURL2Str(&buf->currentURL)->ptr); + (*buf->clone)++; + pushBuffer(buf); + gotoLine(Currentbuf, al->start.line); + if (label_topline) + Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->topLine, + Currentbuf->currentLine->linenumber + - Currentbuf->topLine->linenumber, + FALSE); + Currentbuf->pos = al->start.pos; + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_FORCE_REDRAW); + return; +} + +/* follow HREF link */ +DEFUN(followA, GOTO_LINK, "Go to current link") +{ + Line *l; + Anchor *a; + ParsedURL u; +#ifdef USE_IMAGE + int x = 0, y = 0, map = 0; +#endif + char *url; + + if (Currentbuf->firstLine == NULL) + return; + l = Currentbuf->currentLine; + +#ifdef USE_IMAGE + a = retrieveCurrentImg(Currentbuf); + if (a && a->image && a->image->map) { + _followForm(FALSE); + return; + } + if (a && a->image && a->image->ismap) { + getMapXY(Currentbuf, a, &x, &y); + map = 1; + } +#else + a = retrieveCurrentMap(Currentbuf); + if (a) { + _followForm(FALSE); + return; + } +#endif + a = retrieveCurrentAnchor(Currentbuf); + if (a == NULL) { + _followForm(FALSE); + return; + } + if (*a->url == '#') { /* index within this buffer */ + gotoLabel(a->url + 1); + return; + } + parseURL2(a->url, &u, baseURL(Currentbuf)); + if (Strcmp(parsedURL2Str(&u), parsedURL2Str(&Currentbuf->currentURL)) == 0) { + /* index within this buffer */ + if (u.label) { + gotoLabel(u.label); + return; + } + } + if (!strncasecmp(a->url, "mailto:", 7) +#ifdef USE_W3MMAILER + && non_null(Mailer) && strchr(a->url, '?') == NULL +#endif + ) { + /* invoke external mailer */ + Str to = Strnew_charp(a->url + 7); +#ifndef USE_W3MMAILER + char *pos; + if (!non_null(Mailer)) { + /* FIXME: gettextize? */ + disp_err_message("no mailer is specified", TRUE); + return; + } + if ((pos = strchr(to->ptr, '?')) != NULL) + Strtruncate(to, pos - to->ptr); +#endif + fmTerm(); + system(myExtCommand(Mailer, shell_quote(file_unquote(to->ptr)), + FALSE)->ptr); + fmInit(); + displayBuffer(Currentbuf, B_FORCE_REDRAW); + pushHashHist(URLHist, a->url); + return; + } +#if 0 + else if (!strncasecmp(a->url, "news:", 5) && strchr(a->url, '@') == NULL) { + /* news:newsgroup is not supported */ + /* FIXME: gettextize? */ + disp_err_message("news:newsgroup_name is not supported", TRUE); + return; + } +#endif /* USE_NNTP */ + url = a->url; +#ifdef USE_IMAGE + if (map) + url = Sprintf("%s?%d,%d", a->url, x, y)->ptr; +#endif + + if (check_target && open_tab_blank && a->target && + (!strcasecmp(a->target, "_new") || !strcasecmp(a->target, "_blank"))) { + Buffer *buf; + + _newT(); + buf = Currentbuf; + loadLink(url, a->target, a->referer, NULL); + if (buf != Currentbuf) + delBuffer(buf); + else + deleteTab(CurrentTab); + displayBuffer(Currentbuf, B_FORCE_REDRAW); + return; + } + loadLink(url, a->target, a->referer, NULL); + displayBuffer(Currentbuf, B_NORMAL); +} + +/* follow HREF link in the buffer */ +void +bufferA(void) +{ + on_target = FALSE; + followA(); + on_target = TRUE; +} + +/* view inline image */ +DEFUN(followI, VIEW_IMAGE, "View image") +{ + Line *l; + Anchor *a; + Buffer *buf; + + if (Currentbuf->firstLine == NULL) + return; + l = Currentbuf->currentLine; + + a = retrieveCurrentImg(Currentbuf); + if (a == NULL) + return; + /* FIXME: gettextize? */ + message(Sprintf("loading %s", a->url)->ptr, 0, 0); + refresh(); + buf = loadGeneralFile(a->url, baseURL(Currentbuf), NULL, 0, NULL); + if (buf == NULL) { + /* FIXME: gettextize? */ + char *emsg = Sprintf("Can't load %s", a->url)->ptr; + disp_err_message(emsg, FALSE); + } + else if (buf != NO_BUFFER) { + pushBuffer(buf); + } + displayBuffer(Currentbuf, B_NORMAL); +} + +static FormItemList * +save_submit_formlist(FormItemList *src) +{ + FormList *list; + FormList *srclist; + FormItemList *srcitem; + FormItemList *item; + FormItemList *ret = NULL; +#ifdef MENU_SELECT + FormSelectOptionItem *opt; + FormSelectOptionItem *curopt; + FormSelectOptionItem *srcopt; +#endif /* MENU_SELECT */ + + if (src == NULL) + return NULL; + srclist = src->parent; + list = New(FormList); + list->method = srclist->method; + list->action = Strdup(srclist->action); +#ifdef USE_M17N + list->charset = srclist->charset; +#endif + list->enctype = srclist->enctype; + list->nitems = srclist->nitems; + list->body = srclist->body; + list->boundary = srclist->boundary; + list->length = srclist->length; + + for (srcitem = srclist->item; srcitem; srcitem = srcitem->next) { + item = New(FormItemList); + item->type = srcitem->type; + item->name = Strdup(srcitem->name); + item->value = Strdup(srcitem->value); + item->checked = srcitem->checked; + item->accept = srcitem->accept; + item->size = srcitem->size; + item->rows = srcitem->rows; + item->maxlength = srcitem->maxlength; + item->readonly = srcitem->readonly; +#ifdef MENU_SELECT + opt = curopt = NULL; + for (srcopt = srcitem->select_option; srcopt; srcopt = srcopt->next) { + if (!srcopt->checked) + continue; + opt = New(FormSelectOptionItem); + opt->value = Strdup(srcopt->value); + opt->label = Strdup(srcopt->label); + opt->checked = srcopt->checked; + if (item->select_option == NULL) { + item->select_option = curopt = opt; + } + else { + curopt->next = opt; + curopt = curopt->next; + } + } + item->select_option = opt; + if (srcitem->label) + item->label = Strdup(srcitem->label); +#endif /* MENU_SELECT */ + item->parent = list; + item->next = NULL; + + if (list->lastitem == NULL) { + list->item = list->lastitem = item; + } + else { + list->lastitem->next = item; + list->lastitem = item; + } + + if (srcitem == src) + ret = item; + } + + return ret; +} + +#ifdef USE_M17N +static Str +conv_form_encoding(Str val, FormItemList *fi, Buffer *buf) +{ + wc_ces charset = SystemCharset; + + if (fi->parent->charset) + charset = fi->parent->charset; + else if (buf->document_charset && buf->document_charset != WC_CES_US_ASCII) + charset = buf->document_charset; + return wc_Str_conv_strict(val, InnerCharset, charset); +} +#else +#define conv_form_encoding(val, fi, buf) (val) +#endif + +static void +query_from_followform(Str *query, FormItemList *fi, int multipart) +{ + FormItemList *f2; + FILE *body = NULL; + + if (multipart) { + *query = tmpfname(TMPF_DFL, NULL); + body = fopen((*query)->ptr, "w"); + if (body == NULL) { + return; + } + fi->parent->body = (*query)->ptr; + fi->parent->boundary = + Sprintf("------------------------------%d%ld%ld%ld", CurrentPid, + fi->parent, fi->parent->body, fi->parent->boundary)->ptr; + } + *query = Strnew(); + for (f2 = fi->parent->item; f2; f2 = f2->next) { + if (f2->name == NULL) + continue; + /* is translated into single text form */ + if (f2->name->length == 0 && + (multipart || f2->type != FORM_INPUT_TEXT)) + continue; + switch (f2->type) { + case FORM_INPUT_RESET: + /* do nothing */ + continue; + case FORM_INPUT_SUBMIT: + case FORM_INPUT_IMAGE: + if (f2 != fi || f2->value == NULL) + continue; + break; + case FORM_INPUT_RADIO: + case FORM_INPUT_CHECKBOX: + if (!f2->checked) + continue; + } + if (multipart) { + if (f2->type == FORM_INPUT_IMAGE) { + int x = 0, y = 0; +#ifdef USE_IMAGE + getMapXY(Currentbuf, retrieveCurrentImg(Currentbuf), &x, &y); +#endif + *query = Strdup(conv_form_encoding(f2->name, fi, Currentbuf)); + Strcat_charp(*query, ".x"); + form_write_data(body, fi->parent->boundary, (*query)->ptr, + Sprintf("%d", x)->ptr); + *query = Strdup(conv_form_encoding(f2->name, fi, Currentbuf)); + Strcat_charp(*query, ".y"); + form_write_data(body, fi->parent->boundary, (*query)->ptr, + Sprintf("%d", y)->ptr); + } + else if (f2->name && f2->name->length > 0 && f2->value != NULL) { + /* not IMAGE */ + *query = conv_form_encoding(f2->value, fi, Currentbuf); + if (f2->type == FORM_INPUT_FILE) + form_write_from_file(body, fi->parent->boundary, + conv_form_encoding(f2->name, fi, + Currentbuf)->ptr, + (*query)->ptr, + Str_conv_to_system(f2->value)->ptr); + else + form_write_data(body, fi->parent->boundary, + conv_form_encoding(f2->name, fi, + Currentbuf)->ptr, + (*query)->ptr); + } + } + else { + /* not multipart */ + if (f2->type == FORM_INPUT_IMAGE) { + int x = 0, y = 0; +#ifdef USE_IMAGE + getMapXY(Currentbuf, retrieveCurrentImg(Currentbuf), &x, &y); +#endif + Strcat(*query, + Str_form_quote(conv_form_encoding + (f2->name, fi, Currentbuf))); + Strcat(*query, Sprintf(".x=%d&", x)); + Strcat(*query, + Str_form_quote(conv_form_encoding + (f2->name, fi, Currentbuf))); + Strcat(*query, Sprintf(".y=%d", y)); + } + else { + /* not IMAGE */ + if (f2->name && f2->name->length > 0) { + Strcat(*query, + Str_form_quote(conv_form_encoding + (f2->name, fi, Currentbuf))); + Strcat_char(*query, '='); + } + if (f2->value != NULL) { + if (fi->parent->method == FORM_METHOD_INTERNAL) + Strcat(*query, Str_form_quote(f2->value)); + else { + Strcat(*query, + Str_form_quote(conv_form_encoding + (f2->value, fi, Currentbuf))); + } + } + } + if (f2->next) + Strcat_char(*query, '&'); + } + } + if (multipart) { + fprintf(body, "--%s--\r\n", fi->parent->boundary); + fclose(body); + } + else { + /* remove trailing & */ + while (Strlastchar(*query) == '&') + Strshrink(*query, 1); + } +} + +/* submit form */ +DEFUN(submitForm, SUBMIT, "Submit form") +{ + _followForm(TRUE); +} + +/* process form */ +void +followForm(void) +{ + _followForm(FALSE); +} + +static void +_followForm(int submit) +{ + Line *l; + Anchor *a, *a2; + char *p; + FormItemList *fi, *f2; + Str tmp, tmp2; + int multipart = 0, i; + + if (Currentbuf->firstLine == NULL) + return; + l = Currentbuf->currentLine; + + a = retrieveCurrentForm(Currentbuf); + if (a == NULL) + return; + fi = (FormItemList *)a->url; + switch (fi->type) { + case FORM_INPUT_TEXT: + if (submit) + goto do_submit; + if (fi->readonly) + /* FIXME: gettextize? */ + disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); + /* FIXME: gettextize? */ + p = inputStrHist("TEXT:", fi->value ? fi->value->ptr : NULL, TextHist); + if (p == NULL || fi->readonly) + break; + fi->value = Strnew_charp(p); + formUpdateBuffer(a, Currentbuf, fi); + if (fi->accept || fi->parent->nitems == 1) + goto do_submit; + break; + case FORM_INPUT_FILE: + if (submit) + goto do_submit; + if (fi->readonly) + /* FIXME: gettextize? */ + disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); + /* FIXME: gettextize? */ + p = inputFilenameHist("Filename:", fi->value ? fi->value->ptr : NULL, + NULL); + if (p == NULL || fi->readonly) + break; + fi->value = Strnew_charp(p); + formUpdateBuffer(a, Currentbuf, fi); + if (fi->accept || fi->parent->nitems == 1) + goto do_submit; + break; + case FORM_INPUT_PASSWORD: + if (submit) + goto do_submit; + if (fi->readonly) { + /* FIXME: gettextize? */ + disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); + break; + } + /* FIXME: gettextize? */ + p = inputLine("Password:", fi->value ? fi->value->ptr : NULL, + IN_PASSWORD); + if (p == NULL) + break; + fi->value = Strnew_charp(p); + formUpdateBuffer(a, Currentbuf, fi); + if (fi->accept) + goto do_submit; + break; + case FORM_TEXTAREA: + if (submit) + goto do_submit; + if (fi->readonly) + /* FIXME: gettextize? */ + disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); + input_textarea(fi); + formUpdateBuffer(a, Currentbuf, fi); + break; + case FORM_INPUT_RADIO: + if (submit) + goto do_submit; + if (fi->readonly) { + /* FIXME: gettextize? */ + disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); + break; + } + formRecheckRadio(a, Currentbuf, fi); + break; + case FORM_INPUT_CHECKBOX: + if (submit) + goto do_submit; + if (fi->readonly) { + /* FIXME: gettextize? */ + disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); + break; + } + fi->checked = !fi->checked; + formUpdateBuffer(a, Currentbuf, fi); + break; +#ifdef MENU_SELECT + case FORM_SELECT: + if (submit) + goto do_submit; + if (!formChooseOptionByMenu(fi, + Currentbuf->cursorX - Currentbuf->pos + + a->start.pos + Currentbuf->rootX, + Currentbuf->cursorY + Currentbuf->rootY)) + break; + formUpdateBuffer(a, Currentbuf, fi); + if (fi->parent->nitems == 1) + goto do_submit; + break; +#endif /* MENU_SELECT */ + case FORM_INPUT_IMAGE: + case FORM_INPUT_SUBMIT: + case FORM_INPUT_BUTTON: + do_submit: + tmp = Strnew(); + tmp2 = Strnew(); + multipart = (fi->parent->method == FORM_METHOD_POST && + fi->parent->enctype == FORM_ENCTYPE_MULTIPART); + query_from_followform(&tmp, fi, multipart); + + tmp2 = Strdup(fi->parent->action); + if (!Strcmp_charp(tmp2, "!CURRENT_URL!")) { + /* It means "current URL" */ + tmp2 = parsedURL2Str(&Currentbuf->currentURL); + if ((p = strchr(tmp2->ptr, '?')) != NULL) + Strshrink(tmp2, (tmp2->ptr + tmp2->length) - p); + } + + if (fi->parent->method == FORM_METHOD_GET) { + if ((p = strchr(tmp2->ptr, '?')) != NULL) + Strshrink(tmp2, (tmp2->ptr + tmp2->length) - p); + Strcat_charp(tmp2, "?"); + Strcat(tmp2, tmp); + loadLink(tmp2->ptr, a->target, NULL, NULL); + } + else if (fi->parent->method == FORM_METHOD_POST) { + Buffer *buf; + if (multipart) { + struct stat st; + stat(fi->parent->body, &st); + fi->parent->length = st.st_size; + } + else { + fi->parent->body = tmp->ptr; + fi->parent->length = tmp->length; + } + buf = loadLink(tmp2->ptr, a->target, NULL, fi->parent); + if (multipart) { + unlink(fi->parent->body); + } + if (buf && !(buf->bufferprop & BP_REDIRECTED)) { /* buf must be Currentbuf */ + /* BP_REDIRECTED means that the buffer is obtained through + * Location: header. In this case, buf->form_submit must not be set + * because the page is not loaded by POST method but GET method. + */ + buf->form_submit = save_submit_formlist(fi); + } + } + else if ((fi->parent->method == FORM_METHOD_INTERNAL && (!Strcmp_charp(fi->parent->action, "map") || !Strcmp_charp(fi->parent->action, "none"))) || Currentbuf->bufferprop & BP_INTERNAL) { /* internal */ + do_internal(tmp2->ptr, tmp->ptr); + } + else { + disp_err_message("Can't send form because of illegal method.", + FALSE); + } + break; + case FORM_INPUT_RESET: + for (i = 0; i < Currentbuf->formitem->nanchor; i++) { + a2 = &Currentbuf->formitem->anchors[i]; + f2 = (FormItemList *)a2->url; + if (f2->parent == fi->parent && + f2->name && f2->value && + f2->type != FORM_INPUT_SUBMIT && + f2->type != FORM_INPUT_HIDDEN && + f2->type != FORM_INPUT_RESET) { + f2->value = f2->init_value; + f2->checked = f2->init_checked; +#ifdef MENU_SELECT + f2->label = f2->init_label; + f2->selected = f2->init_selected; +#endif /* MENU_SELECT */ + formUpdateBuffer(a2, Currentbuf, f2); + } + } + break; + case FORM_INPUT_HIDDEN: + default: + break; + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* go to the top anchor */ +DEFUN(topA, LINK_BEGIN, "Go to the first link") +{ + HmarkerList *hl = Currentbuf->hmarklist; + BufferPoint *po; + Anchor *an; + int hseq = 0; + + if (Currentbuf->firstLine == NULL) + return; + if (!hl || hl->nmark == 0) + return; + + if (prec_num > hl->nmark) + hseq = hl->nmark - 1; + else if (prec_num > 0) + hseq = prec_num - 1; + do { + if (hseq >= hl->nmark) + return; + po = hl->marks + hseq; + an = retrieveAnchor(Currentbuf->href, po->line, po->pos); + if (an == NULL) + an = retrieveAnchor(Currentbuf->formitem, po->line, po->pos); + hseq++; + } while (an == NULL); + + gotoLine(Currentbuf, po->line); + Currentbuf->pos = po->pos; + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); +} + +/* go to the last anchor */ +DEFUN(lastA, LINK_END, "Go to the last link") +{ + HmarkerList *hl = Currentbuf->hmarklist; + BufferPoint *po; + Anchor *an; + int hseq; + + if (Currentbuf->firstLine == NULL) + return; + if (!hl || hl->nmark == 0) + return; + + if (prec_num >= hl->nmark) + hseq = 0; + else if (prec_num > 0) + hseq = hl->nmark - prec_num; + else + hseq = hl->nmark - 1; + do { + if (hseq < 0) + return; + po = hl->marks + hseq; + an = retrieveAnchor(Currentbuf->href, po->line, po->pos); + if (an == NULL) + an = retrieveAnchor(Currentbuf->formitem, po->line, po->pos); + hseq--; + } while (an == NULL); + + gotoLine(Currentbuf, po->line); + Currentbuf->pos = po->pos; + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); +} + +/* go to the next anchor */ +DEFUN(nextA, NEXT_LINK, "Move to next link") +{ + _nextA(FALSE); +} + +/* go to the previous anchor */ +DEFUN(prevA, PREV_LINK, "Move to previous link") +{ + _prevA(FALSE); +} + +/* go to the next visited anchor */ +DEFUN(nextVA, NEXT_VISITED, "Move to next visited link") +{ + _nextA(TRUE); +} + +/* go to the previous visited anchor */ +DEFUN(prevVA, PREV_VISITED, "Move to previous visited link") +{ + _prevA(TRUE); +} + +/* go to the next [visited] anchor */ +static void +_nextA(int visited) +{ + HmarkerList *hl = Currentbuf->hmarklist; + BufferPoint *po; + Anchor *an, *pan; + int i, x, y, n = searchKeyNum(); + ParsedURL url; + + if (Currentbuf->firstLine == NULL) + return; + if (!hl || hl->nmark == 0) + return; + + an = retrieveCurrentAnchor(Currentbuf); + if (visited != TRUE && an == NULL) + an = retrieveCurrentForm(Currentbuf); + + y = Currentbuf->currentLine->linenumber; + x = Currentbuf->pos; + + if (visited == TRUE) { + n = hl->nmark; + } + + for (i = 0; i < n; i++) { + pan = an; + if (an && an->hseq >= 0) { + int hseq = an->hseq + 1; + do { + if (hseq >= hl->nmark) { + if (visited == TRUE) + return; + an = pan; + goto _end; + } + po = &hl->marks[hseq]; + an = retrieveAnchor(Currentbuf->href, po->line, po->pos); + if (visited != TRUE && an == NULL) + an = retrieveAnchor(Currentbuf->formitem, po->line, + po->pos); + hseq++; + if (visited == TRUE && an) { + parseURL2(an->url, &url, baseURL(Currentbuf)); + if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) { + goto _end; + } + } + } while (an == NULL || an == pan); + } + else { + an = closest_next_anchor(Currentbuf->href, NULL, x, y); + if (visited != TRUE) + an = closest_next_anchor(Currentbuf->formitem, an, x, y); + if (an == NULL) { + if (visited == TRUE) + return; + an = pan; + break; + } + x = an->start.pos; + y = an->start.line; + if (visited == TRUE) { + parseURL2(an->url, &url, baseURL(Currentbuf)); + if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) { + goto _end; + } + } + } + } + if (visited == TRUE) + return; + + _end: + if (an == NULL || an->hseq < 0) + return; + po = &hl->marks[an->hseq]; + gotoLine(Currentbuf, po->line); + Currentbuf->pos = po->pos; + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); +} + +/* go to the previous anchor */ +static void +_prevA(int visited) +{ + HmarkerList *hl = Currentbuf->hmarklist; + BufferPoint *po; + Anchor *an, *pan; + int i, x, y, n = searchKeyNum(); + ParsedURL url; + + if (Currentbuf->firstLine == NULL) + return; + if (!hl || hl->nmark == 0) + return; + + an = retrieveCurrentAnchor(Currentbuf); + if (visited != TRUE && an == NULL) + an = retrieveCurrentForm(Currentbuf); + + y = Currentbuf->currentLine->linenumber; + x = Currentbuf->pos; + + if (visited == TRUE) { + n = hl->nmark; + } + + for (i = 0; i < n; i++) { + pan = an; + if (an && an->hseq >= 0) { + int hseq = an->hseq - 1; + do { + if (hseq < 0) { + if (visited == TRUE) + return; + an = pan; + goto _end; + } + po = hl->marks + hseq; + an = retrieveAnchor(Currentbuf->href, po->line, po->pos); + if (visited != TRUE && an == NULL) + an = retrieveAnchor(Currentbuf->formitem, po->line, + po->pos); + hseq--; + if (visited == TRUE && an) { + parseURL2(an->url, &url, baseURL(Currentbuf)); + if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) { + goto _end; + } + } + } while (an == NULL || an == pan); + } + else { + an = closest_prev_anchor(Currentbuf->href, NULL, x, y); + if (visited != TRUE) + an = closest_prev_anchor(Currentbuf->formitem, an, x, y); + if (an == NULL) { + if (visited == TRUE) + return; + an = pan; + break; + } + x = an->start.pos; + y = an->start.line; + if (visited == TRUE && an) { + parseURL2(an->url, &url, baseURL(Currentbuf)); + if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) { + goto _end; + } + } + } + } + if (visited == TRUE) + return; + + _end: + if (an == NULL || an->hseq < 0) + return; + po = hl->marks + an->hseq; + gotoLine(Currentbuf, po->line); + Currentbuf->pos = po->pos; + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); +} + +/* go to the next left/right anchor */ +static void +nextX(int d, int dy) +{ + HmarkerList *hl = Currentbuf->hmarklist; + Anchor *an, *pan; + Line *l; + int i, x, y, n = searchKeyNum(); + + if (Currentbuf->firstLine == NULL) + return; + if (!hl || hl->nmark == 0) + return; + + an = retrieveCurrentAnchor(Currentbuf); + if (an == NULL) + an = retrieveCurrentForm(Currentbuf); + + l = Currentbuf->currentLine; + x = Currentbuf->pos; + y = l->linenumber; + pan = NULL; + for (i = 0; i < n; i++) { + if (an) + x = (d > 0) ? an->end.pos : an->start.pos - 1; + an = NULL; + while (1) { + for (; x >= 0 && x < l->len; x += d) { + an = retrieveAnchor(Currentbuf->href, y, x); + if (!an) + an = retrieveAnchor(Currentbuf->formitem, y, x); + if (an) { + pan = an; + break; + } + } + if (!dy || an) + break; + l = (dy > 0) ? l->next : l->prev; + if (!l) + break; + x = (d > 0) ? 0 : l->len - 1; + y = l->linenumber; + } + if (!an) + break; + } + + if (pan == NULL) + return; + gotoLine(Currentbuf, y); + Currentbuf->pos = pan->start.pos; + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); +} + +/* go to the next downward/upward anchor */ +static void +nextY(int d) +{ + HmarkerList *hl = Currentbuf->hmarklist; + Anchor *an, *pan; + int i, x, y, n = searchKeyNum(); + int hseq; + + if (Currentbuf->firstLine == NULL) + return; + if (!hl || hl->nmark == 0) + return; + + an = retrieveCurrentAnchor(Currentbuf); + if (an == NULL) + an = retrieveCurrentForm(Currentbuf); + + x = Currentbuf->pos; + y = Currentbuf->currentLine->linenumber + d; + pan = NULL; + hseq = -1; + for (i = 0; i < n; i++) { + if (an) + hseq = abs(an->hseq); + an = NULL; + for (; y >= 0 && y <= Currentbuf->lastLine->linenumber; y += d) { + an = retrieveAnchor(Currentbuf->href, y, x); + if (!an) + an = retrieveAnchor(Currentbuf->formitem, y, x); + if (an && hseq != abs(an->hseq)) { + pan = an; + break; + } + } + if (!an) + break; + } + + if (pan == NULL) + return; + gotoLine(Currentbuf, pan->start.line); + arrangeLine(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); +} + +/* go to the next left anchor */ +DEFUN(nextL, NEXT_LEFT, "Move to next left link") +{ + nextX(-1, 0); +} + +/* go to the next left-up anchor */ +DEFUN(nextLU, NEXT_LEFT_UP, "Move to next left (or upward) link") +{ + nextX(-1, -1); +} + +/* go to the next right anchor */ +DEFUN(nextR, NEXT_RIGHT, "Move to next right link") +{ + nextX(1, 0); +} + +/* go to the next right-down anchor */ +DEFUN(nextRD, NEXT_RIGHT_DOWN, "Move to next right (or downward) link") +{ + nextX(1, 1); +} + +/* go to the next downward anchor */ +DEFUN(nextD, NEXT_DOWN, "Move to next downward link") +{ + nextY(1); +} + +/* go to the next upward anchor */ +DEFUN(nextU, NEXT_UP, "Move to next upward link") +{ + nextY(-1); +} + +/* go to the next bufferr */ +DEFUN(nextBf, NEXT, "Move to next buffer") +{ + Buffer *buf; + int i; + + for (i = 0; i < PREC_NUM; i++) { + buf = prevBuffer(Firstbuf, Currentbuf); + if (!buf) { + if (i == 0) + return; + break; + } + Currentbuf = buf; + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* go to the previous bufferr */ +DEFUN(prevBf, PREV, "Move to previous buffer") +{ + Buffer *buf; + int i; + + for (i = 0; i < PREC_NUM; i++) { + buf = Currentbuf->nextBuffer; + if (!buf) { + if (i == 0) + return; + break; + } + Currentbuf = buf; + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +static int +checkBackBuffer(Buffer *buf) +{ + Buffer *fbuf = buf->linkBuffer[LB_N_FRAME]; + + if (fbuf) { + if (fbuf->frameQ) + return TRUE; /* Currentbuf has stacked frames */ + /* when no frames stacked and next is frame source, try next's + * nextBuffer */ + if (RenderFrame && fbuf == buf->nextBuffer) { + if (fbuf->nextBuffer != NULL) + return TRUE; + else + return FALSE; + } + } + + if (buf->nextBuffer) + return TRUE; + + return FALSE; +} + +/* delete current buffer and back to the previous buffer */ +DEFUN(backBf, BACK, "Back to previous buffer") +{ + Buffer *buf = Currentbuf->linkBuffer[LB_N_FRAME]; + + if (!checkBackBuffer(Currentbuf)) { + if (close_tab_back && nTab >= 1) { + deleteTab(CurrentTab); + displayBuffer(Currentbuf, B_FORCE_REDRAW); + } + else + /* FIXME: gettextize? */ + disp_message("Can't back...", TRUE); + return; + } + + delBuffer(Currentbuf); + + if (buf) { + if (buf->frameQ) { + struct frameset *fs; + long linenumber = buf->frameQ->linenumber; + long top = buf->frameQ->top_linenumber; + int pos = buf->frameQ->pos; + int currentColumn = buf->frameQ->currentColumn; + AnchorList *formitem = buf->frameQ->formitem; + + fs = popFrameTree(&(buf->frameQ)); + deleteFrameSet(buf->frameset); + buf->frameset = fs; + + if (buf == Currentbuf) { + rFrame(); + Currentbuf->topLine = lineSkip(Currentbuf, + Currentbuf->firstLine, top - 1, + FALSE); + gotoLine(Currentbuf, linenumber); + Currentbuf->pos = pos; + Currentbuf->currentColumn = currentColumn; + arrangeCursor(Currentbuf); + formResetBuffer(Currentbuf, formitem); + } + } + else if (RenderFrame && buf == Currentbuf) { + delBuffer(Currentbuf); + } + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +DEFUN(deletePrevBuf, DELETE_PREVBUF, + "Delete previous buffer (mainly for local-CGI)") +{ + Buffer *buf = Currentbuf->nextBuffer; + if (buf) + delBuffer(buf); +} + +static void +cmd_loadURL(char *url, ParsedURL *current, char *referer, FormList *request) +{ + Buffer *buf; + + if (!strncasecmp(url, "mailto:", 7) +#ifdef USE_W3MMAILER + && non_null(Mailer) && strchr(url, '?') == NULL +#endif + ) { + /* invoke external mailer */ + Str to = Strnew_charp(url + 7); +#ifndef USE_W3MMAILER + char *pos; + if (!non_null(Mailer)) { + /* FIXME: gettextize? */ + disp_err_message("no mailer is specified", TRUE); + return; + } + if ((pos = strchr(to->ptr, '?')) != NULL) + Strtruncate(to, pos - to->ptr); +#endif + fmTerm(); + system(myExtCommand(Mailer, shell_quote(file_unquote(to->ptr)), + FALSE)->ptr); + fmInit(); + displayBuffer(Currentbuf, B_FORCE_REDRAW); + pushHashHist(URLHist, url); + return; + } +#if 0 + if (!strncasecmp(url, "news:", 5) && strchr(url, '@') == NULL) { + /* news:newsgroup is not supported */ + /* FIXME: gettextize? */ + disp_err_message("news:newsgroup_name is not supported", TRUE); + return; + } +#endif /* USE_NNTP */ + + refresh(); + buf = loadGeneralFile(url, current, referer, 0, request); + if (buf == NULL) { + /* FIXME: gettextize? */ + char *emsg = Sprintf("Can't load %s", conv_from_system(url))->ptr; + disp_err_message(emsg, FALSE); + } + else if (buf != NO_BUFFER) { + pushBuffer(buf); + if (RenderFrame && Currentbuf->frameset != NULL) + rFrame(); + } + displayBuffer(Currentbuf, B_NORMAL); +} + + +/* go to specified URL */ +static void +goURL0(char *prompt, int relative) +{ + char *url, *referer; + ParsedURL p_url, *current; + Buffer *cur_buf = Currentbuf; + + url = searchKeyData(); + if (url == NULL) { + Hist *hist = copyHist(URLHist); + Anchor *a; + + current = baseURL(Currentbuf); + if (current) { + char *c_url = parsedURL2Str(current)->ptr; + if (DefaultURLString == DEFAULT_URL_CURRENT) { + url = c_url; + if (DecodeURL) + url = url_unquote_conv(url, 0); + } + else + pushHist(hist, c_url); + } + a = retrieveCurrentAnchor(Currentbuf); + if (a) { + char *a_url; + parseURL2(a->url, &p_url, current); + a_url = parsedURL2Str(&p_url)->ptr; + if (DefaultURLString == DEFAULT_URL_LINK) { + url = a_url; + if (DecodeURL) + url = url_unquote_conv(url, Currentbuf->document_charset); + } + else + pushHist(hist, a_url); + } + url = inputLineHist(prompt, url, IN_URL, hist); + if (url != NULL) + SKIP_BLANKS(url); + } +#ifdef USE_M17N + if (url != NULL) { + if ((relative || *url == '#') && Currentbuf->document_charset) + url = wc_conv_strict(url, InnerCharset, + Currentbuf->document_charset)->ptr; + else + url = conv_to_system(url); + } +#endif + if (url == NULL || *url == '\0') { + displayBuffer(Currentbuf, B_FORCE_REDRAW); + return; + } + if (*url == '#') { + gotoLabel(url + 1); + return; + } + if (relative) { + current = baseURL(Currentbuf); + referer = parsedURL2Str(&Currentbuf->currentURL)->ptr; + } + else { + current = NULL; + referer = NULL; + } + parseURL2(url, &p_url, current); + pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr); + cmd_loadURL(url, current, referer, NULL); + if (Currentbuf != cur_buf) /* success */ + pushHashHist(URLHist, parsedURL2Str(&Currentbuf->currentURL)->ptr); +} + +DEFUN(goURL, GOTO, "Go to URL") +{ + goURL0("Goto URL: ", FALSE); +} + +DEFUN(gorURL, GOTO_RELATIVE, "Go to relative URL") +{ + goURL0("Goto relative URL: ", TRUE); +} + +static void +cmd_loadBuffer(Buffer *buf, int prop, int linkid) +{ + if (buf == NULL) { + disp_err_message("Can't load string", FALSE); + } + else if (buf != NO_BUFFER) { + buf->bufferprop |= (BP_INTERNAL | prop); + if (!(buf->bufferprop & BP_NO_URL)) + copyParsedURL(&buf->currentURL, &Currentbuf->currentURL); + if (linkid != LB_NOLINK) { + buf->linkBuffer[REV_LB[linkid]] = Currentbuf; + Currentbuf->linkBuffer[linkid] = buf; + } + pushBuffer(buf); + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* load bookmark */ +DEFUN(ldBmark, BOOKMARK VIEW_BOOKMARK, "Read bookmark") +{ + cmd_loadURL(BookmarkFile, NULL, NO_REFERER, NULL); +} + + +/* Add current to bookmark */ +DEFUN(adBmark, ADD_BOOKMARK, "Add current page to bookmark") +{ + Str tmp; + FormList *request; + + tmp = Sprintf("mode=panel&cookie=%s&bmark=%s&url=%s&title=%s" +#ifdef USE_M17N + "&charset=%s" +#endif + , + (Str_form_quote(localCookie()))->ptr, + (Str_form_quote(Strnew_charp(BookmarkFile)))->ptr, + (Str_form_quote(parsedURL2Str(&Currentbuf->currentURL)))-> + ptr, +#ifdef USE_M17N + (Str_form_quote(wc_conv_strict(Currentbuf->buffername, + InnerCharset, + BookmarkCharset)))->ptr, + wc_ces_to_charset(BookmarkCharset)); +#else + (Str_form_quote(Strnew_charp(Currentbuf->buffername)))->ptr); +#endif + request = newFormList(NULL, "post", NULL, NULL, NULL, NULL, NULL); + request->body = tmp->ptr; + request->length = tmp->length; + cmd_loadURL("file:///$LIB/" W3MBOOKMARK_CMDNAME, NULL, NO_REFERER, + request); +} + +/* option setting */ +DEFUN(ldOpt, OPTIONS, "Option setting panel") +{ + cmd_loadBuffer(load_option_panel(), BP_NO_URL, LB_NOLINK); +} + +/* set an option */ +DEFUN(setOpt, SET_OPTION, "Set option") +{ + char *opt; + + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + opt = searchKeyData(); + if (opt == NULL || *opt == '\0' || strchr(opt, '=') == NULL) { + if (opt != NULL && *opt != '\0') { + char *v = get_param_option(opt); + opt = Sprintf("%s=%s", opt, v ? v : "")->ptr; + } + opt = inputStrHist("Set option: ", opt, TextHist); + if (opt == NULL || *opt == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + } + if (set_param_option(opt)) + sync_with_option(); + displayBuffer(Currentbuf, B_REDRAW_IMAGE); +} + +/* error message list */ +DEFUN(msgs, MSGS, "Display error messages") +{ + cmd_loadBuffer(message_list_panel(), BP_NO_URL, LB_NOLINK); +} + +/* page info */ +DEFUN(pginfo, INFO, "View info of current document") +{ + Buffer *buf; + + if ((buf = Currentbuf->linkBuffer[LB_N_INFO]) != NULL) { + Currentbuf = buf; + displayBuffer(Currentbuf, B_NORMAL); + return; + } + if ((buf = Currentbuf->linkBuffer[LB_INFO]) != NULL) + delBuffer(buf); + buf = page_info_panel(Currentbuf); + cmd_loadBuffer(buf, BP_NORMAL, LB_INFO); +} + +void +follow_map(struct parsed_tagarg *arg) +{ + char *name = tag_get_value(arg, "link"); +#if defined(MENU_MAP) || defined(USE_IMAGE) + Anchor *an; + MapArea *a; + int x, y; + ParsedURL p_url; + + an = retrieveCurrentImg(Currentbuf); + x = Currentbuf->cursorX + Currentbuf->rootX; + y = Currentbuf->cursorY + Currentbuf->rootY; + a = follow_map_menu(Currentbuf, name, an, x, y); + if (a == NULL || a->url == NULL || *(a->url) == '\0') { +#endif +#ifndef MENU_MAP + Buffer *buf = follow_map_panel(Currentbuf, name); + + if (buf != NULL) + cmd_loadBuffer(buf, BP_NORMAL, LB_NOLINK); +#endif +#if defined(MENU_MAP) || defined(USE_IMAGE) + return; + } + if (*(a->url) == '#') { + gotoLabel(a->url + 1); + return; + } + parseURL2(a->url, &p_url, baseURL(Currentbuf)); + pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr); + if (check_target && open_tab_blank && a->target && + (!strcasecmp(a->target, "_new") || !strcasecmp(a->target, "_blank"))) { + Buffer *buf; + + _newT(); + buf = Currentbuf; + cmd_loadURL(a->url, baseURL(Currentbuf), + parsedURL2Str(&Currentbuf->currentURL)->ptr, NULL); + if (buf != Currentbuf) + delBuffer(buf); + else + deleteTab(CurrentTab); + displayBuffer(Currentbuf, B_FORCE_REDRAW); + return; + } + cmd_loadURL(a->url, baseURL(Currentbuf), + parsedURL2Str(&Currentbuf->currentURL)->ptr, NULL); +#endif +} + +#ifdef USE_MENU +/* link menu */ +DEFUN(linkMn, LINK_MENU, "Popup link element menu") +{ + LinkList *l = link_menu(Currentbuf); + ParsedURL p_url; + + if (!l || !l->url) + return; + if (*(l->url) == '#') { + gotoLabel(l->url + 1); + return; + } + parseURL2(l->url, &p_url, baseURL(Currentbuf)); + pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr); + cmd_loadURL(l->url, baseURL(Currentbuf), + parsedURL2Str(&Currentbuf->currentURL)->ptr, NULL); +} + +static void +anchorMn(Anchor *(*menu_func) (Buffer *), int go) +{ + Anchor *a; + BufferPoint *po; + + if (!Currentbuf->href || !Currentbuf->hmarklist) + return; + a = menu_func(Currentbuf); + if (!a || a->hseq < 0) + return; + po = &Currentbuf->hmarklist->marks[a->hseq]; + gotoLine(Currentbuf, po->line); + Currentbuf->pos = po->pos; + arrangeCursor(Currentbuf); + displayBuffer(Currentbuf, B_NORMAL); + if (go) + followA(); +} + +/* accesskey */ +DEFUN(accessKey, ACCESSKEY, "Popup acceskey menu") +{ + anchorMn(accesskey_menu, TRUE); +} + +/* list menu */ +DEFUN(listMn, LIST_MENU, "Popup link list menu and go to selected link") +{ + anchorMn(list_menu, TRUE); +} + +DEFUN(movlistMn, MOVE_LIST_MENU, + "Popup link list menu and move cursor to selected link") +{ + anchorMn(list_menu, FALSE); +} +#endif + +/* link,anchor,image list */ +DEFUN(linkLst, LIST, "Show all links and images") +{ + Buffer *buf; + + buf = link_list_panel(Currentbuf); + if (buf != NULL) { +#ifdef USE_M17N + buf->document_charset = Currentbuf->document_charset; +#endif + cmd_loadBuffer(buf, BP_NORMAL, LB_NOLINK); + } +} + +#ifdef USE_COOKIE +/* cookie list */ +DEFUN(cooLst, COOKIE, "View cookie list") +{ + Buffer *buf; + + buf = cookie_list_panel(); + if (buf != NULL) + cmd_loadBuffer(buf, BP_NO_URL, LB_NOLINK); +} +#endif /* USE_COOKIE */ + +#ifdef USE_HISTORY +/* History page */ +DEFUN(ldHist, HISTORY, "View history of URL") +{ + cmd_loadBuffer(historyBuffer(URLHist), BP_NO_URL, LB_NOLINK); +} +#endif /* USE_HISTORY */ + +/* download HREF link */ +DEFUN(svA, SAVE_LINK, "Save link to file") +{ + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + do_download = TRUE; + followA(); + do_download = FALSE; +} + +/* download IMG link */ +DEFUN(svI, SAVE_IMAGE, "Save image to file") +{ + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + do_download = TRUE; + followI(); + do_download = FALSE; +} + +/* save buffer */ +DEFUN(svBuf, PRINT SAVE_SCREEN, "Save rendered document to file") +{ + char *qfile = NULL, *file; + FILE *f; + int is_pipe; + + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + file = searchKeyData(); + if (file == NULL || *file == '\0') { + /* FIXME: gettextize? */ + qfile = inputLineHist("Save buffer to: ", NULL, IN_COMMAND, SaveHist); + if (qfile == NULL || *qfile == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + } + file = conv_to_system(qfile ? qfile : file); + if (*file == '|') { + is_pipe = TRUE; + f = popen(file + 1, "w"); + } + else { + if (qfile) { + file = unescape_spaces(Strnew_charp(qfile))->ptr; + file = conv_to_system(file); + } + file = expandPath(file); + if (checkOverWrite(file) < 0) { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + f = fopen(file, "w"); + is_pipe = FALSE; + } + if (f == NULL) { + /* FIXME: gettextize? */ + char *emsg = Sprintf("Can't open %s", conv_from_system(file))->ptr; + disp_err_message(emsg, TRUE); + return; + } + saveBuffer(Currentbuf, f, TRUE); + if (is_pipe) + pclose(f); + else + fclose(f); + displayBuffer(Currentbuf, B_NORMAL); +} + +/* save source */ +DEFUN(svSrc, DOWNLOAD SAVE, "Save document source to file") +{ + char *file; + + if (Currentbuf->sourcefile == NULL) + return; + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + PermitSaveToPipe = TRUE; + if (Currentbuf->real_scheme == SCM_LOCAL) + file = conv_from_system(guess_save_name(NULL, + Currentbuf->currentURL. + real_file)); + else + file = guess_save_name(Currentbuf, Currentbuf->currentURL.file); + doFileCopy(Currentbuf->sourcefile, file); + PermitSaveToPipe = FALSE; + displayBuffer(Currentbuf, B_NORMAL); +} + +static void +_peekURL(int only_img) +{ + + Anchor *a; + ParsedURL pu; + static Str s = NULL; +#ifdef USE_M17N + static Lineprop *p = NULL; + Lineprop *pp; +#endif + static int offset = 0, n; + + if (Currentbuf->firstLine == NULL) + return; + if (CurrentKey == prev_key && s != NULL) { + if (s->length - offset >= COLS) + offset++; + else if (s->length <= offset) /* bug ? */ + offset = 0; + goto disp; + } + else { + offset = 0; + } + s = NULL; + a = (only_img ? NULL : retrieveCurrentAnchor(Currentbuf)); + if (a == NULL) { + a = (only_img ? NULL : retrieveCurrentForm(Currentbuf)); + if (a == NULL) { + a = retrieveCurrentImg(Currentbuf); + if (a == NULL) + return; + } + else + s = Strnew_charp(form2str((FormItemList *)a->url)); + } + if (s == NULL) { + parseURL2(a->url, &pu, baseURL(Currentbuf)); + s = parsedURL2Str(&pu); + } + if (DecodeURL) + s = Strnew_charp(url_unquote_conv + (s->ptr, Currentbuf->document_charset)); +#ifdef USE_M17N + s = checkType(s, &pp, NULL); + p = NewAtom_N(Lineprop, s->length); + bcopy((void *)pp, (void *)p, s->length * sizeof(Lineprop)); +#endif + disp: + n = searchKeyNum(); + if (n > 1 && s->length > (n - 1) * (COLS - 1)) + offset = (n - 1) * (COLS - 1); +#ifdef USE_M17N + while (offset < s->length && p[offset] & PC_WCHAR2) + offset++; +#endif + disp_message_nomouse(&s->ptr[offset], TRUE); +} + +/* peek URL */ +DEFUN(peekURL, PEEK_LINK, "Peek link URL") +{ + _peekURL(0); +} + +/* peek URL of image */ +DEFUN(peekIMG, PEEK_IMG, "Peek image URL") +{ + _peekURL(1); +} + +/* show current URL */ +static Str +currentURL(void) +{ + if (Currentbuf->bufferprop & BP_INTERNAL) + return Strnew_size(0); + return parsedURL2Str(&Currentbuf->currentURL); +} + +DEFUN(curURL, PEEK, "Peek current URL") +{ + static Str s = NULL; +#ifdef USE_M17N + static Lineprop *p = NULL; + Lineprop *pp; +#endif + static int offset = 0, n; + + if (Currentbuf->bufferprop & BP_INTERNAL) + return; + if (CurrentKey == prev_key && s != NULL) { + if (s->length - offset >= COLS) + offset++; + else if (s->length <= offset) /* bug ? */ + offset = 0; + } + else { + offset = 0; + s = currentURL(); + if (DecodeURL) + s = Strnew_charp(url_unquote_conv(s->ptr, 0)); +#ifdef USE_M17N + s = checkType(s, &pp, NULL); + p = NewAtom_N(Lineprop, s->length); + bcopy((void *)pp, (void *)p, s->length * sizeof(Lineprop)); +#endif + } + n = searchKeyNum(); + if (n > 1 && s->length > (n - 1) * (COLS - 1)) + offset = (n - 1) * (COLS - 1); +#ifdef USE_M17N + while (offset < s->length && p[offset] & PC_WCHAR2) + offset++; +#endif + disp_message_nomouse(&s->ptr[offset], TRUE); +} +/* view HTML source */ + +DEFUN(vwSrc, SOURCE VIEW, "View HTML source") +{ + Buffer *buf; + + if (Currentbuf->type == NULL || Currentbuf->bufferprop & BP_FRAME) + return; + if ((buf = Currentbuf->linkBuffer[LB_SOURCE]) != NULL || + (buf = Currentbuf->linkBuffer[LB_N_SOURCE]) != NULL) { + Currentbuf = buf; + displayBuffer(Currentbuf, B_NORMAL); + return; + } + if (Currentbuf->sourcefile == NULL) { + if (Currentbuf->pagerSource && + !strcasecmp(Currentbuf->type, "text/plain")) { +#ifdef USE_M17N + wc_ces old_charset; + wc_bool old_fix_width_conv; +#endif + FILE *f; + Str tmpf = tmpfname(TMPF_SRC, NULL); + f = fopen(tmpf->ptr, "w"); + if (f == NULL) + return; +#ifdef USE_M17N + old_charset = DisplayCharset; + old_fix_width_conv = WcOption.fix_width_conv; + DisplayCharset = (Currentbuf->document_charset != WC_CES_US_ASCII) + ? Currentbuf->document_charset : 0; + WcOption.fix_width_conv = WC_FALSE; +#endif + saveBufferBody(Currentbuf, f, TRUE); +#ifdef USE_M17N + DisplayCharset = old_charset; + WcOption.fix_width_conv = old_fix_width_conv; +#endif + fclose(f); + Currentbuf->sourcefile = tmpf->ptr; + } + else { + return; + } + } + + buf = newBuffer(INIT_BUFFER_WIDTH); + + if (!strcasecmp(Currentbuf->type, "text/html")) { + buf->type = "text/plain"; + if (Currentbuf->real_type && + !strcasecmp(Currentbuf->real_type, "text/html")) + buf->real_type = "text/plain"; + else + buf->real_type = Currentbuf->real_type; + buf->buffername = Sprintf("source of %s", Currentbuf->buffername)->ptr; + buf->linkBuffer[LB_N_SOURCE] = Currentbuf; + Currentbuf->linkBuffer[LB_SOURCE] = buf; + } + else if (!strcasecmp(Currentbuf->type, "text/plain")) { + buf->type = "text/html"; + if (Currentbuf->real_type && + !strcasecmp(Currentbuf->real_type, "text/plain")) + buf->real_type = "text/html"; + else + buf->real_type = Currentbuf->real_type; + buf->buffername = Sprintf("HTML view of %s", + Currentbuf->buffername)->ptr; + buf->linkBuffer[LB_SOURCE] = Currentbuf; + Currentbuf->linkBuffer[LB_N_SOURCE] = buf; + } + else { + return; + } + buf->currentURL = Currentbuf->currentURL; + buf->real_scheme = Currentbuf->real_scheme; + buf->filename = Currentbuf->filename; + buf->sourcefile = Currentbuf->sourcefile; + buf->header_source = Currentbuf->header_source; + buf->search_header = Currentbuf->search_header; +#ifdef USE_M17N + buf->document_charset = Currentbuf->document_charset; +#endif + buf->clone = Currentbuf->clone; + (*buf->clone)++; + + buf->need_reshape = TRUE; + reshapeBuffer(buf); + pushBuffer(buf); + displayBuffer(Currentbuf, B_NORMAL); +} + +/* reload */ +DEFUN(reload, RELOAD, "Reload buffer") +{ + Buffer *buf, *fbuf = NULL, sbuf; +#ifdef USE_M17N + wc_ces old_charset; +#endif + Str url; + FormList *request; + int multipart; + + if (Currentbuf->bufferprop & BP_INTERNAL) { + if (!strcmp(Currentbuf->buffername, DOWNLOAD_LIST_TITLE)) { + ldDL(); + return; + } + /* FIXME: gettextize? */ + disp_err_message("Can't reload...", TRUE); + return; + } + if (Currentbuf->currentURL.scheme == SCM_LOCAL && + !strcmp(Currentbuf->currentURL.file, "-")) { + /* file is std input */ + /* FIXME: gettextize? */ + disp_err_message("Can't reload stdin", TRUE); + return; + } + copyBuffer(&sbuf, Currentbuf); + if (Currentbuf->bufferprop & BP_FRAME && + (fbuf = Currentbuf->linkBuffer[LB_N_FRAME])) { + if (fmInitialized) { + message("Rendering frame", 0, 0); + refresh(); + } + if (!(buf = renderFrame(fbuf, 1))) { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + if (fbuf->linkBuffer[LB_FRAME]) { + if (buf->sourcefile && + fbuf->linkBuffer[LB_FRAME]->sourcefile && + !strcmp(buf->sourcefile, + fbuf->linkBuffer[LB_FRAME]->sourcefile)) + fbuf->linkBuffer[LB_FRAME]->sourcefile = NULL; + delBuffer(fbuf->linkBuffer[LB_FRAME]); + } + fbuf->linkBuffer[LB_FRAME] = buf; + buf->linkBuffer[LB_N_FRAME] = fbuf; + pushBuffer(buf); + Currentbuf = buf; + if (Currentbuf->firstLine) { + COPY_BUFROOT(Currentbuf, &sbuf); + restorePosition(Currentbuf, &sbuf); + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); + return; + } + else if (Currentbuf->frameset != NULL) + fbuf = Currentbuf->linkBuffer[LB_FRAME]; + multipart = 0; + if (Currentbuf->form_submit) { + request = Currentbuf->form_submit->parent; + if (request->method == FORM_METHOD_POST + && request->enctype == FORM_ENCTYPE_MULTIPART) { + Str query; + struct stat st; + multipart = 1; + query_from_followform(&query, Currentbuf->form_submit, multipart); + stat(request->body, &st); + request->length = st.st_size; + } + } + else { + request = NULL; + } + url = parsedURL2Str(&Currentbuf->currentURL); + /* FIXME: gettextize? */ + message("Reloading...", 0, 0); + refresh(); +#ifdef USE_M17N + old_charset = DocumentCharset; + if (Currentbuf->document_charset != WC_CES_US_ASCII) + DocumentCharset = Currentbuf->document_charset; +#endif + SearchHeader = Currentbuf->search_header; + DefaultType = Currentbuf->real_type; + buf = loadGeneralFile(url->ptr, NULL, NO_REFERER, RG_NOCACHE, request); +#ifdef USE_M17N + DocumentCharset = old_charset; +#endif + SearchHeader = FALSE; + DefaultType = NULL; + + if (multipart) + unlink(request->body); + if (buf == NULL) { + /* FIXME: gettextize? */ + disp_err_message("Can't reload...", TRUE); + return; + } + else if (buf == NO_BUFFER) { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + if (fbuf != NULL) + Firstbuf = deleteBuffer(Firstbuf, fbuf); + repBuffer(Currentbuf, buf); + if ((buf->type != NULL) && (sbuf.type != NULL) && + ((!strcasecmp(buf->type, "text/plain") && + !strcasecmp(sbuf.type, "text/html")) || + (!strcasecmp(buf->type, "text/html") && + !strcasecmp(sbuf.type, "text/plain")))) { + vwSrc(); + if (Currentbuf != buf) + Firstbuf = deleteBuffer(Firstbuf, buf); + } + Currentbuf->search_header = sbuf.search_header; + Currentbuf->form_submit = sbuf.form_submit; + if (Currentbuf->firstLine) { + COPY_BUFROOT(Currentbuf, &sbuf); + restorePosition(Currentbuf, &sbuf); + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* reshape */ +DEFUN(reshape, RESHAPE, "Re-render buffer") +{ + Currentbuf->need_reshape = TRUE; + reshapeBuffer(Currentbuf); + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +#ifdef USE_M17N +static void +_docCSet(wc_ces charset) +{ + if (Currentbuf->bufferprop & BP_INTERNAL) + return; + if (Currentbuf->sourcefile == NULL) { + disp_message("Can't reload...", FALSE); + return; + } + Currentbuf->document_charset = charset; + Currentbuf->need_reshape = TRUE; + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +void +change_charset(struct parsed_tagarg *arg) +{ + Buffer *buf = Currentbuf->linkBuffer[LB_N_INFO]; + wc_ces charset; + + if (buf == NULL) + return; + delBuffer(Currentbuf); + Currentbuf = buf; + if (Currentbuf->bufferprop & BP_INTERNAL) + return; + charset = Currentbuf->document_charset; + for (; arg; arg = arg->next) { + if (!strcmp(arg->arg, "charset")) + charset = atoi(arg->value); + } + _docCSet(charset); +} + +DEFUN(docCSet, CHARSET, "Change the current document charset") +{ + char *cs; + wc_ces charset; + + cs = searchKeyData(); + if (cs == NULL || *cs == '\0') + /* FIXME: gettextize? */ + cs = inputStr("Document charset: ", + wc_ces_to_charset(Currentbuf->document_charset)); + charset = wc_guess_charset_short(cs, 0); + if (charset == 0) { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + _docCSet(charset); +} + +DEFUN(defCSet, DEFAULT_CHARSET, "Change the default document charset") +{ + char *cs; + wc_ces charset; + + cs = searchKeyData(); + if (cs == NULL || *cs == '\0') + /* FIXME: gettextize? */ + cs = inputStr("Default document charset: ", + wc_ces_to_charset(DocumentCharset)); + charset = wc_guess_charset_short(cs, 0); + if (charset != 0) + DocumentCharset = charset; + displayBuffer(Currentbuf, B_NORMAL); +} +#endif + +/* mark URL-like patterns as anchors */ +void +chkURLBuffer(Buffer *buf) +{ + static char *url_like_pat[] = { + "https?://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./?=~_\\&+@#,\\$;]*[a-zA-Z0-9_/=\\-]", + "file:/[a-zA-Z0-9:%\\-\\./=_\\+@#,\\$;]*", +#ifdef USE_GOPHER + "gopher://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./_]*", +#endif /* USE_GOPHER */ + "ftp://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./=_+@#,\\$]*[a-zA-Z0-9_/]", +#ifdef USE_NNTP + "news:[^<> ][^<> ]*", + "nntp://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./_]*", +#endif /* USE_NNTP */ +#ifndef USE_W3MMAILER /* see also chkExternalURIBuffer() */ + "mailto:[^<> ][^<> ]*@[a-zA-Z0-9][a-zA-Z0-9\\-\\._]*[a-zA-Z0-9]", +#endif +#ifdef INET6 + "https?://[a-zA-Z0-9:%\\-\\./_@]*\\[[a-fA-F0-9:][a-fA-F0-9:\\.]*\\][a-zA-Z0-9:%\\-\\./?=~_\\&+@#,\\$;]*", + "ftp://[a-zA-Z0-9:%\\-\\./_@]*\\[[a-fA-F0-9:][a-fA-F0-9:\\.]*\\][a-zA-Z0-9:%\\-\\./=_+@#,\\$]*", +#endif /* INET6 */ + NULL + }; + int i; + for (i = 0; url_like_pat[i]; i++) { + reAnchor(buf, url_like_pat[i]); + } +#ifdef USE_EXTERNAL_URI_LOADER + chkExternalURIBuffer(buf); +#endif + buf->check_url |= CHK_URL; +} + +DEFUN(chkURL, MARK_URL, "Mark URL-like strings as anchors") +{ + chkURLBuffer(Currentbuf); + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +DEFUN(chkWORD, MARK_WORD, "Mark current word as anchor") +{ + char *p; + int spos, epos; + p = getCurWord(Currentbuf, &spos, &epos, ":\"\'`<>()[]{}&|;*?$"); + if (p == NULL) + return; + reAnchorWord(Currentbuf, Currentbuf->currentLine, spos, epos); + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +#ifdef USE_NNTP +/* mark Message-ID-like patterns as NEWS anchors */ +void +chkNMIDBuffer(Buffer *buf) +{ + static char *url_like_pat[] = { + "<[!-;=?-~]+@[a-zA-Z0-9\\.\\-_]+>", + NULL, + }; + int i; + for (i = 0; url_like_pat[i]; i++) { + reAnchorNews(buf, url_like_pat[i]); + } + buf->check_url |= CHK_NMID; +} + +DEFUN(chkNMID, MARK_MID, "Mark Message-ID-like strings as anchors") +{ + chkNMIDBuffer(Currentbuf); + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} +#endif /* USE_NNTP */ + +/* render frame */ +DEFUN(rFrame, FRAME, "Render frame") +{ + Buffer *buf; + + if ((buf = Currentbuf->linkBuffer[LB_FRAME]) != NULL) { + Currentbuf = buf; + displayBuffer(Currentbuf, B_NORMAL); + return; + } + if (Currentbuf->frameset == NULL) { + if ((buf = Currentbuf->linkBuffer[LB_N_FRAME]) != NULL) { + Currentbuf = buf; + displayBuffer(Currentbuf, B_NORMAL); + } + return; + } + if (fmInitialized) { + message("Rendering frame", 0, 0); + refresh(); + } + buf = renderFrame(Currentbuf, 0); + if (buf == NULL) { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + buf->linkBuffer[LB_N_FRAME] = Currentbuf; + Currentbuf->linkBuffer[LB_FRAME] = buf; + pushBuffer(buf); + if (fmInitialized && display_ok) + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +/* spawn external browser */ +static void +invoke_browser(char *url) +{ + Str cmd; + char *browser = NULL; + int bg = 0, len; + + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + browser = searchKeyData(); + if (browser == NULL || *browser == '\0') { + switch (prec_num) { + case 0: + case 1: + browser = ExtBrowser; + break; + case 2: + browser = ExtBrowser2; + break; + case 3: + browser = ExtBrowser3; + break; + } + if (browser == NULL || *browser == '\0') { + browser = inputStr("Browse command: ", NULL); + if (browser != NULL) + browser = conv_to_system(browser); + } + } + else { + browser = conv_to_system(browser); + } + if (browser == NULL || *browser == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + + if ((len = strlen(browser)) >= 2 && browser[len - 1] == '&' && + browser[len - 2] != '\\') { + browser = allocStr(browser, len - 2); + bg = 1; + } + cmd = myExtCommand(browser, shell_quote(url), FALSE); + Strremovetrailingspaces(cmd); + fmTerm(); + mySystem(cmd->ptr, bg); + fmInit(); + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +DEFUN(extbrz, EXTERN, "Execute external browser") +{ + if (Currentbuf->bufferprop & BP_INTERNAL) { + /* FIXME: gettextize? */ + disp_err_message("Can't browse...", TRUE); + return; + } + if (Currentbuf->currentURL.scheme == SCM_LOCAL && + !strcmp(Currentbuf->currentURL.file, "-")) { + /* file is std input */ + /* FIXME: gettextize? */ + disp_err_message("Can't browse stdin", TRUE); + return; + } + invoke_browser(parsedURL2Str(&Currentbuf->currentURL)->ptr); +} + +DEFUN(linkbrz, EXTERN_LINK, "View current link using external browser") +{ + Anchor *a; + ParsedURL pu; + + if (Currentbuf->firstLine == NULL) + return; + a = retrieveCurrentAnchor(Currentbuf); + if (a == NULL) + return; + parseURL2(a->url, &pu, baseURL(Currentbuf)); + invoke_browser(parsedURL2Str(&pu)->ptr); +} + +/* show current line number and number of lines in the entire document */ +DEFUN(curlno, LINE_INFO, "Show current line number") +{ + Line *l = Currentbuf->currentLine; + Str tmp; + int cur = 0, all = 0, col = 0, len = 0; + + if (l != NULL) { + cur = l->real_linenumber; + col = l->bwidth + Currentbuf->currentColumn + Currentbuf->cursorX + 1; + while (l->next && l->next->bpos) + l = l->next; + if (l->width < 0) + l->width = COLPOS(l, l->len); + len = l->bwidth + l->width; + } + if (Currentbuf->lastLine) + all = Currentbuf->lastLine->real_linenumber; + if (Currentbuf->pagerSource && !(Currentbuf->bufferprop & BP_CLOSE)) + tmp = Sprintf("line %d col %d/%d", cur, col, len); + else + tmp = Sprintf("line %d/%d (%d%%) col %d/%d", cur, all, + (int)((double)cur * 100.0 / (double)(all ? all : 1) + + 0.5), col, len); +#ifdef USE_M17N + Strcat_charp(tmp, " "); + Strcat_charp(tmp, wc_ces_to_charset_desc(Currentbuf->document_charset)); +#endif + + disp_message(tmp->ptr, FALSE); +} + +#ifdef USE_IMAGE +DEFUN(dispI, DISPLAY_IMAGE, "Restart loading and drawing of images") +{ + if (!displayImage) + initImage(); + if (!activeImage) + return; + displayImage = TRUE; + /* + * if (!(Currentbuf->type && !strcmp(Currentbuf->type, "text/html"))) + * return; + */ + Currentbuf->image_flag = IMG_FLAG_AUTO; + Currentbuf->need_reshape = TRUE; + displayBuffer(Currentbuf, B_REDRAW_IMAGE); +} + +DEFUN(stopI, STOP_IMAGE, "Stop loading and drawing of images") +{ + if (!activeImage) + return; + /* + * if (!(Currentbuf->type && !strcmp(Currentbuf->type, "text/html"))) + * return; + */ + Currentbuf->image_flag = IMG_FLAG_SKIP; + displayBuffer(Currentbuf, B_REDRAW_IMAGE); +} +#endif + +#ifdef USE_MOUSE + +static int +mouse_scroll_line(void) +{ + if (relative_wheel_scroll) + return (relative_wheel_scroll_ratio * LASTLINE + 99) / 100; + else + return fixed_wheel_scroll_count; +} + +static TabBuffer * +posTab(int x, int y) +{ + TabBuffer *tab; + + if (mouse_action.menu_str && x < mouse_action.menu_width && y == 0) + return NO_TABBUFFER; + if (y > LastTab->y) + return NULL; + for (tab = FirstTab; tab; tab = tab->nextTab) { + if (tab->x1 <= x && x <= tab->x2 && tab->y == y) + return tab; + } + return NULL; +} + +static void +do_mouse_action(int btn, int x, int y) +{ + MouseActionMap *map = NULL; + int ny = -1; + + if (nTab > 1 || mouse_action.menu_str) + ny = LastTab->y + 1; + + switch (btn) { + case MOUSE_BTN1_DOWN: + btn = 0; + break; + case MOUSE_BTN2_DOWN: + btn = 1; + break; + case MOUSE_BTN3_DOWN: + btn = 2; + break; + default: + return; + } + if (y < ny) { + if (mouse_action.menu_str && x >= 0 && x < mouse_action.menu_width) { + if (mouse_action.menu_map[btn]) + map = &mouse_action.menu_map[btn][x]; + } + else + map = &mouse_action.tab_map[btn]; + } + else if (y == LASTLINE) { + if (mouse_action.lastline_str && x >= 0 && + x < mouse_action.lastline_width) { + if (mouse_action.lastline_map[btn]) + map = &mouse_action.lastline_map[btn][x]; + } + } + else if (y > ny) { + if (y == Currentbuf->cursorY + Currentbuf->rootY && + (x == Currentbuf->cursorX + Currentbuf->rootX +#ifdef USE_M17N + || (WcOption.use_wide && Currentbuf->currentLine != NULL && + (CharType(Currentbuf->currentLine->propBuf[Currentbuf->pos]) + == PC_KANJI1) + && x == Currentbuf->cursorX + Currentbuf->rootX + 1) +#endif + )) { + if (retrieveCurrentAnchor(Currentbuf) || + retrieveCurrentForm(Currentbuf)) { + map = &mouse_action.active_map[btn]; + if (!(map && map->func)) + map = &mouse_action.anchor_map[btn]; + } + } + else { + int cx = Currentbuf->cursorX, cy = Currentbuf->cursorY; + cursorXY(Currentbuf, x - Currentbuf->rootX, y - Currentbuf->rootY); + if (y == Currentbuf->cursorY + Currentbuf->rootY && + (x == Currentbuf->cursorX + Currentbuf->rootX +#ifdef USE_M17N + || (WcOption.use_wide && Currentbuf->currentLine != NULL && + (CharType(Currentbuf->currentLine-> + propBuf[Currentbuf->pos]) == PC_KANJI1) + && x == Currentbuf->cursorX + Currentbuf->rootX + 1) +#endif + ) && + (retrieveCurrentAnchor(Currentbuf) || + retrieveCurrentForm(Currentbuf))) + map = &mouse_action.anchor_map[btn]; + cursorXY(Currentbuf, cx, cy); + } + } + else { + return; + } + if (!(map && map->func)) + map = &mouse_action.default_map[btn]; + if (map && map->func) { + mouse_action.in_action = TRUE; + mouse_action.cursorX = x; + mouse_action.cursorY = y; + CurrentKey = -1; + CurrentKeyData = NULL; + CurrentCmdData = map->data; + (*map->func) (); + CurrentCmdData = NULL; + } +} + +static void +process_mouse(int btn, int x, int y) +{ + int delta_x, delta_y, i; + static int press_btn = MOUSE_BTN_RESET, press_x, press_y; + TabBuffer *t; + int ny = -1; + + if (nTab > 1 || mouse_action.menu_str) + ny = LastTab->y + 1; + if (btn == MOUSE_BTN_UP) { + switch (press_btn) { + case MOUSE_BTN1_DOWN: + if (press_y == y && press_x == x) + do_mouse_action(press_btn, x, y); + else if (ny > 0 && y < ny) { + if (press_y < ny) { + moveTab(posTab(press_x, press_y), posTab(x, y), + (press_y == y) ? (press_x < x) : (press_y < y)); + return; + } + else if (press_x >= Currentbuf->rootX) { + Buffer *buf = Currentbuf; + int cx = Currentbuf->cursorX, cy = Currentbuf->cursorY; + + t = posTab(x, y); + if (t == NULL) + return; + if (t == NO_TABBUFFER) + t = NULL; /* open new tab */ + cursorXY(Currentbuf, press_x - Currentbuf->rootX, + press_y - Currentbuf->rootY); + if (Currentbuf->cursorY == press_y - Currentbuf->rootY && + (Currentbuf->cursorX == press_x - Currentbuf->rootX +#ifdef USE_M17N + || (WcOption.use_wide && + Currentbuf->currentLine != NULL && + (CharType(Currentbuf->currentLine-> + propBuf[Currentbuf->pos]) == PC_KANJI1) + && Currentbuf->cursorX == press_x + - Currentbuf->rootX - 1) +#endif + )) { + displayBuffer(Currentbuf, B_NORMAL); + followTab(t); + } + if (buf == Currentbuf) + cursorXY(Currentbuf, cx, cy); + } + return; + } + else { + delta_x = x - press_x; + delta_y = y - press_y; + + if (abs(delta_x) < abs(delta_y) / 3) + delta_x = 0; + if (abs(delta_y) < abs(delta_x) / 3) + delta_y = 0; + if (reverse_mouse) { + delta_y = -delta_y; + delta_x = -delta_x; + } + if (delta_y > 0) { + prec_num = delta_y; + ldown1(); + } + else if (delta_y < 0) { + prec_num = -delta_y; + lup1(); + } + if (delta_x > 0) { + prec_num = delta_x; + col1L(); + } + else if (delta_x < 0) { + prec_num = -delta_x; + col1R(); + } + } + break; + case MOUSE_BTN2_DOWN: + case MOUSE_BTN3_DOWN: + if (press_y == y && press_x == x) + do_mouse_action(press_btn, x, y); + break; + case MOUSE_BTN4_DOWN_RXVT: + for (i = 0; i < mouse_scroll_line(); i++) + ldown1(); + break; + case MOUSE_BTN5_DOWN_RXVT: + for (i = 0; i < mouse_scroll_line(); i++) + lup1(); + break; + } + } + else if (btn == MOUSE_BTN4_DOWN_XTERM) { + for (i = 0; i < mouse_scroll_line(); i++) + ldown1(); + } + else if (btn == MOUSE_BTN5_DOWN_XTERM) { + for (i = 0; i < mouse_scroll_line(); i++) + lup1(); + } + + if (btn != MOUSE_BTN4_DOWN_RXVT || press_btn == MOUSE_BTN_RESET) { + press_btn = btn; + press_x = x; + press_y = y; + } + else { + press_btn = MOUSE_BTN_RESET; + } +} + +DEFUN(msToggle, MOUSE_TOGGLE, "Toggle activity of mouse") +{ + if (use_mouse) { + use_mouse = FALSE; + } + else { + use_mouse = TRUE; + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +DEFUN(mouse, MOUSE, "mouse operation") +{ + int btn, x, y; + + btn = (unsigned char)getch() - 32; +#if defined(__CYGWIN__) && CYGWIN_VERSION_DLL_MAJOR < 1005 + if (cygwin_mouse_btn_swapped) { + if (btn == MOUSE_BTN2_DOWN) + btn = MOUSE_BTN3_DOWN; + else if (btn == MOUSE_BTN3_DOWN) + btn = MOUSE_BTN2_DOWN; + } +#endif + x = (unsigned char)getch() - 33; + if (x < 0) + x += 0x100; + y = (unsigned char)getch() - 33; + if (y < 0) + y += 0x100; + + if (x < 0 || x >= COLS || y < 0 || y > LASTLINE) + return; + process_mouse(btn, x, y); +} + +#ifdef USE_GPM +int +gpm_process_mouse(Gpm_Event * event, void *data) +{ + int btn = MOUSE_BTN_RESET, x, y; + if (event->type & GPM_UP) + btn = MOUSE_BTN_UP; + else if (event->type & GPM_DOWN) { + switch (event->buttons) { + case GPM_B_LEFT: + btn = MOUSE_BTN1_DOWN; + break; + case GPM_B_MIDDLE: + btn = MOUSE_BTN2_DOWN; + break; + case GPM_B_RIGHT: + btn = MOUSE_BTN3_DOWN; + break; + } + } + else { + GPM_DRAWPOINTER(event); + return 0; + } + x = event->x; + y = event->y; + process_mouse(btn, x - 1, y - 1); + return 0; +} +#endif /* USE_GPM */ + +#ifdef USE_SYSMOUSE +int +sysm_process_mouse(int x, int y, int nbs, int obs) +{ + int btn; + int bits; + + if (obs & ~nbs) + btn = MOUSE_BTN_UP; + else if (nbs & ~obs) { + bits = nbs & ~obs; + btn = bits & 0x1 ? MOUSE_BTN1_DOWN : + (bits & 0x2 ? MOUSE_BTN2_DOWN : + (bits & 0x4 ? MOUSE_BTN3_DOWN : 0)); + } + else /* nbs == obs */ + return 0; + process_mouse(btn, x, y); + return 0; +} +#endif /* USE_SYSMOUSE */ + +DEFUN(movMs, MOVE_MOUSE, "Move cursor to mouse cursor (for mouse action)") +{ + if (!mouse_action.in_action) + return; + if ((nTab > 1 || mouse_action.menu_str) && + mouse_action.cursorY < LastTab->y + 1) + return; + else if (mouse_action.cursorX >= Currentbuf->rootX && + mouse_action.cursorY < LASTLINE) { + cursorXY(Currentbuf, mouse_action.cursorX - Currentbuf->rootX, + mouse_action.cursorY - Currentbuf->rootY); + } + displayBuffer(Currentbuf, B_NORMAL); +} + +#ifdef USE_MENU +#ifdef KANJI_SYMBOLS +#define FRAME_WIDTH 2 +#else +#define FRAME_WIDTH 1 +#endif + +DEFUN(menuMs, MENU_MOUSE, "Popup menu at mouse cursor (for mouse action)") +{ + if (!mouse_action.in_action) + return; + if ((nTab > 1 || mouse_action.menu_str) && + mouse_action.cursorY < LastTab->y + 1) + mouse_action.cursorX -= FRAME_WIDTH + 1; + else if (mouse_action.cursorX >= Currentbuf->rootX && + mouse_action.cursorY < LASTLINE) { + cursorXY(Currentbuf, mouse_action.cursorX - Currentbuf->rootX, + mouse_action.cursorY - Currentbuf->rootY); + displayBuffer(Currentbuf, B_NORMAL); + } + mainMn(); +} +#endif + +DEFUN(tabMs, TAB_MOUSE, "Move to tab on mouse cursor (for mouse action)") +{ + TabBuffer *tab; + + if (!mouse_action.in_action) + return; + tab = posTab(mouse_action.cursorX, mouse_action.cursorY); + if (!tab || tab == NO_TABBUFFER) + return; + CurrentTab = tab; + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +DEFUN(closeTMs, CLOSE_TAB_MOUSE, + "Close tab on mouse cursor (for mouse action)") +{ + TabBuffer *tab; + + if (!mouse_action.in_action) + return; + tab = posTab(mouse_action.cursorX, mouse_action.cursorY); + if (!tab || tab == NO_TABBUFFER) + return; + deleteTab(tab); + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} +#endif /* USE_MOUSE */ + +DEFUN(dispVer, VERSION, "Display version of w3m") +{ + disp_message(Sprintf("w3m version %s", w3m_version)->ptr, TRUE); +} + +DEFUN(wrapToggle, WRAP_TOGGLE, "Toggle wrap search mode") +{ + if (WrapSearch) { + WrapSearch = FALSE; + /* FIXME: gettextize? */ + disp_message("Wrap search off", TRUE); + } + else { + WrapSearch = TRUE; + /* FIXME: gettextize? */ + disp_message("Wrap search on", TRUE); + } +} + +static int +is_wordchar(int c, const char *badchars) +{ + if (badchars) + return !(IS_SPACE(c) || strchr(badchars, c)); + else + return IS_ALPHA(c); +} + +static char * +getCurWord(Buffer *buf, int *spos, int *epos, const char *badchars) +{ + char *p; + Line *l = buf->currentLine; + int b, e; + + *spos = 0; + *epos = 0; + if (l == NULL) + return NULL; + p = l->lineBuf; + e = buf->pos; + while (e > 0 && !is_wordchar(p[e], badchars)) + e--; + if (!is_wordchar(p[e], badchars)) + return NULL; + b = e; + while (b > 0 && is_wordchar(p[b - 1], badchars)) + b--; + while (e < l->len && is_wordchar(p[e], badchars)) + e++; + *spos = b; + *epos = e; + return &p[b]; +} + +static char * +GetWord(Buffer *buf) +{ + int b, e; + char *p; + + if ((p = getCurWord(buf, &b, &e, 0)) != NULL) { + return Strnew_charp_n(p, e - b)->ptr; + } + return NULL; +} + +#ifdef USE_DICT +static void +execdict(char *word) +{ + char *w, *dictcmd; + Buffer *buf; + + if (!UseDictCommand || word == NULL || *word == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + w = conv_to_system(word); + if (*w == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + dictcmd = Sprintf("%s?%s", DictCommand, + Str_form_quote(Strnew_charp(w))->ptr)->ptr; + buf = loadGeneralFile(dictcmd, NULL, NO_REFERER, 0, NULL); + if (buf == NULL) { + disp_message("Execution failed", TRUE); + return; + } + else { + buf->filename = w; + buf->buffername = Sprintf("%s %s", DICTBUFFERNAME, word)->ptr; + if (buf->type == NULL) + buf->type = "text/plain"; + pushBuffer(buf); + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +DEFUN(dictword, DICT_WORD, "Execute dictionary command (see README.dict)") +{ + execdict(inputStr("(dictionary)!", "")); +} + +DEFUN(dictwordat, DICT_WORD_AT, + "Execute dictionary command for word at cursor") +{ + execdict(GetWord(Currentbuf)); +} +#endif /* USE_DICT */ + +void +set_buffer_environ(Buffer *buf) +{ + static Buffer *prev_buf = NULL; + static Line *prev_line = NULL; + static int prev_pos = -1; + Line *l; + + if (buf == NULL) + return; + if (buf != prev_buf) { + set_environ("W3M_SOURCEFILE", buf->sourcefile); + set_environ("W3M_FILENAME", buf->filename); + set_environ("W3M_TITLE", buf->buffername); + set_environ("W3M_URL", parsedURL2Str(&buf->currentURL)->ptr); + set_environ("W3M_TYPE", buf->real_type ? buf->real_type : "unknown"); +#ifdef USE_M17N + set_environ("W3M_CHARSET", wc_ces_to_charset(buf->document_charset)); +#endif + } + l = buf->currentLine; + if (l && (buf != prev_buf || l != prev_line || buf->pos != prev_pos)) { + Anchor *a; + ParsedURL pu; + char *s = GetWord(buf); + set_environ("W3M_CURRENT_WORD", s ? s : ""); + a = retrieveCurrentAnchor(buf); + if (a) { + parseURL2(a->url, &pu, baseURL(buf)); + set_environ("W3M_CURRENT_LINK", parsedURL2Str(&pu)->ptr); + } + else + set_environ("W3M_CURRENT_LINK", ""); + a = retrieveCurrentImg(buf); + if (a) { + parseURL2(a->url, &pu, baseURL(buf)); + set_environ("W3M_CURRENT_IMG", parsedURL2Str(&pu)->ptr); + } + else + set_environ("W3M_CURRENT_IMG", ""); + a = retrieveCurrentForm(buf); + if (a) + set_environ("W3M_CURRENT_FORM", form2str((FormItemList *)a->url)); + else + set_environ("W3M_CURRENT_FORM", ""); + set_environ("W3M_CURRENT_LINE", Sprintf("%d", + l->real_linenumber)->ptr); + set_environ("W3M_CURRENT_COLUMN", Sprintf("%d", + buf->currentColumn + + buf->cursorX + 1)->ptr); + } + else if (!l) { + set_environ("W3M_CURRENT_WORD", ""); + set_environ("W3M_CURRENT_LINK", ""); + set_environ("W3M_CURRENT_IMG", ""); + set_environ("W3M_CURRENT_FORM", ""); + set_environ("W3M_CURRENT_LINE", "0"); + set_environ("W3M_CURRENT_COLUMN", "0"); + } + prev_buf = buf; + prev_line = l; + prev_pos = buf->pos; +} + +char * +searchKeyData(void) +{ + char *data = NULL; + + if (CurrentKeyData != NULL && *CurrentKeyData != '\0') + data = CurrentKeyData; + else if (CurrentCmdData != NULL && *CurrentCmdData != '\0') + data = CurrentCmdData; + else if (CurrentKey >= 0) + data = getKeyData(CurrentKey); + CurrentKeyData = NULL; + CurrentCmdData = NULL; + if (data == NULL || *data == '\0') + return NULL; + return allocStr(data, -1); +} + +static int +searchKeyNum(void) +{ + char *d; + int n = 1; + + d = searchKeyData(); + if (d != NULL) + n = atoi(d); + return n * PREC_NUM; +} + +#ifdef __EMX__ +#ifdef USE_M17N +static char * +getCodePage(void) +{ + unsigned long CpList[8], CpSize; + + if (!getenv("WINDOWID") && !DosQueryCp(sizeof(CpList), CpList, &CpSize)) + return Sprintf("CP%d", *CpList)->ptr; + return NULL; +} +#endif +#endif + +void +deleteFiles() +{ + Buffer *buf; + char *f; + + for (CurrentTab = FirstTab; CurrentTab; CurrentTab = CurrentTab->nextTab) { + while (Firstbuf && Firstbuf != NO_BUFFER) { + buf = Firstbuf->nextBuffer; + discardBuffer(Firstbuf); + Firstbuf = buf; + } + } + while ((f = popText(fileToDelete)) != NULL) + unlink(f); +} + +void +w3m_exit(int i) +{ +#ifdef USE_MIGEMO + init_migemo(); /* close pipe to migemo */ +#endif + stopDownload(); + deleteFiles(); +#ifdef USE_SSL + free_ssl_ctx(); +#endif + disconnectFTP(); +#ifdef USE_NNTP + disconnectNews(); +#endif +#ifdef __MINGW32_VERSION + WSACleanup(); +#endif + exit(i); +} + +DEFUN(execCmd, COMMAND, "Execute w3m command(s)") +{ + char *data, *p; + int cmd; + + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + data = searchKeyData(); + if (data == NULL || *data == '\0') { + data = inputStrHist("command [; ...]: ", "", TextHist); + if (data == NULL) { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + } + /* data: FUNC [DATA] [; FUNC [DATA] ...] */ + while (*data) { + SKIP_BLANKS(data); + if (*data == ';') { + data++; + continue; + } + p = getWord(&data); + cmd = getFuncList(p); + if (cmd < 0) + break; + p = getQWord(&data); + CurrentKey = -1; + CurrentKeyData = NULL; + CurrentCmdData = *p ? p : NULL; +#ifdef USE_MOUSE + if (use_mouse) + mouse_inactive(); +#endif + w3mFuncList[cmd].func(); +#ifdef USE_MOUSE + if (use_mouse) + mouse_active(); +#endif + CurrentCmdData = NULL; + } + displayBuffer(Currentbuf, B_NORMAL); +} + +#ifdef USE_ALARM +static MySignalHandler +SigAlarm(SIGNAL_ARG) +{ + char *data; + + if (CurrentAlarm->sec > 0) { + CurrentKey = -1; + CurrentKeyData = NULL; + CurrentCmdData = data = (char *)CurrentAlarm->data; +#ifdef USE_MOUSE + if (use_mouse) + mouse_inactive(); +#endif + w3mFuncList[CurrentAlarm->cmd].func(); +#ifdef USE_MOUSE + if (use_mouse) + mouse_active(); +#endif + CurrentCmdData = NULL; + if (CurrentAlarm->status == AL_IMPLICIT_ONCE) { + CurrentAlarm->sec = 0; + CurrentAlarm->status = AL_UNSET; + } + if (Currentbuf->event) { + if (Currentbuf->event->status != AL_UNSET) + CurrentAlarm = Currentbuf->event; + else + Currentbuf->event = NULL; + } + if (!Currentbuf->event) + CurrentAlarm = &DefaultAlarm; + if (CurrentAlarm->sec > 0) { + mySignal(SIGALRM, SigAlarm); + alarm(CurrentAlarm->sec); + } + } + SIGNAL_RETURN; +} + + +DEFUN(setAlarm, ALARM, "Set alarm") +{ + char *data; + int sec = 0, cmd = -1; + + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + data = searchKeyData(); + if (data == NULL || *data == '\0') { + data = inputStrHist("(Alarm)sec command: ", "", TextHist); + if (data == NULL) { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + } + if (*data != '\0') { + sec = atoi(getWord(&data)); + if (sec > 0) + cmd = getFuncList(getWord(&data)); + } + if (cmd >= 0) { + data = getQWord(&data); + setAlarmEvent(&DefaultAlarm, sec, AL_EXPLICIT, cmd, data); + disp_message_nsec(Sprintf("%dsec %s %s", sec, w3mFuncList[cmd].id, + data)->ptr, FALSE, 1, FALSE, TRUE); + } + else { + setAlarmEvent(&DefaultAlarm, 0, AL_UNSET, FUNCNAME_nulcmd, NULL); + } + displayBuffer(Currentbuf, B_NORMAL); +} + +AlarmEvent * +setAlarmEvent(AlarmEvent * event, int sec, short status, int cmd, void *data) +{ + if (event == NULL) + event = New(AlarmEvent); + event->sec = sec; + event->status = status; + event->cmd = cmd; + event->data = data; + return event; +} +#endif + +DEFUN(reinit, REINIT, "Reload configuration files") +{ + char *resource = searchKeyData(); + + if (resource == NULL) { + init_rc(); + sync_with_option(); +#ifdef USE_COOKIE + initCookie(); +#endif + displayBuffer(Currentbuf, B_REDRAW_IMAGE); + return; + } + + if (!strcasecmp(resource, "CONFIG") || !strcasecmp(resource, "RC")) { + init_rc(); + sync_with_option(); + displayBuffer(Currentbuf, B_REDRAW_IMAGE); + return; + } + +#ifdef USE_COOKIE + if (!strcasecmp(resource, "COOKIE")) { + initCookie(); + return; + } +#endif + + if (!strcasecmp(resource, "KEYMAP")) { + initKeymap(TRUE); + return; + } + + if (!strcasecmp(resource, "MAILCAP")) { + initMailcap(); + return; + } + +#ifdef USE_MOUSE + if (!strcasecmp(resource, "MOUSE")) { + initMouseAction(); + displayBuffer(Currentbuf, B_REDRAW_IMAGE); + return; + } +#endif + +#ifdef USE_MENU + if (!strcasecmp(resource, "MENU")) { + initMenu(); + return; + } +#endif + + if (!strcasecmp(resource, "MIMETYPES")) { + initMimeTypes(); + return; + } + +#ifdef USE_EXTERNAL_URI_LOADER + if (!strcasecmp(resource, "URIMETHODS")) { + initURIMethods(); + return; + } +#endif + + disp_err_message(Sprintf("Don't know how to reinitialize '%s'", resource)-> + ptr, FALSE); +} + +DEFUN(defKey, DEFINE_KEY, + "Define a binding between a key stroke and a user command") +{ + char *data; + + CurrentKeyData = NULL; /* not allowed in w3m-control: */ + data = searchKeyData(); + if (data == NULL || *data == '\0') { + data = inputStrHist("Key definition: ", "", TextHist); + if (data == NULL || *data == '\0') { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + } + setKeymap(allocStr(data, -1), -1, TRUE); + displayBuffer(Currentbuf, B_NORMAL); +} + +TabBuffer * +newTab(void) +{ + TabBuffer *n; + + n = New(TabBuffer); + if (n == NULL) + return NULL; + n->nextTab = NULL; + n->currentBuffer = NULL; + n->firstBuffer = NULL; + return n; +} + +static void +_newT(void) +{ + TabBuffer *tag; + Buffer *buf; + int i; + + tag = newTab(); + if (!tag) + return; + + buf = newBuffer(Currentbuf->width); + copyBuffer(buf, Currentbuf); + buf->nextBuffer = NULL; + for (i = 0; i < MAX_LB; i++) + buf->linkBuffer[i] = NULL; + (*buf->clone)++; + tag->firstBuffer = tag->currentBuffer = buf; + + tag->nextTab = CurrentTab->nextTab; + tag->prevTab = CurrentTab; + if (CurrentTab->nextTab) + CurrentTab->nextTab->prevTab = tag; + else + LastTab = tag; + CurrentTab->nextTab = tag; + CurrentTab = tag; + nTab++; +} + +DEFUN(newT, NEW_TAB, "Open new tab") +{ + _newT(); + displayBuffer(Currentbuf, B_REDRAW_IMAGE); +} + +static TabBuffer * +numTab(int n) +{ + TabBuffer *tab; + int i; + + if (n == 0) + return CurrentTab; + if (n == 1) + return FirstTab; + if (nTab <= 1) + return NULL; + for (tab = FirstTab, i = 1; tab && i < n; tab = tab->nextTab, i++) ; + return tab; +} + +void +calcTabPos(void) +{ + TabBuffer *tab; +#if 0 + int lcol = 0, rcol = 2, col; +#else + int lcol = 0, rcol = 0, col; +#endif + int n1, n2, na, nx, ny, ix, iy; + +#ifdef USE_MOUSE + lcol = mouse_action.menu_str ? mouse_action.menu_width : 0; +#endif + + if (nTab <= 0) + return; + n1 = (COLS - rcol - lcol) / TabCols; + if (n1 >= nTab) { + n2 = 1; + ny = 1; + } + else { + if (n1 < 0) + n1 = 0; + n2 = COLS / TabCols; + if (n2 == 0) + n2 = 1; + ny = (nTab - n1 - 1) / n2 + 2; + } + na = n1 + n2 * (ny - 1); + n1 -= (na - nTab) / ny; + if (n1 < 0) + n1 = 0; + na = n1 + n2 * (ny - 1); + tab = FirstTab; + for (iy = 0; iy < ny && tab; iy++) { + if (iy == 0) { + nx = n1; + col = COLS - rcol - lcol; + } + else { + nx = n2 - (na - nTab + (iy - 1)) / (ny - 1); + col = COLS; + } + for (ix = 0; ix < nx && tab; ix++, tab = tab->nextTab) { + tab->x1 = col * ix / nx; + tab->x2 = col * (ix + 1) / nx - 1; + tab->y = iy; + if (iy == 0) { + tab->x1 += lcol; + tab->x2 += lcol; + } + } + } +} + +TabBuffer * +deleteTab(TabBuffer * tab) +{ + Buffer *buf, *next; + + if (nTab <= 1) + return FirstTab; + if (tab->prevTab) { + if (tab->nextTab) + tab->nextTab->prevTab = tab->prevTab; + else + LastTab = tab->prevTab; + tab->prevTab->nextTab = tab->nextTab; + if (tab == CurrentTab) + CurrentTab = tab->prevTab; + } + else { /* tab == FirstTab */ + tab->nextTab->prevTab = NULL; + FirstTab = tab->nextTab; + if (tab == CurrentTab) + CurrentTab = tab->nextTab; + } + nTab--; + buf = tab->firstBuffer; + while (buf && buf != NO_BUFFER) { + next = buf->nextBuffer; + discardBuffer(buf); + buf = next; + } + return FirstTab; +} + +DEFUN(closeT, CLOSE_TAB, "Close current tab") +{ + TabBuffer *tab; + + if (nTab <= 1) + return; + if (prec_num) + tab = numTab(PREC_NUM); + else + tab = CurrentTab; + if (tab) + deleteTab(tab); + displayBuffer(Currentbuf, B_REDRAW_IMAGE); +} + +DEFUN(nextT, NEXT_TAB, "Move to next tab") +{ + int i; + + if (nTab <= 1) + return; + for (i = 0; i < PREC_NUM; i++) { + if (CurrentTab->nextTab) + CurrentTab = CurrentTab->nextTab; + else + CurrentTab = FirstTab; + } + displayBuffer(Currentbuf, B_REDRAW_IMAGE); +} + +DEFUN(prevT, PREV_TAB, "Move to previous tab") +{ + int i; + + if (nTab <= 1) + return; + for (i = 0; i < PREC_NUM; i++) { + if (CurrentTab->prevTab) + CurrentTab = CurrentTab->prevTab; + else + CurrentTab = LastTab; + } + displayBuffer(Currentbuf, B_REDRAW_IMAGE); +} + +static void +followTab(TabBuffer * tab) +{ + Buffer *buf; + Anchor *a; + +#ifdef USE_IMAGE + a = retrieveCurrentImg(Currentbuf); + if (!(a && a->image && a->image->map)) +#endif + a = retrieveCurrentAnchor(Currentbuf); + if (a == NULL) + return; + + if (tab == CurrentTab) { + check_target = FALSE; + followA(); + check_target = TRUE; + return; + } + _newT(); + buf = Currentbuf; + check_target = FALSE; + followA(); + check_target = TRUE; + if (tab == NULL) { + if (buf != Currentbuf) + delBuffer(buf); + else + deleteTab(CurrentTab); + } + else if (buf != Currentbuf) { + /* buf <- p <- ... <- Currentbuf = c */ + Buffer *c, *p; + + c = Currentbuf; + p = prevBuffer(c, buf); + p->nextBuffer = NULL; + Firstbuf = buf; + deleteTab(CurrentTab); + CurrentTab = tab; + for (buf = p; buf; buf = p) { + p = prevBuffer(c, buf); + pushBuffer(buf); + } + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +DEFUN(tabA, TAB_LINK, "Open current link on new tab") +{ + followTab(prec_num ? numTab(PREC_NUM) : NULL); +} + +static void +tabURL0(TabBuffer * tab, char *prompt, int relative) +{ + Buffer *buf; + + if (tab == CurrentTab) { + goURL0(prompt, relative); + return; + } + _newT(); + buf = Currentbuf; + goURL0(prompt, relative); + if (tab == NULL) { + if (buf != Currentbuf) + delBuffer(buf); + else + deleteTab(CurrentTab); + } + else if (buf != Currentbuf) { + /* buf <- p <- ... <- Currentbuf = c */ + Buffer *c, *p; + + c = Currentbuf; + p = prevBuffer(c, buf); + p->nextBuffer = NULL; + Firstbuf = buf; + deleteTab(CurrentTab); + CurrentTab = tab; + for (buf = p; buf; buf = p) { + p = prevBuffer(c, buf); + pushBuffer(buf); + } + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +DEFUN(tabURL, TAB_GOTO, "Open URL on new tab") +{ + tabURL0(prec_num ? numTab(PREC_NUM) : NULL, + "Goto URL on new tab: ", FALSE); +} + +DEFUN(tabrURL, TAB_GOTO_RELATIVE, "Open relative URL on new tab") +{ + tabURL0(prec_num ? numTab(PREC_NUM) : NULL, + "Goto relative URL on new tab: ", TRUE); +} + +static void +moveTab(TabBuffer * t, TabBuffer * t2, int right) +{ + if (t2 == NO_TABBUFFER) + t2 = FirstTab; + if (!t || !t2 || t == t2 || t == NO_TABBUFFER) + return; + if (t->prevTab) { + if (t->nextTab) + t->nextTab->prevTab = t->prevTab; + else + LastTab = t->prevTab; + t->prevTab->nextTab = t->nextTab; + } + else { + t->nextTab->prevTab = NULL; + FirstTab = t->nextTab; + } + if (right) { + t->nextTab = t2->nextTab; + t->prevTab = t2; + if (t2->nextTab) + t2->nextTab->prevTab = t; + else + LastTab = t; + t2->nextTab = t; + } + else { + t->prevTab = t2->prevTab; + t->nextTab = t2; + if (t2->prevTab) + t2->prevTab->nextTab = t; + else + FirstTab = t; + t2->prevTab = t; + } + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +DEFUN(tabR, TAB_RIGHT, "Move current tab right") +{ + TabBuffer *tab; + int i; + + for (tab = CurrentTab, i = 0; tab && i < PREC_NUM; + tab = tab->nextTab, i++) ; + moveTab(CurrentTab, tab ? tab : LastTab, TRUE); +} + +DEFUN(tabL, TAB_LEFT, "Move current tab left") +{ + TabBuffer *tab; + int i; + + for (tab = CurrentTab, i = 0; tab && i < PREC_NUM; + tab = tab->prevTab, i++) ; + moveTab(CurrentTab, tab ? tab : FirstTab, FALSE); +} + +void +addDownloadList(pid_t pid, char *url, char *save, char *lock, clen_t size) +{ + DownloadList *d; + + d = New(DownloadList); + d->pid = pid; + d->url = url; + if (save[0] != '/' && save[0] != '~') + save = Strnew_m_charp(CurrentDir, "/", save, NULL)->ptr; + d->save = expandPath(save); + d->lock = lock; + d->size = size; + d->time = time(0); + d->ok = FALSE; + d->next = NULL; + d->prev = LastDL; + if (LastDL) + LastDL->next = d; + else + FirstDL = d; + LastDL = d; + add_download_list = TRUE; +} + +int +checkDownloadList(void) +{ + DownloadList *d; + struct stat st; + + if (!FirstDL) + return FALSE; + for (d = FirstDL; d != NULL; d = d->next) { + if (!d->ok && !lstat(d->lock, &st)) + return TRUE; + } + return FALSE; +} + +static char * +convert_size3(clen_t size) +{ + Str tmp = Strnew(); + int n; + + do { + n = size % 1000; + size /= 1000; + tmp = Sprintf(size ? ",%.3d%s" : "%d%s", n, tmp->ptr); + } while (size); + return tmp->ptr; +} + +static Buffer * +DownloadListBuffer(void) +{ + DownloadList *d; + Str src = NULL; + struct stat st; + time_t cur_time; + int duration, rate, eta; + size_t size; + + if (!FirstDL) + return NULL; + cur_time = time(0); + /* FIXME: gettextize? */ + src = Strnew_charp("" DOWNLOAD_LIST_TITLE + "\n

" + DOWNLOAD_LIST_TITLE "

\n" + "

\n"); + for (d = LastDL; d != NULL; d = d->prev) { + if (lstat(d->lock, &st)) + d->ok = TRUE; + Strcat_charp(src, "
\n");
+	Strcat(src, Sprintf("%s\n  --> %s\n  ", html_quote(d->url),
+			    html_quote(conv_from_system(d->save))));
+	duration = cur_time - d->time;
+	if (!stat(d->save, &st)) {
+	    size = st.st_size;
+	    if (d->ok) {
+		d->size = size;
+		duration = st.st_mtime - d->time;
+	    }
+	}
+	else
+	    size = 0;
+	if (d->size) {
+	    int i, l = COLS - 6;
+	    if (size < d->size)
+		i = 1.0 * l * size / d->size;
+	    else
+		i = l;
+	    l -= i;
+	    while (i-- > 0)
+		Strcat_char(src, '#');
+	    while (l-- > 0)
+		Strcat_char(src, '_');
+	    Strcat_char(src, '\n');
+	}
+	if (!d->ok && size < d->size)
+	    Strcat(src, Sprintf("  %s / %s bytes (%d%%)",
+				convert_size3(size), convert_size3(d->size),
+				(int)(100.0 * size / d->size)));
+	else
+	    Strcat(src, Sprintf("  %s bytes loaded", convert_size3(size)));
+	if (duration > 0) {
+	    rate = size / duration;
+	    Strcat(src, Sprintf("  %02d:%02d:%02d  rate %s/sec",
+				duration / (60 * 60), (duration / 60) % 60,
+				duration % 60, convert_size(rate, 1)));
+	    if (!d->ok && size < d->size && rate) {
+		eta = (d->size - size) / rate;
+		Strcat(src, Sprintf("  eta %02d:%02d:%02d", eta / (60 * 60),
+				    (eta / 60) % 60, eta % 60));
+	    }
+	}
+	Strcat_char(src, '\n');
+	if (d->ok) {
+	    Strcat(src, Sprintf("",
+				d->pid));
+	    if (size < d->size)
+		Strcat_charp(src, " Download incompleted");
+	    else
+		Strcat_charp(src, " Download completed");
+	}
+	else
+	    Strcat(src, Sprintf("",
+				d->pid));
+	Strcat_charp(src, "\n

\n"); + } + Strcat_charp(src, "
"); + return loadHTMLString(src); +} + +void +download_action(struct parsed_tagarg *arg) +{ + DownloadList *d; + pid_t pid; + + for (; arg; arg = arg->next) { + if (!strncmp(arg->arg, "stop", 4)) { + pid = (pid_t) atoi(&arg->arg[4]); +#ifndef __MINGW32_VERSION + kill(pid, SIGKILL); +#endif + } + else if (!strncmp(arg->arg, "ok", 2)) + pid = (pid_t) atoi(&arg->arg[2]); + else + continue; + for (d = FirstDL; d; d = d->next) { + if (d->pid == pid) { + unlink(d->lock); + if (d->prev) + d->prev->next = d->next; + else + FirstDL = d->next; + if (d->next) + d->next->prev = d->prev; + else + LastDL = d->prev; + break; + } + } + } + ldDL(); +} + +void +stopDownload(void) +{ + DownloadList *d; + + if (!FirstDL) + return; + for (d = FirstDL; d != NULL; d = d->next) { + if (d->ok) + continue; +#ifndef __MINGW32_VERSION + kill(d->pid, SIGKILL); +#endif + unlink(d->lock); + } +} + +/* download panel */ +DEFUN(ldDL, DOWNLOAD_LIST, "Display download list panel") +{ + Buffer *buf; + int replace = FALSE, new_tab = FALSE; +#ifdef USE_ALARM + int reload; +#endif + + if (Currentbuf->bufferprop & BP_INTERNAL && + !strcmp(Currentbuf->buffername, DOWNLOAD_LIST_TITLE)) + replace = TRUE; + if (!FirstDL) { + if (replace) { + if (Currentbuf == Firstbuf && Currentbuf->nextBuffer == NULL) { + if (nTab > 1) + deleteTab(CurrentTab); + } + else + delBuffer(Currentbuf); + displayBuffer(Currentbuf, B_FORCE_REDRAW); + } + return; + } +#ifdef USE_ALARM + reload = checkDownloadList(); +#endif + buf = DownloadListBuffer(); + if (!buf) { + displayBuffer(Currentbuf, B_NORMAL); + return; + } + buf->bufferprop |= (BP_INTERNAL | BP_NO_URL); + if (replace) { + COPY_BUFROOT(buf, Currentbuf); + restorePosition(buf, Currentbuf); + } + if (!replace && open_tab_dl_list) { + _newT(); + new_tab = TRUE; + } + pushBuffer(buf); + if (replace || new_tab) + deletePrevBuf(); +#ifdef USE_ALARM + if (reload) + Currentbuf->event = setAlarmEvent(Currentbuf->event, 1, AL_IMPLICIT, + FUNCNAME_reload, NULL); +#endif + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +static void +save_buffer_position(Buffer *buf) +{ + BufferPos *b = buf->undo; + + if (!buf->firstLine) + return; + if (b && b->top_linenumber == TOP_LINENUMBER(buf) && + b->cur_linenumber == CUR_LINENUMBER(buf) && + b->currentColumn == buf->currentColumn && b->pos == buf->pos) + return; + b = New(BufferPos); + b->top_linenumber = TOP_LINENUMBER(buf); + b->cur_linenumber = CUR_LINENUMBER(buf); + b->currentColumn = buf->currentColumn; + b->pos = buf->pos; + b->bpos = buf->currentLine ? buf->currentLine->bpos : 0; + b->next = NULL; + b->prev = buf->undo; + if (buf->undo) + buf->undo->next = b; + buf->undo = b; +} + +static void +resetPos(BufferPos * b) +{ + Buffer buf; + Line top, cur; + + top.linenumber = b->top_linenumber; + cur.linenumber = b->cur_linenumber; + cur.bpos = b->bpos; + buf.topLine = ⊤ + buf.currentLine = &cur; + buf.pos = b->pos; + buf.currentColumn = b->currentColumn; + restorePosition(Currentbuf, &buf); + Currentbuf->undo = b; + displayBuffer(Currentbuf, B_FORCE_REDRAW); +} + +DEFUN(undoPos, UNDO, "Cancel the last cursor movement") +{ + BufferPos *b = Currentbuf->undo; + int i; + + if (!Currentbuf->firstLine) + return; + if (!b || !b->prev) + return; + for (i = 0; i < PREC_NUM && b->prev; i++, b = b->prev) ; + resetPos(b); +} + +DEFUN(redoPos, REDO, "Cancel the last undo") +{ + BufferPos *b = Currentbuf->undo; + int i; + + if (!Currentbuf->firstLine) + return; + if (!b || !b->next) + return; + for (i = 0; i < PREC_NUM && b->next; i++, b = b->next) ; + resetPos(b); +} diff -urN w3m-0.5.2.orig/rc.c w3m-0.5.2/rc.c --- w3m-0.5.2.orig/rc.c 2007-05-24 00:06:06.000000000 +0900 +++ w3m-0.5.2/rc.c 2010-07-18 08:13:26.000000000 +0900 @@ -330,6 +330,13 @@ }; #endif +static struct sel_c graphic_char_str[] = { + {N_S(GRAPHIC_CHAR_ASCII), N_("No")}, + {N_S(GRAPHIC_CHAR_CHARSET), N_("Yes, but only charset specific")}, + {N_S(GRAPHIC_CHAR_ALL), N_("Yes")}, + {0, NULL, NULL} +}; + struct param_ptr params1[] = { {"tabstop", P_NZINT, PI_TEXT, (void *)&Tabstop, CMT_TABSTOP, NULL}, {"indent_incr", P_NZINT, PI_TEXT, (void *)&IndentIncr, CMT_INDENT_INCR, @@ -364,8 +371,8 @@ {"multicol", P_INT, PI_ONOFF, (void *)&multicolList, CMT_MULTICOL, NULL}, {"alt_entity", P_CHARINT, PI_ONOFF, (void *)&UseAltEntity, CMT_ALT_ENTITY, NULL}, - {"graphic_char", P_CHARINT, PI_ONOFF, (void *)&UseGraphicChar, - CMT_GRAPHIC_CHAR, NULL}, + {"graphic_char", P_CHARINT, PI_SEL_C, (void *)&UseGraphicChar, + CMT_GRAPHIC_CHAR, (void *)graphic_char_str}, {"fold_textarea", P_CHARINT, PI_ONOFF, (void *)&FoldTextarea, CMT_FOLD_TEXTAREA, NULL}, {"display_ins_del", P_INT, PI_SEL_C, (void *)&displayInsDel, diff -urN w3m-0.5.2.orig/rc.c.orig w3m-0.5.2/rc.c.orig --- w3m-0.5.2.orig/rc.c.orig 1970-01-01 09:00:00.000000000 +0900 +++ w3m-0.5.2/rc.c.orig 2007-05-24 00:06:06.000000000 +0900 @@ -0,0 +1,1513 @@ +/* $Id: rc.c,v 1.106 2007/05/23 15:06:06 inu Exp $ */ +/* + * Initialization file etc. + */ +#include "fm.h" +#include "myctype.h" +#include "proto.h" +#include +#include +#include "parsetag.h" +#include "local.h" +#include + +struct param_ptr { + char *name; + int type; + int inputtype; + void *varptr; + char *comment; + void *select; +}; + +struct param_section { + char *name; + struct param_ptr *params; +}; + +struct rc_search_table { + struct param_ptr *param; + short uniq_pos; +}; + +static struct rc_search_table *RC_search_table; +static int RC_table_size; + +#define P_INT 0 +#define P_SHORT 1 +#define P_CHARINT 2 +#define P_CHAR 3 +#define P_STRING 4 +#if defined(USE_SSL) && defined(USE_SSL_VERIFY) +#define P_SSLPATH 5 +#endif +#ifdef USE_COLOR +#define P_COLOR 6 +#endif +#ifdef USE_M17N +#define P_CODE 7 +#endif +#define P_PIXELS 8 +#define P_NZINT 9 +#define P_SCALE 10 + +/* FIXME: gettextize here */ +#ifdef USE_M17N +static wc_ces OptionCharset = WC_CES_US_ASCII; /* FIXME: charset of source code */ +static int OptionEncode = FALSE; +#endif + +#define CMT_HELPER N_("External Viewer Setup") +#define CMT_TABSTOP N_("Tab width in characters") +#define CMT_INDENT_INCR N_("Indent for HTML rendering") +#define CMT_PIXEL_PER_CHAR N_("Number of pixels per character (4.0...32.0)") +#define CMT_PIXEL_PER_LINE N_("Number of pixels per line (4.0...64.0)") +#define CMT_PAGERLINE N_("Number of remembered lines when used as a pager") +#define CMT_HISTORY N_("Use URL history") +#define CMT_HISTSIZE N_("Number of remembered URL") +#define CMT_SAVEHIST N_("Save URL history") +#define CMT_FRAME N_("Render frames automatically") +#define CMT_ARGV_IS_URL N_("Treat argument without scheme as URL") +#define CMT_TSELF N_("Use _self as default target") +#define CMT_OPEN_TAB_BLANK N_("Open link on new tab if target is _blank or _new") +#define CMT_OPEN_TAB_DL_LIST N_("Open download list panel on new tab") +#define CMT_DISPLINK N_("Display link URL automatically") +#define CMT_DECODE_URL N_("Display decoded URL") +#define CMT_DISPLINEINFO N_("Display current line number") +#define CMT_DISP_IMAGE N_("Display inline images") +#ifdef USE_IMAGE +#define CMT_AUTO_IMAGE N_("Load inline images automatically") +#define CMT_MAX_LOAD_IMAGE N_("Maximum processes for parallel image loading") +#define CMT_EXT_IMAGE_VIEWER N_("Use external image viewer") +#define CMT_IMAGE_SCALE N_("Scale of image (%)") +#define CMT_IMGDISPLAY N_("External command to display image") +#define CMT_IMAGE_MAP_LIST N_("Use link list of image map") +#endif +#define CMT_MULTICOL N_("Display file names in multi-column format") +#define CMT_ALT_ENTITY N_("Use ASCII equivalents to display entities") +#define CMT_GRAPHIC_CHAR N_("Use graphic char for border of table and menu") +#define CMT_FOLD_TEXTAREA N_("Fold lines in TEXTAREA") +#define CMT_DISP_INS_DEL N_("Display INS, DEL, S and STRIKE element") +#define CMT_COLOR N_("Display with color") +#define CMT_B_COLOR N_("Color of normal character") +#define CMT_A_COLOR N_("Color of anchor") +#define CMT_I_COLOR N_("Color of image link") +#define CMT_F_COLOR N_("Color of form") +#define CMT_ACTIVE_STYLE N_("Enable coloring of active link") +#define CMT_C_COLOR N_("Color of currently active link") +#define CMT_VISITED_ANCHOR N_("Use visited link color") +#define CMT_V_COLOR N_("Color of visited link") +#define CMT_BG_COLOR N_("Color of background") +#define CMT_MARK_COLOR N_("Color of mark") +#define CMT_USE_PROXY N_("Use proxy") +#define CMT_HTTP_PROXY N_("URL of HTTP proxy host") +#ifdef USE_SSL +#define CMT_HTTPS_PROXY N_("URL of HTTPS proxy host") +#endif /* USE_SSL */ +#ifdef USE_GOPHER +#define CMT_GOPHER_PROXY N_("URL of GOPHER proxy host") +#endif /* USE_GOPHER */ +#define CMT_FTP_PROXY N_("URL of FTP proxy host") +#define CMT_NO_PROXY N_("Domains to be accessed directly (no proxy)") +#define CMT_NOPROXY_NETADDR N_("Check noproxy by network address") +#define CMT_NO_CACHE N_("Disable cache") +#ifdef USE_NNTP +#define CMT_NNTP_SERVER N_("News server") +#define CMT_NNTP_MODE N_("Mode of news server") +#define CMT_MAX_NEWS N_("Number of news messages") +#endif +#define CMT_DNS_ORDER N_("Order of name resolution") +#define CMT_DROOT N_("Directory corresponding to / (document root)") +#define CMT_PDROOT N_("Directory corresponding to /~user") +#define CMT_CGIBIN N_("Directory corresponding to /cgi-bin") +#define CMT_CONFIRM_QQ N_("Confirm when quitting with q") +#define CMT_CLOSE_TAB_BACK N_("Close tab if buffer is last when back") +#ifdef USE_MARK +#define CMT_USE_MARK N_("Enable mark operations") +#endif +#define CMT_EMACS_LIKE_LINEEDIT N_("Enable Emacs-style line editing") +#define CMT_VI_PREC_NUM N_("Enable vi-like numeric prefix") +#define CMT_LABEL_TOPLINE N_("Move cursor to top line when going to label") +#define CMT_NEXTPAGE_TOPLINE N_("Move cursor to top line when moving to next page") +#define CMT_FOLD_LINE N_("Fold lines of plain text file") +#define CMT_SHOW_NUM N_("Show line numbers") +#define CMT_SHOW_SRCH_STR N_("Show search string") +#define CMT_MIMETYPES N_("List of mime.types files") +#define CMT_MAILCAP N_("List of mailcap files") +#define CMT_URIMETHODMAP N_("List of urimethodmap files") +#define CMT_EDITOR N_("Editor") +#define CMT_MAILER N_("Mailer") +#define CMT_EXTBRZ N_("External Browser") +#define CMT_EXTBRZ2 N_("Second External Browser") +#define CMT_EXTBRZ3 N_("Third External Browser") +#define CMT_DISABLE_SECRET_SECURITY_CHECK N_("Disable secret file security check") +#define CMT_PASSWDFILE N_("Password file") +#define CMT_PRE_FORM_FILE N_("File for setting form on loading") +#define CMT_FTPPASS N_("Password for anonymous FTP (your mail address)") +#define CMT_FTPPASS_HOSTNAMEGEN N_("Generate domain part of password for FTP") +#define CMT_USERAGENT N_("User-Agent identification string") +#define CMT_ACCEPTENCODING N_("Accept-Encoding header") +#define CMT_ACCEPTMEDIA N_("Accept header") +#define CMT_ACCEPTLANG N_("Accept-Language header") +#define CMT_MARK_ALL_PAGES N_("Treat URL-like strings as links in all pages") +#define CMT_WRAP N_("Wrap search") +#define CMT_VIEW_UNSEENOBJECTS N_("Display unseen objects (e.g. bgimage tag)") +#define CMT_AUTO_UNCOMPRESS N_("Uncompress compressed data automatically when downloading") +#ifdef __EMX__ +#define CMT_BGEXTVIEW N_("Run external viewer in a separate session") +#else +#define CMT_BGEXTVIEW N_("Run external viewer in the background") +#endif +#define CMT_EXT_DIRLIST N_("Use external program for directory listing") +#define CMT_DIRLIST_CMD N_("URL of directory listing command") +#ifdef USE_DICT +#define CMT_USE_DICTCOMMAND N_("Enable dictionary lookup through CGI") +#define CMT_DICTCOMMAND N_("URL of dictionary lookup command") +#endif /* USE_DICT */ +#define CMT_IGNORE_NULL_IMG_ALT N_("Display link name for images lacking ALT") +#define CMT_IFILE N_("Index file for directories") +#define CMT_RETRY_HTTP N_("Prepend http:// to URL automatically") +#define CMT_DEFAULT_URL N_("Default value for open-URL command") +#define CMT_DECODE_CTE N_("Decode Content-Transfer-Encoding when saving") +#define CMT_PRESERVE_TIMESTAMP N_("Preserve timestamp when saving") +#ifdef USE_MOUSE +#define CMT_MOUSE N_("Enable mouse") +#define CMT_REVERSE_MOUSE N_("Scroll in reverse direction of mouse drag") +#define CMT_RELATIVE_WHEEL_SCROLL N_("Behavior of wheel scroll speed") +#define CMT_RELATIVE_WHEEL_SCROLL_RATIO N_("(A only)Scroll by # (%) of screen") +#define CMT_FIXED_WHEEL_SCROLL_COUNT N_("(B only)Scroll by # lines") +#endif /* USE_MOUSE */ +#define CMT_CLEAR_BUF N_("Free memory of undisplayed buffers") +#define CMT_NOSENDREFERER N_("Suppress `Referer:' header") +#define CMT_IGNORE_CASE N_("Search case-insensitively") +#define CMT_USE_LESSOPEN N_("Use LESSOPEN") +#ifdef USE_SSL +#ifdef USE_SSL_VERIFY +#define CMT_SSL_VERIFY_SERVER N_("Perform SSL server verification") +#define CMT_SSL_CERT_FILE N_("PEM encoded certificate file of client") +#define CMT_SSL_KEY_FILE N_("PEM encoded private key file of client") +#define CMT_SSL_CA_PATH N_("Path to directory for PEM encoded certificates of CAs") +#define CMT_SSL_CA_FILE N_("File consisting of PEM encoded certificates of CAs") +#endif /* USE_SSL_VERIFY */ +#define CMT_SSL_FORBID_METHOD N_("List of forbidden SSL methods (2: SSLv2, 3: SSLv3, t:TLSv1)") +#endif /* USE_SSL */ +#ifdef USE_COOKIE +#define CMT_USECOOKIE N_("Enable cookie processing") +#define CMT_SHOWCOOKIE N_("Print a message when receiving a cookie") +#define CMT_ACCEPTCOOKIE N_("Accept cookies") +#define CMT_ACCEPTBADCOOKIE N_("Action to be taken on invalid cookie") +#define CMT_COOKIE_REJECT_DOMAINS N_("Domains to reject cookies from") +#define CMT_COOKIE_ACCEPT_DOMAINS N_("Domains to accept cookies from") +#endif +#define CMT_FOLLOW_REDIRECTION N_("Number of redirections to follow") +#define CMT_META_REFRESH N_("Enable processing of meta-refresh tag") + +#ifdef USE_MIGEMO +#define CMT_USE_MIGEMO N_("Enable Migemo (Roma-ji search)") +#define CMT_MIGEMO_COMMAND N_("Migemo command") +#endif /* USE_MIGEMO */ + +#ifdef USE_M17N +#define CMT_DISPLAY_CHARSET N_("Display charset") +#define CMT_DOCUMENT_CHARSET N_("Default document charset") +#define CMT_AUTO_DETECT N_("Automatic charset detect when loading") +#define CMT_SYSTEM_CHARSET N_("System charset") +#define CMT_FOLLOW_LOCALE N_("System charset follows locale(LC_CTYPE)") +#define CMT_EXT_HALFDUMP N_("Output halfdump with display charset") +#define CMT_USE_WIDE N_("Use multi column characters") +#define CMT_USE_COMBINING N_("Use combining characters") +#define CMT_USE_LANGUAGE_TAG N_("Use Unicode language tags") +#define CMT_UCS_CONV N_("Charset conversion using Unicode map") +#define CMT_PRE_CONV N_("Charset conversion when loading") +#define CMT_SEARCH_CONV N_("Adjust search string for document charset") +#define CMT_FIX_WIDTH_CONV N_("Fix character width when conversion") +#define CMT_USE_GB12345_MAP N_("Use GB 12345 Unicode map instead of GB 2312's") +#define CMT_USE_JISX0201 N_("Use JIS X 0201 Roman for ISO-2022-JP") +#define CMT_USE_JISC6226 N_("Use JIS C 6226:1978 for ISO-2022-JP") +#define CMT_USE_JISX0201K N_("Use JIS X 0201 Katakana") +#define CMT_USE_JISX0212 N_("Use JIS X 0212:1990 (Supplemental Kanji)") +#define CMT_USE_JISX0213 N_("Use JIS X 0213:2000 (2000JIS)") +#define CMT_STRICT_ISO2022 N_("Strict ISO-2022-JP/KR/CN") +#define CMT_GB18030_AS_UCS N_("Treat 4 bytes char. of GB18030 as Unicode") +#endif + +#define CMT_KEYMAP_FILE N_("keymap file") + +#define PI_TEXT 0 +#define PI_ONOFF 1 +#define PI_SEL_C 2 +#ifdef USE_M17N +#define PI_CODE 3 +#endif + +struct sel_c { + int value; + char *cvalue; + char *text; +}; + +#ifdef USE_COLOR +static struct sel_c colorstr[] = { + {0, "black", N_("black")}, + {1, "red", N_("red")}, + {2, "green", N_("green")}, + {3, "yellow", N_("yellow")}, + {4, "blue", N_("blue")}, + {5, "magenta", N_("magenta")}, + {6, "cyan", N_("cyan")}, + {7, "white", N_("white")}, + {8, "terminal", N_("terminal")}, + {0, NULL, NULL} +}; +#endif /* USE_COLOR */ + +#if 1 /* ANSI-C ? */ +#define N_STR(x) #x +#define N_S(x) (x), N_STR(x) +#else /* for traditional cpp? */ +static char n_s[][2] = { + {'0', 0}, + {'1', 0}, + {'2', 0}, +}; +#define N_S(x) (x), n_s[(x)] +#endif + + +static struct sel_c defaulturls[] = { + {N_S(DEFAULT_URL_EMPTY), N_("none")}, + {N_S(DEFAULT_URL_CURRENT), N_("current URL")}, + {N_S(DEFAULT_URL_LINK), N_("link URL")}, + {0, NULL, NULL} +}; + +static struct sel_c displayinsdel[] = { + {N_S(DISPLAY_INS_DEL_SIMPLE), N_("simple")}, + {N_S(DISPLAY_INS_DEL_NORMAL), N_("use tag")}, + {N_S(DISPLAY_INS_DEL_FONTIFY), N_("fontify")}, + {0, NULL, NULL} +}; + +#ifdef USE_MOUSE +static struct sel_c wheelmode[] = { + {TRUE, "1", N_("A:relative to screen height")}, + {FALSE, "0", N_("B:fixed speed")}, + {0, NULL, NULL} +}; +#endif /* MOUSE */ + +#ifdef INET6 +static struct sel_c dnsorders[] = { + {N_S(DNS_ORDER_UNSPEC), N_("unspecified")}, + {N_S(DNS_ORDER_INET_INET6), N_("inet inet6")}, + {N_S(DNS_ORDER_INET6_INET), N_("inet6 inet")}, + {N_S(DNS_ORDER_INET_ONLY), N_("inet only")}, + {N_S(DNS_ORDER_INET6_ONLY), N_("inet6 only")}, + {0, NULL, NULL} +}; +#endif /* INET6 */ + +#ifdef USE_COOKIE +static struct sel_c badcookiestr[] = { + {N_S(ACCEPT_BAD_COOKIE_DISCARD), N_("discard")}, +#if 0 + {N_S(ACCEPT_BAD_COOKIE_ACCEPT), N_("accept")}, +#endif + {N_S(ACCEPT_BAD_COOKIE_ASK), N_("ask")}, + {0, NULL, NULL} +}; +#endif /* USE_COOKIE */ + +#ifdef USE_M17N +static wc_ces_list *display_charset_str = NULL; +static wc_ces_list *document_charset_str = NULL; +static wc_ces_list *system_charset_str = NULL; +static struct sel_c auto_detect_str[] = { + {N_S(WC_OPT_DETECT_OFF), N_("OFF")}, + {N_S(WC_OPT_DETECT_ISO_2022), N_("Only ISO 2022")}, + {N_S(WC_OPT_DETECT_ON), N_("ON")}, + {0, NULL, NULL} +}; +#endif + +struct param_ptr params1[] = { + {"tabstop", P_NZINT, PI_TEXT, (void *)&Tabstop, CMT_TABSTOP, NULL}, + {"indent_incr", P_NZINT, PI_TEXT, (void *)&IndentIncr, CMT_INDENT_INCR, + NULL}, + {"pixel_per_char", P_PIXELS, PI_TEXT, (void *)&pixel_per_char, + CMT_PIXEL_PER_CHAR, NULL}, +#ifdef USE_IMAGE + {"pixel_per_line", P_PIXELS, PI_TEXT, (void *)&pixel_per_line, + CMT_PIXEL_PER_LINE, NULL}, +#endif + {"frame", P_CHARINT, PI_ONOFF, (void *)&RenderFrame, CMT_FRAME, NULL}, + {"target_self", P_CHARINT, PI_ONOFF, (void *)&TargetSelf, CMT_TSELF, NULL}, + {"open_tab_blank", P_INT, PI_ONOFF, (void *)&open_tab_blank, + CMT_OPEN_TAB_BLANK, NULL}, + {"open_tab_dl_list", P_INT, PI_ONOFF, (void *)&open_tab_dl_list, + CMT_OPEN_TAB_DL_LIST, NULL}, + {"display_link", P_INT, PI_ONOFF, (void *)&displayLink, CMT_DISPLINK, + NULL}, + {"decode_url", P_INT, PI_ONOFF, (void *)&DecodeURL, CMT_DECODE_URL, NULL}, + {"display_lineinfo", P_INT, PI_ONOFF, (void *)&displayLineInfo, + CMT_DISPLINEINFO, NULL}, + {"ext_dirlist", P_INT, PI_ONOFF, (void *)&UseExternalDirBuffer, + CMT_EXT_DIRLIST, NULL}, + {"dirlist_cmd", P_STRING, PI_TEXT, (void *)&DirBufferCommand, + CMT_DIRLIST_CMD, NULL}, +#ifdef USE_DICT + {"use_dictcommand", P_INT, PI_ONOFF, (void *)&UseDictCommand, + CMT_USE_DICTCOMMAND, NULL}, + {"dictcommand", P_STRING, PI_TEXT, (void *)&DictCommand, + CMT_DICTCOMMAND, NULL}, +#endif /* USE_DICT */ + {"multicol", P_INT, PI_ONOFF, (void *)&multicolList, CMT_MULTICOL, NULL}, + {"alt_entity", P_CHARINT, PI_ONOFF, (void *)&UseAltEntity, CMT_ALT_ENTITY, + NULL}, + {"graphic_char", P_CHARINT, PI_ONOFF, (void *)&UseGraphicChar, + CMT_GRAPHIC_CHAR, NULL}, + {"fold_textarea", P_CHARINT, PI_ONOFF, (void *)&FoldTextarea, + CMT_FOLD_TEXTAREA, NULL}, + {"display_ins_del", P_INT, PI_SEL_C, (void *)&displayInsDel, + CMT_DISP_INS_DEL, displayinsdel}, + {"ignore_null_img_alt", P_INT, PI_ONOFF, (void *)&ignore_null_img_alt, + CMT_IGNORE_NULL_IMG_ALT, NULL}, + {"view_unseenobject", P_INT, PI_ONOFF, (void *)&view_unseenobject, + CMT_VIEW_UNSEENOBJECTS, NULL}, + /* XXX: emacs-w3m force to off display_image even if image options off */ + {"display_image", P_INT, PI_ONOFF, (void *)&displayImage, CMT_DISP_IMAGE, + NULL}, +#ifdef USE_IMAGE + {"auto_image", P_INT, PI_ONOFF, (void *)&autoImage, CMT_AUTO_IMAGE, NULL}, + {"max_load_image", P_INT, PI_TEXT, (void *)&maxLoadImage, + CMT_MAX_LOAD_IMAGE, NULL}, + {"ext_image_viewer", P_INT, PI_ONOFF, (void *)&useExtImageViewer, + CMT_EXT_IMAGE_VIEWER, NULL}, + {"image_scale", P_SCALE, PI_TEXT, (void *)&image_scale, CMT_IMAGE_SCALE, + NULL}, + {"imgdisplay", P_STRING, PI_TEXT, (void *)&Imgdisplay, CMT_IMGDISPLAY, + NULL}, + {"image_map_list", P_INT, PI_ONOFF, (void *)&image_map_list, + CMT_IMAGE_MAP_LIST, NULL}, +#endif + {"fold_line", P_INT, PI_ONOFF, (void *)&FoldLine, CMT_FOLD_LINE, NULL}, + {"show_lnum", P_INT, PI_ONOFF, (void *)&showLineNum, CMT_SHOW_NUM, NULL}, + {"show_srch_str", P_INT, PI_ONOFF, (void *)&show_srch_str, + CMT_SHOW_SRCH_STR, NULL}, + {"label_topline", P_INT, PI_ONOFF, (void *)&label_topline, + CMT_LABEL_TOPLINE, NULL}, + {"nextpage_topline", P_INT, PI_ONOFF, (void *)&nextpage_topline, + CMT_NEXTPAGE_TOPLINE, NULL}, + {NULL, 0, 0, NULL, NULL, NULL}, +}; + +#ifdef USE_COLOR +struct param_ptr params2[] = { + {"color", P_INT, PI_ONOFF, (void *)&useColor, CMT_COLOR, NULL}, + {"basic_color", P_COLOR, PI_SEL_C, (void *)&basic_color, CMT_B_COLOR, + (void *)colorstr}, + {"anchor_color", P_COLOR, PI_SEL_C, (void *)&anchor_color, CMT_A_COLOR, + (void *)colorstr}, + {"image_color", P_COLOR, PI_SEL_C, (void *)&image_color, CMT_I_COLOR, + (void *)colorstr}, + {"form_color", P_COLOR, PI_SEL_C, (void *)&form_color, CMT_F_COLOR, + (void *)colorstr}, +#ifdef USE_BG_COLOR + {"mark_color", P_COLOR, PI_SEL_C, (void *)&mark_color, CMT_MARK_COLOR, + (void *)colorstr}, + {"bg_color", P_COLOR, PI_SEL_C, (void *)&bg_color, CMT_BG_COLOR, + (void *)colorstr}, +#endif /* USE_BG_COLOR */ + {"active_style", P_INT, PI_ONOFF, (void *)&useActiveColor, + CMT_ACTIVE_STYLE, NULL}, + {"active_color", P_COLOR, PI_SEL_C, (void *)&active_color, CMT_C_COLOR, + (void *)colorstr}, + {"visited_anchor", P_INT, PI_ONOFF, (void *)&useVisitedColor, + CMT_VISITED_ANCHOR, NULL}, + {"visited_color", P_COLOR, PI_SEL_C, (void *)&visited_color, CMT_V_COLOR, + (void *)colorstr}, + {NULL, 0, 0, NULL, NULL, NULL}, +}; +#endif /* USE_COLOR */ + + +struct param_ptr params3[] = { + {"pagerline", P_NZINT, PI_TEXT, (void *)&PagerMax, CMT_PAGERLINE, NULL}, +#ifdef USE_HISTORY + {"use_history", P_INT, PI_ONOFF, (void *)&UseHistory, CMT_HISTORY, NULL}, + {"history", P_INT, PI_TEXT, (void *)&URLHistSize, CMT_HISTSIZE, NULL}, + {"save_hist", P_INT, PI_ONOFF, (void *)&SaveURLHist, CMT_SAVEHIST, NULL}, +#endif /* USE_HISTORY */ + {"confirm_qq", P_INT, PI_ONOFF, (void *)&confirm_on_quit, CMT_CONFIRM_QQ, + NULL}, + {"close_tab_back", P_INT, PI_ONOFF, (void *)&close_tab_back, + CMT_CLOSE_TAB_BACK, NULL}, +#ifdef USE_MARK + {"mark", P_INT, PI_ONOFF, (void *)&use_mark, CMT_USE_MARK, NULL}, +#endif + {"emacs_like_lineedit", P_INT, PI_ONOFF, (void *)&emacs_like_lineedit, + CMT_EMACS_LIKE_LINEEDIT, NULL}, + {"vi_prec_num", P_INT, PI_ONOFF, (void *)&vi_prec_num, CMT_VI_PREC_NUM, + NULL}, + {"mark_all_pages", P_INT, PI_ONOFF, (void *)&MarkAllPages, + CMT_MARK_ALL_PAGES, NULL}, + {"wrap_search", P_INT, PI_ONOFF, (void *)&WrapDefault, CMT_WRAP, NULL}, + {"ignorecase_search", P_INT, PI_ONOFF, (void *)&IgnoreCase, + CMT_IGNORE_CASE, NULL}, +#ifdef USE_MIGEMO + {"use_migemo", P_INT, PI_ONOFF, (void *)&use_migemo, CMT_USE_MIGEMO, + NULL}, + {"migemo_command", P_STRING, PI_TEXT, (void *)&migemo_command, + CMT_MIGEMO_COMMAND, NULL}, +#endif /* USE_MIGEMO */ +#ifdef USE_MOUSE + {"use_mouse", P_INT, PI_ONOFF, (void *)&use_mouse, CMT_MOUSE, NULL}, + {"reverse_mouse", P_INT, PI_ONOFF, (void *)&reverse_mouse, + CMT_REVERSE_MOUSE, NULL}, + {"relative_wheel_scroll", P_INT, PI_SEL_C, (void *)&relative_wheel_scroll, + CMT_RELATIVE_WHEEL_SCROLL, (void *)wheelmode}, + {"relative_wheel_scroll_ratio", P_INT, PI_TEXT, + (void *)&relative_wheel_scroll_ratio, + CMT_RELATIVE_WHEEL_SCROLL_RATIO, NULL}, + {"fixed_wheel_scroll_count", P_INT, PI_TEXT, + (void *)&fixed_wheel_scroll_count, + CMT_FIXED_WHEEL_SCROLL_COUNT, NULL}, +#endif /* USE_MOUSE */ + {"clear_buffer", P_INT, PI_ONOFF, (void *)&clear_buffer, CMT_CLEAR_BUF, + NULL}, + {"decode_cte", P_CHARINT, PI_ONOFF, (void *)&DecodeCTE, CMT_DECODE_CTE, + NULL}, + {"auto_uncompress", P_CHARINT, PI_ONOFF, (void *)&AutoUncompress, + CMT_AUTO_UNCOMPRESS, NULL}, + {"preserve_timestamp", P_CHARINT, PI_ONOFF, (void *)&PreserveTimestamp, + CMT_PRESERVE_TIMESTAMP, NULL}, + {"keymap_file", P_STRING, PI_TEXT, (void *)&keymap_file, CMT_KEYMAP_FILE, + NULL}, + {NULL, 0, 0, NULL, NULL, NULL}, +}; + +struct param_ptr params4[] = { + {"use_proxy", P_CHARINT, PI_ONOFF, (void *)&use_proxy, CMT_USE_PROXY, + NULL}, + {"http_proxy", P_STRING, PI_TEXT, (void *)&HTTP_proxy, CMT_HTTP_PROXY, + NULL}, +#ifdef USE_SSL + {"https_proxy", P_STRING, PI_TEXT, (void *)&HTTPS_proxy, CMT_HTTPS_PROXY, + NULL}, +#endif /* USE_SSL */ +#ifdef USE_GOPHER + {"gopher_proxy", P_STRING, PI_TEXT, (void *)&GOPHER_proxy, + CMT_GOPHER_PROXY, NULL}, +#endif /* USE_GOPHER */ + {"ftp_proxy", P_STRING, PI_TEXT, (void *)&FTP_proxy, CMT_FTP_PROXY, NULL}, + {"no_proxy", P_STRING, PI_TEXT, (void *)&NO_proxy, CMT_NO_PROXY, NULL}, + {"noproxy_netaddr", P_INT, PI_ONOFF, (void *)&NOproxy_netaddr, + CMT_NOPROXY_NETADDR, NULL}, + {"no_cache", P_CHARINT, PI_ONOFF, (void *)&NoCache, CMT_NO_CACHE, NULL}, + + {NULL, 0, 0, NULL, NULL, NULL}, +}; + +struct param_ptr params5[] = { + {"document_root", P_STRING, PI_TEXT, (void *)&document_root, CMT_DROOT, + NULL}, + {"personal_document_root", P_STRING, PI_TEXT, + (void *)&personal_document_root, CMT_PDROOT, NULL}, + {"cgi_bin", P_STRING, PI_TEXT, (void *)&cgi_bin, CMT_CGIBIN, NULL}, + {"index_file", P_STRING, PI_TEXT, (void *)&index_file, CMT_IFILE, NULL}, + {NULL, 0, 0, NULL, NULL, NULL}, +}; + +struct param_ptr params6[] = { + {"mime_types", P_STRING, PI_TEXT, (void *)&mimetypes_files, CMT_MIMETYPES, + NULL}, + {"mailcap", P_STRING, PI_TEXT, (void *)&mailcap_files, CMT_MAILCAP, NULL}, +#ifdef USE_EXTERNAL_URI_LOADER + {"urimethodmap", P_STRING, PI_TEXT, (void *)&urimethodmap_files, + CMT_URIMETHODMAP, NULL}, +#endif + {"editor", P_STRING, PI_TEXT, (void *)&Editor, CMT_EDITOR, NULL}, + {"mailer", P_STRING, PI_TEXT, (void *)&Mailer, CMT_MAILER, NULL}, + {"extbrowser", P_STRING, PI_TEXT, (void *)&ExtBrowser, CMT_EXTBRZ, NULL}, + {"extbrowser2", P_STRING, PI_TEXT, (void *)&ExtBrowser2, CMT_EXTBRZ2, + NULL}, + {"extbrowser3", P_STRING, PI_TEXT, (void *)&ExtBrowser3, CMT_EXTBRZ3, + NULL}, + {"bgextviewer", P_INT, PI_ONOFF, (void *)&BackgroundExtViewer, + CMT_BGEXTVIEW, NULL}, + {"use_lessopen", P_INT, PI_ONOFF, (void *)&use_lessopen, CMT_USE_LESSOPEN, + NULL}, + {NULL, 0, 0, NULL, NULL, NULL}, +}; + +#ifdef USE_SSL +struct param_ptr params7[] = { + {"ssl_forbid_method", P_STRING, PI_TEXT, (void *)&ssl_forbid_method, + CMT_SSL_FORBID_METHOD, NULL}, +#ifdef USE_SSL_VERIFY + {"ssl_verify_server", P_INT, PI_ONOFF, (void *)&ssl_verify_server, + CMT_SSL_VERIFY_SERVER, NULL}, + {"ssl_cert_file", P_SSLPATH, PI_TEXT, (void *)&ssl_cert_file, + CMT_SSL_CERT_FILE, NULL}, + {"ssl_key_file", P_SSLPATH, PI_TEXT, (void *)&ssl_key_file, + CMT_SSL_KEY_FILE, NULL}, + {"ssl_ca_path", P_SSLPATH, PI_TEXT, (void *)&ssl_ca_path, CMT_SSL_CA_PATH, + NULL}, + {"ssl_ca_file", P_SSLPATH, PI_TEXT, (void *)&ssl_ca_file, CMT_SSL_CA_FILE, + NULL}, +#endif /* USE_SSL_VERIFY */ + {NULL, 0, 0, NULL, NULL, NULL}, +}; +#endif /* USE_SSL */ + +#ifdef USE_COOKIE +struct param_ptr params8[] = { + {"use_cookie", P_INT, PI_ONOFF, (void *)&use_cookie, CMT_USECOOKIE, NULL}, + {"show_cookie", P_INT, PI_ONOFF, (void *)&show_cookie, + CMT_SHOWCOOKIE, NULL}, + {"accept_cookie", P_INT, PI_ONOFF, (void *)&accept_cookie, + CMT_ACCEPTCOOKIE, NULL}, + {"accept_bad_cookie", P_INT, PI_SEL_C, (void *)&accept_bad_cookie, + CMT_ACCEPTBADCOOKIE, (void *)badcookiestr}, + {"cookie_reject_domains", P_STRING, PI_TEXT, + (void *)&cookie_reject_domains, CMT_COOKIE_REJECT_DOMAINS, NULL}, + {"cookie_accept_domains", P_STRING, PI_TEXT, + (void *)&cookie_accept_domains, CMT_COOKIE_ACCEPT_DOMAINS, NULL}, + {NULL, 0, 0, NULL, NULL, NULL}, +}; +#endif + +struct param_ptr params9[] = { + {"passwd_file", P_STRING, PI_TEXT, (void *)&passwd_file, CMT_PASSWDFILE, + NULL}, + {"disable_secret_security_check", P_INT, PI_ONOFF, + (void *)&disable_secret_security_check, CMT_DISABLE_SECRET_SECURITY_CHECK, + NULL}, + {"ftppasswd", P_STRING, PI_TEXT, (void *)&ftppasswd, CMT_FTPPASS, NULL}, + {"ftppass_hostnamegen", P_INT, PI_ONOFF, (void *)&ftppass_hostnamegen, + CMT_FTPPASS_HOSTNAMEGEN, NULL}, + {"pre_form_file", P_STRING, PI_TEXT, (void *)&pre_form_file, + CMT_PRE_FORM_FILE, NULL}, + {"user_agent", P_STRING, PI_TEXT, (void *)&UserAgent, CMT_USERAGENT, NULL}, + {"no_referer", P_INT, PI_ONOFF, (void *)&NoSendReferer, CMT_NOSENDREFERER, + NULL}, + {"accept_language", P_STRING, PI_TEXT, (void *)&AcceptLang, CMT_ACCEPTLANG, + NULL}, + {"accept_encoding", P_STRING, PI_TEXT, (void *)&AcceptEncoding, + CMT_ACCEPTENCODING, + NULL}, + {"accept_media", P_STRING, PI_TEXT, (void *)&AcceptMedia, CMT_ACCEPTMEDIA, + NULL}, + {"argv_is_url", P_CHARINT, PI_ONOFF, (void *)&ArgvIsURL, CMT_ARGV_IS_URL, + NULL}, + {"retry_http", P_INT, PI_ONOFF, (void *)&retryAsHttp, CMT_RETRY_HTTP, + NULL}, + {"default_url", P_INT, PI_SEL_C, (void *)&DefaultURLString, + CMT_DEFAULT_URL, (void *)defaulturls}, + {"follow_redirection", P_INT, PI_TEXT, &FollowRedirection, + CMT_FOLLOW_REDIRECTION, NULL}, + {"meta_refresh", P_CHARINT, PI_ONOFF, (void *)&MetaRefresh, + CMT_META_REFRESH, NULL}, +#ifdef INET6 + {"dns_order", P_INT, PI_SEL_C, (void *)&DNS_order, CMT_DNS_ORDER, + (void *)dnsorders}, +#endif /* INET6 */ +#ifdef USE_NNTP + {"nntpserver", P_STRING, PI_TEXT, (void *)&NNTP_server, CMT_NNTP_SERVER, + NULL}, + {"nntpmode", P_STRING, PI_TEXT, (void *)&NNTP_mode, CMT_NNTP_MODE, NULL}, + {"max_news", P_INT, PI_TEXT, (void *)&MaxNewsMessage, CMT_MAX_NEWS, NULL}, +#endif + {NULL, 0, 0, NULL, NULL, NULL}, +}; + +#ifdef USE_M17N +struct param_ptr params10[] = { + {"display_charset", P_CODE, PI_CODE, (void *)&DisplayCharset, + CMT_DISPLAY_CHARSET, (void *)&display_charset_str}, + {"document_charset", P_CODE, PI_CODE, (void *)&DocumentCharset, + CMT_DOCUMENT_CHARSET, (void *)&document_charset_str}, + {"auto_detect", P_CHARINT, PI_SEL_C, (void *)&WcOption.auto_detect, + CMT_AUTO_DETECT, (void *)auto_detect_str}, + {"system_charset", P_CODE, PI_CODE, (void *)&SystemCharset, + CMT_SYSTEM_CHARSET, (void *)&system_charset_str}, + {"follow_locale", P_CHARINT, PI_ONOFF, (void *)&FollowLocale, + CMT_FOLLOW_LOCALE, NULL}, + {"ext_halfdump", P_CHARINT, PI_ONOFF, (void *)&ExtHalfdump, + CMT_EXT_HALFDUMP, NULL}, + {"use_wide", P_CHARINT, PI_ONOFF, (void *)&WcOption.use_wide, CMT_USE_WIDE, + NULL}, + {"use_combining", P_CHARINT, PI_ONOFF, (void *)&WcOption.use_combining, + CMT_USE_COMBINING, NULL}, +#ifdef USE_UNICODE + {"use_language_tag", P_CHARINT, PI_ONOFF, + (void *)&WcOption.use_language_tag, CMT_USE_LANGUAGE_TAG, NULL}, + {"ucs_conv", P_CHARINT, PI_ONOFF, (void *)&WcOption.ucs_conv, CMT_UCS_CONV, + NULL}, +#endif + {"pre_conv", P_CHARINT, PI_ONOFF, (void *)&WcOption.pre_conv, CMT_PRE_CONV, + NULL}, + {"search_conv", P_CHARINT, PI_ONOFF, (void *)&SearchConv, CMT_SEARCH_CONV, + NULL}, + {"fix_width_conv", P_CHARINT, PI_ONOFF, (void *)&WcOption.fix_width_conv, + CMT_FIX_WIDTH_CONV, NULL}, +#ifdef USE_UNICODE + {"use_gb12345_map", P_CHARINT, PI_ONOFF, (void *)&WcOption.use_gb12345_map, + CMT_USE_GB12345_MAP, NULL}, +#endif + {"use_jisx0201", P_CHARINT, PI_ONOFF, (void *)&WcOption.use_jisx0201, + CMT_USE_JISX0201, NULL}, + {"use_jisc6226", P_CHARINT, PI_ONOFF, (void *)&WcOption.use_jisc6226, + CMT_USE_JISC6226, NULL}, + {"use_jisx0201k", P_CHARINT, PI_ONOFF, (void *)&WcOption.use_jisx0201k, + CMT_USE_JISX0201K, NULL}, + {"use_jisx0212", P_CHARINT, PI_ONOFF, (void *)&WcOption.use_jisx0212, + CMT_USE_JISX0212, NULL}, + {"use_jisx0213", P_CHARINT, PI_ONOFF, (void *)&WcOption.use_jisx0213, + CMT_USE_JISX0213, NULL}, + {"strict_iso2022", P_CHARINT, PI_ONOFF, (void *)&WcOption.strict_iso2022, + CMT_STRICT_ISO2022, NULL}, +#ifdef USE_UNICODE + {"gb18030_as_ucs", P_CHARINT, PI_ONOFF, (void *)&WcOption.gb18030_as_ucs, + CMT_GB18030_AS_UCS, NULL}, +#endif + {NULL, 0, 0, NULL, NULL, NULL}, +}; +#endif + +struct param_section sections[] = { + {N_("Display Settings"), params1}, +#ifdef USE_COLOR + {N_("Color Settings"), params2}, +#endif /* USE_COLOR */ + {N_("Miscellaneous Settings"), params3}, + {N_("Directory Settings"), params5}, + {N_("External Program Settings"), params6}, + {N_("Network Settings"), params9}, + {N_("Proxy Settings"), params4}, +#ifdef USE_SSL + {N_("SSL Settings"), params7}, +#endif +#ifdef USE_COOKIE + {N_("Cookie Settings"), params8}, +#endif +#ifdef USE_M17N + {N_("Charset Settings"), params10}, +#endif + {NULL, NULL} +}; + +static Str to_str(struct param_ptr *p); + +static int +compare_table(struct rc_search_table *a, struct rc_search_table *b) +{ + return strcmp(a->param->name, b->param->name); +} + +static void +create_option_search_table() +{ + int i, j, k; + int diff1, diff2; + char *p, *q; + + /* count table size */ + RC_table_size = 0; + for (j = 0; sections[j].name != NULL; j++) { + i = 0; + while (sections[j].params[i].name) { + i++; + RC_table_size++; + } + } + + RC_search_table = New_N(struct rc_search_table, RC_table_size); + k = 0; + for (j = 0; sections[j].name != NULL; j++) { + i = 0; + while (sections[j].params[i].name) { + RC_search_table[k].param = §ions[j].params[i]; + k++; + i++; + } + } + + qsort(RC_search_table, RC_table_size, sizeof(struct rc_search_table), + (int (*)(const void *, const void *))compare_table); + + diff1 = diff2 = 0; + for (i = 0; i < RC_table_size - 1; i++) { + p = RC_search_table[i].param->name; + q = RC_search_table[i + 1].param->name; + for (j = 0; p[j] != '\0' && q[j] != '\0' && p[j] == q[j]; j++) ; + diff1 = j; + if (diff1 > diff2) + RC_search_table[i].uniq_pos = diff1 + 1; + else + RC_search_table[i].uniq_pos = diff2 + 1; + diff2 = diff1; + } +} + +struct param_ptr * +search_param(char *name) +{ + size_t b, e, i; + int cmp; + int len = strlen(name); + + for (b = 0, e = RC_table_size - 1; b <= e;) { + i = (b + e) / 2; + cmp = strncmp(name, RC_search_table[i].param->name, len); + + if (!cmp) { + if (len >= RC_search_table[i].uniq_pos) { + return RC_search_table[i].param; + } + else { + while ((cmp = + strcmp(name, RC_search_table[i].param->name)) <= 0) + if (!cmp) + return RC_search_table[i].param; + else if (i == 0) + return NULL; + else + i--; + /* ambiguous */ + return NULL; + } + } + else if (cmp < 0) { + if (i == 0) + return NULL; + e = i - 1; + } + else + b = i + 1; + } + return NULL; +} + +/* show parameter with bad options invokation */ +void +show_params(FILE * fp) +{ + int i, j, l; + char *t = NULL; + char *cmt; + +#ifdef USE_M17N +#ifdef ENABLE_NLS + OptionCharset = SystemCharset; /* FIXME */ +#endif +#endif + + fputs("\nconfiguration parameters\n", fp); + for (j = 0; sections[j].name != NULL; j++) { +#ifdef USE_M17N + if (!OptionEncode) + cmt = + wc_conv(_(sections[j].name), OptionCharset, + InnerCharset)->ptr; + else +#endif + cmt = sections[j].name; + fprintf(fp, " section[%d]: %s\n", j, conv_to_system(cmt)); + i = 0; + while (sections[j].params[i].name) { + switch (sections[j].params[i].type) { + case P_INT: + case P_SHORT: + case P_CHARINT: + case P_NZINT: + t = (sections[j].params[i].inputtype == + PI_ONOFF) ? "bool" : "number"; + break; + case P_CHAR: + t = "char"; + break; + case P_STRING: + t = "string"; + break; +#if defined(USE_SSL) && defined(USE_SSL_VERIFY) + case P_SSLPATH: + t = "path"; + break; +#endif +#ifdef USE_COLOR + case P_COLOR: + t = "color"; + break; +#endif +#ifdef USE_M17N + case P_CODE: + t = "charset"; + break; +#endif + case P_PIXELS: + t = "number"; + break; + case P_SCALE: + t = "percent"; + break; + } +#ifdef USE_M17N + if (!OptionEncode) + cmt = wc_conv(_(sections[j].params[i].comment), + OptionCharset, InnerCharset)->ptr; + else +#endif + cmt = sections[j].params[i].comment; + l = 30 - (strlen(sections[j].params[i].name) + strlen(t)); + if (l < 0) + l = 1; + fprintf(fp, " -o %s=<%s>%*s%s\n", + sections[j].params[i].name, t, l, " ", + conv_to_system(cmt)); + i++; + } + } +} + +int +str_to_bool(char *value, int old) +{ + if (value == NULL) + return 1; + switch (TOLOWER(*value)) { + case '0': + case 'f': /* false */ + case 'n': /* no */ + case 'u': /* undef */ + return 0; + case 'o': + if (TOLOWER(value[1]) == 'f') /* off */ + return 0; + return 1; /* on */ + case 't': + if (TOLOWER(value[1]) == 'o') /* toggle */ + return !old; + return 1; /* true */ + case '!': + case 'r': /* reverse */ + case 'x': /* exchange */ + return !old; + } + return 1; +} + +#ifdef USE_COLOR +static int +str_to_color(char *value) +{ + if (value == NULL) + return 8; /* terminal */ + switch (TOLOWER(*value)) { + case '0': + return 0; /* black */ + case '1': + case 'r': + return 1; /* red */ + case '2': + case 'g': + return 2; /* green */ + case '3': + case 'y': + return 3; /* yellow */ + case '4': + return 4; /* blue */ + case '5': + case 'm': + return 5; /* magenta */ + case '6': + case 'c': + return 6; /* cyan */ + case '7': + case 'w': + return 7; /* white */ + case '8': + case 't': + return 8; /* terminal */ + case 'b': + if (!strncasecmp(value, "blu", 3)) + return 4; /* blue */ + else + return 0; /* black */ + } + return 8; /* terminal */ +} +#endif + +static int +set_param(char *name, char *value) +{ + struct param_ptr *p; + double ppc; + + if (value == NULL) + return 0; + p = search_param(name); + if (p == NULL) + return 0; + switch (p->type) { + case P_INT: + if (atoi(value) >= 0) + *(int *)p->varptr = (p->inputtype == PI_ONOFF) + ? str_to_bool(value, *(int *)p->varptr) : atoi(value); + break; + case P_NZINT: + if (atoi(value) > 0) + *(int *)p->varptr = atoi(value); + break; + case P_SHORT: + *(short *)p->varptr = (p->inputtype == PI_ONOFF) + ? str_to_bool(value, *(short *)p->varptr) : atoi(value); + break; + case P_CHARINT: + *(char *)p->varptr = (p->inputtype == PI_ONOFF) + ? str_to_bool(value, *(char *)p->varptr) : atoi(value); + break; + case P_CHAR: + *(char *)p->varptr = value[0]; + break; + case P_STRING: + *(char **)p->varptr = value; + break; +#if defined(USE_SSL) && defined(USE_SSL_VERIFY) + case P_SSLPATH: + if (value != NULL && value[0] != '\0') + *(char **)p->varptr = rcFile(value); + else + *(char **)p->varptr = NULL; + ssl_path_modified = 1; + break; +#endif +#ifdef USE_COLOR + case P_COLOR: + *(int *)p->varptr = str_to_color(value); + break; +#endif +#ifdef USE_M17N + case P_CODE: + *(wc_ces *) p->varptr = + wc_guess_charset_short(value, *(wc_ces *) p->varptr); + break; +#endif + case P_PIXELS: + ppc = atof(value); + if (ppc >= MINIMUM_PIXEL_PER_CHAR && ppc <= MAXIMUM_PIXEL_PER_CHAR * 2) + *(double *)p->varptr = ppc; + break; + case P_SCALE: + ppc = atof(value); + if (ppc >= 10 && ppc <= 1000) + *(double *)p->varptr = ppc; + break; + } + return 1; +} + +int +set_param_option(char *option) +{ + Str tmp = Strnew(); + char *p = option, *q; + + while (*p && !IS_SPACE(*p) && *p != '=') + Strcat_char(tmp, *p++); + while (*p && IS_SPACE(*p)) + p++; + if (*p == '=') { + p++; + while (*p && IS_SPACE(*p)) + p++; + } + Strlower(tmp); + if (set_param(tmp->ptr, p)) + goto option_assigned; + q = tmp->ptr; + if (!strncmp(q, "no", 2)) { /* -o noxxx, -o no-xxx, -o no_xxx */ + q += 2; + if (*q == '-' || *q == '_') + q++; + } + else if (tmp->ptr[0] == '-') /* -o -xxx */ + q++; + else + return 0; + if (set_param(q, "0")) + goto option_assigned; + return 0; + option_assigned: + return 1; +} + +char * +get_param_option(char *name) +{ + struct param_ptr *p; + + p = search_param(name); + return p ? to_str(p)->ptr : NULL; +} + +static void +interpret_rc(FILE * f) +{ + Str line; + Str tmp; + char *p; + + for (;;) { + line = Strfgets(f); + Strchop(line); + if (line->length == 0) + break; + Strremovefirstspaces(line); + if (line->ptr[0] == '#') /* comment */ + continue; + tmp = Strnew(); + p = line->ptr; + while (*p && !IS_SPACE(*p)) + Strcat_char(tmp, *p++); + while (*p && IS_SPACE(*p)) + p++; + Strlower(tmp); + set_param(tmp->ptr, p); + } +} + +void +parse_proxy() +{ + if (non_null(HTTP_proxy)) + parseURL(HTTP_proxy, &HTTP_proxy_parsed, NULL); +#ifdef USE_SSL + if (non_null(HTTPS_proxy)) + parseURL(HTTPS_proxy, &HTTPS_proxy_parsed, NULL); +#endif /* USE_SSL */ +#ifdef USE_GOPHER + if (non_null(GOPHER_proxy)) + parseURL(GOPHER_proxy, &GOPHER_proxy_parsed, NULL); +#endif + if (non_null(FTP_proxy)) + parseURL(FTP_proxy, &FTP_proxy_parsed, NULL); + if (non_null(NO_proxy)) + set_no_proxy(NO_proxy); +} + +#ifdef USE_COOKIE +void +parse_cookie() +{ + if (non_null(cookie_reject_domains)) + Cookie_reject_domains = make_domain_list(cookie_reject_domains); + if (non_null(cookie_accept_domains)) + Cookie_accept_domains = make_domain_list(cookie_accept_domains); +} +#endif + +#ifdef __EMX__ +static int +do_mkdir(const char *dir, long mode) +{ + char *r, abs[_MAX_PATH]; + size_t n; + + _abspath(abs, rc_dir, _MAX_PATH); /* Translate '\\' to '/' */ + + if (!(n = strlen(abs))) + return -1; + + if (*(r = abs + n - 1) == '/') /* Ignore tailing slash if it is */ + *r = 0; + + return mkdir(abs, mode); +} +#else /* not __EMX__ */ +#ifdef __MINGW32_VERSION +#define do_mkdir(dir,mode) mkdir(dir) +#else +#define do_mkdir(dir,mode) mkdir(dir,mode) +#endif /* not __MINW32_VERSION */ +#endif /* not __EMX__ */ + +void +sync_with_option(void) +{ + if (PagerMax < LINES) + PagerMax = LINES; + WrapSearch = WrapDefault; + parse_proxy(); +#ifdef USE_COOKIE + parse_cookie(); +#endif + initMailcap(); + initMimeTypes(); +#ifdef USE_EXTERNAL_URI_LOADER + initURIMethods(); +#endif +#ifdef USE_MIGEMO + init_migemo(); +#endif +#ifdef USE_IMAGE + if (fmInitialized && displayImage) + initImage(); +#else + displayImage = FALSE; /* XXX */ +#endif + loadPasswd(); + loadPreForm(); + + if (AcceptLang == NULL || *AcceptLang == '\0') { + /* TRANSLATORS: + * AcceptLang default: this is used in Accept-Language: HTTP request + * header. For example, ja.po should translate it as + * "ja;q=1.0, en;q=0.5" like that. + */ + AcceptLang = _("en;q=1.0"); + } + if (AcceptEncoding == NULL || *AcceptEncoding == '\0') + AcceptEncoding = acceptableEncoding(); + if (AcceptMedia == NULL || *AcceptMedia == '\0') + AcceptMedia = acceptableMimeTypes(); + if (fmInitialized) { + initKeymap(FALSE); +#ifdef USE_MOUSE + initMouseAction(); +#endif /* MOUSE */ +#ifdef USE_MENU + initMenu(); +#endif /* MENU */ + } +} + +void +init_rc(void) +{ + int i; + struct stat st; + FILE *f; + + if (rc_dir != NULL) + goto open_rc; + + rc_dir = expandPath(RC_DIR); + i = strlen(rc_dir); + if (i > 1 && rc_dir[i - 1] == '/') + rc_dir[i - 1] = '\0'; + +#ifdef USE_M17N + display_charset_str = wc_get_ces_list(); + document_charset_str = display_charset_str; + system_charset_str = display_charset_str; +#endif + + if (stat(rc_dir, &st) < 0) { + if (errno == ENOENT) { /* no directory */ + if (do_mkdir(rc_dir, 0700) < 0) { + fprintf(stderr, "Can't create config directory (%s)!", rc_dir); + goto rc_dir_err; + } + else { + stat(rc_dir, &st); + } + } + else { + fprintf(stderr, "Can't open config directory (%s)!", rc_dir); + goto rc_dir_err; + } + } + if (!S_ISDIR(st.st_mode)) { + /* not a directory */ + fprintf(stderr, "%s is not a directory!", rc_dir); + goto rc_dir_err; + } + if (!(st.st_mode & S_IWUSR)) { + fprintf(stderr, "%s is not writable!", rc_dir); + goto rc_dir_err; + } + no_rc_dir = FALSE; + tmp_dir = rc_dir; + + if (config_file == NULL) + config_file = rcFile(CONFIG_FILE); + + create_option_search_table(); + + open_rc: + /* open config file */ + if ((f = fopen(etcFile(W3MCONFIG), "rt")) != NULL) { + interpret_rc(f); + fclose(f); + } + if ((f = fopen(confFile(CONFIG_FILE), "rt")) != NULL) { + interpret_rc(f); + fclose(f); + } + if ((f = fopen(config_file, "rt")) != NULL) { + interpret_rc(f); + fclose(f); + } + return; + + rc_dir_err: + no_rc_dir = TRUE; + if (((tmp_dir = getenv("TMPDIR")) == NULL || *tmp_dir == '\0') && + ((tmp_dir = getenv("TMP")) == NULL || *tmp_dir == '\0') && + ((tmp_dir = getenv("TEMP")) == NULL || *tmp_dir == '\0')) + tmp_dir = "/tmp"; +} + + +static char optionpanel_src1[] = + "Option Setting Panel\ +

Option Setting Panel
(w3m version %s)

\ +
\ +\ +\ +\ +

\ +
"; + +static Str optionpanel_str = NULL; + +static Str +to_str(struct param_ptr *p) +{ + switch (p->type) { + case P_INT: +#ifdef USE_COLOR + case P_COLOR: +#endif +#ifdef USE_M17N + case P_CODE: + return Sprintf("%d", (int)(*(wc_ces *) p->varptr)); +#endif + case P_NZINT: + return Sprintf("%d", *(int *)p->varptr); + case P_SHORT: + return Sprintf("%d", *(short *)p->varptr); + case P_CHARINT: + return Sprintf("%d", *(char *)p->varptr); + case P_CHAR: + return Sprintf("%c", *(char *)p->varptr); + case P_STRING: +#if defined(USE_SSL) && defined(USE_SSL_VERIFY) + case P_SSLPATH: +#endif + /* SystemCharset -> InnerCharset */ + return Strnew_charp(conv_from_system(*(char **)p->varptr)); + case P_PIXELS: + case P_SCALE: + return Sprintf("%g", *(double *)p->varptr); + } + /* not reached */ + return NULL; +} + +Buffer * +load_option_panel(void) +{ + Str src; + struct param_ptr *p; + struct sel_c *s; +#ifdef USE_M17N + wc_ces_list *c; +#endif + int x, i; + Str tmp; + Buffer *buf; + + if (optionpanel_str == NULL) + optionpanel_str = Sprintf(optionpanel_src1, w3m_version, + html_quote(localCookie()->ptr), _(CMT_HELPER)); +#ifdef USE_M17N +#ifdef ENABLE_NLS + OptionCharset = SystemCharset; /* FIXME */ +#endif + if (!OptionEncode) { + optionpanel_str = + wc_Str_conv(optionpanel_str, OptionCharset, InnerCharset); + for (i = 0; sections[i].name != NULL; i++) { + sections[i].name = + wc_conv(_(sections[i].name), OptionCharset, + InnerCharset)->ptr; + for (p = sections[i].params; p->name; p++) { + p->comment = + wc_conv(_(p->comment), OptionCharset, + InnerCharset)->ptr; + if (p->inputtype == PI_SEL_C +#ifdef USE_COLOR + && p->select != colorstr +#endif + ) { + for (s = (struct sel_c *)p->select; s->text != NULL; s++) { + s->text = + wc_conv(_(s->text), OptionCharset, + InnerCharset)->ptr; + } + } + } + } +#ifdef USE_COLOR + for (s = colorstr; s->text; s++) + s->text = wc_conv(_(s->text), OptionCharset, + InnerCharset)->ptr; +#endif + OptionEncode = TRUE; + } +#endif + src = Strdup(optionpanel_str); + + Strcat_charp(src, "
"); + for (i = 0; sections[i].name != NULL; i++) { + Strcat_m_charp(src, "

", sections[i].name, "

", NULL); + p = sections[i].params; + Strcat_charp(src, ""); + while (p->name) { + Strcat_m_charp(src, "\n"); + p++; + } + Strcat_charp(src, + ""); + Strcat_charp(src, "
", p->comment, NULL); + Strcat(src, Sprintf("", + (int)(28 * pixel_per_char))); + switch (p->inputtype) { + case PI_TEXT: + Strcat_m_charp(src, "ptr), "\">", NULL); + break; + case PI_ONOFF: + x = atoi(to_str(p)->ptr); + Strcat_m_charp(src, "YES  NO", NULL); + break; + case PI_SEL_C: + tmp = to_str(p); + Strcat_m_charp(src, ""); + break; +#ifdef USE_M17N + case PI_CODE: + tmp = to_str(p); + Strcat_m_charp(src, ""); + break; +#endif + } + Strcat_charp(src, "


"); + } + Strcat_charp(src, "
"); + buf = loadHTMLString(src); +#ifdef USE_M17N + if (buf) + buf->document_charset = OptionCharset; +#endif + return buf; +} + +void +panel_set_option(struct parsed_tagarg *arg) +{ + FILE *f = NULL; + char *p; + + if (no_rc_dir) { + disp_message("There's no ~/.w3m directory... config not saved", FALSE); + } + else { + f = fopen(config_file, "wt"); + if (f == NULL) { + disp_message("Can't write option!", FALSE); + } + } + while (arg) { + /* InnerCharset -> SystemCharset */ + if (arg->value) { + p = conv_to_system(arg->value); + if (set_param(arg->arg, p)) { + if (f) + fprintf(f, "%s %s\n", arg->arg, p); + } + } + arg = arg->next; + } + if (f) + fclose(f); + sync_with_option(); + backBf(); +} + +char * +rcFile(char *base) +{ + if (base && + (base[0] == '/' || + (base[0] == '.' + && (base[1] == '/' || (base[1] == '.' && base[2] == '/'))) + || (base[0] == '~' && base[1] == '/'))) + /* /file, ./file, ../file, ~/file */ + return expandPath(base); + return expandPath(Strnew_m_charp(rc_dir, "/", base, NULL)->ptr); +} + +char * +auxbinFile(char *base) +{ + return expandPath(Strnew_m_charp(w3m_auxbin_dir(), "/", base, NULL)->ptr); +} + +#if 0 /* not used */ +char * +libFile(char *base) +{ + return expandPath(Strnew_m_charp(w3m_lib_dir(), "/", base, NULL)->ptr); +} +#endif + +char * +etcFile(char *base) +{ + return expandPath(Strnew_m_charp(w3m_etc_dir(), "/", base, NULL)->ptr); +} + +char * +confFile(char *base) +{ + return expandPath(Strnew_m_charp(w3m_conf_dir(), "/", base, NULL)->ptr); +} + +#ifndef USE_HELP_CGI +char * +helpFile(char *base) +{ + return expandPath(Strnew_m_charp(w3m_help_dir(), "/", base, NULL)->ptr); +} +#endif diff -urN w3m-0.5.2.orig/symbol.c w3m-0.5.2/symbol.c --- w3m-0.5.2.orig/symbol.c 2003-09-23 06:02:21.000000000 +0900 +++ w3m-0.5.2/symbol.c 2010-07-18 08:13:26.000000000 +0900 @@ -86,24 +86,29 @@ charset_symbol_set *p; symbol_set *s = NULL; - if (charset == save_charset && save_symbol != NULL && - *width == save_symbol->width) { - *width = save_symbol->width; - return save_symbol->item; - } - save_charset = charset; - for (p = charset_symbol_list; p->charset; p++) { - if (charset == p->charset && - (*width == 0 || *width == p->symbol->width)) { - s = p->symbol; - break; + if (UseGraphicChar != GRAPHIC_CHAR_ASCII) { + if (charset == save_charset && save_symbol != NULL && + *width == save_symbol->width) + return save_symbol->item; + save_charset = charset; + for (p = charset_symbol_list; p->charset; p++) { + if (charset == p->charset && + (*width == 0 || *width == p->symbol->width)) { + s = p->symbol; + break; + } } - } - if (s == NULL) + if (s == NULL) + s = (*width == 2) ? &alt2_symbol_set : &alt_symbol_set; + if (s != save_symbol) { + if (!s->encode) + encode_symbol(s); + save_symbol = s; + } + } else { + if (save_symbol != NULL && *width == save_symbol->width) + return save_symbol->item; s = (*width == 2) ? &alt2_symbol_set : &alt_symbol_set; - if (s != save_symbol) { - if (!s->encode) - encode_symbol(s); save_symbol = s; } *width = s->width; diff -urN w3m-0.5.2.orig/terms.c w3m-0.5.2/terms.c --- w3m-0.5.2.orig/terms.c 2007-05-30 13:44:00.000000000 +0900 +++ w3m-0.5.2/terms.c 2010-07-18 08:13:26.000000000 +0900 @@ -1201,7 +1201,7 @@ int graph_ok(void) { - if (!UseGraphicChar) + if (UseGraphicChar != GRAPHIC_CHAR_ALL) return 0; return T_as[0] != 0 && T_ae[0] != 0 && T_ac[0] != 0; } diff -urN w3m-0.5.2.orig/terms.c.orig w3m-0.5.2/terms.c.orig --- w3m-0.5.2.orig/terms.c.orig 1970-01-01 09:00:00.000000000 +0900 +++ w3m-0.5.2/terms.c.orig 2007-05-30 13:44:00.000000000 +0900 @@ -0,0 +1,2257 @@ +/* $Id: terms.c,v 1.57 2007/05/30 04:44:00 inu Exp $ */ +/* + * An original curses library for EUC-kanji by Akinori ITO, December 1989 + * revised by Akinori ITO, January 1995 + */ +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifndef __MINGW32_VERSION +#include +#else +#include +#endif /* __MINGW32_VERSION */ +#ifdef USE_MOUSE +#ifdef USE_GPM +#include +#endif /* USE_GPM */ +#ifdef USE_SYSMOUSE +#include +#if (__FreeBSD_version >= 400017) +#include +#include +#else +#include +#endif +int (*sysm_handler) (int x, int y, int nbs, int obs); +static int cwidth = 8, cheight = 16; +static int xpix, ypix, nbs, obs = 0; +#endif /* use_SYSMOUSE */ + +static int is_xterm = 0; + +void mouse_init(), mouse_end(); +int mouseActive = 0; +#endif /* USE_MOUSE */ + +static char *title_str = NULL; + +static int tty; + +#include "terms.h" +#include "fm.h" +#include "myctype.h" + +#ifdef __EMX__ +#define INCL_DOSNLS +#include +#endif /* __EMX__ */ + +#if defined(__CYGWIN__) +#include +#include +static int isWinConsole = 0; +#define TERM_CYGWIN 1 +#define TERM_CYGWIN_RESERVE_IME 2 +static int isLocalConsole = 0; + +#if CYGWIN_VERSION_DLL_MAJOR < 1005 && defined(USE_MOUSE) +int cygwin_mouse_btn_swapped = 0; +#endif + +#if defined(SUPPORT_WIN9X_CONSOLE_MBCS) +static HANDLE hConIn = INVALID_HANDLE_VALUE; +static int isWin95 = 0; +static char *ConInV; +static int iConIn, nConIn, nConInMax; + +static void +check_win9x(void) +{ + OSVERSIONINFO winVersionInfo; + + winVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (GetVersionEx(&winVersionInfo) == 0) { + fprintf(stderr, "can't get Windows version information.\n"); + exit(1); + } + if (winVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { + isWin95 = 1; + } + else { + isWin95 = 0; + } +} + +void +enable_win9x_console_input(void) +{ + if (isWin95 && isWinConsole && isLocalConsole && + hConIn == INVALID_HANDLE_VALUE) { + hConIn = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (hConIn != INVALID_HANDLE_VALUE) { + getch(); + } + } +} + +void +disable_win9x_console_input(void) +{ + if (hConIn != INVALID_HANDLE_VALUE) { + CloseHandle(hConIn); + hConIn = INVALID_HANDLE_VALUE; + } +} + +static void +expand_win32_console_input_buffer(int n) +{ + if (nConIn + n >= nConInMax) { + char *oldv; + + nConInMax = ((nConIn + n) / 2 + 1) * 3; + oldv = ConInV; + ConInV = GC_MALLOC_ATOMIC(nConInMax); + memcpy(ConInV, oldv, nConIn); + } +} + +static int +read_win32_console_input(void) +{ + INPUT_RECORD rec; + DWORD nevents; + + if (PeekConsoleInput(hConIn, &rec, 1, &nevents) && nevents) { + switch (rec.EventType) { + case KEY_EVENT: + expand_win32_console_input_buffer(3); + + if (ReadConsole(hConIn, &ConInV[nConIn], 1, &nevents, NULL)) { + nConIn += nevents; + return nevents; + } + + break; + default: + break; + } + + ReadConsoleInput(hConIn, &rec, 1, &nevents); + } + return 0; +} + +static int +read_win32_console(char *s, int n) +{ + KEY_EVENT_RECORD *ker; + + if (hConIn == INVALID_HANDLE_VALUE) + return read(tty, s, n); + + if (n > 0) + for (;;) { + if (iConIn < nConIn) { + if (n > nConIn - iConIn) + n = nConIn - iConIn; + + memcpy(s, ConInV, n); + + if ((iConIn += n) >= nConIn) + iConIn = nConIn = 0; + + break; + } + + iConIn = nConIn = 0; + + while (!read_win32_console_input()) ; + } + + return n; +} + +#endif /* SUPPORT_WIN9X_CONSOLE_MBCS */ + +static HWND +GetConsoleHwnd(void) +{ +#define MY_BUFSIZE 1024 + HWND hwndFound; + char pszNewWindowTitle[MY_BUFSIZE]; + char pszOldWindowTitle[MY_BUFSIZE]; + + GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE); + wsprintf(pszNewWindowTitle, "%d/%d", + GetTickCount(), GetCurrentProcessId()); + SetConsoleTitle(pszNewWindowTitle); + Sleep(40); + hwndFound = FindWindow(NULL, pszNewWindowTitle); + SetConsoleTitle(pszOldWindowTitle); + return (hwndFound); +} + +#if CYGWIN_VERSION_DLL_MAJOR < 1005 && defined(USE_MOUSE) +static unsigned long +cygwin_version(void) +{ + struct per_process *p; + + p = (struct per_process *)cygwin_internal(CW_USER_DATA); + if (p != NULL) { + return (p->dll_major * 1000) + p->dll_minor; + } + return 0; +} +#endif + +static void +check_cygwin_console(void) +{ + char *term = getenv("TERM"); + HANDLE hWnd; + + if (term == NULL) + term = DEFAULT_TERM; + if (term && strncmp(term, "cygwin", 6) == 0) { + isWinConsole = TERM_CYGWIN; + } + if (isWinConsole) { + hWnd = GetConsoleHwnd(); + if (hWnd != INVALID_HANDLE_VALUE) { + if (IsWindowVisible(hWnd)) { + isLocalConsole = 1; + } + } + if (strncmp(getenv("LANG"), "ja", 2) == 0) { + isWinConsole = TERM_CYGWIN_RESERVE_IME; + } +#ifdef SUPPORT_WIN9X_CONSOLE_MBCS + check_win9x(); + if (isWin95 && ttyslot() != -1) { + isLocalConsole = 0; + } +#endif + } +#if CYGWIN_VERSION_DLL_MAJOR < 1005 && defined(USE_MOUSE) + if (cygwin_version() <= 1003015) { + /* cygwin DLL 1.3.15 or earler */ + cygwin_mouse_btn_swapped = 1; + } +#endif +} +#endif /* __CYGWIN__ */ + +char *getenv(const char *); +MySignalHandler reset_exit(SIGNAL_ARG), error_dump(SIGNAL_ARG); +void setlinescols(void); +void flush_tty(); + +#ifndef SIGIOT +#define SIGIOT SIGABRT +#endif /* not SIGIOT */ + +#ifdef HAVE_TERMIO_H +#include +typedef struct termio TerminalMode; +#define TerminalSet(fd,x) ioctl(fd,TCSETA,x) +#define TerminalGet(fd,x) ioctl(fd,TCGETA,x) +#define MODEFLAG(d) ((d).c_lflag) +#define IMODEFLAG(d) ((d).c_iflag) +#endif /* HAVE_TERMIO_H */ + +#ifdef HAVE_TERMIOS_H +#include +#include +typedef struct termios TerminalMode; +#define TerminalSet(fd,x) tcsetattr(fd,TCSANOW,x) +#define TerminalGet(fd,x) tcgetattr(fd,x) +#define MODEFLAG(d) ((d).c_lflag) +#define IMODEFLAG(d) ((d).c_iflag) +#endif /* HAVE_TERMIOS_H */ + +#ifdef HAVE_SGTTY_H +#include +typedef struct sgttyb TerminalMode; +#define TerminalSet(fd,x) ioctl(fd,TIOCSETP,x) +#define TerminalGet(fd,x) ioctl(fd,TIOCGETP,x) +#define MODEFLAG(d) ((d).sg_flags) +#endif /* HAVE_SGTTY_H */ + +#ifdef __MINGW32_VERSION +/* dummy struct */ +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ + }; +typedef struct termios TerminalMode; +#define TerminalSet(fd,x) (0) +#define TerminalGet(fd,x) (0) +#define MODEFLAG(d) (0) + +/* dummy defines */ +#define SIGHUP (0) +#define SIGQUIT (0) +#define ECHO (0) +#define ISIG (0) +#define VEOF (0) +#define ICANON (0) +#define IXON (0) +#define IXOFF (0) + +char *ttyname(int); +#endif /* __MINGW32_VERSION */ + +#define MAX_LINE 200 +#define MAX_COLUMN 400 + +/* Screen properties */ +#define S_SCREENPROP 0x0f +#define S_NORMAL 0x00 +#define S_STANDOUT 0x01 +#define S_UNDERLINE 0x02 +#define S_BOLD 0x04 +#define S_EOL 0x08 + +/* Sort of Character */ +#define C_WHICHCHAR 0xc0 +#define C_ASCII 0x00 +#ifdef USE_M17N +#define C_WCHAR1 0x40 +#define C_WCHAR2 0x80 +#endif +#define C_CTRL 0xc0 + +#define CHMODE(c) ((c)&C_WHICHCHAR) +#define SETCHMODE(var,mode) ((var) = (((var)&~C_WHICHCHAR) | mode)) +#ifdef USE_M17N +#define SETCH(var,ch,len) ((var) = New_Reuse(char, (var), (len) + 1), \ + strncpy((var), (ch), (len)), (var)[len] = '\0') +#else +#define SETCH(var,ch,len) ((var) = (ch)) +#endif + +/* Charactor Color */ +#define COL_FCOLOR 0xf00 +#define COL_FBLACK 0x800 +#define COL_FRED 0x900 +#define COL_FGREEN 0xa00 +#define COL_FYELLOW 0xb00 +#define COL_FBLUE 0xc00 +#define COL_FMAGENTA 0xd00 +#define COL_FCYAN 0xe00 +#define COL_FWHITE 0xf00 +#define COL_FTERM 0x000 + +#define S_COLORED 0xf00 + +#ifdef USE_BG_COLOR +/* Background Color */ +#define COL_BCOLOR 0xf000 +#define COL_BBLACK 0x8000 +#define COL_BRED 0x9000 +#define COL_BGREEN 0xa000 +#define COL_BYELLOW 0xb000 +#define COL_BBLUE 0xc000 +#define COL_BMAGENTA 0xd000 +#define COL_BCYAN 0xe000 +#define COL_BWHITE 0xf000 +#define COL_BTERM 0x0000 + +#define S_BCOLORED 0xf000 +#endif /* USE_BG_COLOR */ + + +#define S_GRAPHICS 0x10 + +#define S_DIRTY 0x20 + +#define SETPROP(var,prop) (var = (((var)&S_DIRTY) | prop)) + +/* Line status */ +#define L_DIRTY 0x01 +#define L_UNUSED 0x02 +#define L_NEED_CE 0x04 +#define L_CLRTOEOL 0x08 + +#define ISDIRTY(d) ((d) & L_DIRTY) +#define ISUNUSED(d) ((d) & L_UNUSED) +#define NEED_CE(d) ((d) & L_NEED_CE) + +typedef unsigned short l_prop; + +typedef struct scline { +#ifdef USE_M17N + char **lineimage; +#else + char *lineimage; +#endif + l_prop *lineprop; + short isdirty; + short eol; +} Screen; + +static TerminalMode d_ioval; +static int tty = -1; +static FILE *ttyf = NULL; + +static +char bp[1024], funcstr[256]; + +char *T_cd, *T_ce, *T_kr, *T_kl, *T_cr, *T_bt, *T_ta, *T_sc, *T_rc, + *T_so, *T_se, *T_us, *T_ue, *T_cl, *T_cm, *T_al, *T_sr, *T_md, *T_me, + *T_ti, *T_te, *T_nd, *T_as, *T_ae, *T_eA, *T_ac, *T_op; + +int LINES, COLS; +#if defined(__CYGWIN__) +int LASTLINE; +#endif /* defined(__CYGWIN__) */ + +static int max_LINES = 0, max_COLS = 0; +static int tab_step = 8; +static int CurLine, CurColumn; +static Screen *ScreenElem = NULL, **ScreenImage = NULL; +static l_prop CurrentMode = 0; +static int graph_enabled = 0; + +static char gcmap[96]; + +extern int tgetent(char *, char *); +extern int tgetnum(char *); +extern int tgetflag(char *); +extern char *tgetstr(char *, char **); +extern char *tgoto(char *, int, int); +extern int tputs(char *, int, int (*)(char)); +void clear(), wrap(), touch_line(), touch_column(int); +#if 0 +void need_clrtoeol(void); +#endif +void clrtoeol(void); /* conflicts with curs_clear(3)? */ + +static int write1(char); + +static void +writestr(char *s) +{ + tputs(s, 1, write1); +} + +#define MOVE(line,column) writestr(tgoto(T_cm,column,line)); + +#ifdef USE_MOUSE +#define W3M_TERM_INFO(name, title, mouse) name, title, mouse +#define NEED_XTERM_ON (1) +#define NEED_XTERM_OFF (1<<1) +#ifdef __CYGWIN__ +#define NEED_CYGWIN_ON (1<<2) +#define NEED_CYGWIN_OFF (1<<3) +#endif +#else +#define W3M_TERM_INFO(name, title, mouse) name, title +#endif + +static char XTERM_TITLE[] = "\033]0;w3m: %s\007"; +static char SCREEN_TITLE[] = "\033k%s\033\134"; +#ifdef __CYGWIN__ +static char CYGWIN_TITLE[] = "w3m: %s"; +#endif + +/* *INDENT-OFF* */ +static struct w3m_term_info { + char *term; + char *title_str; +#ifdef USE_MOUSE + int mouse_flag; +#endif +} w3m_term_info_list[] = { + {W3M_TERM_INFO("xterm", XTERM_TITLE, (NEED_XTERM_ON|NEED_XTERM_OFF))}, + {W3M_TERM_INFO("kterm", XTERM_TITLE, (NEED_XTERM_ON|NEED_XTERM_OFF))}, + {W3M_TERM_INFO("rxvt", XTERM_TITLE, (NEED_XTERM_ON|NEED_XTERM_OFF))}, + {W3M_TERM_INFO("Eterm", XTERM_TITLE, (NEED_XTERM_ON|NEED_XTERM_OFF))}, + {W3M_TERM_INFO("mlterm", XTERM_TITLE, (NEED_XTERM_ON|NEED_XTERM_OFF))}, + {W3M_TERM_INFO("screen", SCREEN_TITLE, 0)}, +#ifdef __CYGWIN__ + {W3M_TERM_INFO("cygwin", CYGWIN_TITLE, (NEED_CYGWIN_ON|NEED_CYGWIN_OFF))}, +#endif + {W3M_TERM_INFO(NULL, NULL, 0)} +}; +#undef W3M_TERM_INFO +/* *INDENT-ON * */ + +int +set_tty(void) +{ + char *ttyn; + + if (isatty(0)) /* stdin */ + ttyn = ttyname(0); + else + ttyn = DEV_TTY_PATH; + tty = open(ttyn, O_RDWR); + if (tty < 0) { + /* use stderr instead of stdin... is it OK???? */ + tty = 2; + } + ttyf = fdopen(tty, "w"); +#ifdef __CYGWIN__ + check_cygwin_console(); +#endif + TerminalGet(tty, &d_ioval); + if (displayTitleTerm != NULL) { + struct w3m_term_info *p; + for (p = w3m_term_info_list; p->term != NULL; p++) { + if (!strncmp(displayTitleTerm, p->term, strlen(p->term))) { + title_str = p->title_str; + break; + } + } + } +#ifdef USE_MOUSE + { + char *term = getenv("TERM"); + if (term != NULL) { + struct w3m_term_info *p; + for (p = w3m_term_info_list; p->term != NULL; p++) { + if (!strncmp(term, p->term, strlen(p->term))) { + is_xterm = p->mouse_flag; + break; + } + } + } + } +#endif + return 0; +} + +void +ttymode_set(int mode, int imode) +{ +#ifndef __MINGW32_VERSION + TerminalMode ioval; + + TerminalGet(tty, &ioval); + MODEFLAG(ioval) |= mode; +#ifndef HAVE_SGTTY_H + IMODEFLAG(ioval) |= imode; +#endif /* not HAVE_SGTTY_H */ + + while (TerminalSet(tty, &ioval) == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + printf("Error occured while set %x: errno=%d\n", mode, errno); + reset_exit(SIGNAL_ARGLIST); + } +#endif +} + +void +ttymode_reset(int mode, int imode) +{ +#ifndef __MINGW32_VERSION + TerminalMode ioval; + + TerminalGet(tty, &ioval); + MODEFLAG(ioval) &= ~mode; +#ifndef HAVE_SGTTY_H + IMODEFLAG(ioval) &= ~imode; +#endif /* not HAVE_SGTTY_H */ + + while (TerminalSet(tty, &ioval) == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + printf("Error occured while reset %x: errno=%d\n", mode, errno); + reset_exit(SIGNAL_ARGLIST); + } +#endif /* __MINGW32_VERSION */ +} + +#ifndef HAVE_SGTTY_H +void +set_cc(int spec, int val) +{ + TerminalMode ioval; + + TerminalGet(tty, &ioval); + ioval.c_cc[spec] = val; + while (TerminalSet(tty, &ioval) == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + printf("Error occured: errno=%d\n", errno); + reset_exit(SIGNAL_ARGLIST); + } +} +#endif /* not HAVE_SGTTY_H */ + +void +close_tty(void) +{ + if (tty > 2) + close(tty); +} + +char * +ttyname_tty(void) +{ + return ttyname(tty); +} + +void +reset_tty(void) +{ + writestr(T_op); /* turn off */ + writestr(T_me); + if (!Do_not_use_ti_te) { + if (T_te && *T_te) + writestr(T_te); + else + writestr(T_cl); + } + writestr(T_se); /* reset terminal */ + flush_tty(); + TerminalSet(tty, &d_ioval); + close_tty(); +} + +MySignalHandler +reset_exit(SIGNAL_ARG) +{ +#ifdef USE_MOUSE + if (mouseActive) + mouse_end(); +#endif /* USE_MOUSE */ + reset_tty(); + w3m_exit(0); + SIGNAL_RETURN; +} + +MySignalHandler +error_dump(SIGNAL_ARG) +{ + mySignal(SIGIOT, SIG_DFL); + reset_tty(); + abort(); + SIGNAL_RETURN; +} + +void +set_int(void) +{ + mySignal(SIGHUP, reset_exit); + mySignal(SIGINT, reset_exit); + mySignal(SIGQUIT, reset_exit); + mySignal(SIGTERM, reset_exit); + mySignal(SIGILL, error_dump); + mySignal(SIGIOT, error_dump); + mySignal(SIGFPE, error_dump); +#ifdef SIGBUS + mySignal(SIGBUS, error_dump); +#endif /* SIGBUS */ + /* mySignal(SIGSEGV, error_dump); */ +} + + +static void +setgraphchar(void) +{ + int c, i, n; + + for (c = 0; c < 96; c++) + gcmap[c] = (char)(c + ' '); + + if (!T_ac) + return; + + n = strlen(T_ac); + for (i = 0; i < n - 1; i += 2) { + c = (unsigned)T_ac[i] - ' '; + if (c >= 0 && c < 96) + gcmap[c] = T_ac[i + 1]; + } +} + +#define graphchar(c) (((unsigned)(c)>=' ' && (unsigned)(c)<128)? gcmap[(c)-' '] : (c)) +#define GETSTR(v,s) {v = pt; suc = tgetstr(s,&pt); if (!suc) v = ""; else v = allocStr(suc, -1); } + +void +getTCstr(void) +{ + char *ent; + char *suc; + char *pt = funcstr; + int r; + + ent = getenv("TERM") ? getenv("TERM") : DEFAULT_TERM; + if (ent == NULL) { + fprintf(stderr, "TERM is not set\n"); + reset_exit(SIGNAL_ARGLIST); + } + + r = tgetent(bp, ent); + if (r != 1) { + /* Can't find termcap entry */ + fprintf(stderr, "Can't find termcap entry %s\n", ent); + reset_exit(SIGNAL_ARGLIST); + } + + GETSTR(T_ce, "ce"); /* clear to the end of line */ + GETSTR(T_cd, "cd"); /* clear to the end of display */ + GETSTR(T_kr, "nd"); /* cursor right */ + if (suc == NULL) + GETSTR(T_kr, "kr"); + if (tgetflag("bs")) + T_kl = "\b"; /* cursor left */ + else { + GETSTR(T_kl, "le"); + if (suc == NULL) + GETSTR(T_kl, "kb"); + if (suc == NULL) + GETSTR(T_kl, "kl"); + } + GETSTR(T_cr, "cr"); /* carriage return */ + GETSTR(T_ta, "ta"); /* tab */ + GETSTR(T_sc, "sc"); /* save cursor */ + GETSTR(T_rc, "rc"); /* restore cursor */ + GETSTR(T_so, "so"); /* standout mode */ + GETSTR(T_se, "se"); /* standout mode end */ + GETSTR(T_us, "us"); /* underline mode */ + GETSTR(T_ue, "ue"); /* underline mode end */ + GETSTR(T_md, "md"); /* bold mode */ + GETSTR(T_me, "me"); /* bold mode end */ + GETSTR(T_cl, "cl"); /* clear screen */ + GETSTR(T_cm, "cm"); /* cursor move */ + GETSTR(T_al, "al"); /* append line */ + GETSTR(T_sr, "sr"); /* scroll reverse */ + GETSTR(T_ti, "ti"); /* terminal init */ + GETSTR(T_te, "te"); /* terminal end */ + GETSTR(T_nd, "nd"); /* move right one space */ + GETSTR(T_eA, "eA"); /* enable alternative charset */ + GETSTR(T_as, "as"); /* alternative (graphic) charset start */ + GETSTR(T_ae, "ae"); /* alternative (graphic) charset end */ + GETSTR(T_ac, "ac"); /* graphics charset pairs */ + GETSTR(T_op, "op"); /* set default color pair to its original value */ +#if defined( CYGWIN ) && CYGWIN < 1 + /* for TERM=pcansi on MS-DOS prompt. */ +#if 0 + T_eA = ""; + T_as = "\033[12m"; + T_ae = "\033[10m"; + T_ac = "l\001k\002m\003j\004x\005q\006n\020a\024v\025w\026u\027t\031"; +#endif + T_eA = ""; + T_as = ""; + T_ae = ""; + T_ac = ""; +#endif /* CYGWIN */ + + LINES = COLS = 0; + setlinescols(); + setgraphchar(); +} + +void +setlinescols(void) +{ + char *p; + int i; +#ifdef __EMX__ + { + int s[2]; + _scrsize(s); + COLS = s[0]; + LINES = s[1]; + + if (getenv("WINDOWID")) { + FILE *fd = popen("scrsize", "rt"); + if (fd) { + fscanf(fd, "%i %i", &COLS, &LINES); + pclose(fd); + } + } + } +#elif defined(HAVE_TERMIOS_H) && defined(TIOCGWINSZ) + struct winsize wins; + + i = ioctl(tty, TIOCGWINSZ, &wins); + if (i >= 0 && wins.ws_row != 0 && wins.ws_col != 0) { + LINES = wins.ws_row; + COLS = wins.ws_col; + } +#endif /* defined(HAVE-TERMIOS_H) && defined(TIOCGWINSZ) */ + if (LINES <= 0 && (p = getenv("LINES")) != NULL && (i = atoi(p)) >= 0) + LINES = i; + if (COLS <= 0 && (p = getenv("COLUMNS")) != NULL && (i = atoi(p)) >= 0) + COLS = i; + if (LINES <= 0) + LINES = tgetnum("li"); /* number of line */ + if (COLS <= 0) + COLS = tgetnum("co"); /* number of column */ + if (COLS > MAX_COLUMN) + COLS = MAX_COLUMN; + if (LINES > MAX_LINE) + LINES = MAX_LINE; +#if defined(__CYGWIN__) + LASTLINE = LINES - (isWinConsole == TERM_CYGWIN_RESERVE_IME ? 2 : 1); +#endif /* defined(__CYGWIN__) */ +} + +void +setupscreen(void) +{ + int i; + + if (LINES + 1 > max_LINES) { + max_LINES = LINES + 1; + max_COLS = 0; + ScreenElem = New_N(Screen, max_LINES); + ScreenImage = New_N(Screen *, max_LINES); + } + if (COLS + 1 > max_COLS) { + max_COLS = COLS + 1; + for (i = 0; i < max_LINES; i++) { +#ifdef USE_M17N + ScreenElem[i].lineimage = New_N(char *, max_COLS); + bzero((void *)ScreenElem[i].lineimage, max_COLS * sizeof(char *)); +#else + ScreenElem[i].lineimage = New_N(char, max_COLS); +#endif + ScreenElem[i].lineprop = New_N(l_prop, max_COLS); + } + } + for (i = 0; i < LINES; i++) { + ScreenImage[i] = &ScreenElem[i]; + ScreenImage[i]->lineprop[0] = S_EOL; + ScreenImage[i]->isdirty = 0; + } + for (; i < max_LINES; i++) { + ScreenElem[i].isdirty = L_UNUSED; + } + + clear(); +} + +/* + * Screen initialize + */ +int +initscr(void) +{ + if (set_tty() < 0) + return -1; + set_int(); + getTCstr(); + if (T_ti && !Do_not_use_ti_te) + writestr(T_ti); + setupscreen(); + return 0; +} + +static int +write1(char c) +{ + putc(c, ttyf); +#ifdef SCREEN_DEBUG + flush_tty(); +#endif /* SCREEN_DEBUG */ + return 0; +} + +void +move(int line, int column) +{ + if (line >= 0 && line < LINES) + CurLine = line; + if (column >= 0 && column < COLS) + CurColumn = column; +} + +#ifdef USE_BG_COLOR +#define M_SPACE (S_SCREENPROP|S_COLORED|S_BCOLORED|S_GRAPHICS) +#else /* not USE_BG_COLOR */ +#define M_SPACE (S_SCREENPROP|S_COLORED|S_GRAPHICS) +#endif /* not USE_BG_COLOR */ + +static int +#ifdef USE_M17N +need_redraw(char *c1, l_prop pr1, char *c2, l_prop pr2) +{ + if (!c1 || !c2 || strcmp(c1, c2)) + return 1; + if (*c1 == ' ') +#else +need_redraw(char c1, l_prop pr1, char c2, l_prop pr2) +{ + if (c1 != c2) + return 1; + if (c1 == ' ') +#endif + return (pr1 ^ pr2) & M_SPACE & ~S_DIRTY; + + if ((pr1 ^ pr2) & ~S_DIRTY) + return 1; + + return 0; +} + +#define M_CEOL (~(M_SPACE|C_WHICHCHAR)) + +#ifdef USE_M17N +#define SPACE " " +#else +#define SPACE ' ' +#endif + +#ifdef USE_M17N +void +addch(char c) +{ + addmch(&c, 1); +} + +void +addmch(char *pc, size_t len) +#else +void +addch(char pc) +#endif +{ + l_prop *pr; + int dest, i; + short *dirty; +#ifdef USE_M17N + static Str tmp = NULL; + char **p; + char c = *pc; + int width = wtf_width((wc_uchar *) pc); + + if (tmp == NULL) + tmp = Strnew(); + Strcopy_charp_n(tmp, pc, len); + pc = tmp->ptr; +#else + char *p; + char c = pc; +#endif + + if (CurColumn == COLS) + wrap(); + if (CurColumn >= COLS) + return; + p = ScreenImage[CurLine]->lineimage; + pr = ScreenImage[CurLine]->lineprop; + dirty = &ScreenImage[CurLine]->isdirty; + +#ifndef USE_M17N + /* Eliminate unprintables according to * iso-8859-*. + * Particularly 0x96 messes up T.Dickey's * (xfree-)xterm */ + if (IS_INTSPACE(c)) + c = ' '; +#endif + + if (pr[CurColumn] & S_EOL) { + if (c == ' ' && !(CurrentMode & M_SPACE)) { + CurColumn++; + return; + } + for (i = CurColumn; i >= 0 && (pr[i] & S_EOL); i--) { + SETCH(p[i], SPACE, 1); + SETPROP(pr[i], (pr[i] & M_CEOL) | C_ASCII); + } + } + + if (c == '\t' || c == '\n' || c == '\r' || c == '\b') + SETCHMODE(CurrentMode, C_CTRL); +#ifdef USE_M17N + else if (len > 1) + SETCHMODE(CurrentMode, C_WCHAR1); +#endif + else if (!IS_CNTRL(c)) + SETCHMODE(CurrentMode, C_ASCII); + else + return; + + /* Required to erase bold or underlined character for some * terminal + * emulators. */ +#ifdef USE_M17N + i = CurColumn + width - 1; +#else + i = CurColumn; +#endif + if (i < COLS && + (((pr[i] & S_BOLD) && need_redraw(p[i], pr[i], pc, CurrentMode)) || + ((pr[i] & S_UNDERLINE) && !(CurrentMode & S_UNDERLINE)))) { + touch_line(); + i++; + if (i < COLS) { + touch_column(i); + if (pr[i] & S_EOL) { + SETCH(p[i], SPACE, 1); + SETPROP(pr[i], (pr[i] & M_CEOL) | C_ASCII); + } +#ifdef USE_M17N + else { + for (i++; i < COLS && CHMODE(pr[i]) == C_WCHAR2; i++) + touch_column(i); + } +#endif + } + } + +#ifdef USE_M17N + if (CurColumn + width > COLS) { + touch_line(); + for (i = CurColumn; i < COLS; i++) { + SETCH(p[i], SPACE, 1); + SETPROP(pr[i], (pr[i] & ~C_WHICHCHAR) | C_ASCII); + touch_column(i); + } + wrap(); + if (CurColumn + width > COLS) + return; + p = ScreenImage[CurLine]->lineimage; + pr = ScreenImage[CurLine]->lineprop; + } + if (CHMODE(pr[CurColumn]) == C_WCHAR2) { + touch_line(); + for (i = CurColumn - 1; i >= 0; i--) { + l_prop l = CHMODE(pr[i]); + SETCH(p[i], SPACE, 1); + SETPROP(pr[i], (pr[i] & ~C_WHICHCHAR) | C_ASCII); + touch_column(i); + if (l != C_WCHAR2) + break; + } + } +#endif + if (CHMODE(CurrentMode) != C_CTRL) { + if (need_redraw(p[CurColumn], pr[CurColumn], pc, CurrentMode)) { + SETCH(p[CurColumn], pc, len); + SETPROP(pr[CurColumn], CurrentMode); + touch_line(); + touch_column(CurColumn); +#ifdef USE_M17N + SETCHMODE(CurrentMode, C_WCHAR2); + for (i = CurColumn + 1; i < CurColumn + width; i++) { + SETCH(p[i], SPACE, 1); + SETPROP(pr[i], (pr[CurColumn] & ~C_WHICHCHAR) | C_WCHAR2); + touch_column(i); + } + for (; i < COLS && CHMODE(pr[i]) == C_WCHAR2; i++) { + SETCH(p[i], SPACE, 1); + SETPROP(pr[i], (pr[i] & ~C_WHICHCHAR) | C_ASCII); + touch_column(i); + } + } + CurColumn += width; +#else + } + CurColumn++; +#endif + } + else if (c == '\t') { + dest = (CurColumn + tab_step) / tab_step * tab_step; + if (dest >= COLS) { + wrap(); + touch_line(); + dest = tab_step; + p = ScreenImage[CurLine]->lineimage; + pr = ScreenImage[CurLine]->lineprop; + } + for (i = CurColumn; i < dest; i++) { + if (need_redraw(p[i], pr[i], SPACE, CurrentMode)) { + SETCH(p[i], SPACE, 1); + SETPROP(pr[i], CurrentMode); + touch_line(); + touch_column(i); + } + } + CurColumn = i; + } + else if (c == '\n') { + wrap(); + } + else if (c == '\r') { /* Carriage return */ + CurColumn = 0; + } + else if (c == '\b' && CurColumn > 0) { /* Backspace */ + CurColumn--; +#ifdef USE_M17N + while (CurColumn > 0 && CHMODE(pr[CurColumn]) == C_WCHAR2) + CurColumn--; +#endif + } +} + +void +wrap(void) +{ + if (CurLine == LASTLINE) + return; + CurLine++; + CurColumn = 0; +} + +void +touch_column(int col) +{ + if (col >= 0 && col < COLS) + ScreenImage[CurLine]->lineprop[col] |= S_DIRTY; +} + +void +touch_line(void) +{ + if (!(ScreenImage[CurLine]->isdirty & L_DIRTY)) { + int i; + for (i = 0; i < COLS; i++) + ScreenImage[CurLine]->lineprop[i] &= ~S_DIRTY; + ScreenImage[CurLine]->isdirty |= L_DIRTY; + } + +} + +void +standout(void) +{ + CurrentMode |= S_STANDOUT; +} + +void +standend(void) +{ + CurrentMode &= ~S_STANDOUT; +} + +void +toggle_stand(void) +{ +#ifdef USE_M17N + int i; +#endif + l_prop *pr = ScreenImage[CurLine]->lineprop; + pr[CurColumn] ^= S_STANDOUT; +#ifdef USE_M17N + if (CHMODE(pr[CurColumn]) != C_WCHAR2) { + for (i = CurColumn + 1; CHMODE(pr[i]) == C_WCHAR2; i++) + pr[i] ^= S_STANDOUT; + } +#endif +} + +void +bold(void) +{ + CurrentMode |= S_BOLD; +} + +void +boldend(void) +{ + CurrentMode &= ~S_BOLD; +} + +void +underline(void) +{ + CurrentMode |= S_UNDERLINE; +} + +void +underlineend(void) +{ + CurrentMode &= ~S_UNDERLINE; +} + +void +graphstart(void) +{ + CurrentMode |= S_GRAPHICS; +} + +void +graphend(void) +{ + CurrentMode &= ~S_GRAPHICS; +} + +int +graph_ok(void) +{ + if (!UseGraphicChar) + return 0; + return T_as[0] != 0 && T_ae[0] != 0 && T_ac[0] != 0; +} + +void +setfcolor(int color) +{ + CurrentMode &= ~COL_FCOLOR; + if ((color & 0xf) <= 7) + CurrentMode |= (((color & 7) | 8) << 8); +} + +static char * +color_seq(int colmode) +{ + static char seqbuf[32]; + sprintf(seqbuf, "\033[%dm", ((colmode >> 8) & 7) + 30); + return seqbuf; +} + +#ifdef USE_BG_COLOR +void +setbcolor(int color) +{ + CurrentMode &= ~COL_BCOLOR; + if ((color & 0xf) <= 7) + CurrentMode |= (((color & 7) | 8) << 12); +} + +static char * +bcolor_seq(int colmode) +{ + static char seqbuf[32]; + sprintf(seqbuf, "\033[%dm", ((colmode >> 12) & 7) + 40); + return seqbuf; +} +#endif /* USE_BG_COLOR */ + +#define RF_NEED_TO_MOVE 0 +#define RF_CR_OK 1 +#define RF_NONEED_TO_MOVE 2 +#ifdef USE_BG_COLOR +#define M_MEND (S_STANDOUT|S_UNDERLINE|S_BOLD|S_COLORED|S_BCOLORED|S_GRAPHICS) +#else /* not USE_BG_COLOR */ +#define M_MEND (S_STANDOUT|S_UNDERLINE|S_BOLD|S_COLORED|S_GRAPHICS) +#endif /* not USE_BG_COLOR */ +void +refresh(void) +{ + int line, col, pcol; + int pline = CurLine; + int moved = RF_NEED_TO_MOVE; +#ifdef USE_M17N + char **pc; +#else + char *pc; +#endif + l_prop *pr, mode = 0; + l_prop color = COL_FTERM; +#ifdef USE_BG_COLOR + l_prop bcolor = COL_BTERM; +#endif /* USE_BG_COLOR */ + short *dirty; + +#ifdef USE_M17N + wc_putc_init(InnerCharset, DisplayCharset); +#endif + for (line = 0; line <= LASTLINE; line++) { + dirty = &ScreenImage[line]->isdirty; + if (*dirty & L_DIRTY) { + *dirty &= ~L_DIRTY; + pc = ScreenImage[line]->lineimage; + pr = ScreenImage[line]->lineprop; + for (col = 0; col < COLS && !(pr[col] & S_EOL); col++) { + if (*dirty & L_NEED_CE && col >= ScreenImage[line]->eol) { + if (need_redraw(pc[col], pr[col], SPACE, 0)) + break; + } + else { + if (pr[col] & S_DIRTY) + break; + } + } + if (*dirty & (L_NEED_CE | L_CLRTOEOL)) { + pcol = ScreenImage[line]->eol; + if (pcol >= COLS) { + *dirty &= ~(L_NEED_CE | L_CLRTOEOL); + pcol = col; + } + } + else { + pcol = col; + } + if (line < LINES - 2 && pline == line - 1 && pcol == 0) { + switch (moved) { + case RF_NEED_TO_MOVE: + MOVE(line, 0); + moved = RF_CR_OK; + break; + case RF_CR_OK: + write1('\n'); + write1('\r'); + break; + case RF_NONEED_TO_MOVE: + moved = RF_CR_OK; + break; + } + } + else { + MOVE(line, pcol); + moved = RF_CR_OK; + } + if (*dirty & (L_NEED_CE | L_CLRTOEOL)) { + writestr(T_ce); + if (col != pcol) + MOVE(line, col); + } + pline = line; + pcol = col; + for (; col < COLS; col++) { + if (pr[col] & S_EOL) + break; + + /* + * some terminal emulators do linefeed when a + * character is put on COLS-th column. this behavior + * is different from one of vt100, but such terminal + * emulators are used as vt100-compatible + * emulators. This behaviour causes scroll when a + * character is drawn on (COLS-1,LINES-1) point. To + * avoid the scroll, I prohibit to draw character on + * (COLS-1,LINES-1). + */ +#if !defined(USE_BG_COLOR) || defined(__CYGWIN__) +#ifdef __CYGWIN__ + if (isWinConsole) +#endif + if (line == LINES - 1 && col == COLS - 1) + break; +#endif /* !defined(USE_BG_COLOR) || defined(__CYGWIN__) */ + if ((!(pr[col] & S_STANDOUT) && (mode & S_STANDOUT)) || + (!(pr[col] & S_UNDERLINE) && (mode & S_UNDERLINE)) || + (!(pr[col] & S_BOLD) && (mode & S_BOLD)) || + (!(pr[col] & S_COLORED) && (mode & S_COLORED)) +#ifdef USE_BG_COLOR + || (!(pr[col] & S_BCOLORED) && (mode & S_BCOLORED)) +#endif /* USE_BG_COLOR */ + || (!(pr[col] & S_GRAPHICS) && (mode & S_GRAPHICS))) { + if ((mode & S_COLORED) +#ifdef USE_BG_COLOR + || (mode & S_BCOLORED) +#endif /* USE_BG_COLOR */ + ) + writestr(T_op); + if (mode & S_GRAPHICS) + writestr(T_ae); + writestr(T_me); + mode &= ~M_MEND; + } + if ((*dirty & L_NEED_CE && col >= ScreenImage[line]->eol) ? + need_redraw(pc[col], pr[col], SPACE, + 0) : (pr[col] & S_DIRTY)) { + if (pcol == col - 1) + writestr(T_nd); + else if (pcol != col) + MOVE(line, col); + + if ((pr[col] & S_STANDOUT) && !(mode & S_STANDOUT)) { + writestr(T_so); + mode |= S_STANDOUT; + } + if ((pr[col] & S_UNDERLINE) && !(mode & S_UNDERLINE)) { + writestr(T_us); + mode |= S_UNDERLINE; + } + if ((pr[col] & S_BOLD) && !(mode & S_BOLD)) { + writestr(T_md); + mode |= S_BOLD; + } + if ((pr[col] & S_COLORED) && (pr[col] ^ mode) & COL_FCOLOR) { + color = (pr[col] & COL_FCOLOR); + mode = ((mode & ~COL_FCOLOR) | color); + writestr(color_seq(color)); + } +#ifdef USE_BG_COLOR + if ((pr[col] & S_BCOLORED) + && (pr[col] ^ mode) & COL_BCOLOR) { + bcolor = (pr[col] & COL_BCOLOR); + mode = ((mode & ~COL_BCOLOR) | bcolor); + writestr(bcolor_seq(bcolor)); + } +#endif /* USE_BG_COLOR */ + if ((pr[col] & S_GRAPHICS) && !(mode & S_GRAPHICS)) { +#ifdef USE_M17N + wc_putc_end(ttyf); +#endif + if (!graph_enabled) { + graph_enabled = 1; + writestr(T_eA); + } + writestr(T_as); + mode |= S_GRAPHICS; + } +#ifdef USE_M17N + if (pr[col] & S_GRAPHICS) + write1(graphchar(*pc[col])); + else if (CHMODE(pr[col]) != C_WCHAR2) + wc_putc(pc[col], ttyf); +#else + write1((pr[col] & S_GRAPHICS) ? graphchar(pc[col]) : + pc[col]); +#endif + pcol = col + 1; + } + } + if (col == COLS) + moved = RF_NEED_TO_MOVE; + for (; col < COLS && !(pr[col] & S_EOL); col++) + pr[col] |= S_EOL; + } + *dirty &= ~(L_NEED_CE | L_CLRTOEOL); + if (mode & M_MEND) { + if (mode & (S_COLORED +#ifdef USE_BG_COLOR + | S_BCOLORED +#endif /* USE_BG_COLOR */ + )) + writestr(T_op); + if (mode & S_GRAPHICS) { + writestr(T_ae); +#ifdef USE_M17N + wc_putc_clear_status(); +#endif + } + writestr(T_me); + mode &= ~M_MEND; + } + } +#ifdef USE_M17N + wc_putc_end(ttyf); +#endif + MOVE(CurLine, CurColumn); + flush_tty(); +} + +void +clear(void) +{ + int i, j; + l_prop *p; + writestr(T_cl); + move(0, 0); + for (i = 0; i < LINES; i++) { + ScreenImage[i]->isdirty = 0; + p = ScreenImage[i]->lineprop; + for (j = 0; j < COLS; j++) { + p[j] = S_EOL; + } + } + CurrentMode = C_ASCII; +} + +#ifdef USE_RAW_SCROLL +static void +scroll_raw(void) +{ /* raw scroll */ + MOVE(LINES - 1, 0); + write1('\n'); +} + +void +scroll(int n) +{ /* scroll up */ + int cli = CurLine, cco = CurColumn; + Screen *t; + int i, j, k; + + i = LINES; + j = n; + do { + k = j; + j = i % k; + i = k; + } while (j); + do { + k--; + i = k; + j = (i + n) % LINES; + t = ScreenImage[k]; + while (j != k) { + ScreenImage[i] = ScreenImage[j]; + i = j; + j = (i + n) % LINES; + } + ScreenImage[i] = t; + } while (k); + + for (i = 0; i < n; i++) { + t = ScreenImage[LINES - 1 - i]; + t->isdirty = 0; + for (j = 0; j < COLS; j++) + t->lineprop[j] = S_EOL; + scroll_raw(); + } + move(cli, cco); +} + +void +rscroll(int n) +{ /* scroll down */ + int cli = CurLine, cco = CurColumn; + Screen *t; + int i, j, k; + + i = LINES; + j = n; + do { + k = j; + j = i % k; + i = k; + } while (j); + do { + k--; + i = k; + j = (LINES + i - n) % LINES; + t = ScreenImage[k]; + while (j != k) { + ScreenImage[i] = ScreenImage[j]; + i = j; + j = (LINES + i - n) % LINES; + } + ScreenImage[i] = t; + } while (k); + if (T_sr && *T_sr) { + MOVE(0, 0); + for (i = 0; i < n; i++) { + t = ScreenImage[i]; + t->isdirty = 0; + for (j = 0; j < COLS; j++) + t->lineprop[j] = S_EOL; + writestr(T_sr); + } + move(cli, cco); + } + else { + for (i = 0; i < LINES; i++) { + t = ScreenImage[i]; + t->isdirty |= L_DIRTY | L_NEED_CE; + for (j = 0; j < COLS; j++) { + t->lineprop[j] |= S_DIRTY; + } + } + } +} +#endif + +#if 0 +void +need_clrtoeol(void) +{ + /* Clear to the end of line as the need arises */ + l_prop *lprop = ScreenImage[CurLine]->lineprop; + + if (lprop[CurColumn] & S_EOL) + return; + + if (!(ScreenImage[CurLine]->isdirty & (L_NEED_CE | L_CLRTOEOL)) || + ScreenImage[CurLine]->eol > CurColumn) + ScreenImage[CurLine]->eol = CurColumn; + + ScreenImage[CurLine]->isdirty |= L_NEED_CE; +} +#endif /* 0 */ + +/* XXX: conflicts with curses's clrtoeol(3) ? */ +void +clrtoeol(void) +{ /* Clear to the end of line */ + int i; + l_prop *lprop = ScreenImage[CurLine]->lineprop; + + if (lprop[CurColumn] & S_EOL) + return; + + if (!(ScreenImage[CurLine]->isdirty & (L_NEED_CE | L_CLRTOEOL)) || + ScreenImage[CurLine]->eol > CurColumn) + ScreenImage[CurLine]->eol = CurColumn; + + ScreenImage[CurLine]->isdirty |= L_CLRTOEOL; + touch_line(); + for (i = CurColumn; i < COLS && !(lprop[i] & S_EOL); i++) { + lprop[i] = S_EOL | S_DIRTY; + } +} + +#ifdef USE_BG_COLOR +void +clrtoeol_with_bcolor(void) +{ + int i, cli, cco; + l_prop pr; + + if (!(CurrentMode & S_BCOLORED)) { + clrtoeol(); + return; + } + cli = CurLine; + cco = CurColumn; + pr = CurrentMode; + CurrentMode = (CurrentMode & (M_CEOL | S_BCOLORED)) | C_ASCII; + for (i = CurColumn; i < COLS; i++) + addch(' '); + move(cli, cco); + CurrentMode = pr; +} + +void +clrtoeolx(void) +{ + clrtoeol_with_bcolor(); +} +#else /* not USE_BG_COLOR */ + +void +clrtoeolx(void) +{ + clrtoeol(); +} +#endif /* not USE_BG_COLOR */ + +void +clrtobot_eol(void (*clrtoeol) ()) +{ + int l, c; + + l = CurLine; + c = CurColumn; + (*clrtoeol) (); + CurColumn = 0; + CurLine++; + for (; CurLine < LINES; CurLine++) + (*clrtoeol) (); + CurLine = l; + CurColumn = c; +} + +void +clrtobot(void) +{ + clrtobot_eol(clrtoeol); +} + +void +clrtobotx(void) +{ + clrtobot_eol(clrtoeolx); +} + +#if 0 +void +no_clrtoeol(void) +{ + int i; + l_prop *lprop = ScreenImage[CurLine]->lineprop; + + ScreenImage[CurLine]->isdirty &= ~L_CLRTOEOL; +} +#endif /* 0 */ + +void +addstr(char *s) +{ +#ifdef USE_M17N + int len; + + while (*s != '\0') { + len = wtf_len((wc_uchar *) s); + addmch(s, len); + s += len; + } +#else + while (*s != '\0') + addch(*(s++)); +#endif +} + +void +addnstr(char *s, int n) +{ + int i; +#ifdef USE_M17N + int len, width; + + for (i = 0; *s != '\0';) { + width = wtf_width((wc_uchar *) s); + if (i + width > n) + break; + len = wtf_len((wc_uchar *) s); + addmch(s, len); + s += len; + i += width; + } +#else + for (i = 0; i < n && *s != '\0'; i++) + addch(*(s++)); +#endif +} + +void +addnstr_sup(char *s, int n) +{ + int i; +#ifdef USE_M17N + int len, width; + + for (i = 0; *s != '\0';) { + width = wtf_width((wc_uchar *) s); + if (i + width > n) + break; + len = wtf_len((wc_uchar *) s); + addmch(s, len); + s += len; + i += width; + } +#else + for (i = 0; i < n && *s != '\0'; i++) + addch(*(s++)); +#endif + for (; i < n; i++) + addch(' '); +} + +void +crmode(void) +#ifndef HAVE_SGTTY_H +{ + ttymode_reset(ICANON, IXON); + ttymode_set(ISIG, 0); +#ifdef HAVE_TERMIOS_H + set_cc(VMIN, 1); +#else /* not HAVE_TERMIOS_H */ + set_cc(VEOF, 1); +#endif /* not HAVE_TERMIOS_H */ +} +#else /* HAVE_SGTTY_H */ +{ + ttymode_set(CBREAK, 0); +} +#endif /* HAVE_SGTTY_H */ + +void +nocrmode(void) +#ifndef HAVE_SGTTY_H +{ + ttymode_set(ICANON, 0); +#ifdef HAVE_TERMIOS_H + set_cc(VMIN, 4); +#else /* not HAVE_TERMIOS_H */ + set_cc(VEOF, 4); +#endif /* not HAVE_TERMIOS_H */ +} +#else /* HAVE_SGTTY_H */ +{ + ttymode_reset(CBREAK, 0); +} +#endif /* HAVE_SGTTY_H */ + +void +term_echo(void) +{ + ttymode_set(ECHO, 0); +} + +void +term_noecho(void) +{ + ttymode_reset(ECHO, 0); +} + +void +term_raw(void) +#ifndef HAVE_SGTTY_H +#ifdef IEXTEN +#define TTY_MODE ISIG|ICANON|ECHO|IEXTEN +#else /* not IEXTEN */ +#define TTY_MODE ISIG|ICANON|ECHO +#endif /* not IEXTEN */ +{ + ttymode_reset(TTY_MODE, IXON | IXOFF); +#ifdef HAVE_TERMIOS_H + set_cc(VMIN, 1); +#else /* not HAVE_TERMIOS_H */ + set_cc(VEOF, 1); +#endif /* not HAVE_TERMIOS_H */ +} +#else /* HAVE_SGTTY_H */ +{ + ttymode_set(RAW, 0); +} +#endif /* HAVE_SGTTY_H */ + +void +term_cooked(void) +#ifndef HAVE_SGTTY_H +{ +#ifdef __EMX__ + /* On XFree86/OS2, some scrambled characters + * will appear when asserting IEXTEN flag. + */ + ttymode_set((TTY_MODE) & ~IEXTEN, 0); +#else + ttymode_set(TTY_MODE, 0); +#endif +#ifdef HAVE_TERMIOS_H + set_cc(VMIN, 4); +#else /* not HAVE_TERMIOS_H */ + set_cc(VEOF, 4); +#endif /* not HAVE_TERMIOS_H */ +} +#else /* HAVE_SGTTY_H */ +{ + ttymode_reset(RAW, 0); +} +#endif /* HAVE_SGTTY_H */ + +void +term_cbreak(void) +{ + term_cooked(); + term_noecho(); +} + +void +term_title(char *s) +{ + if (!fmInitialized) + return; + if (title_str != NULL) { +#ifdef __CYGWIN__ + if (isLocalConsole && title_str == CYGWIN_TITLE) { + Str buff; + buff = Sprintf(title_str, s); + if (buff->length > 1024) { + Strtruncate(buff, 1024); + } + SetConsoleTitle(buff->ptr); + } + else if (isLocalConsole || !isWinConsole) +#endif + fprintf(ttyf, title_str, s); + } +} + +char +getch(void) +{ + char c; + + while ( +#ifdef SUPPORT_WIN9X_CONSOLE_MBCS + read_win32_console(&c, 1) +#else + read(tty, &c, 1) +#endif + < (int)1) { + if (errno == EINTR || errno == EAGAIN) + continue; + /* error happend on read(2) */ + quitfm(); + break; /* unreachable */ + } + return c; +} + +#ifdef USE_MOUSE +#ifdef USE_GPM +char +wgetch(void *p) +{ + char c; + + /* read(tty, &c, 1); */ + while (read(tty, &c, 1) < (ssize_t) 1) { + if (errno == EINTR || errno == EAGAIN) + continue; + /* error happend on read(2) */ + quitfm(); + break; /* unreachable */ + } + return c; +} + +int +do_getch() +{ + if (is_xterm) + return getch(); + else + return Gpm_Getch(); +} +#endif /* USE_GPM */ + +#ifdef USE_SYSMOUSE +int +sysm_getch() +{ + fd_set rfd; + int key, x, y; + + FD_ZERO(&rfd); + FD_SET(tty, &rfd); + while (select(tty + 1, &rfd, NULL, NULL, NULL) <= 0) { + if (errno == EINTR) { + x = xpix / cwidth; + y = ypix / cheight; + key = (*sysm_handler) (x, y, nbs, obs); + if (key != 0) + return key; + } + } + return getch(); +} + +int +do_getch() +{ + if (is_xterm || !sysm_handler) + return getch(); + else + return sysm_getch(); +} + +MySignalHandler +sysmouse(SIGNAL_ARG) +{ + struct mouse_info mi; + + mi.operation = MOUSE_GETINFO; + if (ioctl(tty, CONS_MOUSECTL, &mi) == -1) + return; + xpix = mi.u.data.x; + ypix = mi.u.data.y; + obs = nbs; + nbs = mi.u.data.buttons & 0x7; + /* for cosmetic bug in syscons.c on FreeBSD 3.[34] */ + mi.operation = MOUSE_HIDE; + ioctl(tty, CONS_MOUSECTL, &mi); + mi.operation = MOUSE_SHOW; + ioctl(tty, CONS_MOUSECTL, &mi); +} +#endif /* USE_SYSMOUSE */ +#endif /* USE_MOUSE */ + +void +bell(void) +{ + write1(7); +} + +void +skip_escseq(void) +{ + int c; + + c = getch(); + if (c == '[' || c == 'O') { + c = getch(); +#ifdef USE_MOUSE + if (is_xterm && c == 'M') { + getch(); + getch(); + getch(); + } + else +#endif + while (IS_DIGIT(c)) + c = getch(); + } +} + +int +sleep_till_anykey(int sec, int purge) +{ + fd_set rfd; + struct timeval tim; + int er, c, ret; + TerminalMode ioval; + + TerminalGet(tty, &ioval); + term_raw(); + + tim.tv_sec = sec; + tim.tv_usec = 0; + + FD_ZERO(&rfd); + FD_SET(tty, &rfd); + + ret = select(tty + 1, &rfd, 0, 0, &tim); + if (ret > 0 && purge) { + c = getch(); + if (c == ESC_CODE) + skip_escseq(); + } + er = TerminalSet(tty, &ioval); + if (er == -1) { + printf("Error occured: errno=%d\n", errno); + reset_exit(SIGNAL_ARGLIST); + } + return ret; +} + +#ifdef USE_MOUSE + +#define XTERM_ON {fputs("\033[?1001s\033[?1000h",ttyf); flush_tty();} +#define XTERM_OFF {fputs("\033[?1000l\033[?1001r",ttyf); flush_tty();} +#define CYGWIN_ON {fputs("\033[?1000h",ttyf); flush_tty();} +#define CYGWIN_OFF {fputs("\033[?1000l",ttyf); flush_tty();} + +#ifdef USE_GPM +/* Linux console with GPM support */ + +void +mouse_init() +{ + Gpm_Connect conn; + extern int gpm_process_mouse(Gpm_Event *, void *); + int r; + + if (mouseActive) + return; + conn.eventMask = ~0; + conn.defaultMask = 0; + conn.maxMod = 0; + conn.minMod = 0; + + r = Gpm_Open(&conn, 0); + if (r == -2) { + /* + * If Gpm_Open() success, returns >= 0 + * Gpm_Open() returns -2 in case of xterm. + * Gpm_Close() is necessary here. Otherwise, + * xterm is being left in the mode where the mouse clicks are + * passed through to the application. + */ + Gpm_Close(); + is_xterm = (NEED_XTERM_ON | NEED_XTERM_OFF); + } + else if (r >= 0) { + gpm_handler = gpm_process_mouse; + is_xterm = 0; + } + if (is_xterm) { + XTERM_ON; + } + mouseActive = 1; +} + +void +mouse_end() +{ + if (mouseActive == 0) + return; + if (is_xterm) { + XTERM_OFF; + } + else + Gpm_Close(); + mouseActive = 0; +} + +#elif defined(USE_SYSMOUSE) +/* *BSD console with sysmouse support */ +void +mouse_init() +{ + mouse_info_t mi; + extern int sysm_process_mouse(); + + if (mouseActive) + return; + if (is_xterm) { + XTERM_ON; + } + else { +#if defined(FBIO_MODEINFO) || defined(CONS_MODEINFO) /* FreeBSD > 2.x */ +#ifndef FBIO_GETMODE /* FreeBSD 3.x */ +#define FBIO_GETMODE CONS_GET +#define FBIO_MODEINFO CONS_MODEINFO +#endif /* FBIO_GETMODE */ + video_info_t vi; + + if (ioctl(tty, FBIO_GETMODE, &vi.vi_mode) != -1 && + ioctl(tty, FBIO_MODEINFO, &vi) != -1) { + cwidth = vi.vi_cwidth; + cheight = vi.vi_cheight; + } +#endif /* defined(FBIO_MODEINFO) || + * defined(CONS_MODEINFO) */ + mySignal(SIGUSR2, SIG_IGN); + mi.operation = MOUSE_MODE; + mi.u.mode.mode = 0; + mi.u.mode.signal = SIGUSR2; + sysm_handler = NULL; + if (ioctl(tty, CONS_MOUSECTL, &mi) != -1) { + mySignal(SIGUSR2, sysmouse); + mi.operation = MOUSE_SHOW; + ioctl(tty, CONS_MOUSECTL, &mi); + sysm_handler = sysm_process_mouse; + } + } + mouseActive = 1; +} + +void +mouse_end() +{ + if (mouseActive == 0) + return; + if (is_xterm) { + XTERM_OFF; + } + else { + mouse_info_t mi; + mi.operation = MOUSE_MODE; + mi.u.mode.mode = 0; + mi.u.mode.signal = 0; + ioctl(tty, CONS_MOUSECTL, &mi); + } + mouseActive = 0; +} + +#else +/* not GPM nor SYSMOUSE, but use mouse with xterm */ + +void +mouse_init() +{ + if (mouseActive) + return; + if (is_xterm & NEED_XTERM_ON) { + XTERM_ON; + } +#ifdef __CYGWIN__ + else if (is_xterm & NEED_CYGWIN_ON) { + CYGWIN_ON; + } +#endif + mouseActive = 1; +} + +void +mouse_end() +{ + if (mouseActive == 0) + return; + if (is_xterm & NEED_XTERM_OFF) { + XTERM_OFF; + } +#ifdef __CYGWIN__ + else if (is_xterm & NEED_CYGWIN_OFF) { + CYGWIN_OFF; + } +#endif + mouseActive = 0; +} + +#endif /* not USE_GPM nor USE_SYSMOUSE */ + + +void +mouse_active() +{ + if (!mouseActive) + mouse_init(); +} + +void +mouse_inactive() +{ + if (mouseActive && is_xterm) + mouse_end(); +} + +#endif /* USE_MOUSE */ + +void +flush_tty() +{ + if (ttyf) + fflush(ttyf); +} + +#ifdef USE_IMAGE +void +touch_cursor() +{ +#ifdef USE_M17N + int i; +#endif + touch_line(); +#ifdef USE_M17N + for (i = CurColumn; i >= 0; i--) { + touch_column(i); + if (CHMODE(ScreenImage[CurLine]->lineprop[i]) != C_WCHAR2) + break; + } + for (i = CurColumn + 1; i < COLS; i++) { + if (CHMODE(ScreenImage[CurLine]->lineprop[i]) != C_WCHAR2) + break; + touch_column(i); + } +#else + touch_column(CurColumn); +#endif +} +#endif + +#ifdef __MINGW32_VERSION + +int tgetent(char *bp, char *name) +{ + return 0; +} + +int tgetnum(char *id) +{ + return -1; +} + +int tgetflag(char *id) +{ + return 0; +} + +char *tgetstr(char *id, char **area) +{ + id = ""; +} + +char *tgoto(char *cap, int col, int row) +{ +} + +int tputs(char *str, int affcnt, int (*putc)(char)) +{ +} + +char *ttyname(int tty) +{ + return "CON"; +} + +#endif /* __MINGW32_VERSION */