aboutsummaryrefslogtreecommitdiffstats
path: root/debian/patches
diff options
context:
space:
mode:
authorTatsuya Kinoshita <tats@vega.ocn.ne.jp>2011-05-04 07:38:07 +0000
committerTatsuya Kinoshita <tats@vega.ocn.ne.jp>2011-05-04 07:38:07 +0000
commitfa32682a5bfdd176e582cf6128a3c40c1c0cd189 (patch)
treee53c179239dcfb65582c3bb844896b678c9f61cd /debian/patches
parentReleasing debian version 0.5.2-6 (diff)
downloadw3m-fa32682a5bfdd176e582cf6128a3c40c1c0cd189.tar.gz
w3m-fa32682a5bfdd176e582cf6128a3c40c1c0cd189.zip
Releasing debian version 0.5.2-7debian/0.5.2-7
Diffstat (limited to '')
-rw-r--r--debian/patches/100_download-error-short-write.patch188
-rw-r--r--debian/patches/110_no-graph-restriction.patch11756
-rw-r--r--debian/patches/120_config-file-handling.patch38
-rw-r--r--debian/patches/130_rc-blank-line-fix.patch23
-rw-r--r--debian/patches/140_pseudo-inlines.patch75
-rw-r--r--debian/patches/150_numbered-links.patch163
-rw-r--r--debian/patches/160_tls-sni.patch18
-rw-r--r--debian/patches/170_number-prefix.patch39
-rw-r--r--debian/patches/180_non-xterm.patch32
-rw-r--r--debian/patches/190_codepage.patch196
-rw-r--r--debian/patches/series10
11 files changed, 12538 insertions, 0 deletions
diff --git a/debian/patches/100_download-error-short-write.patch b/debian/patches/100_download-error-short-write.patch
new file mode 100644
index 0000000..d1af5aa
--- /dev/null
+++ b/debian/patches/100_download-error-short-write.patch
@@ -0,0 +1,188 @@
+Description: Tell a download failure when full disk
+Origin: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=185006#22
+Author: Karsten Schoelzel <kuser@gmx.de>
+Bug-Debian: http://bugs.debian.org/185006
+
+diff -urNp w3m-0.5.2.orig/file.c w3m-0.5.2/file.c
+--- w3m-0.5.2.orig/file.c 2007-05-24 00:06:05.000000000 +0900
++++ w3m-0.5.2/file.c 2010-07-07 22:12:03.000000000 +0900
+@@ -7749,7 +7749,13 @@ save2tmp(URLFile uf, char *tmpf)
+ {
+ Str buf = Strnew_size(SAVE_BUF_SIZE);
+ while (UFread(&uf, buf, SAVE_BUF_SIZE)) {
+- Strfputs(buf, ff);
++ if (Strfputs(buf, ff) != buf->length) {
++ bcopy(env_bak, AbortLoading, sizeof(JMP_BUF));
++ TRAP_OFF;
++ fclose(ff);
++ current_content_length = 0;
++ return -2;
++ }
+ linelen += buf->length;
+ showProgress(&linelen, &trbyte);
+ }
+@@ -8078,16 +8084,20 @@ doFileSave(URLFile uf, char *defstr)
+ flush_tty();
+ pid = fork();
+ if (!pid) {
++ int err;
+ if ((uf.content_encoding != CMP_NOCOMPRESS) && AutoUncompress) {
+ uncompress_stream(&uf, &tmpf);
+ if (tmpf)
+ unlink(tmpf);
+ }
+ setup_child(FALSE, 0, UFfileno(&uf));
+- if (!save2tmp(uf, p) && PreserveTimestamp && uf.modtime != -1)
++ err = save2tmp(uf, p);
++ if (err == 0 && PreserveTimestamp && uf.modtime != -1)
+ setModtime(p, uf.modtime);
+ UFclose(&uf);
+ unlink(lock);
++ if (err != 0)
++ exit(-err);
+ exit(0);
+ }
+ addDownloadList(pid, uf.url, p, lock, current_content_length);
+diff -urNp 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-07 21:51:07.000000000 +0900
+@@ -517,7 +517,8 @@ typedef struct _DownloadList {
+ char *lock;
+ clen_t size;
+ time_t time;
+- int ok;
++ int running;
++ int err;
+ struct _DownloadList *next;
+ struct _DownloadList *prev;
+ } DownloadList;
+diff -urNp 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-07 21:51:07.000000000 +0900
+@@ -323,21 +323,26 @@ static void
+ sig_chld(int signo)
+ {
+ int p_stat;
+-#ifdef HAVE_WAITPID
+ pid_t pid;
+
++#ifdef HAVE_WAITPID
+ 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);
++ if ((pid = wait(&p_stat)) > 0) {
+ #endif
++ DownloadList *d;
++
++ if (WIFEXITED(p_stat)) {
++ for (d = FirstDL; d != NULL; d = d->next) {
++ if (d->pid == pid) {
++ d->err = WEXITSTATUS(p_stat);
++ break;
++ }
++ }
++ }
++ }
+ mySignal(SIGCHLD, sig_chld);
+ return;
+ }
+@@ -6355,7 +6360,8 @@ addDownloadList(pid_t pid, char *url, ch
+ d->lock = lock;
+ d->size = size;
+ d->time = time(0);
+- d->ok = FALSE;
++ d->running = TRUE;
++ d->err = 0;
+ d->next = NULL;
+ d->prev = LastDL;
+ if (LastDL)
+@@ -6375,7 +6381,7 @@ checkDownloadList(void)
+ if (!FirstDL)
+ return FALSE;
+ for (d = FirstDL; d != NULL; d = d->next) {
+- if (!d->ok && !lstat(d->lock, &st))
++ if (d->running && !lstat(d->lock, &st))
+ return TRUE;
+ }
+ return FALSE;
+@@ -6415,15 +6421,16 @@ DownloadListBuffer(void)
+ "<form method=internal action=download><hr>\n");
+ for (d = LastDL; d != NULL; d = d->prev) {
+ if (lstat(d->lock, &st))
+- d->ok = TRUE;
++ d->running = FALSE;
+ Strcat_charp(src, "<pre>\n");
+ Strcat(src, Sprintf("%s\n --&gt; %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;
++ if (!d->running) {
++ if (!d->err)
++ d->size = size;
+ duration = st.st_mtime - d->time;
+ }
+ }
+@@ -6442,7 +6449,7 @@ DownloadListBuffer(void)
+ Strcat_char(src, '_');
+ Strcat_char(src, '\n');
+ }
+- if (!d->ok && size < d->size)
++ if ((d->running || d->err) && size < d->size)
+ Strcat(src, Sprintf(" %s / %s bytes (%d%%)",
+ convert_size3(size), convert_size3(d->size),
+ (int)(100.0 * size / d->size)));
+@@ -6453,20 +6460,28 @@ DownloadListBuffer(void)
+ 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) {
++ if (d->running && 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) {
++ if (!d->running) {
+ Strcat(src, Sprintf("<input type=submit name=ok%d value=OK>",
+ d->pid));
+- if (size < d->size)
+- Strcat_charp(src, " Download incompleted");
+- else
+- Strcat_charp(src, " Download completed");
++ switch (d->err) {
++ case 0: if (size < d->size)
++ Strcat_charp(src, " Download ended but probably not complete");
++ else
++ Strcat_charp(src, " Download complete");
++ break;
++ case 1: Strcat_charp(src, " Error: could not open destination file");
++ break;
++ case 2: Strcat_charp(src, " Error: could not write to file (disk full)");
++ break;
++ default: Strcat_charp(src, " Error: unknown reason");
++ }
+ }
+ else
+ Strcat(src, Sprintf("<input type=submit name=stop%d value=STOP>",
+@@ -6520,7 +6535,7 @@ stopDownload(void)
+ if (!FirstDL)
+ return;
+ for (d = FirstDL; d != NULL; d = d->next) {
+- if (d->ok)
++ if (!d->running)
+ continue;
+ #ifndef __MINGW32_VERSION
+ kill(d->pid, SIGKILL);
diff --git a/debian/patches/110_no-graph-restriction.patch b/debian/patches/110_no-graph-restriction.patch
new file mode 100644
index 0000000..2e0f499
--- /dev/null
+++ b/debian/patches/110_no-graph-restriction.patch
@@ -0,0 +1,11756 @@
+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 <kuser@gmx.de>
+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 <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#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 <gc.h>
++#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 <locale.h>
++#endif
++#if !HAVE_SETLOCALE
++#define setlocale(category, locale) /* empty */
++#endif
++
++#ifdef ENABLE_NLS
++#include <libintl.h>
++#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 <strings.h> /* for bzero() and bcopy() */
++#endif
++
++#ifdef MAINPROGRAM
++#define global
++#define init(x) =(x)
++#else /* not MAINPROGRAM */
++#define global extern
++#define init(x)
++#endif /* not MAINPROGRAM */
++
++#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 /* <! */
++#define R_ST_CMNT2 9 /* <!- */
++#define R_ST_CMNT 10 /* within comment */
++#define R_ST_NCMNT1 11 /* comment - */
++#define R_ST_NCMNT2 12 /* comment -- */
++#define R_ST_NCMNT3 13 /* comment -- space */
++#define R_ST_IRRTAG 14 /* within irregular tag */
++#define R_ST_VALUE 15 /* within tag attribule value */
++
++#define ST_IS_REAL_TAG(s) ((s)==R_ST_TAG||(s)==R_ST_TAG0||(s)==R_ST_EQL||(s)==R_ST_VALUE)
++
++/* is this '<' really means the beginning of a tag? */
++#define REALLY_THE_BEGINNING_OF_A_TAG(p) \
++ (IS_ALPHA(p[1]) || p[1] == '/' || p[1] == '!' || p[1] == '?' || p[1] == '\0' || p[1] == '_')
++
++/* flags for loadGeneralFile */
++#define RG_NOCACHE 1
++#define RG_FRAME 2
++#define RG_FRAME_SRC 4
++
++struct html_feed_environ {
++ struct readbuffer *obuf;
++ TextLineList *buf;
++ FILE *f;
++ Str tagbuf;
++ int limit;
++ int maxlimit;
++ struct environment *envs;
++ int nenv;
++ int envc;
++ int envc_real;
++ char *title;
++ int blank_lines;
++};
++
++#ifdef USE_COOKIE
++struct portlist {
++ unsigned short port;
++ struct portlist *next;
++};
++
++struct cookie {
++ ParsedURL url;
++ Str name;
++ Str value;
++ time_t expires;
++ Str path;
++ Str domain;
++ Str comment;
++ Str commentURL;
++ struct portlist *portl;
++ char version;
++ char flag;
++ struct cookie *next;
++};
++#define COO_USE 1
++#define COO_SECURE 2
++#define COO_DOMAIN 4
++#define COO_PATH 8
++#define COO_DISCARD 16
++#define COO_OVERRIDE 32 /* user chose to override security checks */
++
++#define COO_OVERRIDE_OK 32 /* flag to specify that an error is overridable */
++ /* version 0 refers to the original cookie_spec.html */
++ /* version 1 refers to RFC 2109 */
++ /* version 1' refers to the Internet draft to obsolete RFC 2109 */
++#define COO_EINTERNAL (1) /* unknown error; probably forgot to convert "return 1" in cookie.c */
++#define COO_ETAIL (2 | COO_OVERRIDE_OK) /* tail match failed (version 0) */
++#define COO_ESPECIAL (3) /* special domain check failed (version 0) */
++#define COO_EPATH (4) /* Path attribute mismatch (version 1 case 1) */
++#define COO_ENODOT (5 | COO_OVERRIDE_OK) /* no embedded dots in Domain (version 1 case 2.1) */
++#define COO_ENOTV1DOM (6 | COO_OVERRIDE_OK) /* Domain does not start with a dot (version 1 case 2.2) */
++#define COO_EDOM (7 | COO_OVERRIDE_OK) /* domain-match failed (version 1 case 3) */
++#define COO_EBADHOST (8 | COO_OVERRIDE_OK) /* dot in matched host name in FQDN (version 1 case 4) */
++#define COO_EPORT (9) /* Port match failed (version 1' case 5) */
++#define COO_EMAX COO_EPORT
++#endif /* USE_COOKIE */
++
++/* modes for align() */
++
++#define ALIGN_CENTER 0
++#define ALIGN_LEFT 1
++#define ALIGN_RIGHT 2
++#define ALIGN_MIDDLE 4
++#define ALIGN_TOP 5
++#define ALIGN_BOTTOM 6
++
++#define VALIGN_MIDDLE 0
++#define VALIGN_TOP 1
++#define VALIGN_BOTTOM 2
++
++typedef struct http_request {
++ char command;
++ char flag;
++ char *referer;
++ FormList *request;
++} HRequest;
++
++#define HR_COMMAND_GET 0
++#define HR_COMMAND_POST 1
++#define HR_COMMAND_CONNECT 2
++#define HR_COMMAND_HEAD 3
++
++#define HR_FLAG_LOCAL 1
++#define HR_FLAG_PROXY 2
++
++#define HTST_UNKNOWN 255
++#define HTST_MISSING 254
++#define HTST_NORMAL 0
++#define HTST_CONNECT 1
++
++#define TMPF_DFL 0
++#define TMPF_SRC 1
++#define TMPF_FRAME 2
++#define TMPF_CACHE 3
++#define TMPF_COOKIE 4
++#define MAX_TMPF_TYPE 5
++
++#define set_no_proxy(domains) (NO_proxy_domains=make_domain_list(domains))
++
++/*
++ * Globals.
++ */
++
++extern int LINES, COLS;
++#if defined(__CYGWIN__)
++extern int LASTLINE;
++#else /* not defined(__CYGWIN__) */
++#define LASTLINE (LINES-1)
++#endif /* not defined(__CYGWIN__) */
++
++global int Tabstop init(8);
++global int IndentIncr init(4);
++global int ShowEffect init(TRUE);
++global int PagerMax init(PAGER_MAX_LINE);
++
++global char SearchHeader init(FALSE);
++global char *DefaultType init(NULL);
++global char RenderFrame init(FALSE);
++global char TargetSelf init(FALSE);
++global char PermitSaveToPipe init(FALSE);
++global char DecodeCTE init(FALSE);
++global char AutoUncompress init(FALSE);
++global char PreserveTimestamp init(TRUE);
++global char ArgvIsURL init(FALSE);
++global char MetaRefresh init(FALSE);
++
++global char fmInitialized init(FALSE);
++global char QuietMessage init(FALSE);
++global char TrapSignal init(TRUE);
++#define TRAP_ON if (TrapSignal) { \
++ prevtrap = mySignal(SIGINT, KeyAbort); \
++ if (fmInitialized) \
++ term_cbreak(); \
++}
++#define TRAP_OFF if (TrapSignal) { \
++ if (fmInitialized) \
++ term_raw(); \
++ if (prevtrap) \
++ mySignal(SIGINT, prevtrap); \
++}
++
++extern unsigned char GlobalKeymap[];
++extern unsigned char EscKeymap[];
++extern unsigned char EscBKeymap[];
++extern unsigned char EscDKeymap[];
++#ifdef __EMX__
++extern unsigned char PcKeymap[];
++#endif
++extern FuncList w3mFuncList[];
++
++global char *HTTP_proxy init(NULL);
++#ifdef USE_SSL
++global char *HTTPS_proxy init(NULL);
++#endif /* USE_SSL */
++#ifdef USE_GOPHER
++global char *GOPHER_proxy init(NULL);
++#endif /* USE_GOPHER */
++global char *FTP_proxy init(NULL);
++global ParsedURL HTTP_proxy_parsed;
++#ifdef USE_SSL
++global ParsedURL HTTPS_proxy_parsed;
++#endif /* USE_SSL */
++#ifdef USE_GOPHER
++global ParsedURL GOPHER_proxy_parsed;
++#endif /* USE_GOPHER */
++global ParsedURL FTP_proxy_parsed;
++global char *NO_proxy init(NULL);
++global int NOproxy_netaddr init(TRUE);
++#ifdef INET6
++#define DNS_ORDER_UNSPEC 0
++#define DNS_ORDER_INET_INET6 1
++#define DNS_ORDER_INET6_INET 2
++#define DNS_ORDER_INET_ONLY 4
++#define DNS_ORDER_INET6_ONLY 6
++global int DNS_order init(DNS_ORDER_UNSPEC);
++extern int ai_family_order_table[7][3]; /* XXX */
++#endif /* INET6 */
++global TextList *NO_proxy_domains;
++global char NoCache init(FALSE);
++global char use_proxy init(TRUE);
++#define Do_not_use_proxy (!use_proxy)
++global int Do_not_use_ti_te init(FALSE);
++#ifdef USE_NNTP
++global char *NNTP_server init(NULL);
++global char *NNTP_mode init(NULL);
++global int MaxNewsMessage init(50);
++#endif
++
++global char *document_root init(NULL);
++global char *personal_document_root init(NULL);
++global char *cgi_bin init(NULL);
++global char *index_file init(NULL);
++
++global char *CurrentDir;
++global int CurrentPid;
++/*
++ * global Buffer *Currentbuf;
++ * global Buffer *Firstbuf;
++ */
++global TabBuffer *CurrentTab;
++global TabBuffer *FirstTab;
++global TabBuffer *LastTab;
++global int open_tab_blank init(FALSE);
++global int open_tab_dl_list init(FALSE);
++global int close_tab_back init(FALSE);
++global int nTab;
++global int TabCols init(10);
++#define NO_TABBUFFER ((TabBuffer *)1)
++#define Currentbuf (CurrentTab->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 <signal.h>
++#include <setjmp.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <unistd.h>
++#include <fcntl.h>
++#if defined(HAVE_WAITPID) || defined(HAVE_WAIT3)
++#include <sys/wait.h>
++#endif
++#include <time.h>
++#include "terms.h"
++#include "myctype.h"
++#include "regex.h"
++#ifdef USE_MOUSE
++#ifdef USE_GPM
++#include <gpm.h>
++#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 <winsock.h>
++
++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, " +<num> goto <num> 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
++ ("<title>W3M startup page</title><center><b>Welcome to ");
++ Strcat_charp(s_page, "<a href='http://w3m.sourceforge.net/'>");
++ Strcat_m_charp(s_page,
++ "w3m</a>!<p><p>This is w3m version ",
++ w3m_version,
++ "<br>Written by <a href='mailto:aito@fw.ipsj.or.jp'>Akinori Ito</a>",
++ NULL);
++#ifdef DEBIAN
++ Strcat_m_charp(s_page,
++ "<p>Debian package is maintained by <a href='mailto:ukai@debian.or.jp'>Fumitoshi UKAI</a>.",
++ "You can read <a href='file:///usr/share/doc/w3m/'>w3m documents on your local system</a>.",
++ 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 <g96p0935@mse.waseda.ac.jp> 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 <frameset> 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;
++ /* <ISINDEX> 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("<html><head><title>" DOWNLOAD_LIST_TITLE
++ "</title></head>\n<body><h1 align=center>"
++ DOWNLOAD_LIST_TITLE "</h1>\n"
++ "<form method=internal action=download><hr>\n");
++ for (d = LastDL; d != NULL; d = d->prev) {
++ if (lstat(d->lock, &st))
++ d->ok = TRUE;
++ Strcat_charp(src, "<pre>\n");
++ Strcat(src, Sprintf("%s\n --&gt; %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("<input type=submit name=ok%d value=OK>",
++ d->pid));
++ if (size < d->size)
++ Strcat_charp(src, " Download incompleted");
++ else
++ Strcat_charp(src, " Download completed");
++ }
++ else
++ Strcat(src, Sprintf("<input type=submit name=stop%d value=STOP>",
++ d->pid));
++ Strcat_charp(src, "\n</pre><hr>\n");
++ }
++ Strcat_charp(src, "</form></body></html>");
++ 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 = &top;
++ 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 <stdio.h>
++#include <errno.h>
++#include "parsetag.h"
++#include "local.h"
++#include <stdlib.h>
++
++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 = &sections[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[] =
++ "<html><head><title>Option Setting Panel</title></head><body>\
++<h1 align=center>Option Setting Panel<br>(w3m version %s)</b></h1>\
++<form method=post action=\"file:///$LIB/" W3MHELPERPANEL_CMDNAME "\">\
++<input type=hidden name=mode value=panel>\
++<input type=hidden name=cookie value=\"%s\">\
++<input type=submit value=\"%s\">\
++</form><br>\
++<form method=internal action=option>";
++
++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, "<table><tr><td>");
++ for (i = 0; sections[i].name != NULL; i++) {
++ Strcat_m_charp(src, "<h1>", sections[i].name, "</h1>", NULL);
++ p = sections[i].params;
++ Strcat_charp(src, "<table width=100% cellpadding=0>");
++ while (p->name) {
++ Strcat_m_charp(src, "<tr><td>", p->comment, NULL);
++ Strcat(src, Sprintf("</td><td width=%d>",
++ (int)(28 * pixel_per_char)));
++ switch (p->inputtype) {
++ case PI_TEXT:
++ Strcat_m_charp(src, "<input type=text name=",
++ p->name,
++ " value=\"",
++ html_quote(to_str(p)->ptr), "\">", NULL);
++ break;
++ case PI_ONOFF:
++ x = atoi(to_str(p)->ptr);
++ Strcat_m_charp(src, "<input type=radio name=",
++ p->name,
++ " value=1",
++ (x ? " checked" : ""),
++ ">YES&nbsp;&nbsp;<input type=radio name=",
++ p->name,
++ " value=0", (x ? "" : " checked"), ">NO", NULL);
++ break;
++ case PI_SEL_C:
++ tmp = to_str(p);
++ Strcat_m_charp(src, "<select name=", p->name, ">", NULL);
++ for (s = (struct sel_c *)p->select; s->text != NULL; s++) {
++ Strcat_charp(src, "<option value=");
++ Strcat(src, Sprintf("%s\n", s->cvalue));
++ if ((p->type != P_CHAR && s->value == atoi(tmp->ptr)) ||
++ (p->type == P_CHAR && (char)s->value == *(tmp->ptr)))
++ Strcat_charp(src, " selected");
++ Strcat_char(src, '>');
++ Strcat_charp(src, s->text);
++ }
++ Strcat_charp(src, "</select>");
++ break;
++#ifdef USE_M17N
++ case PI_CODE:
++ tmp = to_str(p);
++ Strcat_m_charp(src, "<select name=", p->name, ">", NULL);
++ for (c = *(wc_ces_list **) p->select; c->desc != NULL; c++) {
++ Strcat_charp(src, "<option value=");
++ Strcat(src, Sprintf("%s\n", c->name));
++ if (c->id == atoi(tmp->ptr))
++ Strcat_charp(src, " selected");
++ Strcat_char(src, '>');
++ Strcat_charp(src, c->desc);
++ }
++ Strcat_charp(src, "</select>");
++ break;
++#endif
++ }
++ Strcat_charp(src, "</td></tr>\n");
++ p++;
++ }
++ Strcat_charp(src,
++ "<tr><td></td><td><p><input type=submit value=\"OK\"></td></tr>");
++ Strcat_charp(src, "</table><hr width=50%>");
++ }
++ Strcat_charp(src, "</table></form></body></html>");
++ 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 <stdio.h>
++#include <signal.h>
++#include <sys/types.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <sys/time.h>
++#include <unistd.h>
++#include "config.h"
++#include <string.h>
++#ifdef HAVE_SYS_SELECT_H
++#include <sys/select.h>
++#endif
++#ifndef __MINGW32_VERSION
++#include <sys/ioctl.h>
++#else
++#include <winsock.h>
++#endif /* __MINGW32_VERSION */
++#ifdef USE_MOUSE
++#ifdef USE_GPM
++#include <gpm.h>
++#endif /* USE_GPM */
++#ifdef USE_SYSMOUSE
++#include <osreldate.h>
++#if (__FreeBSD_version >= 400017)
++#include <sys/consio.h>
++#include <sys/fbio.h>
++#else
++#include <machine/console.h>
++#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 <os2.h>
++#endif /* __EMX__ */
++
++#if defined(__CYGWIN__)
++#include <windows.h>
++#include <sys/cygwin.h>
++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 <termio.h>
++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 <termios.h>
++#include <unistd.h>
++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 <sgtty.h>
++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 */
diff --git a/debian/patches/120_config-file-handling.patch b/debian/patches/120_config-file-handling.patch
new file mode 100644
index 0000000..ded2c85
--- /dev/null
+++ b/debian/patches/120_config-file-handling.patch
@@ -0,0 +1,38 @@
+Description: Fix segfault when changing options if ~/.w3m not accessible
+Origin: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=366284#5
+Author: Karsten Schoelzel <kuser@gmx.de>
+Bug-Debian: http://bugs.debian.org/366284
+
+diff --git a/rc.c b/rc.c
+index 17f30d8..b88a3fd 100644
+--- a/rc.c
++++ b/rc.c
+@@ -1253,7 +1253,7 @@ init_rc(void)
+ interpret_rc(f);
+ fclose(f);
+ }
+- if ((f = fopen(config_file, "rt")) != NULL) {
++ if (config_file && (f = fopen(config_file, "rt")) != NULL) {
+ interpret_rc(f);
+ fclose(f);
+ }
+@@ -1265,6 +1265,8 @@ init_rc(void)
+ ((tmp_dir = getenv("TMP")) == NULL || *tmp_dir == '\0') &&
+ ((tmp_dir = getenv("TEMP")) == NULL || *tmp_dir == '\0'))
+ tmp_dir = "/tmp";
++ create_option_search_table();
++ goto open_rc;
+ }
+
+
+@@ -1446,8 +1448,8 @@ panel_set_option(struct parsed_tagarg *a
+ FILE *f = NULL;
+ char *p;
+
+- if (no_rc_dir) {
+- disp_message("There's no ~/.w3m directory... config not saved", FALSE);
++ if (config_file == NULL) {
++ disp_message("There's no config file... config not saved", FALSE);
+ }
+ else {
+ f = fopen(config_file, "wt");
diff --git a/debian/patches/130_rc-blank-line-fix.patch b/debian/patches/130_rc-blank-line-fix.patch
new file mode 100644
index 0000000..b4c36c5
--- /dev/null
+++ b/debian/patches/130_rc-blank-line-fix.patch
@@ -0,0 +1,23 @@
+Description: Fix .w3m/config parser confused by blank lines
+Origin: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=537706#10
+Author: "Trent W. Buck" <twb@cybersource.com.au>
+Bug-Debian: http://bugs.debian.org/537706
+
+Index: w3m-0.5.2/rc.c
+===================================================================
+--- w3m-0.5.2.orig/rc.c 2009-07-20 20:48:47.426565387 +1000
++++ w3m-0.5.2/rc.c 2009-07-20 20:49:24.086565581 +1000
+@@ -1061,9 +1061,11 @@
+
+ for (;;) {
+ line = Strfgets(f);
+- Strchop(line);
+- if (line->length == 0)
++ if (line->length == 0) /* end of file */
+ break;
++ Strchop(line);
++ if (line->length == 0) /* blank line */
++ continue;
+ Strremovefirstspaces(line);
+ if (line->ptr[0] == '#') /* comment */
+ continue;
diff --git a/debian/patches/140_pseudo-inlines.patch b/debian/patches/140_pseudo-inlines.patch
new file mode 100644
index 0000000..18cbea1
--- /dev/null
+++ b/debian/patches/140_pseudo-inlines.patch
@@ -0,0 +1,75 @@
+Description: New option "pseudo_inlines"
+ Add option pseudo_inlines (Display pseudo-ALTs for inline images with no
+ ALT or TITLE string) so
+ w3m -o pseudo_inlines=0
+ works like
+ lynx -pseudo_inlines
+ If there is no ALT tag or it is "" and ignore_null_img_alt=1 then use TITLE
+ instead.
+Origin: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=329863#8
+Author: Karsten Schoelzel <kuser@gmx.de>
+Bug-Debian: http://bugs.debian.org/329863
+
+---
+commit 1c2e64c5ba38727f991c9787b95067391a4a0907
+tree 292b46472454ad69dee708029915cef0b0a718da
+parent 1e6c13cac0c2954de5c377fe2120710c7c2b30fe
+author Karsten Schoelzel <kuser@asus.karsten.local> Thu, 04 May 2006 13:05:03 +0200
+committer Karsten Schoelzel <kuser@asus.karsten.local> Thu, 04 May 2006 13:05:03 +0200
+
+ file.c | 7 +++++++
+ fm.h | 1 +
+ rc.c | 3 +++
+ 3 files changed, 11 insertions(+), 0 deletions(-)
+
+diff --git a/file.c b/file.c
+index d067d47..913ac7c 100644
+--- a/file.c
++++ b/file.c
+@@ -3171,6 +3171,13 @@ process_img(struct parsed_tag *tag, int
+ parsedtag_get_value(tag, ATTR_ALT, &q);
+ t = q;
+ parsedtag_get_value(tag, ATTR_TITLE, &t);
++ if (q == NULL || (*q == '\0' && ignore_null_img_alt)) {
++ if (!pseudoInlines && (t == NULL ||
++ (*t == '\0' && ignore_null_img_alt)))
++ return tmp;
++ q = t;
++ }
++
+ w = -1;
+ if (parsedtag_get_value(tag, ATTR_WIDTH, &w)) {
+ if (w < 0) {
+diff --git a/fm.h b/fm.h
+index a593a3f..e10c2a7 100644
+--- a/fm.h
++++ b/fm.h
+@@ -926,6 +926,7 @@ global int image_map_list init(TRUE);
+ #else
+ global int displayImage init(FALSE); /* XXX: emacs-w3m use display_image=off */
+ #endif
++global int pseudoInlines init(TRUE);
+ global char *Editor init(DEF_EDITOR);
+ #ifdef USE_W3MMAILER
+ global char *Mailer init(NULL);
+diff --git a/rc.c b/rc.c
+index 2860a35..5d009bb 100644
+--- a/rc.c
++++ b/rc.c
+@@ -76,6 +76,7 @@ static int OptionEncode = FALSE;
+ #define CMT_DECODE_URL N_("Display decoded URL")
+ #define CMT_DISPLINEINFO N_("Display current line number")
+ #define CMT_DISP_IMAGE N_("Display inline images")
++#define CMT_PSEUDO_INLINES N_("Display pseudo-ALTs for inline images with no ALT or TITLE string")
+ #ifdef USE_IMAGE
+ #define CMT_AUTO_IMAGE N_("Load inline images automatically")
+ #define CMT_MAX_LOAD_IMAGE N_("Maximum processes for parallel image loading")
+@@ -380,6 +381,8 @@ struct param_ptr params1[] = {
+ /* 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},
++ {"pseudo_inlines", P_INT, PI_ONOFF, (void *)&pseudoInlines,
++ CMT_PSEUDO_INLINES, 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,
diff --git a/debian/patches/150_numbered-links.patch b/debian/patches/150_numbered-links.patch
new file mode 100644
index 0000000..45e393a
--- /dev/null
+++ b/debian/patches/150_numbered-links.patch
@@ -0,0 +1,163 @@
+Description: New option "display_link_number"
+Origin: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=329862#30
+Author: Karsten Schoelzel <kuser@gmx.de>
+Bug-Debian: http://bugs.debian.org/329862
+
+diff --git a/file.c b/file.c
+index d537c8d..ea37647 100644
+--- a/file.c
++++ b/file.c
+@@ -1671,6 +1678,12 @@ checkRedirection(ParsedURL *pu)
+ return TRUE;
+ }
+
++Str
++getLinkNumberStr(int correction)
++{
++ return Sprintf("[%d]", cur_hseq + correction);
++}
++
+ /*
+ * loadGeneralFile: load file to buffer
+ */
+@@ -3530,9 +3554,13 @@ process_input(struct parsed_tag *tag)
+ case FORM_INPUT_TEXT:
+ case FORM_INPUT_FILE:
+ case FORM_INPUT_CHECKBOX:
++ if (displayLinkNumber)
++ Strcat(tmp, getLinkNumberStr(0));
+ Strcat_char(tmp, '[');
+ break;
+ case FORM_INPUT_RADIO:
++ if (displayLinkNumber)
++ Strcat(tmp, getLinkNumberStr(0));
+ Strcat_char(tmp, '(');
+ }
+ Strcat(tmp, Sprintf("<input_alt hseq=\"%d\" fid=\"%d\" type=%s "
+@@ -3573,6 +3601,8 @@ process_input(struct parsed_tag *tag)
+ case FORM_INPUT_SUBMIT:
+ case FORM_INPUT_BUTTON:
+ case FORM_INPUT_RESET:
++ if (displayLinkNumber)
++ Strcat(tmp, getLinkNumberStr(-1));
+ Strcat_charp(tmp, "[");
+ break;
+ }
+@@ -3659,9 +3689,12 @@ process_select(struct parsed_tag *tag)
+
+ #ifdef MENU_SELECT
+ if (!select_is_multiple) {
+- select_str = Sprintf("<pre_int>[<input_alt hseq=\"%d\" "
++ select_str = Strnew_charp("<pre_int>");
++ if (displayLinkNumber)
++ Strcat(select_str, getLinkNumberStr(0));
++ Strcat(select_str, Sprintf("[<input_alt hseq=\"%d\" "
+ "fid=\"%d\" type=select name=\"%s\" selectnumber=%d",
+- cur_hseq++, cur_form_id, html_quote(p), n_select);
++ cur_hseq++, cur_form_id, html_quote(p), n_select));
+ Strcat_charp(select_str, ">");
+ if (n_select == max_select) {
+ max_select *= 2;
+@@ -4688,6 +4721,8 @@ HTMLtagproc1(struct parsed_tag *tag, str
+ obuf->anchor.hseq = cur_hseq;
+ tmp = process_anchor(tag, h_env->tagbuf->ptr);
+ push_tag(obuf, tmp->ptr, HTML_A);
++ if (displayLinkNumber)
++ HTMLlineproc1(getLinkNumberStr(-1)->ptr, h_env);
+ return 1;
+ }
+ return 0;
+diff --git a/proto.h b/proto.h
+index 8929580..6f02b5b 100644
+--- a/proto.h
++++ b/proto.h
+@@ -776,6 +777,8 @@ extern void wrapToggle(void);
+ extern void saveBufferInfo(void);
+ #endif
+
++extern Str getLinkNumberStr(int correction);
++
+ extern void dispVer(void);
+
+ #ifdef USE_INCLUDED_SRAND48
+diff --git a/rc.c b/rc.c
+index f57b564..17f30d8 100644
+--- a/rc.c
++++ b/rc.c
+@@ -72,6 +72,7 @@ static int OptionEncode = FALSE;
+ #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_DISPLINKNUMBER N_("Display link numbers")
+ #define CMT_DECODE_URL N_("Display decoded URL")
+ #define CMT_DISPLINEINFO N_("Display current line number")
+ #define CMT_DISP_IMAGE N_("Display inline images")
+@@ -338,6 +357,8 @@ struct param_ptr params1[] = {
+ CMT_OPEN_TAB_DL_LIST, NULL},
+ {"display_link", P_INT, PI_ONOFF, (void *)&displayLink, CMT_DISPLINK,
+ NULL},
++ {"display_link_number", P_INT, PI_ONOFF, (void *)&displayLinkNumber,
++ CMT_DISPLINKNUMBER, NULL},
+ {"decode_url", P_INT, PI_ONOFF, (void *)&DecodeURL, CMT_DECODE_URL, NULL},
+ {"display_lineinfo", P_INT, PI_ONOFF, (void *)&displayLineInfo,
+ CMT_DISPLINEINFO, NULL},
+diff --git a/table.c b/table.c
+index 2024632..94d61d6 100644
+--- a/table.c
++++ b/table.c
+@@ -2937,6 +2937,12 @@ feed_table_tag(struct table *tbl, char *
+ check_rowcol(tbl, mode);
+ if (i == 0) {
+ Str tmp = process_anchor(tag, line);
++ if (displayLinkNumber)
++ {
++ Str t = getLinkNumberStr(-1);
++ feed_table_inline_tag(tbl, NULL, mode, t->length);
++ Strcat(tmp, t);
++ }
+ pushdata(tbl, tbl->row, tbl->col, tmp->ptr);
+ }
+ else
+diff --git a/fm.h b/fm.h
+index 8686866..1a1a60c 100644
+--- a/fm.h
++++ b/fm.h
+@@ -909,6 +909,7 @@ global int label_topline init(FALSE);
+ global int nextpage_topline init(FALSE);
+ global char *displayTitleTerm init(NULL);
+ global int displayLink init(FALSE);
++global int displayLinkNumber init(FALSE);
+ global int displayLineInfo init(FALSE);
+ global int DecodeURL init(FALSE);
+ global int retryAsHttp init(TRUE);
+diff --git a/main.c b/main.c
+index 0d709ef..70c8c1d 100644
+--- a/main.c
++++ b/main.c
+@@ -1239,8 +1239,25 @@ do_dump(Buffer *buf)
+ dump_head(buf);
+ if (w3m_dump & DUMP_SOURCE)
+ dump_source(buf);
+- if (w3m_dump == DUMP_BUFFER)
++ if (w3m_dump == DUMP_BUFFER) {
++ int i;
+ saveBuffer(buf, stdout, FALSE);
++ if (displayLinkNumber && buf->href) {
++ printf("\nReferences:\n\n");
++ for (i = 0; i < buf->href->nanchor; i++) {
++ ParsedURL pu;
++ static Str s = NULL;
++ if (buf->href->anchors[i].slave)
++ continue;
++ parseURL2(buf->href->anchors[i].url, &pu, baseURL(buf));
++ s = parsedURL2Str(&pu);
++ if (DecodeURL)
++ s = Strnew_charp(url_unquote_conv
++ (s->ptr, Currentbuf->document_charset));
++ printf("[%d] %s\n", buf->href->anchors[i].hseq + 1, s->ptr);
++ }
++ }
++ }
+ mySignal(SIGINT, prevtrap);
+ }
+
diff --git a/debian/patches/160_tls-sni.patch b/debian/patches/160_tls-sni.patch
new file mode 100644
index 0000000..0a2e83a
--- /dev/null
+++ b/debian/patches/160_tls-sni.patch
@@ -0,0 +1,18 @@
+Description: Support for TLS SNI (Server Name Indication)
+Origin: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=523159#5
+Author: Sascha Silbe <sascha-debian-bugs-w3m-1@silbe.org>
+Bug-Debian: http://bugs.debian.org/523159
+
+diff -ur w3m-0.5.2/url.c w3m-0.5.2-sni/url.c
+--- w3m-0.5.2/url.c 2007-05-23 17:06:06.000000000 +0200
++++ w3m-0.5.2-sni/url.c 2009-03-11 17:44:51.210620186 +0100
+@@ -374,6 +374,9 @@
+ #if SSLEAY_VERSION_NUMBER >= 0x00905100
+ init_PRNG();
+ #endif /* SSLEAY_VERSION_NUMBER >= 0x00905100 */
++#if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
++ SSL_set_tlsext_host_name(handle,hostname);
++#endif /* (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT) */
+ if (SSL_connect(handle) > 0) {
+ Str serv_cert = ssl_get_certificate(handle, hostname);
+ if (serv_cert) {
diff --git a/debian/patches/170_number-prefix.patch b/debian/patches/170_number-prefix.patch
new file mode 100644
index 0000000..5ad5f13
--- /dev/null
+++ b/debian/patches/170_number-prefix.patch
@@ -0,0 +1,39 @@
+Description: Make number prefixes working when vi_prec_num=0
+ * [w3m-dev 04271] vi_prec_num
+ * main.c: make number prefixes working when vi_prec_num=0.
+Origin: upstream, http://w3m.cvs.sourceforge.net/viewvc/w3m/w3m/
+Author: Hironori Sakamoto <hsaka@mth.biglobe.ne.jp>
+
+diff -urN w3m-0.5.2.orig/main.c w3m/main.c
+--- w3m-0.5.2.orig/main.c 2007-05-31 10:19:50.000000000 +0900
++++ w3m/main.c 2007-06-04 22:21:10.000000000 +0900
+@@ -1,4 +1,4 @@
+-/* $Id: main.c,v 1.258 2007/05/31 01:19:50 inu Exp $ */
++/* $Id: main.c,v 1.259 2007/06/04 13:21:10 inu Exp $ */
+ #define MAINPROGRAM
+ #include "fm.h"
+ #include <signal.h>
+@@ -1152,18 +1152,11 @@
+ 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;
+- }
++ if (('0' <= c) && (c <= '9') &&
++ (prec_num || (GlobalKeymap[c] == FUNCNAME_nulcmd))) {
++ prec_num = prec_num * 10 + (int)(c - '0');
++ if (prec_num > PREC_LIMIT)
++ prec_num = PREC_LIMIT;
+ }
+ else {
+ set_buffer_environ(Currentbuf);
diff --git a/debian/patches/180_non-xterm.patch b/debian/patches/180_non-xterm.patch
new file mode 100644
index 0000000..a531e64
--- /dev/null
+++ b/debian/patches/180_non-xterm.patch
@@ -0,0 +1,32 @@
+Description: Fix segfault on non-xterm
+ * [w3m-dev 04278] Re: segfault on CentOS4.5/libgc6.8
+ * term.c: add handling xterm-incompatible terminals without gpm.
+Origin: upstream, http://w3m.cvs.sourceforge.net/viewvc/w3m/w3m/
+Author: Hironori Sakamoto <hsaka@mth.biglobe.ne.jp>
+
+diff -urN w3m-0.5.2.orig/terms.c w3m/terms.c
+--- w3m-0.5.2.orig/terms.c 2007-05-30 13:44:00.000000000 +0900
++++ w3m/terms.c 2007-06-07 19:54:10.000000000 +0900
+@@ -1,4 +1,4 @@
+-/* $Id: terms.c,v 1.57 2007/05/30 04:44:00 inu Exp $ */
++/* $Id: terms.c,v 1.58 2007/06/07 10:54:10 inu Exp $ */
+ /*
+ * An original curses library for EUC-kanji by Akinori ITO, December 1989
+ * revised by Akinori ITO, January 1995
+@@ -1897,7 +1897,7 @@
+ int
+ do_getch()
+ {
+- if (is_xterm)
++ if (is_xterm || !gpm_handler)
+ return getch();
+ else
+ return Gpm_Getch();
+@@ -2037,6 +2037,7 @@
+ conn.maxMod = 0;
+ conn.minMod = 0;
+
++ gpm_handler = NULL;
+ r = Gpm_Open(&conn, 0);
+ if (r == -2) {
+ /*
diff --git a/debian/patches/190_codepage.patch b/debian/patches/190_codepage.patch
new file mode 100644
index 0000000..8e30d05
--- /dev/null
+++ b/debian/patches/190_codepage.patch
@@ -0,0 +1,196 @@
+Description: Handling of codepage with wc_codepage
+ * [w3m-dev 04279] charset
+ * libwc/ces.h, libwc/charset.c: set charset to Shift_JIS, when locale
+ is japanese, jp_JP.PCK, ja_JP.IBM-932, ja_JP.IBM-943, or windows-31j.
+Origin: upstream, http://w3m.cvs.sourceforge.net/viewvc/w3m/w3m/
+Author: Hironori Sakamoto <hsaka@mth.biglobe.ne.jp>
+
+diff -urN w3m-0.5.2.orig/libwc/ces.h w3m/libwc/ces.h
+--- w3m-0.5.2.orig/libwc/ces.h 2003-09-23 06:02:23.000000000 +0900
++++ w3m/libwc/ces.h 2007-06-07 19:59:52.000000000 +0900
+@@ -176,6 +176,7 @@
+
+ #define WC_CES_SHIFT_JIS (WC_CES_E_PRIV2|WC_CES_N_SHIFT_JIS)
+ #define WC_CES_CP932 WC_CES_SHIFT_JIS
++#define WC_CES_CP943 WC_CES_SHIFT_JIS
+ #define WC_CES_SHIFT_JISX0213 (WC_CES_E_PRIV2|WC_CES_N_SHIFT_JISX0213)
+ #define WC_CES_GBK (WC_CES_E_PRIV2|WC_CES_N_GBK)
+ #define WC_CES_CP936 WC_CES_GBK
+diff -urN w3m-0.5.2.orig/libwc/charset.c w3m/libwc/charset.c
+--- w3m-0.5.2.orig/libwc/charset.c 2007-05-23 21:34:20.000000000 +0900
++++ w3m/libwc/charset.c 2007-06-07 19:59:52.000000000 +0900
+@@ -32,6 +32,46 @@
+ { NULL, 0 }
+ };
+
++static wc_ces
++wc_codepage(int n)
++{
++ switch (n) {
++ case 437: return WC_CES_CP437;
++ case 737: return WC_CES_CP737;
++ case 775: return WC_CES_CP775;
++ case 850: return WC_CES_CP850;
++ case 852: return WC_CES_CP852;
++ case 855: return WC_CES_CP855;
++ case 856: return WC_CES_CP856;
++ case 857: return WC_CES_CP857;
++ case 860: return WC_CES_CP860;
++ case 861: return WC_CES_CP861;
++ case 862: return WC_CES_CP862;
++ case 863: return WC_CES_CP863;
++ case 864: return WC_CES_CP864;
++ case 865: return WC_CES_CP865;
++ case 866: return WC_CES_CP866;
++ case 869: return WC_CES_CP869;
++ case 874: return WC_CES_CP874;
++ case 932: return WC_CES_CP932; /* CP932 = Shift_JIS */
++ case 936: return WC_CES_CP936; /* CP936 = GBK > EUC_CN */
++ case 943: return WC_CES_CP943; /* CP943 = Shift_JIS */
++ case 949: return WC_CES_CP949; /* CP949 = UHC > EUC_KR */
++ case 950: return WC_CES_CP950; /* CP950 = Big5 */
++ case 1006: return WC_CES_CP1006;
++ case 1250: return WC_CES_CP1250;
++ case 1251: return WC_CES_CP1251;
++ case 1252: return WC_CES_CP1252;
++ case 1253: return WC_CES_CP1253;
++ case 1254: return WC_CES_CP1254;
++ case 1255: return WC_CES_CP1255;
++ case 1256: return WC_CES_CP1256;
++ case 1257: return WC_CES_CP1257;
++ case 1258: return WC_CES_CP1258;
++ }
++ return 0;
++}
++
+ wc_ces
+ wc_guess_charset(char *charset, wc_ces orig)
+ {
+@@ -119,6 +159,11 @@
+ if (n >= 1 && n <= 16 && n != 12)
+ return (WC_CES_E_ISO_8859 | n);
+ return WC_CES_ISO_8859_1;
++ } else if (! strncmp(p, "ibm", 3)) {
++ p += 3;
++ if (*p >= '1' && *p <= '9')
++ return wc_codepage(atoi(p));
++ return wc_charset_to_ces(p);
+ }
+ break;
+ case 'j':
+@@ -135,6 +180,10 @@
+ ! strncmp(p, "sjis", 4))
+ return WC_CES_SHIFT_JIS;
+ break;
++ case 'p':
++ if (! strncmp(p, "pck", 3))
++ return WC_CES_SHIFT_JIS;
++ break;
+ case 'g':
+ if (! strncmp(p, "gb18030", 7) ||
+ ! strncmp(p, "gbk2k", 5))
+@@ -210,58 +259,18 @@
+ return WC_CES_EUC_CN;
+ if (*(p+1) != 'p')
+ break;
+- n = atoi(p + 2);
+- switch (n) {
+- case 437: return WC_CES_CP437;
+- case 737: return WC_CES_CP737;
+- case 775: return WC_CES_CP775;
+- case 850: return WC_CES_CP850;
+- case 852: return WC_CES_CP852;
+- case 855: return WC_CES_CP855;
+- case 856: return WC_CES_CP856;
+- case 857: return WC_CES_CP857;
+- case 860: return WC_CES_CP860;
+- case 861: return WC_CES_CP861;
+- case 862: return WC_CES_CP862;
+- case 863: return WC_CES_CP863;
+- case 864: return WC_CES_CP864;
+- case 865: return WC_CES_CP865;
+- case 866: return WC_CES_CP866;
+- case 869: return WC_CES_CP869;
+- case 874: return WC_CES_CP874;
+- case 932: return WC_CES_CP932; /* CP932 = Shift_JIS */
+- case 936: return WC_CES_CP936; /* CP936 = GBK > EUC_CN */
+- case 949: return WC_CES_CP949; /* CP949 = UHC > EUC_KR */
+- case 950: return WC_CES_CP950; /* CP950 = Big5 */
+- case 1006: return WC_CES_CP1006;
+- case 1250: return WC_CES_CP1250;
+- case 1251: return WC_CES_CP1251;
+- case 1252: return WC_CES_CP1252;
+- case 1253: return WC_CES_CP1253;
+- case 1254: return WC_CES_CP1254;
+- case 1255: return WC_CES_CP1255;
+- case 1256: return WC_CES_CP1256;
+- case 1257: return WC_CES_CP1257;
+- case 1258: return WC_CES_CP1258;
+- }
++ p += 2;
++ if (*p >= '1' && *p <= '9')
++ return wc_codepage(atoi(p));
+ break;
+ case 'w':
+ if (strncmp(p, "windows", 7))
+ break;
++ p += 7;
+ if (! strncmp(p, "31j", 3))
+ return WC_CES_CP932;
+- n = atoi(p + 7);
+- switch (n) {
+- case 1250: return WC_CES_CP1250;
+- case 1251: return WC_CES_CP1251;
+- case 1252: return WC_CES_CP1252;
+- case 1253: return WC_CES_CP1253;
+- case 1254: return WC_CES_CP1254;
+- case 1255: return WC_CES_CP1255;
+- case 1256: return WC_CES_CP1256;
+- case 1257: return WC_CES_CP1257;
+- case 1258: return WC_CES_CP1258;
+- }
++ if (*p >= '1' && *p <= '9')
++ return wc_codepage(atoi(p));
+ break;
+ }
+ return 0;
+@@ -345,18 +354,9 @@
+ case 'c':
+ return WC_CES_ISO_2022_CN;
+ case 'w':
+- n = atoi(p + 1);
+- switch (n) {
+- case 1250: return WC_CES_CP1250;
+- case 1251: return WC_CES_CP1251;
+- case 1252: return WC_CES_CP1252;
+- case 1253: return WC_CES_CP1253;
+- case 1254: return WC_CES_CP1254;
+- case 1255: return WC_CES_CP1255;
+- case 1256: return WC_CES_CP1256;
+- case 1257: return WC_CES_CP1257;
+- case 1258: return WC_CES_CP1258;
+- }
++ p++;
++ if (*p >= '1' && *p <= '9')
++ return wc_codepage(atoi(p));
+ break;
+ case 'r':
+ return WC_CES_RAW;
+@@ -368,7 +368,7 @@
+ wc_locale_to_ces(char *locale)
+ {
+ char *p = locale;
+- char buf[6];
++ char buf[8];
+ int n;
+
+ if (*p == 'C' && *(p+1) == '\0')
+@@ -380,7 +380,7 @@
+ return wc_charset_to_ces(cs);
+ }
+ #endif
+- for (n = 0; *p && *p != '.' && n < 5; p++) {
++ for (n = 0; *p && *p != '.' && n < 7; p++) {
+ if ((unsigned char)*p > 0x20)
+ buf[n++] = tolower(*p);
+ }
diff --git a/debian/patches/series b/debian/patches/series
index e6327bd..bf0fbe2 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -7,3 +7,13 @@
070_form-update.patch
080_xhtml-support.patch
090_simple-preserve-space.patch
+100_download-error-short-write.patch
+110_no-graph-restriction.patch
+120_config-file-handling.patch
+130_rc-blank-line-fix.patch
+140_pseudo-inlines.patch
+150_numbered-links.patch
+160_tls-sni.patch
+170_number-prefix.patch
+180_non-xterm.patch
+190_codepage.patch