aboutsummaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
authorAkinori Ito <aito@eie.yz.yamagata-u.ac.jp>2001-11-08 05:14:08 +0000
committerAkinori Ito <aito@eie.yz.yamagata-u.ac.jp>2001-11-08 05:14:08 +0000
commit68a07bf03b7624c9924065cce9ffa45497225834 (patch)
treec2adb06a909a8594445e4a3f8587c4bad46e3ecd /main.c
downloadw3m-68a07bf03b7624c9924065cce9ffa45497225834.tar.gz
w3m-68a07bf03b7624c9924065cce9ffa45497225834.zip
Initial revision
Diffstat (limited to 'main.c')
-rw-r--r--main.c3990
1 files changed, 3990 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..0e13388
--- /dev/null
+++ b/main.c
@@ -0,0 +1,3990 @@
+/* $Id: main.c,v 1.1 2001/11/08 05:15:13 a-ito Exp $ */
+#define MAINPROGRAM
+#include "fm.h"
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include "terms.h"
+#include "myctype.h"
+#ifdef 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
+
+#define DSTR_LEN 256
+
+Hist *LoadHist;
+Hist *SaveHist;
+Hist *URLHist;
+Hist *ShellHist;
+Hist *TextHist;
+
+#define N_EVENT_QUEUE 10
+typedef struct {
+ int cmd;
+ void *user_data;
+} Event;
+static Event eventQueue[N_EVENT_QUEUE];
+static int n_event_queue;
+
+#ifdef USE_MARK
+static char *MarkString = NULL;
+#endif
+static char *SearchString = NULL;
+int (*searchRoutine) (Buffer *, char *);
+
+JMP_BUF IntReturn;
+
+static void cmd_loadfile(char *path);
+static void cmd_loadURL(char *url, ParsedURL * current);
+static void cmd_loadBuffer(Buffer * buf, int prop, int link);
+static void keyPressEventProc(int c);
+#ifdef USE_MARK
+static void cmd_mark(Lineprop * p);
+#endif /* USE_MARK */
+#ifdef SHOW_PARAMS
+int show_params_p = 0;
+void show_params(FILE * fp);
+#endif
+
+static int display_ok = FALSE;
+int w3m_dump = 0;
+int w3m_dump_source = 0;
+int w3m_dump_head = 0;
+static void dump_source(Buffer *);
+static void dump_head(Buffer *);
+int prec_num = 0;
+int prev_key = -1;
+int on_target = 1;
+
+static void _goLine(char*);
+#define PREC_NUM (prec_num ? prec_num : 1)
+#define PREC_LIMIT 10000
+#if 0
+static int searchKeyNum(void);
+#endif
+
+#include "gcmain.c"
+
+#define help() fusage(stdout, 0)
+#define usage() fusage(stderr, 1)
+
+static void
+fusage(FILE *f, int err)
+{
+ fprintf(f, "version %s\n", version);
+ 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 JP_CHARSET
+#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
+ fprintf(f, " -I e|s document code\n");
+#endif /* JP_CHARSET */
+ 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 COLOR
+ fprintf(f, " -M monochrome display\n");
+#endif /* COLOR */
+ fprintf(f, " -F automatically render frame\n");
+ fprintf(f, " -dump dump formatted page into stdout\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");
+ fprintf(f, " -dump_source dump page source into stdout\n");
+ fprintf(f, " -dump_head dump response of HEAD request into stdout\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 MOUSE
+ fprintf(f, " -no-mouse don't use mouse\n");
+#endif /* MOUSE */
+#ifdef USE_COOKIE
+ fprintf(f, " -cookie use cookie (-no-cookie: don't use cookie)\n");
+ fprintf(f, " -pauth user:pass proxy authentication\n");
+#endif /* USE_COOKIE */
+#ifndef KANJI_SYMBOLS
+ fprintf(f, " -no-graph don't use graphic character\n");
+#endif /* not KANJI_SYMBOLS */
+#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, " -o opt=value assign value to config option\n");
+ fprintf(f, " -config file specify config file\n");
+ fprintf(f, " -debug DO NOT USE\n");
+#ifdef SHOW_PARAMS
+ if (show_params_p)
+ show_params(f);
+#endif
+ exit(err);
+}
+
+static int option_assigned = 0;
+extern void parse_proxy(void);
+
+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) {
+ static struct {
+ char *msg;
+ GC_word arg;
+ } msg_ring[GC_WARN_KEEP_MAX] = {
+ {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0},
+ {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0},
+ {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0},
+ {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0}, {NULL, 0},
+ };
+ 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]);
+ disp_message_nsec(Sprintf(msg_ring[i].msg, (unsigned long)msg_ring[i].arg)->ptr, FALSE, 1, TRUE, FALSE);
+ }
+
+ lock = 0;
+ }
+ }
+ else if (orig_GC_warn_proc)
+ orig_GC_warn_proc(msg, arg);
+ else
+ fprintf(stderr, msg, (unsigned long)arg);
+}
+
+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;
+
+#ifndef SYS_ERRLIST
+ prepare_sys_errlist();
+#endif /* not SYS_ERRLIST */
+
+ srand48(time(0));
+
+ NO_proxy_domains = newTextList();
+ fileToDelete = newTextList();
+
+ load_argv = New_N(char *, argc - 1);
+ load_argc = 0;
+
+ CurrentDir = currentdir();
+ BookmarkFile = NULL;
+ rc_dir = expandName(RC_DIR);
+ i = strlen(rc_dir);
+ if (i > 1 && rc_dir[i - 1] == '/')
+ rc_dir[i - 1] = '\0';
+ config_file = rcFile(CONFIG_FILE);
+ create_option_search_table();
+
+ /* 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]))
+ help();
+ }
+ }
+
+ /* initializations */
+ init_rc(config_file);
+ initKeymap();
+#ifdef MENU
+ initMenu();
+ CurrentMenuData = NULL;
+#endif /* MENU */
+#ifdef USE_COOKIE
+ initCookie();
+#endif /* USE_COOKIE */
+ setLocalCookie(); /* setup cookie for local CGI */
+
+ LoadHist = newHist();
+ SaveHist = newHist();
+ ShellHist = newHist();
+ TextHist = newHist();
+ URLHist = newHist();
+#ifdef USE_HISTORY
+ loadHistory(URLHist);
+#endif /* not USE_HISTORY */
+
+ if (!non_null(HTTP_proxy) &&
+ ((p = getenv("HTTP_PROXY")) ||
+ (p = getenv("http_proxy")) ||
+ (p = getenv("HTTP_proxy")))) {
+ HTTP_proxy = p;
+ parseURL(p, &HTTP_proxy_parsed, NULL);
+ }
+#ifdef USE_GOPHER
+ if (!non_null(GOPHER_proxy) &&
+ ((p = getenv("GOPHER_PROXY")) ||
+ (p = getenv("gopher_proxy")) ||
+ (p = getenv("GOPHER_proxy")))) {
+ GOPHER_proxy = p;
+ parseURL(p, &GOPHER_proxy_parsed, NULL);
+ }
+#endif /* USE_GOPHER */
+ if (!non_null(FTP_proxy) &&
+ ((p = getenv("FTP_PROXY")) ||
+ (p = getenv("ftp_proxy")) ||
+ (p = getenv("FTP_proxy")))) {
+ FTP_proxy = p;
+ parseURL(p, &FTP_proxy_parsed, NULL);
+ }
+ if (!non_null(NO_proxy) &&
+ ((p = getenv("NO_PROXY")) ||
+ (p = getenv("no_proxy")) ||
+ (p = getenv("NO_proxy")))) {
+ NO_proxy = p;
+ set_no_proxy(p);
+ }
+
+ if (Editor == NULL && (p = getenv("EDITOR")) != NULL)
+ Editor = p;
+ if (Mailer == NULL && (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();
+ PagerMax = atoi(argv[i]);
+ }
+#ifdef JP_CHARSET
+#ifndef DEBIAN /* XXX: use -o kanjicode={S|J|E} */
+ else if (!strcmp("-s", argv[i]))
+ DisplayCode = CODE_SJIS;
+ else if (!strcmp("-j", argv[i]))
+ DisplayCode = CODE_JIS_n;
+ else if (!strcmp("-e", argv[i]))
+ DisplayCode = CODE_EUC;
+#endif
+ else if (!strcmp("-I", argv[i])) {
+ if (++i >= argc)
+ usage();
+ DocumentCode = str_to_code(argv[i]);
+ }
+#endif /* JP_CHARSET */
+#ifndef KANJI_SYMBOLS
+ else if (!strcmp("-no-graph", argv[i]))
+ no_graphic_char = TRUE;
+#endif /* not KANJI_SYMBOLS */
+ else if (!strcmp("-T", argv[i])) {
+ if (++i >= argc)
+ usage();
+ DefaultType = argv[i];
+ }
+ else if (!strcmp("-m", argv[i]))
+ SearchHeader = TRUE;
+ else if (!strcmp("-v", argv[i]))
+ visual_start = TRUE;
+#ifdef COLOR
+ else if (!strcmp("-M", argv[i]))
+ useColor = FALSE;
+#endif /* 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 (WrapSearch) {
+ WrapSearch = FALSE;
+ }
+ else {
+ WrapSearch = TRUE;
+ }
+ }
+ else if (!strcmp("-dump", argv[i])) {
+ w3m_dump = TRUE;
+ w3m_dump_source = FALSE;
+ w3m_dump_head = FALSE;
+ w3m_halfdump = FALSE;
+ if (COLS == 0)
+ COLS = 80;
+ }
+ else if (!strcmp("-dump_source", argv[i])) {
+ w3m_dump = TRUE;
+ w3m_dump_source = TRUE;
+ w3m_dump_head = FALSE;
+ w3m_halfdump = FALSE;
+ if (COLS == 0)
+ COLS = 80;
+ }
+ else if (!strcmp("-dump_head", argv[i])) {
+ w3m_dump = TRUE;
+ w3m_dump_head = TRUE;
+ w3m_dump_source = FALSE;
+ w3m_halfdump = FALSE;
+ if (COLS == 0)
+ COLS = 80;
+ }
+ else if (!strcmp("-halfdump", argv[i])) {
+ w3m_halfdump = TRUE;
+ w3m_dump = FALSE;
+ if (COLS == 0)
+ COLS = 80;
+ }
+ else if (!strcmp("-halfload", argv[i])) {
+ w3m_halfload = TRUE;
+ w3m_dump = FALSE;
+ w3m_halfdump = FALSE;
+ }
+ 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;
+ }
+ else if (!strcmp("-num", argv[i]))
+ showLineNum = TRUE;
+ else if (!strcmp("-no-proxy", argv[i]))
+ Do_not_use_proxy = TRUE;
+#ifdef MOUSE
+ else if (!strcmp("-no-mouse", argv[i])) {
+ mouse_end();
+ use_mouse = FALSE;
+ }
+#endif /* MOUSE */
+#ifdef USE_COOKIE
+ else if (!strcmp("-no-cookie", argv[i])) {
+ use_cookie = FALSE;
+ }
+ else if (!strcmp("-cookie", argv[i])) {
+ use_cookie = TRUE;
+ }
+ else if (!strcmp("-pauth", argv[i])) {
+ if (++i >= argc)
+ usage();
+ proxy_auth_cookie = encodeB(argv[i]);
+ while (argv[i][0]) {
+ argv[i][0] = '\0';
+ argv[i]++;
+ }
+ }
+#endif /* USE_COOKIE */
+#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("-o", argv[i])) {
+#ifdef SHOW_PARAMS
+ if (++i >= argc || !strcmp(argv[i], "?")) {
+ show_params_p = 1;
+ usage();
+ }
+#else
+ if (++i >= argc)
+ usage();
+#endif
+ if (!set_param_option(argv[i])) {
+ /* option set failed */
+ fprintf(stderr, "%s: bad option\n", argv[i]);
+#ifdef SHOW_PARAMS
+ show_params_p = 1;
+ usage();
+#else
+ exit(1);
+#endif
+ }
+ option_assigned = 1;
+ }
+ else if (!strcmp("-dummy", argv[i])) {
+ /* do nothing */
+ }
+ else if (!strcmp("-debug", argv[i]))
+ w3m_debug = TRUE;
+ else {
+ usage();
+ }
+ }
+ else if (*argv[i] == '+') {
+ line_str = argv[i] + 1;
+ }
+ else {
+ load_argv[load_argc++] = argv[i];
+ }
+ i++;
+ }
+
+ if (option_assigned) {
+ parse_proxy();
+ }
+
+#ifdef __WATT32__
+ if (w3m_debug)
+ dbug_init();
+ sock_init();
+#endif
+
+ Firstbuf = NULL;
+ Currentbuf = NULL;
+ CurrentKey = -1;
+ if (BookmarkFile == NULL)
+ BookmarkFile = rcFile(BOOKMARK);
+
+ if (!isatty(1) && !w3m_dump && !w3m_halfdump) {
+ /* redirected output */
+ w3m_dump = TRUE;
+ if (COLS == 0)
+ COLS = 80;
+ }
+ if (w3m_backend)
+ backend();
+ if (!w3m_dump && !w3m_halfdump)
+ fmInit();
+ orig_GC_warn_proc = GC_set_warn_proc(wrap_GC_warn_proc);
+ if (w3m_halfdump)
+ printf("<pre>\n");
+
+ if (load_argc == 0) {
+ 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)
+ fprintf(stderr, "w3m: Can't load bookmark\n");
+ }
+ else if (visual_start) {
+ Str s_page;
+ s_page = Strnew_charp("<title>W3M startup page</title><center><b>Welcome to ");
+#ifdef JP_CHARSET
+ Strcat_charp(s_page, "<a href='http://ei5nazha.yz.yamagata-u.ac.jp/~aito/w3m/'>");
+#else
+ Strcat_charp(s_page, "<a href='http://ei5nazha.yz.yamagata-u.ac.jp/~aito/w3m/eng/'>");
+#endif /* JP_CHARSET */
+ Strcat_m_charp(s_page,
+ "w3m</a>!<p><p>This is w3m version ",
+ version,
+ "<br>Written by <a href='mailto:aito@ei5sun.yz.yamagata-u.ac.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)
+ fprintf(stderr, "w3m: Can't load string\n");
+ else
+ 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)
+ fprintf(stderr, "w3m: Can't load %s\n", p);
+ }
+ else {
+ if (fmInitialized)
+ fmTerm();
+ usage();
+ }
+ if (newbuf == NULL) {
+ deleteFiles();
+ if (fmInitialized) {
+ sleep_till_anykey(1, 0);
+ fmTerm();
+ }
+ exit(2);
+ }
+ i = -1;
+ }
+ else {
+ i = 0;
+ }
+ for (; i < load_argc; i++) {
+ if (i >= 0) {
+ if (w3m_dump && w3m_dump_head) {
+ request = New(FormList);
+ request->method = FORM_METHOD_HEAD;
+ newbuf = loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0, request);
+ }
+ else {
+ newbuf = loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0, NULL);
+ }
+ if (newbuf == NULL) {
+ fprintf(stderr, "w3m: Can't load %s\n", load_argv[i]);
+ continue;
+ }
+ else if (newbuf == NO_BUFFER)
+ continue;
+ switch (newbuf->real_scheme) {
+#ifdef USE_NNTP
+ case SCM_NNTP:
+ case SCM_NEWS:
+#endif /* USE_NNTP */
+ case SCM_MAILTO:
+ break;
+ case SCM_LOCAL:
+ case SCM_LOCAL_CGI:
+ unshiftHist(LoadHist, load_argv[i]);
+ break;
+ default:
+ pushHashHist(URLHist, parsedURL2Str(&newbuf->currentURL)->ptr);
+ break;
+ }
+ }
+ if (newbuf == NO_BUFFER)
+ continue;
+ if (w3m_halfdump) {
+ Currentbuf = Firstbuf = newbuf;
+ printf("</pre><title>%s</title>\n", htmlquote_str(newbuf->buffername));
+ deleteFiles();
+ exit(0);
+ }
+ if (w3m_dump) {
+ Currentbuf = Firstbuf = newbuf;
+ if (w3m_dump_source)
+ dump_source(Currentbuf);
+ else if (w3m_dump_head)
+ dump_head(Currentbuf);
+ else {
+ if (Currentbuf->frameset != NULL && RenderFrame)
+ rFrame();
+ saveBuffer(Currentbuf, stdout);
+ }
+ deleteFiles();
+#ifdef USE_COOKIES
+ save_cookies();
+#endif /* USE_COOKIES */
+ exit(0);
+ }
+ if (Currentbuf == NULL)
+ Firstbuf = Currentbuf = newbuf;
+ else {
+ Currentbuf->nextBuffer = newbuf;
+ Currentbuf = newbuf;
+ }
+ if (Currentbuf && Currentbuf != NO_BUFFER &&
+ RenderFrame && Currentbuf->frameset != NULL) {
+ rFrame();
+ Currentbuf = newbuf;
+ }
+#ifdef BUFINFO
+ saveBufferInfo();
+#endif
+
+ }
+ if (!Firstbuf || Firstbuf == NO_BUFFER) {
+ if (newbuf == NO_BUFFER) {
+ if (fmInitialized)
+ inputStr("Hit any key to quit w3m:", "");
+ quitfm();
+ }
+ deleteFiles();
+ if (fmInitialized) {
+ sleep_till_anykey(1, 0);
+ fmTerm();
+ }
+ exit(2);
+ }
+
+#ifdef SIGWINCH
+ signal(SIGWINCH, resize_hook);
+#else /* not SIGWINCH */
+ setlinescols();
+ setupscreen();
+#endif /* not SIGWINCH */
+ Currentbuf = Firstbuf;
+ displayBuffer(Currentbuf, B_NORMAL);
+ onA();
+ if (line_str) {
+ _goLine(line_str);
+ }
+ for (;;) {
+ /* event processing */
+ if (n_event_queue > 0) {
+ for (i = 0; i < n_event_queue; i++) {
+ CurrentKey = -1;
+ CurrentKeyData = eventQueue[i].user_data;
+#ifdef MENU
+ CurrentMenuData = NULL;
+#endif
+ w3mFuncList[eventQueue[i].cmd].func();
+ }
+ n_event_queue = 0;
+ }
+ CurrentKeyData = NULL;
+ /* get keypress event */
+#ifdef MOUSE
+ if (use_mouse)
+ mouse_active();
+#endif /* MOUSE */
+ c = getch();
+#ifdef MOUSE
+ if (use_mouse)
+ mouse_inactive();
+#endif /* MOUSE */
+ if (IS_ASCII(c)) { /* Ascii */
+ 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 {
+ keyPressEventProc((int) c);
+ prec_num = 0;
+ }
+ }
+ prev_key = CurrentKey;
+ CurrentKey = -1;
+ }
+}
+
+static void
+keyPressEventProc(int c)
+{
+ CurrentKey = c;
+ w3mFuncList[(int) GlobalKeymap[c]].func();
+ onA();
+}
+
+void
+pushEvent(int event, void *user_data)
+{
+ if (n_event_queue < N_EVENT_QUEUE) {
+ eventQueue[n_event_queue].cmd = event;
+ eventQueue[n_event_queue].user_data = user_data;
+ n_event_queue++;
+ }
+}
+
+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)
+ return;
+ for (ti = buf->document_header->first; ti; ti = ti->next) {
+ printf("%s", ti->ptr);
+ }
+ puts("");
+}
+
+void
+nulcmd(void)
+{ /* do nothing */
+}
+
+#ifdef __EMX__
+void
+pcmap(void)
+{
+ w3mFuncList[(int) PcKeymap[(int) getch()].func();
+}
+#else /* not __EMX__ */
+void pcmap(void)
+{
+}
+#endif
+
+void
+escmap(void)
+{
+ char c;
+ c = getch();
+ if (IS_ASCII(c)) {
+ CurrentKey = K_ESC | c;
+ w3mFuncList[(int) EscKeymap[(int) c]].func();
+ }
+}
+
+void
+escbmap(void)
+{
+ char c;
+ c = getch();
+
+ if (IS_DIGIT(c))
+ escdmap(c);
+ else if (IS_ASCII(c)) {
+ CurrentKey = K_ESCB | c;
+ w3mFuncList[(int) EscBKeymap[(int) c]].func();
+ }
+}
+
+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 == '~') {
+ CurrentKey = K_ESCD | d;
+ w3mFuncList[(int) EscDKeymap[d]].func();
+ }
+}
+
+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);
+
+void
+saveBufferInfo()
+{
+ FILE *fp;
+ if ((fp = fopen(rcFile("bufinfo"), "w")) == NULL) {
+ return;
+ }
+ else {
+ fprintf(fp, "%s\n", currentURL()->ptr);
+ fclose(fp);
+ }
+}
+
+
+static void
+pushBuffer(Buffer * buf)
+{
+ Buffer *b;
+
+ 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 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
+MySignalHandler
+resize_hook(SIGNAL_ARG)
+{
+ setlinescols();
+ setupscreen();
+ if (Currentbuf)
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+ signal(SIGWINCH, resize_hook);
+ SIGNAL_RETURN;
+}
+#endif /* SIGWINCH */
+
+/*
+ * Command functions: These functions are called with a keystroke.
+ */
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+static void
+nscroll(int n, int mode)
+{
+ Line *curtop = Currentbuf->topLine;
+ int lnum, tlnum, llnum, diff_n;
+
+ if (Currentbuf->firstLine == NULL)
+ return;
+ lnum = Currentbuf->currentLine->linenumber;
+ Currentbuf->topLine = lineSkip(Currentbuf, curtop, n, FALSE);
+ if (Currentbuf->topLine == curtop) {
+ lnum += n;
+ if (lnum < Currentbuf->topLine->linenumber)
+ lnum = Currentbuf->topLine->linenumber;
+ else if (lnum > Currentbuf->lastLine->linenumber)
+ lnum = Currentbuf->lastLine->linenumber;
+ } else {
+ tlnum = Currentbuf->topLine->linenumber;
+ llnum = Currentbuf->topLine->linenumber + LASTLINE - 1;
+ diff_n = n - (tlnum - curtop->linenumber);
+ if (lnum < tlnum)
+ lnum = tlnum + diff_n;
+ if (lnum > llnum)
+ lnum = llnum + diff_n;
+ }
+ gotoLine(Currentbuf, lnum);
+ arrangeLine(Currentbuf);
+ displayBuffer(Currentbuf, mode);
+}
+
+/* Move page forward */
+void
+pgFore(void)
+{
+#ifdef VI_PREC_NUM
+ nscroll(PREC_NUM * (LASTLINE - 1), B_NORMAL);
+#else /* not VI_PREC_NUM */
+ nscroll(prec_num ? prec_num : (LASTLINE - 1),
+ prec_num ? B_SCROLL : B_NORMAL);
+#endif /* not VI_PREC_NUM */
+}
+
+/* Move page backward */
+void
+pgBack(void)
+{
+#ifdef VI_PREC_NUM
+ nscroll(- PREC_NUM * (LASTLINE - 1), B_NORMAL);
+#else /* not VI_PREC_NUM */
+ nscroll(- (prec_num ? prec_num : (LASTLINE - 1)),
+ prec_num ? B_SCROLL : B_NORMAL);
+#endif /* not VI_PREC_NUM */
+}
+
+/* 1 line up */
+void
+lup1(void)
+{
+ nscroll(PREC_NUM, B_SCROLL);
+}
+
+/* 1 line down */
+void
+ldown1(void)
+{
+ nscroll(-PREC_NUM, B_SCROLL);
+}
+
+/* move cursor position to the center of screen */
+void
+ctrCsrV(void)
+{
+ int offsety;
+ if (Currentbuf->firstLine == NULL)
+ return;
+ offsety = LASTLINE / 2 - Currentbuf->cursorY;
+ if (offsety != 0) {
+/* Currentbuf->currentLine = lineSkip(Currentbuf,
+ * Currentbuf->currentLine,offsety, FALSE); */
+ Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->topLine, -offsety, FALSE);
+ arrangeLine(Currentbuf);
+ displayBuffer(Currentbuf, B_NORMAL);
+ }
+}
+
+void
+ctrCsrH(void)
+{
+ int offsetx;
+ if (Currentbuf->firstLine == NULL)
+ return;
+ offsetx = Currentbuf->cursorX - COLS / 2;
+ if (offsetx != 0) {
+ columnSkip(Currentbuf, offsetx);
+ arrangeCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_NORMAL);
+ }
+}
+
+/* Redraw screen */
+void
+rdrwSc(void)
+{
+ clear();
+ arrangeCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+/* Search regular expression forward */
+void
+srchfor(void)
+{
+ MySignalHandler(*prevtrap) ();
+ char *str;
+ int i;
+ int wrapped = 0;
+
+ str = inputStrHist("Forward: ", NULL, TextHist);
+ if (str != NULL && *str == '\0')
+ str = SearchString;
+ if (str == NULL || *str == '\0') {
+ displayBuffer(Currentbuf, B_NORMAL);
+ return;
+ }
+ SearchString = str;
+ prevtrap = signal(SIGINT, intTrap);
+ crmode();
+ if (SETJMP(IntReturn) == 0)
+ for (i = 0; i < PREC_NUM; i++)
+ wrapped = forwardSearch(Currentbuf, SearchString);
+ signal(SIGINT, prevtrap);
+ term_raw();
+ displayBuffer(Currentbuf, B_NORMAL);
+ if (wrapped) {
+ disp_message("Search wrapped", FALSE);
+ }
+ searchRoutine = forwardSearch;
+}
+
+/* Search regular expression backward */
+void
+srchbak(void)
+{
+ MySignalHandler(*prevtrap) ();
+ char *str;
+ int i;
+ int wrapped = 0;
+
+ str = inputStrHist("Backward: ", NULL, TextHist);
+ if (str != NULL && *str == '\0')
+ str = SearchString;
+ if (str == NULL || *str == '\0') {
+ displayBuffer(Currentbuf, B_NORMAL);
+ return;
+ }
+ SearchString = str;
+ prevtrap = signal(SIGINT, intTrap);
+ crmode();
+ if (SETJMP(IntReturn) == 0)
+ for (i = 0; i < PREC_NUM; i++)
+ wrapped = backwardSearch(Currentbuf, SearchString);
+ signal(SIGINT, prevtrap);
+ term_raw();
+ displayBuffer(Currentbuf, B_NORMAL);
+ if (wrapped) {
+ disp_message("Search wrapped", FALSE);
+ }
+ searchRoutine = backwardSearch;
+}
+
+static void
+srch_nxtprv(int reverse)
+{
+ int i;
+ int wrapped = 0;
+ static int (*routine[2]) (Buffer *, char *) =
+ {
+ forwardSearch, backwardSearch
+ };
+ MySignalHandler(*prevtrap) ();
+
+ if (searchRoutine == NULL) {
+ disp_message("No previous regular expression", TRUE);
+ return;
+ }
+ move(LASTLINE, 0);
+ addstr(searchRoutine == forwardSearch ? "Forward: " : "Backward: ");
+ addstr(SearchString);
+ clrtoeolx();
+ move(LASTLINE, 0);
+ refresh();
+ if (reverse != 0)
+ reverse = 1;
+ if (searchRoutine == backwardSearch)
+ reverse ^= 1;
+ prevtrap = signal(SIGINT, intTrap);
+ crmode();
+ if (SETJMP(IntReturn) == 0)
+ for (i = 0; i < PREC_NUM; i++)
+ wrapped = (*routine[reverse]) (Currentbuf, SearchString);
+ signal(SIGINT, prevtrap);
+ term_raw();
+ displayBuffer(Currentbuf, B_NORMAL);
+ if (wrapped) {
+ disp_message("Search wrapped", FALSE);
+ }
+}
+
+/* Search next matching */
+void
+srchnxt(void)
+{
+ srch_nxtprv(0);
+}
+
+/* Search previous matching */
+void
+srchprv(void)
+{
+ srch_nxtprv(1);
+}
+
+static void
+shiftvisualpos(Buffer * buf, int shift)
+{
+ buf->visualpos -= shift;
+ if (buf->visualpos >= COLS)
+ buf->visualpos = COLS - 1;
+ else if (buf->visualpos < 0)
+ buf->visualpos = 0;
+ arrangeLine(buf);
+ if (buf->visualpos == -shift && buf->cursorX == 0)
+ buf->visualpos = 0;
+}
+
+/* Shift screen left */
+void
+shiftl(void)
+{
+ int column;
+
+ if (Currentbuf->firstLine == NULL)
+ return;
+ column = Currentbuf->currentColumn;
+ columnSkip(Currentbuf, PREC_NUM * (-COLS + 1) + 1);
+ shiftvisualpos(Currentbuf, Currentbuf->currentColumn - column);
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+/* Shift screen right */
+void
+shiftr(void)
+{
+ int column;
+
+ if (Currentbuf->firstLine == NULL)
+ return;
+ column = Currentbuf->currentColumn;
+ columnSkip(Currentbuf, PREC_NUM * (COLS - 1) - 1);
+ shiftvisualpos(Currentbuf, Currentbuf->currentColumn - column);
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+void
+col1R(void)
+{
+ Buffer *buf = Currentbuf;
+ Line *l = buf->currentLine;
+ int j, column;
+
+ if (l == NULL)
+ return;
+ for (j = 0; j < PREC_NUM; j++) {
+ column = buf->currentColumn;
+ columnSkip(Currentbuf, 1);
+ if (column == buf->currentColumn)
+ break;
+ shiftvisualpos(Currentbuf, 1);
+ }
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+void
+col1L(void)
+{
+ Buffer *buf = Currentbuf;
+ Line *l = buf->currentLine;
+ int j;
+
+ if (l == NULL)
+ return;
+ for (j = 0; j < PREC_NUM; j++) {
+ if (buf->currentColumn == 0)
+ break;
+ columnSkip(Currentbuf, -1);
+ shiftvisualpos(Currentbuf, -1);
+ }
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+/* Execute shell command and read output ac pipe. */
+void
+pipesh(void)
+{
+ 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 == '\0') {
+ displayBuffer(Currentbuf, B_NORMAL);
+ return;
+ }
+ }
+ buf = getpipe(cmd);
+ if (buf == NULL) {
+ disp_message("Execution failed", FALSE);
+ }
+ 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 */
+void
+readsh(void)
+{
+ 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 == '\0') {
+ displayBuffer(Currentbuf, B_NORMAL);
+ return;
+ }
+ }
+ prevtrap = signal(SIGINT, intTrap);
+ crmode();
+ buf = getshell(cmd);
+ signal(SIGINT, prevtrap);
+ term_raw();
+ if (buf == NULL) {
+ disp_message("Execution failed", FALSE);
+ }
+ 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 */
+void
+execsh(void)
+{
+#ifdef MOUSE
+ int use_m = use_mouse;
+#endif
+ 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 != '\0') {
+ fmTerm();
+ system(cmd);
+ printf("\n[Hit any key]");
+ fflush(stdout);
+#ifdef MOUSE
+ use_mouse = FALSE;
+#endif
+ fmInit();
+ getch();
+#ifdef MOUSE
+ use_mouse = use_m;
+ if (use_mouse)
+ mouse_init();
+#endif
+ }
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+/* Load file */
+void
+ldfile(void)
+{
+ char *fn;
+
+ fn = searchKeyData();
+ if (fn == NULL || *fn == '\0') {
+ fn = inputFilenameHist("(Load)Filename? ", NULL, LoadHist);
+ if (fn == NULL || *fn == '\0') {
+ displayBuffer(Currentbuf, B_NORMAL);
+ return;
+ }
+ }
+ cmd_loadfile(fn);
+}
+
+/* Load help file */
+void
+ldhelp(void)
+{
+ cmd_loadURL(helpFile(HELP_FILE), NULL);
+}
+
+static void
+cmd_loadfile(char *fn)
+{
+ Buffer *buf;
+
+ buf = loadGeneralFile(fn, NULL, NO_REFERER, 0, NULL);
+ if (buf == NULL) {
+ char *emsg = Sprintf("%s not found", 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 */
+void
+movL(void)
+{
+ int i;
+ if (Currentbuf->firstLine == NULL)
+ return;
+ for (i = 0; i < PREC_NUM; i++)
+ cursorLeft(Currentbuf);
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+/* Move cursor downward */
+void
+movD(void)
+{
+ int i;
+ if (Currentbuf->firstLine == NULL)
+ return;
+ for (i = 0; i < PREC_NUM; i++)
+ cursorDown(Currentbuf);
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+/* move cursor upward */
+void
+movU(void)
+{
+ int i;
+ if (Currentbuf->firstLine == NULL)
+ return;
+ for (i = 0; i < PREC_NUM; i++)
+ cursorUp(Currentbuf);
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+/* Move cursor right */
+void
+movR(void)
+{
+ int i;
+ if (Currentbuf->firstLine == NULL)
+ return;
+ for (i = 0; i < PREC_NUM; i++)
+ cursorRight(Currentbuf);
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+
+
+/* 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;
+}
+
+void
+movLW(void)
+{
+ char *lb;
+ Lineprop *pb;
+ Line *pline;
+ int ppos;
+ int i;
+
+ if (Currentbuf->firstLine == NULL)
+ return;
+
+ for (i = 0; i < PREC_NUM; 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;
+}
+
+void
+movRW(void)
+{
+ char *lb;
+ Lineprop *pb;
+ Line *pline;
+ int ppos;
+ int i;
+
+ if (Currentbuf->firstLine == NULL)
+ return;
+
+ for (i = 0; i < PREC_NUM; 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);
+}
+
+/* Question and Quit */
+void
+qquitfm(void)
+{
+ char *ans;
+ if (!confirm_on_quit)
+ quitfm();
+ ans = inputStr("Do you want to exit w3m? (y or n)", "");
+ if (ans != NULL && tolower(*ans) == 'y')
+ quitfm();
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+/* Quit */
+void
+quitfm(void)
+{
+ fmTerm();
+ deleteFiles();
+#ifdef USE_COOKIE
+ save_cookies();
+#endif /* USE_COOKIE */
+#ifdef USE_HISTORY
+ if (SaveURLHist)
+ saveHistory(URLHist, URLHistSize);
+#endif /* USE_HISTORY */
+ exit(0);
+}
+
+/* Select buffer */
+void
+selBuf(void)
+{
+ 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);
+
+ if (clear_buffer) {
+ for (buf = Firstbuf; buf != NULL; buf = buf->nextBuffer)
+ tmpClearBuffer(buf);
+ }
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+/* Suspend (on BSD), or run interactive shell (on SysV) */
+void
+susp(void)
+{
+#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, -(LASTLINE + 1) / 2, TRUE);
+ Currentbuf->currentLine = Currentbuf->lastLine;
+ }
+ else
+ gotoRealLine(Currentbuf, atoi(l));
+ arrangeCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+void
+goLine(void)
+{
+ char *l = inputStr("Goto line: ", "");
+ prec_num = 0;
+ _goLine(l);
+}
+
+void
+goLineF(void)
+{
+ _goLine("^");
+}
+
+void
+goLineL(void)
+{
+ _goLine("$");
+}
+
+/* Go to the beginning of the line */
+void
+linbeg(void)
+{
+ if (Currentbuf->firstLine == NULL)
+ return;
+ Currentbuf->pos = 0;
+ arrangeCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+/* Go to the bottom of the line */
+void
+linend(void)
+{
+ if (Currentbuf->firstLine == NULL)
+ return;
+ Currentbuf->pos = Currentbuf->currentLine->len - 1;
+ arrangeCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+/* Run editor on the current buffer */
+void
+editBf(void)
+{
+ char *fn = Currentbuf->filename;
+ char *type = Currentbuf->type;
+ int top, linenum, cursorY, pos, currentColumn;
+ Buffer *buf, *fbuf = NULL;
+ 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->frameset != NULL)
+ fbuf = Currentbuf->linkBuffer[LB_FRAME];
+ if (Currentbuf->firstLine == NULL) {
+ top = 1;
+ linenum = 1;
+ } else {
+ top = Currentbuf->topLine->linenumber;
+ linenum = Currentbuf->currentLine->linenumber;
+ }
+ cursorY = Currentbuf->cursorY;
+ pos = Currentbuf->pos;
+ currentColumn = Currentbuf->currentColumn;
+ if (Currentbuf->edit) {
+ cmd = unquote_mailcap(Currentbuf->edit,
+ Currentbuf->real_type,
+ quoteShell(fn)->ptr, NULL);
+ }
+ else {
+ char *file = quoteShell(fn)->ptr;
+ if (strcasestr(Editor, "%s")) {
+ if (strcasestr(Editor, "%d"))
+ cmd = Sprintf(Editor, linenum, file);
+ else
+ cmd = Sprintf(Editor, file);
+ } else {
+ if (strcasestr(Editor, "%d"))
+ cmd = Sprintf(Editor, linenum);
+ else if (strcasestr(Editor, "vi"))
+ cmd = Sprintf("%s +%d", Editor, linenum);
+ else
+ cmd = Strnew_charp(Editor);
+ Strcat_m_charp(cmd, " ", file, NULL);
+ }
+ }
+ fmTerm();
+ system(cmd->ptr);
+ fmInit();
+ buf = loadGeneralFile(fn, NULL, NO_REFERER, 0, NULL);
+ if (buf == NULL) {
+ disp_err_message("Re-loading failed", FALSE);
+ buf = nullBuffer();
+ }
+ else if (buf == NO_BUFFER) {
+ buf = nullBuffer();
+ }
+ if (fbuf != NULL)
+ Firstbuf = deleteBuffer(Firstbuf, fbuf);
+ repBuffer(Currentbuf, buf);
+ if ((type != NULL) && (buf->type != NULL) &&
+ ((!strcasecmp(buf->type, "text/plain") &&
+ !strcasecmp(type, "text/html")) ||
+ (!strcasecmp(buf->type, "text/html") &&
+ !strcasecmp(type, "text/plain")))) {
+ vwSrc();
+ if (Currentbuf != buf)
+ Firstbuf = deleteBuffer(Firstbuf, buf);
+ }
+ if (Currentbuf->firstLine == NULL) {
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+ return;
+ }
+ Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->topLine, top - 1, FALSE);
+ gotoLine(Currentbuf, linenum);
+ Currentbuf->pos = pos;
+ Currentbuf->currentColumn = currentColumn;
+ arrangeCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+/* Run editor on the current screen */
+void
+editScr(void)
+{
+ int lnum;
+ Str cmd;
+ Str tmpf;
+ FILE *f;
+
+ tmpf = tmpfname(TMPF_DFL, NULL);
+ f = fopen(tmpf->ptr, "w");
+ if (f == NULL) {
+ cmd = Sprintf("Can't open %s\n", tmpf->ptr);
+ disp_err_message(cmd->ptr, TRUE);
+ return;
+ }
+ saveBuffer(Currentbuf, f);
+ fclose(f);
+ if (Currentbuf->currentLine)
+ lnum = Currentbuf->currentLine->linenumber;
+ else
+ lnum = 1;
+ if (strcasestr(Editor, "%s")) {
+ if (strcasestr(Editor, "%d"))
+ cmd = Sprintf(Editor, lnum, tmpf->ptr);
+ else
+ cmd = Sprintf(Editor, tmpf->ptr);
+ } else {
+ if (strcasestr(Editor, "%d"))
+ cmd = Sprintf(Editor, lnum);
+ else if (strcasestr(Editor, "vi"))
+ cmd = Sprintf("%s +%d", Editor, lnum);
+ else
+ cmd = Strnew_charp(Editor);
+ Strcat_m_charp(cmd, " ", tmpf->ptr, NULL);
+ }
+ fmTerm();
+ system(cmd->ptr);
+ fmInit();
+ unlink(tmpf->ptr);
+ gotoLine(Currentbuf, lnum);
+ arrangeCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+#ifdef USE_MARK
+
+/* Set / unset mark */
+void
+_mark(void)
+{
+ Line *l;
+ if (Currentbuf->firstLine == NULL)
+ return;
+ l = Currentbuf->currentLine;
+ cmd_mark(&l->propBuf[Currentbuf->pos]);
+ redrawLine(Currentbuf, l, l->linenumber - Currentbuf->topLine->linenumber);
+}
+
+static void
+cmd_mark(Lineprop * p)
+{
+ if ((*p & PM_MARK) && (*p & PE_STAND))
+ *p &= ~PE_STAND;
+ else if (!(*p & PM_MARK) && !(*p & PE_STAND))
+ *p |= PE_STAND;
+ *p ^= PM_MARK;
+}
+
+/* Go to next mark */
+void
+nextMk(void)
+{
+ Line *l;
+ int i;
+
+ 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] & PM_MARK) {
+ Currentbuf->currentLine = l;
+ Currentbuf->pos = i;
+ arrangeCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_NORMAL);
+ return;
+ }
+ }
+ l = l->next;
+ i = 0;
+ }
+ disp_message("No mark exist after here", TRUE);
+}
+
+/* Go to previous mark */
+void
+prevMk(void)
+{
+ Line *l;
+ int i;
+
+ 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] & PM_MARK) {
+ Currentbuf->currentLine = l;
+ Currentbuf->pos = i;
+ arrangeCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_NORMAL);
+ return;
+ }
+ }
+ l = l->prev;
+ if (l != NULL)
+ i = l->len - 1;
+ }
+ disp_message("No mark exist before here", TRUE);
+}
+
+/* Mark place to which the regular expression matches */
+void
+reMark(void)
+{
+ Line *l;
+ char *str;
+ char *p, *p1, *p2;
+
+ str = inputStrHist("(Mark)Regexp: ", MarkString, TextHist);
+ if (str == NULL || *str == '\0') {
+ displayBuffer(Currentbuf, B_NORMAL);
+ return;
+ }
+ MarkString = str;
+ if ((MarkString = regexCompile(MarkString, 1)) != NULL) {
+ disp_message(MarkString, TRUE);
+ return;
+ }
+ 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);
+ cmd_mark(l->propBuf + (p1 - l->lineBuf));
+ p = p2;
+ }
+ else
+ break;
+ }
+ }
+
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+#endif /* USE_MARK */
+
+#ifdef JP_CHARSET
+static char *
+cURLcode(char *url, Buffer * buf)
+{
+ char *p;
+ Str s;
+
+ for (p = url; *p; p++) {
+ if (!IS_ASCII(*p)) {
+ /* URL contains Kanji... uugh */
+ s = conv(url, InnerCode, buf->document_code);
+ return s->ptr;
+ }
+ }
+ return url;
+}
+#else /* not JP_CHARSET */
+#define cURLcode(url,buf) (url)
+#endif /* not JP_CHARSET */
+
+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\n", 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(cURLcode(url, Currentbuf),
+ baseURL(Currentbuf),
+ referer,
+ flag,
+ request);
+ if (buf == NULL) {
+ char *emsg = Sprintf("Can't load %s\n", 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->currentLine ?
+ Currentbuf->currentLine->linenumber : 0,
+ Currentbuf->pos);
+ /* 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);
+ 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) {
+ 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, 0);
+ pushHashHist(URLHist, parsedURL2Str(&buf->currentURL)->ptr);
+ (*buf->clone)++;
+ pushBuffer(buf);
+ gotoLine(Currentbuf, al->start.line);
+ Currentbuf->pos = al->start.pos;
+ arrangeCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+ return;
+}
+
+/* follow HREF link */
+void
+followA(void)
+{
+ Line *l;
+ Anchor *a;
+ ParsedURL u;
+
+ if (Currentbuf->firstLine == NULL)
+ return;
+ l = Currentbuf->currentLine;
+
+ a = retrieveCurrentAnchor(Currentbuf);
+ if (a == NULL) {
+ followForm();
+ return;
+ }
+ if (*a->url == '#') { /* index within this buffer */
+ gotoLabel(a->url + 1);
+ return;
+ }
+ parseURL2(a->url, &u, baseURL(Currentbuf));
+ if (u.scheme == Currentbuf->currentURL.scheme &&
+ u.port == Currentbuf->currentURL.port &&
+ ((u.host == NULL && Currentbuf->currentURL.host == NULL) ||
+ (u.host != NULL && Currentbuf->currentURL.host != NULL &&
+ strcasecmp(u.host, Currentbuf->currentURL.host) == 0)) &&
+ ((u.file == NULL && Currentbuf->currentURL.file == NULL) ||
+ (u.file != NULL && Currentbuf->currentURL.file != NULL &&
+ strcmp(u.file, Currentbuf->currentURL.file) == 0))) {
+ /* index within this buffer */
+ if (u.label) {
+ gotoLabel(u.label);
+ return;
+ }
+ }
+ if (!strncasecmp(a->url, "mailto:", 7)) {
+ /* invoke external mailer */
+ Str tmp;
+ char *to = quoteShell(a->url + 7)->ptr;
+ if (strcasestr(Mailer, "%s"))
+ tmp = Sprintf(Mailer, to);
+ else
+ tmp = Strnew_m_charp(Mailer, " ", to, NULL);
+ fmTerm();
+ system(tmp->ptr);
+ fmInit();
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+ return;
+ }
+#ifdef USE_NNTP
+ else if (!strncasecmp(a->url, "news:", 5) &&
+ strchr(a->url, '@') == NULL) {
+ /* news:newsgroup is not supported */
+ disp_err_message("news:newsgroup_name is not supported", TRUE);
+ return;
+ }
+#endif /* USE_NNTP */
+ loadLink(a->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 */
+void
+followI(void)
+{
+ Line *l;
+ Anchor *a;
+ Buffer *buf;
+
+ if (Currentbuf->firstLine == NULL)
+ return;
+ l = Currentbuf->currentLine;
+
+ a = retrieveCurrentImg(Currentbuf);
+ if (a == NULL)
+ return;
+ message(Sprintf("loading %s\n", a->url)->ptr, 0, 0);
+ refresh();
+ buf = loadGeneralFile(cURLcode(a->url, Currentbuf), baseURL(Currentbuf), NULL, 0, NULL);
+ if (buf == NULL) {
+ char *emsg = Sprintf("Can't load %s\n", a->url)->ptr;
+ disp_err_message(emsg, FALSE);
+ }
+ else if (buf != NO_BUFFER) {
+ pushBuffer(buf);
+ }
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+static void
+do_update_form_radio(FormItemList * f, void *data)
+{
+ Buffer *buf = (Buffer *) data;
+ formUpdateBuffer(&buf->formitem->anchors[f->anchor_num], buf, f);
+}
+
+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);
+ list->charset = srclist->charset;
+ 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;
+#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;
+}
+
+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",
+ getpid(), 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) {
+ *query = Strdup(f2->name);
+ Strcat_charp(*query, ".x");
+ form_write_data(body, fi->parent->boundary, (*query)->ptr, "1");
+ *query = Strdup(f2->name);
+ Strcat_charp(*query, ".y");
+ form_write_data(body, fi->parent->boundary, (*query)->ptr, "1");
+ }
+ else if (f2->name && f2->name->length > 0) {
+ /* not IMAGE */
+ if (f2->value != NULL) {
+#ifdef JP_CHARSET
+ if (fi->parent->charset != 0)
+ *query = conv_str(f2->value, InnerCode, fi->parent->charset);
+ else
+ *query = conv_str(f2->value, InnerCode, Currentbuf->document_code);
+#else /* not JP_CHARSET */
+ *query = f2->value;
+#endif /* not JP_CHARSET */
+ }
+ if (f2->type == FORM_INPUT_FILE)
+ form_write_form_file(body, fi->parent->boundary, f2->name->ptr, (*query)->ptr);
+ else
+ form_write_data(body, fi->parent->boundary, f2->name->ptr, (*query)->ptr);
+ }
+ }
+ else {
+ /* not multipart */
+ if (f2->type == FORM_INPUT_IMAGE) {
+ Strcat(*query, f2->name);
+ Strcat_charp(*query, ".x=1&");
+ Strcat(*query, f2->name);
+ Strcat_charp(*query, ".y=1");
+ }
+ else {
+ /* not IMAGE */
+ if (f2->name && f2->name->length > 0) {
+ Strcat(*query, form_quote(f2->name));
+ Strcat_char(*query, '=');
+ }
+ if (f2->value != NULL) {
+ if (fi->parent->method == FORM_METHOD_INTERNAL)
+ Strcat(*query, form_quote(f2->value));
+ else {
+#ifdef JP_CHARSET
+ if (fi->parent->charset != 0)
+ Strcat(*query,
+ form_quote(conv_str(f2->value,
+ InnerCode,
+ fi->parent->charset)));
+ else
+ Strcat(*query,
+ form_quote(conv_str(f2->value,
+ InnerCode,
+ Currentbuf->document_code)));
+#else /* not JP_CHARSET */
+ Strcat(*query, form_quote(f2->value));
+#endif /* not JP_CHARSET */
+ }
+ }
+ }
+ 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);
+ }
+}
+
+/* process form */
+void
+followForm(void)
+{
+ Line *l;
+ Anchor *a;
+ char *p;
+ FormItemList *fi, *f2;
+ Str tmp = Strnew(), tmp2 = Strnew();
+ int multipart = 0;
+
+ 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:
+ p = inputStrHist("TEXT:", fi->value ? fi->value->ptr : NULL, TextHist);
+ if (p == NULL)
+ return;
+ fi->value = Strnew_charp(p);
+ formUpdateBuffer(a, Currentbuf, fi);
+ if (fi->accept || fi->parent->nitems == 1)
+ goto do_submit;
+ break;
+ case FORM_INPUT_FILE:
+ p = inputFilenameHist("Filename:", fi->value ? fi->value->ptr : NULL, NULL);
+ if (p == NULL)
+ return;
+ fi->value = Strnew_charp(p);
+ formUpdateBuffer(a, Currentbuf, fi);
+ if (fi->accept || fi->parent->nitems == 1)
+ goto do_submit;
+ break;
+ case FORM_INPUT_PASSWORD:
+ p = inputLine("TEXT:", fi->value ? fi->value->ptr : NULL, IN_PASSWORD);
+ if (p == NULL)
+ return;
+ fi->value = Strnew_charp(p);
+ formUpdateBuffer(a, Currentbuf, fi);
+ if (fi->accept)
+ goto do_submit;
+ break;
+ case FORM_TEXTAREA:
+ if (fi->rows == 1) {
+ p = inputStrHist("TEXT:", fi->value ? fi->value->ptr : NULL, TextHist);
+ if (p == NULL)
+ return;
+ fi->value = Strnew_charp(p);
+ }
+ else
+ input_textarea(fi);
+ formUpdateBuffer(a, Currentbuf, fi);
+ break;
+ case FORM_INPUT_RADIO:
+ form_recheck_radio(fi, Currentbuf, do_update_form_radio);
+ break;
+ case FORM_INPUT_CHECKBOX:
+ fi->checked = !fi->checked;
+ formUpdateBuffer(a, Currentbuf, fi);
+ break;
+#ifdef MENU_SELECT
+ case FORM_SELECT:
+ formChooseOptionByMenu(fi,
+ Currentbuf->cursorX - Currentbuf->pos + a->start.pos,
+ Currentbuf->cursorY);
+ formUpdateBuffer(a, Currentbuf, fi);
+ break;
+#endif /* MENU_SELECT */
+ case FORM_INPUT_IMAGE:
+ case FORM_INPUT_SUBMIT:
+ case FORM_INPUT_BUTTON:
+ do_submit:
+ 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 (fi->parent->method == FORM_METHOD_GET) {
+ 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") == 0) ||
+ Currentbuf->bufferprop & BP_INTERNAL) { /* internal */
+ do_internal(tmp2->ptr, tmp->ptr);
+ return;
+ }
+ else {
+ disp_err_message("Can't send form because of illegal method.", FALSE);
+ }
+ break;
+ case FORM_INPUT_RESET:
+ for (f2 = fi->parent->item; f2; f2 = f2->next) {
+ if (f2->name && f2->value &&
+ f2->type != FORM_INPUT_RADIO &&
+ f2->type != FORM_INPUT_CHECKBOX &&
+ f2->type != FORM_INPUT_SUBMIT &&
+ f2->type != FORM_INPUT_HIDDEN &&
+ f2->type != FORM_INPUT_RESET) {
+ f2->value = Strnew();
+ formUpdateBuffer(&Currentbuf->formitem->anchors[f2->anchor_num], Currentbuf, f2);
+ }
+ }
+ break;
+ case FORM_INPUT_HIDDEN:
+ default:
+ break;
+ }
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+static void
+drawAnchorCursor0(Buffer * buf, int hseq, int prevhseq, int tline, int eline, int active)
+{
+ int i, j;
+ Line *l;
+ Anchor *an;
+
+ l = buf->topLine;
+ for (j = 0; j < buf->href->nanchor; j++) {
+ an = &buf->href->anchors[j];
+ if (an->start.line < tline)
+ continue;
+ if (an->start.line >= eline)
+ return;
+ for (;; l = l->next) {
+ if (l == NULL)
+ return;
+ if (l->linenumber == an->start.line)
+ break;
+ }
+ if (hseq >= 0 && an->hseq == hseq) {
+ for (i = an->start.pos; i < an->end.pos; i++) {
+ if (l->propBuf[i] & (PE_IMAGE | PE_ANCHOR | PE_FORM)) {
+ if (active)
+ l->propBuf[i] |= PE_ACTIVE;
+ else
+ l->propBuf[i] &= ~PE_ACTIVE;
+ }
+ }
+ if (active)
+ redrawLineRegion(buf, l, l->linenumber - tline,
+ an->start.pos, an->end.pos);
+ }
+ else if (prevhseq >= 0 && an->hseq == prevhseq) {
+ if (active)
+ redrawLineRegion(buf, l, l->linenumber - tline,
+ an->start.pos, an->end.pos);
+ }
+ }
+}
+
+
+void
+drawAnchorCursor(Buffer * buf)
+{
+ Anchor *an;
+ int hseq, prevhseq;
+ int tline, eline;
+
+ if (buf->firstLine == NULL)
+ return;
+ if (buf->href == NULL)
+ return;
+
+ an = retrieveCurrentAnchor(buf);
+ if (an != NULL)
+ hseq = an->hseq;
+ else
+ hseq = -1;
+ tline = buf->topLine->linenumber;
+ eline = tline + LASTLINE;
+ prevhseq = buf->hmarklist->prevhseq;
+
+ drawAnchorCursor0(buf, hseq, prevhseq, tline, eline, 1);
+ drawAnchorCursor0(buf, hseq, -1, tline, eline, 0);
+ buf->hmarklist->prevhseq = hseq;
+}
+
+/* underline an anchor if cursor is on the anchor. */
+void
+onA(void)
+{
+ drawAnchorCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+/* go to the top anchor */
+void
+topA(void)
+{
+ HmarkerList *hl = Currentbuf->hmarklist;
+ BufferPoint *po;
+ Anchor *an;
+ int hseq;
+
+ if (Currentbuf->firstLine == NULL)
+ return;
+ if (!hl || hl->nmark == 0)
+ return;
+
+ hseq = 0;
+ 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 */
+void
+lastA(void)
+{
+ HmarkerList *hl = Currentbuf->hmarklist;
+ BufferPoint *po;
+ Anchor *an;
+ int hseq;
+
+ if (Currentbuf->firstLine == NULL)
+ return;
+ if (!hl || hl->nmark == 0)
+ return;
+
+ 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 */
+void
+nextA(void)
+{
+ HmarkerList *hl = Currentbuf->hmarklist;
+ BufferPoint *po;
+ Anchor *an, *pan;
+ int i, x, y;
+
+ if (Currentbuf->firstLine == NULL)
+ return;
+ if (!hl || hl->nmark == 0)
+ return;
+
+ an = retrieveCurrentAnchor(Currentbuf);
+ if (an == NULL)
+ an = retrieveCurrentForm(Currentbuf);
+
+ y = Currentbuf->currentLine->linenumber;
+ x = Currentbuf->pos;
+
+ for (i = 0; i < PREC_NUM; i++) {
+ pan = an;
+ if (an && an->hseq >= 0) {
+ int hseq = an->hseq + 1;
+ do {
+ if (hseq >= hl->nmark) {
+ pan = an;
+ goto _end;
+ }
+ 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 || an == pan);
+ }
+ else {
+ an = closest_next_anchor(Currentbuf->href, NULL, x, y);
+ an = closest_next_anchor(Currentbuf->formitem, an, x, y);
+ if (an == NULL) {
+ an = pan;
+ break;
+ }
+ x = an->start.pos;
+ y = an->start.line;
+ }
+ }
+
+ _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 */
+void
+prevA(void)
+{
+ HmarkerList *hl = Currentbuf->hmarklist;
+ BufferPoint *po;
+ Anchor *an, *pan;
+ int i, x, y;
+
+ if (Currentbuf->firstLine == NULL)
+ return;
+ if (!hl || hl->nmark == 0)
+ return;
+
+ an = retrieveCurrentAnchor(Currentbuf);
+ if (an == NULL)
+ an = retrieveCurrentForm(Currentbuf);
+
+ y = Currentbuf->currentLine->linenumber;
+ x = Currentbuf->pos;
+
+ for (i = 0; i < PREC_NUM; i++) {
+ pan = an;
+ if (an && an->hseq >= 0) {
+ int hseq = an->hseq - 1;
+ do {
+ if (hseq < 0) {
+ an = pan;
+ goto _end;
+ }
+ 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 || an == pan);
+ }
+ else {
+ an = closest_prev_anchor(Currentbuf->href, NULL, x, y);
+ an = closest_prev_anchor(Currentbuf->formitem, an, x, y);
+ if (an == NULL) {
+ an = pan;
+ break;
+ }
+ x = an->start.pos;
+ y = an->start.line;
+ }
+ }
+
+ _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);
+}
+
+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 */
+void
+backBf(void)
+{
+ Buffer *buf = Currentbuf->linkBuffer[LB_N_FRAME];
+
+ if (!checkBackBuffer(Currentbuf)) {
+ disp_message("Can't back...", TRUE);
+ return;
+ }
+
+ delBuffer(Currentbuf);
+
+ if (buf) {
+ if (buf->frameQ) {
+ long linenumber;
+ short pos;
+ struct frameset *fs;
+
+ fs = popFrameTree(&(buf->frameQ), &linenumber, &pos);
+ deleteFrameSet(buf->frameset);
+ buf->frameset = fs;
+
+ if (buf == Currentbuf) {
+ rFrame();
+ gotoLine(Currentbuf, linenumber);
+ arrangeCursor(Currentbuf);
+ }
+ } else if (RenderFrame && buf == Currentbuf) {
+ delBuffer(Currentbuf);
+ }
+ }
+
+ clear();
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+void
+deletePrevBuf()
+{
+ Buffer *buf = Currentbuf->nextBuffer;
+ if (buf)
+ delBuffer(buf);
+}
+
+static void
+cmd_loadURL(char *url, ParsedURL * current)
+{
+ Buffer *buf;
+
+ if (!strncasecmp(url, "mailto:", 7)) {
+ /* invoke external mailer */
+ Str tmp;
+ char *to = quoteShell(url + 7)->ptr;
+ if (strcasestr(Mailer, "%s"))
+ tmp = Sprintf(Mailer, to);
+ else
+ tmp = Strnew_m_charp(Mailer, " ", to, NULL);
+ fmTerm();
+ system(tmp->ptr);
+ fmInit();
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+ return;
+ }
+#ifdef USE_NNTP
+ else if (!strncasecmp(url, "news:", 5) &&
+ strchr(url, '@') == NULL) {
+ /* news:newsgroup is not supported */
+ disp_err_message("news:newsgroup_name is not supported", TRUE);
+ return;
+ }
+#endif /* USE_NNTP */
+
+/* message(Sprintf("loading %s\n", url)->ptr, 0, 0); */
+ refresh();
+ buf = loadGeneralFile(url, current, NO_REFERER, 0, NULL);
+ if (buf == NULL) {
+ char *emsg = Sprintf("Can't load %s\n", 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 */
+void
+goURL(void)
+{
+ char *url;
+ ParsedURL p_url;
+
+ url = searchKeyData();
+ if (url == NULL) {
+ if (!(Currentbuf->bufferprop & BP_INTERNAL))
+ pushHashHist(URLHist, parsedURL2Str(&Currentbuf->currentURL)->ptr);
+ url = inputLineHist("Goto URL: ", NULL, IN_URL, URLHist);
+ if (url != NULL)
+ SKIP_BLANKS(url);
+ }
+ if (url == NULL || *url == '\0') {
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+ return;
+ }
+ if (*url == '#') {
+ gotoLabel(url + 1);
+ return;
+ }
+ parseURL2(url, &p_url, NULL);
+ pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr);
+ cmd_loadURL(url, baseURL(Currentbuf));
+}
+
+static void
+cmd_loadBuffer(Buffer * buf, int prop, int link)
+{
+ 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 (link != LB_NOLINK) {
+ buf->linkBuffer[REV_LB[link]] = Currentbuf;
+ Currentbuf->linkBuffer[link] = buf;
+ }
+ pushBuffer(buf);
+ }
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+/* load bookmark */
+void
+ldBmark(void)
+{
+ cmd_loadURL(BookmarkFile, NULL);
+}
+
+
+/* Add current to bookmark */
+void
+adBmark(void)
+{
+ Str url, title, tmp;
+ /* cmd_loadBuffer(load_bookmark_panel(Currentbuf), BP_NO_URL, *
+ * LB_NOLINK); */
+ url = form_quote(parsedURL2Str(&Currentbuf->currentURL));
+ title = form_quote(Strnew_charp(Currentbuf->buffername));
+#ifdef __EMX__
+ tmp = Sprintf("%s/w3mbookmark.exe?mode=panel&bmark=%s&url=%s&title=%s",
+ get_os2_dft("W3M_LIB_DIR", LIB_DIR), BookmarkFile, url->ptr, title->ptr);
+#else /* not __EMX__ */
+ tmp = Sprintf("%s/w3mbookmark?mode=panel&bmark=%s&url=%s&title=%s",
+ LIB_DIR, BookmarkFile, url->ptr, title->ptr);
+#endif /* not __EMX__ */
+ cmd_loadURL(tmp->ptr, NULL);
+}
+
+/* option setting */
+void
+ldOpt(void)
+{
+ cmd_loadBuffer(load_option_panel(), BP_NO_URL, LB_NOLINK);
+}
+
+/* error message list */
+void
+msgs(void)
+{
+ cmd_loadBuffer(message_list_panel(), BP_NO_URL, LB_NOLINK);
+}
+
+/* page info */
+void
+pginfo(void)
+{
+ 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);
+#ifdef JP_CHARSET
+ if (buf != NULL)
+ buf->document_code = Currentbuf->document_code;
+#endif /* JP_CHARSET */
+ cmd_loadBuffer(buf, BP_NORMAL, LB_INFO);
+}
+
+void
+follow_map(struct parsed_tagarg *arg)
+{
+#ifdef MENU_MAP
+ Anchor *a;
+ char *url;
+ int x;
+ ParsedURL p_url;
+
+ a = retrieveCurrentImg(Currentbuf);
+ if (a != NULL)
+ x = Currentbuf->cursorX - Currentbuf->pos + a->start.pos;
+ else
+ x = Currentbuf->cursorX;
+ url = follow_map_menu(Currentbuf, arg, x, Currentbuf->cursorY + 2);
+ if (url == NULL || *url == '\0')
+ return;
+ if (*url == '#') {
+ gotoLabel(url + 1);
+ return;
+ }
+ parseURL2(url, &p_url, baseURL(Currentbuf));
+ pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr);
+ cmd_loadURL(url, baseURL(Currentbuf));
+#else
+ Buffer *buf;
+
+ buf = follow_map_panel(Currentbuf, arg);
+ if (buf != NULL)
+ cmd_loadBuffer(buf, BP_NORMAL, LB_NOLINK);
+#endif
+}
+
+#ifdef USE_COOKIE
+/* cookie list */
+void
+cooLst(void)
+{
+ 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 */
+void
+ldHist(void)
+{
+ cmd_loadBuffer(historyBuffer(URLHist), BP_NO_URL, LB_NOLINK);
+}
+#endif /* USE_HISTORY */
+
+/* download HREF link */
+void
+svA(void)
+{
+ CurrentKeyData = NULL; /* not allowed in w3m-control: */
+ do_download = TRUE;
+ followA();
+ do_download = FALSE;
+}
+
+/* download IMG link */
+void
+svI(void)
+{
+ CurrentKeyData = NULL; /* not allowed in w3m-control: */
+ do_download = TRUE;
+ followI();
+ do_download = FALSE;
+}
+
+/* save buffer */
+void
+svBuf(void)
+{
+ char *file;
+ FILE *f;
+ int is_pipe;
+
+ CurrentKeyData = NULL; /* not allowed in w3m-control: */
+ file = searchKeyData();
+ if (file == NULL || *file == '\0') {
+ file = inputLineHist("Save buffer to: ", NULL, IN_COMMAND, SaveHist);
+ if (file == NULL || *file == '\0') {
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+ return;
+ }
+ }
+ if (*file == '|') {
+ is_pipe = TRUE;
+ f = popen(file + 1, "w");
+ }
+ else {
+ file = expandName(file);
+ if (checkOverWrite(file) < 0)
+ return;
+ f = fopen(file, "w");
+ is_pipe = FALSE;
+ }
+ if (f == NULL) {
+ char *emsg = Sprintf("Can't open %s\n", file)->ptr;
+ disp_err_message(emsg, TRUE);
+ return;
+ }
+ saveBuffer(Currentbuf, f);
+ if (is_pipe)
+ pclose(f);
+ else
+ fclose(f);
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+/* save source */
+void
+svSrc(void)
+{
+ if (Currentbuf->sourcefile == NULL)
+ return;
+ CurrentKeyData = NULL; /* not allowed in w3m-control: */
+ PermitSaveToPipe = TRUE;
+ doFileCopy(Currentbuf->sourcefile,
+ guess_save_name(Currentbuf->currentURL.file));
+ PermitSaveToPipe = FALSE;
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+static void
+_peekURL(int only_img){
+
+ Anchor *a;
+ ParsedURL pu;
+ static Str s = NULL;
+ static int offset = 0;
+
+ 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;
+ }
+ a = (only_img ? NULL : retrieveCurrentAnchor(Currentbuf));
+ if (a == NULL) {
+ a = retrieveCurrentImg(Currentbuf);
+ if (a == NULL) {
+ a = retrieveCurrentForm(Currentbuf);
+ if (a == NULL)
+ return;
+ s = Strnew_charp(form2str((FormItemList *) a->url));
+ goto disp;
+ }
+ }
+ parseURL2(a->url, &pu, baseURL(Currentbuf));
+ s = parsedURL2Str(&pu);
+ disp:
+ if (PREC_NUM > 1 && s->length > (PREC_NUM - 1) * (COLS - 1))
+ disp_message_nomouse(&s->ptr[(PREC_NUM - 1) * (COLS - 1)], TRUE);
+ else
+ disp_message_nomouse(&s->ptr[offset], TRUE);
+}
+
+/* peek URL */
+void
+peekURL(void)
+{
+ _peekURL(0);
+}
+
+/* peek URL of image */
+void
+peekIMG(void)
+{
+ _peekURL(1);
+}
+
+/* show current URL */
+static Str
+currentURL(void)
+{
+ if (Currentbuf->bufferprop & BP_INTERNAL)
+ return Strnew_size(0);
+ return parsedURL2Str(&Currentbuf->currentURL);
+}
+
+void
+curURL(void)
+{
+ static Str s = NULL;
+ static int offset = 0;
+
+ 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 (PREC_NUM > 1 && s->length > (PREC_NUM - 1) * (COLS - 1))
+ disp_message_nomouse(&s->ptr[(PREC_NUM - 1) * (COLS - 1)], TRUE);
+ else
+ disp_message_nomouse(&s->ptr[offset], TRUE);
+}
+
+/* view HTML source */
+void
+vwSrc(void)
+{
+ char *fn;
+ 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")) {
+ FILE *f;
+ Str tmpf = tmpfname(TMPF_SRC, NULL);
+ f = fopen(tmpf->ptr, "w");
+ if (f == NULL)
+ return;
+ saveBufferDelNum(Currentbuf, f, showLineNum);
+ fclose(f);
+ fn = tmpf->ptr;
+ }
+ else {
+ return;
+ }
+ } else if (Currentbuf->real_scheme == SCM_LOCAL) {
+ fn = Currentbuf->filename;
+ } else {
+ fn = Currentbuf->sourcefile;
+ }
+ if (!strcasecmp(Currentbuf->type, "text/html")) {
+#ifdef JP_CHARSET
+ char old_code = DocumentCode;
+ DocumentCode = Currentbuf->document_code;
+#endif
+ buf = loadFile(fn);
+#ifdef JP_CHARSET
+ DocumentCode = old_code;
+#endif
+ if (buf == NULL)
+ return;
+ 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->bufferprop |= BP_SOURCE;
+ 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")) {
+ char *old_type = DefaultType;
+ DefaultType = "text/html";
+ buf = loadGeneralFile(fn, NULL, NO_REFERER, 0, NULL);
+ DefaultType = old_type;
+ if (buf == NULL || buf == NO_BUFFER)
+ return;
+ if (Currentbuf->real_type &&
+ !strcasecmp(Currentbuf->real_type, "text/plain"))
+ buf->real_type = "text/html";
+ else
+ buf->real_type = Currentbuf->real_type;
+ if (!strcmp(buf->buffername, mybasename(fn)))
+ 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->sourcefile = Currentbuf->sourcefile;
+ buf->clone = Currentbuf->clone;
+ (*buf->clone)++;
+ pushBuffer(buf);
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+/* reload */
+void
+reload(void)
+{
+ Buffer *buf, *fbuf = NULL;
+ char *type = Currentbuf->type;
+ Str url;
+ int top, linenum, cursorY, pos, currentColumn;
+ FormList *request;
+ int multipart;
+
+ if (Currentbuf->bufferprop & BP_INTERNAL) {
+ disp_err_message("Can't reload...", FALSE);
+ return;
+ }
+ if (Currentbuf->currentURL.scheme == SCM_LOCAL &&
+ !strcmp(Currentbuf->currentURL.file, "-")) {
+ /* file is std input */
+ disp_err_message("Can't reload stdin", TRUE);
+ return;
+ }
+ if (Currentbuf->firstLine == NULL) {
+ top = 1;
+ linenum = 1;
+ } else {
+ top = Currentbuf->topLine->linenumber;
+ linenum = Currentbuf->currentLine->linenumber;
+ }
+ cursorY = Currentbuf->cursorY;
+ pos = Currentbuf->pos;
+ currentColumn = Currentbuf->currentColumn;
+ if (Currentbuf->bufferprop & BP_FRAME &&
+ (fbuf = Currentbuf->linkBuffer[LB_N_FRAME])) {
+ if (fmInitialized) {
+ message("Rendering frame", 0, 0);
+ refresh();
+ }
+ if (!(buf = renderFrame(fbuf, 1)))
+ 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 == NULL) {
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+ return;
+ }
+ gotoLine(Currentbuf, linenum);
+ Currentbuf->pos = pos;
+ Currentbuf->currentColumn = currentColumn;
+ arrangeCursor(Currentbuf);
+ 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);
+ message("Reloading...", 0, 0);
+ refresh();
+ buf = loadGeneralFile(url->ptr, NULL, NO_REFERER, RG_NOCACHE, request);
+ if (multipart)
+ unlink(request->body);
+ if (buf == NULL) {
+ disp_err_message("Can't reload...", FALSE);
+ return;
+ }
+ else if (buf == NO_BUFFER) {
+ return;
+ }
+ buf->form_submit = Currentbuf->form_submit;
+ if (fbuf != NULL)
+ Firstbuf = deleteBuffer(Firstbuf, fbuf);
+ repBuffer(Currentbuf, buf);
+ if ((type != NULL) && (buf->type != NULL) &&
+ ((!strcasecmp(buf->type, "text/plain") &&
+ !strcasecmp(type, "text/html")) ||
+ (!strcasecmp(buf->type, "text/html") &&
+ !strcasecmp(type, "text/plain")))) {
+ vwSrc();
+ if (Currentbuf != buf)
+ Firstbuf = deleteBuffer(Firstbuf, buf);
+ }
+ if (Currentbuf->firstLine == NULL) {
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+ return;
+ }
+ Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->firstLine, top - 1, FALSE);
+ gotoLine(Currentbuf, linenum);
+ Currentbuf->pos = pos;
+ Currentbuf->currentColumn = currentColumn;
+ arrangeCursor(Currentbuf);
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+/* mark URL-like patterns as anchors */
+void
+chkURL(void)
+{
+ static char *url_like_pat[] =
+ {
+ "http://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./?=~_\\&+@#,\\$]*",
+#ifdef USE_SSL
+ "https://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./?=~_\\&+@#,\\$]*",
+#endif /* USE_SSL */
+#ifdef USE_GOPHER
+ "gopher://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./_]*",
+#endif /* USE_GOPHER */
+ "ftp://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./=_+@#,\\$]*",
+#ifdef USE_NNTP
+ "news:[^<> ][^<> ]*",
+ "nntp://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./_]*",
+#endif /* USE_NNTP */
+ NULL,
+ };
+ int i;
+ for (i = 0; url_like_pat[i]; i++) {
+ reAnchor(Currentbuf, url_like_pat[i]);
+ }
+ Currentbuf->check_url |= CHK_URL;
+
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+#ifdef USE_NNTP
+/* mark Message-ID-like patterns as NEWS anchors */
+void
+chkNMID(void)
+{
+ static char *url_like_pat[] =
+ {
+ "<[^<> ][^<> ]*@[A-z0-9\\.\\-_][A-z0-9\\.\\-_]*>",
+ NULL,
+ };
+ int i;
+ for (i = 0; url_like_pat[i]; i++) {
+ reAnchorNews(Currentbuf, url_like_pat[i]);
+ }
+ Currentbuf->check_url |= CHK_NMID;
+
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+#endif /* USE_NNTP */
+
+/* render frame */
+void
+rFrame(void)
+{
+ 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)
+ 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 tmp;
+ char *browser = NULL;
+ int bg = 0;
+
+ 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 == '\0')
+ return;
+ }
+ }
+ url = quoteShell(url)->ptr;
+ if (strcasestr(browser, "%s")) {
+ tmp = Sprintf(browser, url);
+ Strremovetrailingspaces(tmp);
+ if (Strlastchar(tmp) == '&') {
+ Strshrink(tmp, 1);
+ bg = 1;
+ }
+ }
+ else {
+ tmp = Strnew_charp(browser);
+ Strcat_char(tmp, ' ');
+ Strcat_charp(tmp, url);
+ }
+ fmTerm();
+ mySystem(tmp->ptr, bg);
+ fmInit();
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+void
+extbrz()
+{
+ if (Currentbuf->bufferprop & BP_INTERNAL) {
+ disp_err_message("Can't browse...", FALSE);
+ return;
+ }
+ if (Currentbuf->currentURL.scheme == SCM_LOCAL &&
+ !strcmp(Currentbuf->currentURL.file, "-")) {
+ /* file is std input */
+ disp_err_message("Can't browse stdin", TRUE);
+ return;
+ }
+ invoke_browser(parsedURL2Str(&Currentbuf->currentURL)->ptr);
+}
+
+void
+linkbrz()
+{
+ 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 */
+void
+curlno()
+{
+ Str tmp;
+ int cur = 0, all, col, len = 0;
+
+ if (Currentbuf->currentLine != NULL) {
+ Line *l = Currentbuf->currentLine;
+ cur = l->real_linenumber;
+ if (l->width < 0)
+ l->width = COLPOS(l, l->len);
+ len = l->width;
+ }
+ col = Currentbuf->currentColumn + Currentbuf->cursorX + 1;
+ all = (Currentbuf->lastLine ? Currentbuf->lastLine->real_linenumber : Currentbuf->allLine);
+ if (all == 0 && Currentbuf->lastLine != NULL)
+ all = Currentbuf->currentLine->real_linenumber;
+ if (all == 0)
+ all = 1;
+ 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, cur * 100 / all, col, len);
+#ifdef JP_CHARSET
+ Strcat_charp(tmp, " ");
+ Strcat_charp(tmp, code_to_str(Currentbuf->document_code));
+#endif /* not JP_CHARSET */
+
+ disp_message(tmp->ptr, FALSE);
+}
+
+#ifdef MOUSE
+/* Addition:mouse event */
+#define MOUSE_BTN1_DOWN 0
+#define MOUSE_BTN2_DOWN 1
+#define MOUSE_BTN3_DOWN 2
+#define MOUSE_BTN4_DOWN_RXVT 3
+#define MOUSE_BTN5_DOWN_RXVT 4
+#define MOUSE_BTN4_DOWN_XTERM 64
+#define MOUSE_BTN5_DOWN_XTERM 65
+#define MOUSE_BTN_UP 3
+#define MOUSE_BTN_RESET -1
+#define MOUSE_SCROLL_LINE 5
+
+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;
+
+ if (btn == MOUSE_BTN_UP) {
+ switch (press_btn) {
+ case MOUSE_BTN1_DOWN:
+ if (press_x != x || press_y != y) {
+ 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();
+ }
+ }
+ else {
+ if (y == LASTLINE) {
+ switch (x) {
+ case 0:
+ case 1:
+ backBf();
+ break;
+ case 2:
+ case 3:
+ pgBack();
+ break;
+ case 4:
+ case 5:
+ pgFore();
+ break;
+ }
+ return;
+ }
+ if (y == Currentbuf->cursorY &&
+ (x == Currentbuf->cursorX
+#ifdef JP_CHARSET
+ || (Currentbuf->currentLine != NULL &&
+ (Currentbuf->currentLine->propBuf[Currentbuf->pos] & PC_KANJI1)
+ && x == Currentbuf->cursorX + 1)
+#endif /* JP_CHARSET */
+ )) {
+ followA();
+ return;
+ }
+
+ cursorXY(Currentbuf, x, y);
+ displayBuffer(Currentbuf, B_NORMAL);
+
+ }
+ break;
+ case MOUSE_BTN2_DOWN:
+ backBf();
+ break;
+ case MOUSE_BTN3_DOWN:
+#ifdef MENU
+ cursorXY(Currentbuf, x, y);
+ onA();
+ mainMenu(x, y);
+#endif /* MENU */
+ 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;
+ }
+}
+
+void
+msToggle(void)
+{
+ if (use_mouse) {
+ use_mouse = FALSE;
+ }
+ else {
+ use_mouse = TRUE;
+ }
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+void
+mouse()
+{
+ int btn, x, y;
+
+ btn = (unsigned char) getch() - 32;
+ 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, 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 */
+#endif /* MOUSE */
+
+void
+wrapToggle(void)
+{
+ if (WrapSearch) {
+ WrapSearch = FALSE;
+ disp_message("Wrap search off", FALSE);
+ }
+ else {
+ WrapSearch = TRUE;
+ disp_message("Wrap search on", FALSE);
+ }
+}
+
+#ifdef DICT
+static char *
+GetWord(Buffer * buf)
+{
+ Line *l = buf->currentLine;
+ char *lb = l->lineBuf;
+ int i, b, e, pos = buf->pos;
+
+ i = pos;
+ while (!IS_ALPHA(lb[i]) && i >= 0)
+ i--;
+ pos = i;
+ while (IS_ALPHA(lb[i]) && i >= 0)
+ i--;
+ i++;
+ if (!IS_ALPHA(lb[i]))
+ return NULL;
+ b = i;
+ i = pos;
+ while (IS_ALPHA(lb[i]) && i <= l->len - 1)
+ i++;
+ e = i - 1;
+ return Strnew_charp_n(&lb[b], e - b + 1)->ptr;
+}
+
+static void
+execdict(char *word)
+{
+ Buffer *buf;
+ Str cmd, bn;
+ MySignalHandler(*prevtrap) ();
+
+ if (word == NULL || *word == '\0') {
+ displayBuffer(Currentbuf, B_NORMAL);
+ return;
+ }
+ cmd = Strnew_charp(DICTCMD);
+ Strcat_char(cmd, ' ');
+ Strcat_charp(cmd, word);
+ prevtrap = signal(SIGINT, intTrap);
+ crmode();
+ buf = getshell(cmd->ptr);
+ bn = Sprintf("%s %s", DICTBUFFERNAME, word);
+ buf->buffername = bn->ptr;
+ buf->filename = word;
+ signal(SIGINT, prevtrap);
+ term_raw();
+ if (buf == NULL) {
+ disp_message("Execution failed", FALSE);
+ }
+ else if (buf->firstLine == NULL) {
+ /* if the dictionary doesn't describe the word. */
+ disp_message(Sprintf("Word \"%s\" Not Found", word)->ptr, FALSE);
+ }
+ else {
+ buf->bufferprop |= (BP_INTERNAL | BP_NO_URL);
+ pushBuffer(buf);
+ }
+ displayBuffer(Currentbuf, B_FORCE_REDRAW);
+}
+
+void
+dictword(void)
+{
+ execdict(inputStr("(dictionary)!", ""));
+}
+
+void
+dictwordat(void)
+{
+ execdict(GetWord(Currentbuf));
+}
+#endif /* DICT */
+
+char *
+searchKeyData(void)
+{
+ KeyListItem *item;
+
+ if (CurrentKeyData != NULL && *CurrentKeyData != '\0')
+ return allocStr(CurrentKeyData, 0);
+#ifdef MENU
+ if (CurrentMenuData != NULL && *CurrentMenuData != '\0')
+ return allocStr(CurrentMenuData, 0);
+#endif
+ if (CurrentKey < 0)
+ return NULL;
+ item = searchKeyList(&w3mKeyList, CurrentKey);
+ if (item == NULL || item->data == NULL || *item->data == '\0')
+ return NULL;
+ return allocStr(item->data, 0);
+}
+
+#if 0
+static int
+searchKeyNum(void)
+{
+ char *d;
+ int n = 1;
+
+ d = searchKeyData();
+ if (d != NULL)
+ n = atoi(d);
+ return n * PREC_NUM;
+}
+#endif