6601 lines
		
	
	
		
			151 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			6601 lines
		
	
	
		
			151 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /* $Id: main.c,v 1.253 2006/12/10 10:49:23 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
 | |
| 
 | |
| #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 *);
 | |
| 
 | |
| JMP_BUF IntReturn;
 | |
| 
 | |
| 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 ENABLE_NLS
 | |
|     setlocale(LC_ALL, "");
 | |
|     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
 | |
| 
 | |
|     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(((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;
 | |
| 	    }
 | |
| 	}
 | |
| 	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.
 | |
|  */
 | |
| 
 | |
| #define MAX(a, b)  ((a) > (b) ? (a) : (b))
 | |
| #define MIN(a, b)  ((a) < (b) ? (a) : (b))
 | |
| 
 | |
| 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)
 | |
| 	    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)
 | |
| 	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);
 | |
| 	}
 | |
|     }
 | |
|     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
 | |
|     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);
 | |
| }
 | |
| 
 | |
| 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);
 | |
| }
 | |
| 
 | |
| 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  --> %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]);
 | |
| 	    kill(pid, SIGKILL);
 | |
| 	}
 | |
| 	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;
 | |
| 	kill(d->pid, SIGKILL);
 | |
| 	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)
 | |
| 	restorePosition(buf, Currentbuf);
 | |
|     if (!replace && open_tab_dl_list) {
 | |
| 	_newT();
 | |
| 	new_tab = TRUE;
 | |
|     }
 | |
|     pushBuffer(buf);
 | |
|     if (replace || new_tab)
 | |
| 	deletePrevBuf();
 | |
| #ifdef USE_ALARM
 | |
|     if (reload)
 | |
| 	Currentbuf->event = setAlarmEvent(Currentbuf->event, 1, AL_IMPLICIT,
 | |
| 					  FUNCNAME_reload, NULL);
 | |
| #endif
 | |
|     displayBuffer(Currentbuf, B_FORCE_REDRAW);
 | |
| }
 | |
| 
 | |
| static void
 | |
| save_buffer_position(Buffer *buf)
 | |
| {
 | |
|     BufferPos *b = buf->undo;
 | |
| 
 | |
|     if (!buf->firstLine)
 | |
| 	return;
 | |
|     if (b && b->top_linenumber == TOP_LINENUMBER(buf) &&
 | |
| 	b->cur_linenumber == CUR_LINENUMBER(buf) &&
 | |
| 	b->currentColumn == buf->currentColumn && b->pos == buf->pos)
 | |
| 	return;
 | |
|     b = New(BufferPos);
 | |
|     b->top_linenumber = TOP_LINENUMBER(buf);
 | |
|     b->cur_linenumber = CUR_LINENUMBER(buf);
 | |
|     b->currentColumn = buf->currentColumn;
 | |
|     b->pos = buf->pos;
 | |
|     b->bpos = buf->currentLine ? buf->currentLine->bpos : 0;
 | |
|     b->next = NULL;
 | |
|     b->prev = buf->undo;
 | |
|     if (buf->undo)
 | |
| 	buf->undo->next = b;
 | |
|     buf->undo = b;
 | |
| }
 | |
| 
 | |
| static void
 | |
| resetPos(BufferPos * b)
 | |
| {
 | |
|     Buffer buf;
 | |
|     Line top, cur;
 | |
| 
 | |
|     top.linenumber = b->top_linenumber;
 | |
|     cur.linenumber = b->cur_linenumber;
 | |
|     cur.bpos = b->bpos;
 | |
|     buf.topLine = ⊤
 | |
|     buf.currentLine = &cur;
 | |
|     buf.pos = b->pos;
 | |
|     buf.currentColumn = b->currentColumn;
 | |
|     restorePosition(Currentbuf, &buf);
 | |
|     Currentbuf->undo = b;
 | |
|     displayBuffer(Currentbuf, B_FORCE_REDRAW);
 | |
| }
 | |
| 
 | |
| DEFUN(undoPos, UNDO, "Cancel the last cursor movement")
 | |
| {
 | |
|     BufferPos *b = Currentbuf->undo;
 | |
|     int i;
 | |
| 
 | |
|     if (!Currentbuf->firstLine)
 | |
| 	return;
 | |
|     if (!b || !b->prev)
 | |
| 	return;
 | |
|     for (i = 0; i < PREC_NUM && b->prev; i++, b = b->prev) ;
 | |
|     resetPos(b);
 | |
| }
 | |
| 
 | |
| DEFUN(redoPos, REDO, "Cancel the last undo")
 | |
| {
 | |
|     BufferPos *b = Currentbuf->undo;
 | |
|     int i;
 | |
| 
 | |
|     if (!Currentbuf->firstLine)
 | |
| 	return;
 | |
|     if (!b || !b->next)
 | |
| 	return;
 | |
|     for (i = 0; i < PREC_NUM && b->next; i++, b = b->next) ;
 | |
|     resetPos(b);
 | |
| }
 |