1 /* $Id: main.c,v 1.258 2007/05/31 01:19:50 inu Exp $ */
10 #if defined(HAVE_WAITPID) || defined(HAVE_WAIT3)
21 #if defined(USE_GPM) || defined(USE_SYSMOUSE)
22 extern int do_getch();
23 #define getch() do_getch()
24 #endif /* defined(USE_GPM) || defined(USE_SYSMOUSE) */
27 #ifdef __MINGW32_VERSION
41 typedef struct _Event {
46 static Event *CurrentEvent = NULL;
47 static Event *LastEvent = NULL;
50 static AlarmEvent DefaultAlarm = {
51 0, AL_UNSET, FUNCNAME_nulcmd, NULL
53 static AlarmEvent *CurrentAlarm = &DefaultAlarm;
54 static MySignalHandler SigAlarm(SIGNAL_ARG);
58 static int need_resize_screen = FALSE;
59 static MySignalHandler resize_hook(SIGNAL_ARG);
60 static void resize_screen(void);
64 static MySignalHandler SigPipe(SIGNAL_ARG);
68 static char *MarkString = NULL;
70 static char *SearchString = NULL;
71 int (*searchRoutine) (Buffer *, char *);
73 #ifndef __MINGW32_VERSION
76 _JBTYPE IntReturn[_JBLEN];
77 #endif /* __MINGW32_VERSION */
79 static void delBuffer(Buffer *buf);
80 static void cmd_loadfile(char *path);
81 static void cmd_loadURL(char *url, ParsedURL *current, char *referer,
83 static void cmd_loadBuffer(Buffer *buf, int prop, int linkid);
84 static void keyPressEventProc(int c);
85 int show_params_p = 0;
86 void show_params(FILE * fp);
88 static char *getCurWord(Buffer *buf, int *spos, int *epos,
89 const char *badchars);
91 static int display_ok = FALSE;
92 static void do_dump(Buffer *);
96 static int add_download_list = FALSE;
98 void set_buffer_environ(Buffer *);
99 static void save_buffer_position(Buffer *buf);
101 static void _followForm(int);
102 static void _goLine(char *);
103 static void _newT(void);
104 static void followTab(TabBuffer * tab);
105 static void moveTab(TabBuffer * t, TabBuffer * t2, int right);
106 static void _nextA(int);
107 static void _prevA(int);
108 static int check_target = TRUE;
109 #define PREC_NUM (prec_num ? prec_num : 1)
110 #define PREC_LIMIT 10000
111 static int searchKeyNum(void);
113 #define help() fusage(stdout, 0)
114 #define usage() fusage(stderr, 1)
119 fprintf(f, "w3m version %s, options %s\n", w3m_version,
133 #ifdef USE_ANSI_COLOR
154 #ifdef USE_SSL_VERIFY
158 #ifdef USE_EXTERNAL_URI_LOADER
159 ",external-uri-loader"
186 fusage(FILE * f, int err)
189 /* FIXME: gettextize? */
190 fprintf(f, "usage: w3m [options] [URL or filename]\noptions:\n");
191 fprintf(f, " -t tab set tab width\n");
192 fprintf(f, " -r ignore backspace effect\n");
193 fprintf(f, " -l line # of preserved line (default 10000)\n");
195 fprintf(f, " -I charset document charset\n");
196 fprintf(f, " -O charset display/output charset\n");
197 #ifndef DEBIAN /* disabled by ukai: -s is used for squeeze multi lines */
198 fprintf(f, " -e EUC-JP\n");
199 fprintf(f, " -s Shift_JIS\n");
200 fprintf(f, " -j JIS\n");
203 fprintf(f, " -B load bookmark\n");
204 fprintf(f, " -bookmark file specify bookmark file\n");
205 fprintf(f, " -T type specify content-type\n");
206 fprintf(f, " -m internet message mode\n");
207 fprintf(f, " -v visual startup mode\n");
209 fprintf(f, " -M monochrome display\n");
210 #endif /* USE_COLOR */
212 " -N open URL of command line on each new tab\n");
213 fprintf(f, " -F automatically render frame\n");
215 " -cols width specify column width (used with -dump)\n");
217 " -ppc count specify the number of pixels per character (4.0...32.0)\n");
220 " -ppl count specify the number of pixels per line (4.0...64.0)\n");
222 fprintf(f, " -dump dump formatted page into stdout\n");
224 " -dump_head dump response of HEAD request into stdout\n");
225 fprintf(f, " -dump_source dump page source into stdout\n");
226 fprintf(f, " -dump_both dump HEAD and source into stdout\n");
228 " -dump_extra dump HEAD, source, and extra information into stdout\n");
229 fprintf(f, " -post file use POST method with file content\n");
230 fprintf(f, " -header string insert string as a header\n");
231 fprintf(f, " +<num> goto <num> line\n");
232 fprintf(f, " -num show line number\n");
233 fprintf(f, " -no-proxy don't use proxy\n");
235 fprintf(f, " -4 IPv4 only (-o dns_order=4)\n");
236 fprintf(f, " -6 IPv6 only (-o dns_order=6)\n");
239 fprintf(f, " -no-mouse don't use mouse\n");
240 #endif /* USE_MOUSE */
243 " -cookie use cookie (-no-cookie: don't use cookie)\n");
244 #endif /* USE_COOKIE */
245 fprintf(f, " -pauth user:pass proxy authentication\n");
246 fprintf(f, " -graph use graphic character\n");
247 fprintf(f, " -no-graph don't use graphic character\n");
248 #ifdef DEBIAN /* replaced by ukai: pager requires -s */
249 fprintf(f, " -s squeeze multiple blank lines\n");
251 fprintf(f, " -S squeeze multiple blank lines\n");
253 fprintf(f, " -W toggle wrap search mode\n");
254 fprintf(f, " -X don't use termcap init/deinit\n");
256 " -title[=TERM] set buffer name to terminal title string\n");
257 fprintf(f, " -o opt=value assign value to config option\n");
258 fprintf(f, " -show-option print all config options\n");
259 fprintf(f, " -config file specify config file\n");
260 fprintf(f, " -help print this usage message\n");
261 fprintf(f, " -version print w3m version\n");
262 fprintf(f, " -reqlog write request logfile\n");
263 fprintf(f, " -debug DO NOT USE\n");
271 static char *getCodePage(void);
275 static GC_warn_proc orig_GC_warn_proc = NULL;
276 #define GC_WARN_KEEP_MAX (20)
279 wrap_GC_warn_proc(char *msg, GC_word arg)
286 } msg_ring[GC_WARN_KEEP_MAX];
293 j = (i + n) % (sizeof(msg_ring) / sizeof(msg_ring[0]));
294 msg_ring[j].msg = msg;
295 msg_ring[j].arg = arg;
297 if (n < sizeof(msg_ring) / sizeof(msg_ring[0]))
305 for (; n > 0; --n, ++i) {
306 i %= sizeof(msg_ring) / sizeof(msg_ring[0]);
308 printf(msg_ring[i].msg, (unsigned long)msg_ring[i].arg);
309 sleep_till_anykey(1, 1);
315 else if (orig_GC_warn_proc)
316 orig_GC_warn_proc(msg, arg);
318 fprintf(stderr, msg, (unsigned long)arg);
329 while ((pid = waitpid(-1, &p_stat, WNOHANG)) > 0) {
335 while ((pid = wait3(&p_stat, WNOHANG, NULL)) > 0) {
341 mySignal(SIGCHLD, sig_chld);
347 make_optional_header_string(char *s)
352 if (strchr(s, '\n') || strchr(s, '\r'))
354 for (p = s; *p && *p != ':'; p++) ;
355 if (*p != ':' || p == s)
357 hs = Strnew_size(strlen(s) + 3);
358 Strcopy_charp_n(hs, s, p - s);
359 if (!Strcasecmp_charp(hs, "content-type"))
360 override_content_type = TRUE;
361 Strcat_charp(hs, ": ");
362 if (*(++p)) { /* not null header */
363 SKIP_BLANKS(p); /* skip white spaces */
366 Strcat_charp(hs, "\r\n");
371 main(int argc, char **argv, char **envp)
373 Buffer *newbuf = NULL;
377 char *line_str = NULL;
381 int load_bookmark = FALSE;
382 int visual_start = FALSE;
383 int open_new_tab = FALSE;
384 char search_header = FALSE;
385 char *default_type = NULL;
386 char *post_file = NULL;
390 wc_uint8 auto_detect;
396 #if defined(ENABLE_NLS) || (defined(USE_M17N) && defined(HAVE_LANGINFO_CODESET))
397 setlocale(LC_ALL, "");
400 bindtextdomain(PACKAGE, LOCALEDIR);
404 #ifndef HAVE_SYS_ERRLIST
405 prepare_sys_errlist();
406 #endif /* not HAVE_SYS_ERRLIST */
408 NO_proxy_domains = newTextList();
409 fileToDelete = newTextList();
411 load_argv = New_N(char *, argc - 1);
414 CurrentDir = currentdir();
415 CurrentPid = (int)getpid();
419 /* argument search 1 */
420 for (i = 1; i < argc; i++) {
421 if (*argv[i] == '-') {
422 if (!strcmp("-config", argv[i])) {
426 config_file = argv[i];
429 else if (!strcmp("-h", argv[i]) || !strcmp("-help", argv[i]))
431 else if (!strcmp("-V", argv[i]) || !strcmp("-version", argv[i])) {
439 if (non_null(Locale = getenv("LC_ALL")) ||
440 non_null(Locale = getenv("LC_CTYPE")) ||
441 non_null(Locale = getenv("LANG"))) {
442 DisplayCharset = wc_guess_locale_charset(Locale, DisplayCharset);
443 DocumentCharset = wc_guess_locale_charset(Locale, DocumentCharset);
444 SystemCharset = wc_guess_locale_charset(Locale, SystemCharset);
447 CodePage = wc_guess_charset(getCodePage(), 0);
449 DisplayCharset = DocumentCharset = SystemCharset = CodePage;
453 /* initializations */
456 LoadHist = newHist();
457 SaveHist = newHist();
458 ShellHist = newHist();
459 TextHist = newHist();
463 if (FollowLocale && Locale) {
464 DisplayCharset = wc_guess_locale_charset(Locale, DisplayCharset);
465 SystemCharset = wc_guess_locale_charset(Locale, SystemCharset);
467 auto_detect = WcOption.auto_detect;
468 BookmarkCharset = DocumentCharset;
471 if (!non_null(HTTP_proxy) &&
472 ((p = getenv("HTTP_PROXY")) ||
473 (p = getenv("http_proxy")) || (p = getenv("HTTP_proxy"))))
476 if (!non_null(HTTPS_proxy) &&
477 ((p = getenv("HTTPS_PROXY")) ||
478 (p = getenv("https_proxy")) || (p = getenv("HTTPS_proxy"))))
480 if (HTTPS_proxy == NULL && non_null(HTTP_proxy))
481 HTTPS_proxy = HTTP_proxy;
484 if (!non_null(GOPHER_proxy) &&
485 ((p = getenv("GOPHER_PROXY")) ||
486 (p = getenv("gopher_proxy")) || (p = getenv("GOPHER_proxy"))))
488 #endif /* USE_GOPHER */
489 if (!non_null(FTP_proxy) &&
490 ((p = getenv("FTP_PROXY")) ||
491 (p = getenv("ftp_proxy")) || (p = getenv("FTP_proxy"))))
493 if (!non_null(NO_proxy) &&
494 ((p = getenv("NO_PROXY")) ||
495 (p = getenv("no_proxy")) || (p = getenv("NO_proxy"))))
498 if (!non_null(NNTP_server) && (p = getenv("NNTPSERVER")) != NULL)
500 if (!non_null(NNTP_mode) && (p = getenv("NNTPMODE")) != NULL)
504 if (!non_null(Editor) && (p = getenv("EDITOR")) != NULL)
506 if (!non_null(Mailer) && (p = getenv("MAILER")) != NULL)
509 /* argument search 2 */
512 if (*argv[i] == '-') {
513 if (!strcmp("-t", argv[i])) {
516 if (atoi(argv[i]) > 0)
517 Tabstop = atoi(argv[i]);
519 else if (!strcmp("-r", argv[i]))
521 else if (!strcmp("-l", argv[i])) {
524 if (atoi(argv[i]) > 0)
525 PagerMax = atoi(argv[i]);
528 #ifndef DEBIAN /* XXX: use -o kanjicode={S|J|E} */
529 else if (!strcmp("-s", argv[i]))
530 DisplayCharset = WC_CES_SHIFT_JIS;
531 else if (!strcmp("-j", argv[i]))
532 DisplayCharset = WC_CES_ISO_2022_JP;
533 else if (!strcmp("-e", argv[i]))
534 DisplayCharset = WC_CES_EUC_JP;
536 else if (!strncmp("-I", argv[i], 2)) {
537 if (argv[i][2] != '\0')
544 DocumentCharset = wc_guess_charset_short(p, DocumentCharset);
545 WcOption.auto_detect = WC_OPT_DETECT_OFF;
546 UseContentCharset = FALSE;
548 else if (!strncmp("-O", argv[i], 2)) {
549 if (argv[i][2] != '\0')
556 DisplayCharset = wc_guess_charset_short(p, DisplayCharset);
559 else if (!strcmp("-graph", argv[i]))
560 UseGraphicChar = TRUE;
561 else if (!strcmp("-no-graph", argv[i]))
562 UseGraphicChar = FALSE;
563 else if (!strcmp("-T", argv[i])) {
566 DefaultType = default_type = argv[i];
568 else if (!strcmp("-m", argv[i]))
569 SearchHeader = search_header = TRUE;
570 else if (!strcmp("-v", argv[i]))
572 else if (!strcmp("-N", argv[i]))
575 else if (!strcmp("-M", argv[i]))
577 #endif /* USE_COLOR */
578 else if (!strcmp("-B", argv[i]))
579 load_bookmark = TRUE;
580 else if (!strcmp("-bookmark", argv[i])) {
583 BookmarkFile = argv[i];
584 if (BookmarkFile[0] != '~' && BookmarkFile[0] != '/') {
585 Str tmp = Strnew_charp(CurrentDir);
586 if (Strlastchar(tmp) != '/')
587 Strcat_char(tmp, '/');
588 Strcat_charp(tmp, BookmarkFile);
589 BookmarkFile = cleanupName(tmp->ptr);
592 else if (!strcmp("-F", argv[i]))
594 else if (!strcmp("-W", argv[i])) {
600 else if (!strcmp("-dump", argv[i]))
601 w3m_dump = DUMP_BUFFER;
602 else if (!strcmp("-dump_source", argv[i]))
603 w3m_dump = DUMP_SOURCE;
604 else if (!strcmp("-dump_head", argv[i]))
605 w3m_dump = DUMP_HEAD;
606 else if (!strcmp("-dump_both", argv[i]))
607 w3m_dump = (DUMP_HEAD | DUMP_SOURCE);
608 else if (!strcmp("-dump_extra", argv[i]))
609 w3m_dump = (DUMP_HEAD | DUMP_SOURCE | DUMP_EXTRA);
610 else if (!strcmp("-halfdump", argv[i]))
611 w3m_dump = DUMP_HALFDUMP;
612 else if (!strcmp("-halfload", argv[i])) {
615 DefaultType = default_type = "text/html";
617 else if (!strcmp("-backend", argv[i])) {
620 else if (!strcmp("-backend_batch", argv[i])) {
624 if (!backend_batch_commands)
625 backend_batch_commands = newTextList();
626 pushText(backend_batch_commands, argv[i]);
628 else if (!strcmp("-cols", argv[i])) {
631 COLS = atoi(argv[i]);
633 else if (!strcmp("-ppc", argv[i])) {
638 if (ppc >= MINIMUM_PIXEL_PER_CHAR &&
639 ppc <= MAXIMUM_PIXEL_PER_CHAR) {
640 pixel_per_char = ppc;
641 set_pixel_per_char = TRUE;
645 else if (!strcmp("-ppl", argv[i])) {
650 if (ppc >= MINIMUM_PIXEL_PER_CHAR &&
651 ppc <= MAXIMUM_PIXEL_PER_CHAR * 2) {
652 pixel_per_line = ppc;
653 set_pixel_per_line = TRUE;
657 else if (!strcmp("-num", argv[i]))
659 else if (!strcmp("-no-proxy", argv[i]))
662 else if (!strcmp("-4", argv[i]) || !strcmp("-6", argv[i]))
663 set_param_option(Sprintf("dns_order=%c", argv[i][1])->ptr);
665 else if (!strcmp("-post", argv[i])) {
670 else if (!strcmp("-header", argv[i])) {
674 if ((hs = make_optional_header_string(argv[i])) != NULL) {
675 if (header_string == NULL)
678 Strcat(header_string, hs);
686 else if (!strcmp("-no-mouse", argv[i])) {
689 #endif /* USE_MOUSE */
691 else if (!strcmp("-no-cookie", argv[i])) {
693 accept_cookie = FALSE;
695 else if (!strcmp("-cookie", argv[i])) {
697 accept_cookie = TRUE;
699 #endif /* USE_COOKIE */
700 else if (!strcmp("-pauth", argv[i])) {
703 proxy_auth_cookie = Strnew_m_charp("Basic ",
704 encodeB(argv[i])->ptr,
712 else if (!strcmp("-s", argv[i]))
714 else if (!strcmp("-S", argv[i]))
716 squeezeBlankLine = TRUE;
717 else if (!strcmp("-X", argv[i]))
718 Do_not_use_ti_te = TRUE;
719 else if (!strcmp("-title", argv[i]))
720 displayTitleTerm = getenv("TERM");
721 else if (!strncmp("-title=", argv[i], 7))
722 displayTitleTerm = argv[i] + 7;
723 else if (!strcmp("-o", argv[i]) ||
724 !strcmp("-show-option", argv[i])) {
725 if (!strcmp("-show-option", argv[i]) || ++i >= argc ||
726 !strcmp(argv[i], "?")) {
730 if (!set_param_option(argv[i])) {
731 /* option set failed */
732 /* FIXME: gettextize? */
733 fprintf(stderr, "%s: bad option\n", argv[i]);
738 else if (!strcmp("-dummy", argv[i])) {
741 else if (!strcmp("-debug", argv[i])) {
744 else if (!strcmp("-reqlog",argv[i])) {
745 w3m_reqlog=rcFile("request.log");
751 else if (*argv[i] == '+') {
752 line_str = argv[i] + 1;
755 load_argv[load_argc++] = argv[i];
766 #ifdef __MINGW32_VERSION
771 wVerReq = MAKEWORD(1, 1);
773 err = WSAStartup(wVerReq, &WSAData);
776 fprintf(stderr, "Can't find winsock\n");
788 if (BookmarkFile == NULL)
789 BookmarkFile = rcFile(BOOKMARK);
791 if (!isatty(1) && !w3m_dump) {
792 /* redirected output */
793 w3m_dump = DUMP_BUFFER;
800 #ifdef USE_BINMODE_STREAM
801 setmode(fileno(stdout), O_BINARY);
803 if (!w3m_dump && !w3m_backend) {
806 mySignal(SIGWINCH, resize_hook);
807 #else /* not SIGWINCH */
810 #endif /* not SIGWINCH */
813 else if (w3m_halfdump && displayImage)
820 #endif /* USE_COOKIE */
823 loadHistory(URLHist);
824 #endif /* not USE_HISTORY */
827 wtf_init(DocumentCharset, DisplayCharset);
829 * WcOption.pre_conv = WC_TRUE;
837 mySignal(SIGINT, SIG_IGN);
839 mySignal(SIGCHLD, sig_chld);
842 mySignal(SIGPIPE, SigPipe);
845 orig_GC_warn_proc = GC_set_warn_proc(wrap_GC_warn_proc);
847 if (load_argc == 0) {
848 /* no URL specified */
850 redin = newFileStream(fdopen(dup(0), "rb"), (void (*)())pclose);
851 newbuf = openGeneralPagerBuffer(redin);
854 else if (load_bookmark) {
855 newbuf = loadGeneralFile(BookmarkFile, NULL, NO_REFERER, 0, NULL);
857 Strcat_charp(err_msg, "w3m: Can't load bookmark.\n");
859 else if (visual_start) {
860 /* FIXME: gettextize? */
864 ("<title>W3M startup page</title><center><b>Welcome to ");
865 Strcat_charp(s_page, "<a href='http://w3m.sourceforge.net/'>");
866 Strcat_m_charp(s_page,
867 "w3m</a>!<p><p>This is w3m version ",
869 "<br>Written by <a href='mailto:aito@fw.ipsj.or.jp'>Akinori Ito</a>",
872 Strcat_m_charp(s_page,
873 "<p>Debian package is maintained by <a href='mailto:ukai@debian.or.jp'>Fumitoshi UKAI</a>.",
874 "You can read <a href='file:///usr/share/doc/w3m/'>w3m documents on your local system</a>.",
877 newbuf = loadHTMLString(s_page);
879 Strcat_charp(err_msg, "w3m: Can't load string.\n");
880 else if (newbuf != NO_BUFFER)
881 newbuf->bufferprop |= (BP_INTERNAL | BP_NO_URL);
883 else if ((p = getenv("HTTP_HOME")) != NULL ||
884 (p = getenv("WWW_HOME")) != NULL) {
885 newbuf = loadGeneralFile(p, NULL, NO_REFERER, 0, NULL);
887 Strcat(err_msg, Sprintf("w3m: Can't load %s.\n", p));
888 else if (newbuf != NO_BUFFER)
889 pushHashHist(URLHist, parsedURL2Str(&newbuf->currentURL)->ptr);
896 if (newbuf == NULL) {
900 fprintf(stderr, "%s", err_msg->ptr);
908 for (; i < load_argc; i++) {
910 SearchHeader = search_header;
911 DefaultType = default_type;
912 if (w3m_dump == DUMP_HEAD) {
913 request = New(FormList);
914 request->method = FORM_METHOD_HEAD;
916 loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0,
920 if (post_file && i == 0) {
923 if (!strcmp(post_file, "-"))
926 fp = fopen(post_file, "r");
928 /* FIXME: gettextize? */
930 Sprintf("w3m: Can't open %s.\n", post_file));
933 body = Strfgetall(fp);
937 newFormList(NULL, "post", NULL, NULL, NULL, NULL,
939 request->body = body->ptr;
940 request->boundary = NULL;
941 request->length = body->length;
947 loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0,
950 if (newbuf == NULL) {
951 /* FIXME: gettextize? */
953 Sprintf("w3m: Can't load %s.\n", load_argv[i]));
956 else if (newbuf == NO_BUFFER)
958 switch (newbuf->real_scheme) {
963 unshiftHist(LoadHist, conv_from_system(load_argv[i]));
965 pushHashHist(URLHist, parsedURL2Str(&newbuf->currentURL)->ptr);
969 else if (newbuf == NO_BUFFER)
971 if (newbuf->pagerSource ||
972 (newbuf->real_scheme == SCM_LOCAL && newbuf->header_source &&
973 newbuf->currentURL.file && strcmp(newbuf->currentURL.file, "-")))
974 newbuf->search_header = search_header;
975 if (CurrentTab == NULL) {
976 FirstTab = LastTab = CurrentTab = newTab();
978 Firstbuf = Currentbuf = newbuf;
980 else if (open_new_tab) {
982 Currentbuf->nextBuffer = newbuf;
983 delBuffer(Currentbuf);
986 Currentbuf->nextBuffer = newbuf;
989 if (!w3m_dump || w3m_dump == DUMP_BUFFER) {
990 if (Currentbuf->frameset != NULL && RenderFrame)
1003 if (err_msg->length)
1004 fprintf(stderr, "%s", err_msg->ptr);
1007 #endif /* USE_COOKIE */
1011 if (add_download_list) {
1012 add_download_list = FALSE;
1013 CurrentTab = LastTab;
1015 FirstTab = LastTab = CurrentTab = newTab();
1018 if (!Firstbuf || Firstbuf == NO_BUFFER) {
1019 Firstbuf = Currentbuf = newBuffer(INIT_BUFFER_WIDTH);
1020 Currentbuf->bufferprop = BP_INTERNAL | BP_NO_URL;
1021 Currentbuf->buffername = DOWNLOAD_LIST_TITLE;
1024 Currentbuf = Firstbuf;
1028 CurrentTab = FirstTab;
1029 if (!FirstTab || !Firstbuf || Firstbuf == NO_BUFFER) {
1030 if (newbuf == NO_BUFFER) {
1032 /* FIXME: gettextize? */
1033 inputChar("Hit any key to quit w3m:");
1037 if (err_msg->length)
1038 fprintf(stderr, "%s", err_msg->ptr);
1039 if (newbuf == NO_BUFFER) {
1042 #endif /* USE_COOKIE */
1043 if (!err_msg->length)
1048 if (err_msg->length)
1049 disp_message_nsec(err_msg->ptr, FALSE, 1, TRUE, FALSE);
1051 SearchHeader = FALSE;
1054 UseContentCharset = TRUE;
1055 WcOption.auto_detect = auto_detect;
1058 Currentbuf = Firstbuf;
1059 displayBuffer(Currentbuf, B_FORCE_REDRAW);
1064 if (add_download_list) {
1065 add_download_list = FALSE;
1068 if (Currentbuf->submit) {
1069 Anchor *a = Currentbuf->submit;
1070 Currentbuf->submit = NULL;
1071 gotoLine(Currentbuf, a->start.line);
1072 Currentbuf->pos = a->start.pos;
1076 /* event processing */
1079 CurrentKeyData = NULL;
1080 CurrentCmdData = (char *)CurrentEvent->data;
1081 w3mFuncList[CurrentEvent->cmd].func();
1082 CurrentCmdData = NULL;
1083 CurrentEvent = CurrentEvent->next;
1086 /* get keypress event */
1088 if (Currentbuf->event) {
1089 if (Currentbuf->event->status != AL_UNSET) {
1090 CurrentAlarm = Currentbuf->event;
1091 if (CurrentAlarm->sec == 0) { /* refresh (0sec) */
1092 Currentbuf->event = NULL;
1094 CurrentKeyData = NULL;
1095 CurrentCmdData = (char *)CurrentAlarm->data;
1096 w3mFuncList[CurrentAlarm->cmd].func();
1097 CurrentCmdData = NULL;
1102 Currentbuf->event = NULL;
1104 if (!Currentbuf->event)
1105 CurrentAlarm = &DefaultAlarm;
1108 mouse_action.in_action = FALSE;
1111 #endif /* USE_MOUSE */
1113 if (CurrentAlarm->sec > 0) {
1114 mySignal(SIGALRM, SigAlarm);
1115 alarm(CurrentAlarm->sec);
1119 mySignal(SIGWINCH, resize_hook);
1122 if (activeImage && displayImage && Currentbuf->img &&
1123 !Currentbuf->image_loaded) {
1126 if (need_resize_screen)
1129 loadImage(Currentbuf, IMG_FLAG_NEXT);
1130 } while (sleep_till_anykey(1, 0) <= 0);
1139 if (need_resize_screen)
1141 } while (sleep_till_anykey(1, 0) <= 0);
1146 if (CurrentAlarm->sec > 0) {
1153 #endif /* USE_MOUSE */
1154 if (IS_ASCII(c)) { /* Ascii */
1156 if(((prec_num && c == '0') || '1' <= c) && (c <= '9')) {
1157 prec_num = prec_num * 10 + (int)(c - '0');
1158 if (prec_num > PREC_LIMIT)
1159 prec_num = PREC_LIMIT;
1162 set_buffer_environ(Currentbuf);
1163 save_buffer_position(Currentbuf);
1164 keyPressEventProc((int)c);
1169 set_buffer_environ(Currentbuf);
1170 save_buffer_position(Currentbuf);
1171 keyPressEventProc((int)c);
1175 prev_key = CurrentKey;
1177 CurrentKeyData = NULL;
1182 keyPressEventProc(int c)
1185 w3mFuncList[(int)GlobalKeymap[c]].func();
1189 pushEvent(int cmd, void *data)
1198 LastEvent->next = event;
1200 CurrentEvent = event;
1205 dump_source(Buffer *buf)
1209 if (buf->sourcefile == NULL)
1211 f = fopen(buf->sourcefile, "r");
1214 while (c = fgetc(f), !feof(f)) {
1221 dump_head(Buffer *buf)
1225 if (buf->document_header == NULL) {
1226 if (w3m_dump & DUMP_EXTRA)
1230 for (ti = buf->document_header->first; ti; ti = ti->next) {
1233 wc_conv_strict(ti->ptr, InnerCharset,
1234 buf->document_charset)->ptr);
1236 printf("%s", ti->ptr);
1243 dump_extra(Buffer *buf)
1245 printf("W3m-current-url: %s\n", parsedURL2Str(&buf->currentURL)->ptr);
1247 printf("W3m-base-url: %s\n", parsedURL2Str(buf->baseURL)->ptr);
1249 printf("W3m-document-charset: %s\n",
1250 wc_ces_to_charset(buf->document_charset));
1253 if (buf->ssl_certificate) {
1256 for (p = buf->ssl_certificate; *p; p++) {
1257 Strcat_char(tmp, *p);
1259 for (; *(p + 1) == '\n'; p++) ;
1261 Strcat_char(tmp, '\t');
1264 if (Strlastchar(tmp) != '\n')
1265 Strcat_char(tmp, '\n');
1266 printf("W3m-ssl-certificate: %s", tmp->ptr);
1272 do_dump(Buffer *buf)
1274 MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
1276 prevtrap = mySignal(SIGINT, intTrap);
1277 if (SETJMP(IntReturn) != 0) {
1278 mySignal(SIGINT, prevtrap);
1281 if (w3m_dump & DUMP_EXTRA)
1283 if (w3m_dump & DUMP_HEAD)
1285 if (w3m_dump & DUMP_SOURCE)
1287 if (w3m_dump == DUMP_BUFFER)
1288 saveBuffer(buf, stdout, FALSE);
1289 mySignal(SIGINT, prevtrap);
1292 DEFUN(nulcmd, NOTHING NULL @@@, "Do nothing")
1297 DEFUN(pcmap, PCMAP, "pcmap")
1299 w3mFuncList[(int)PcKeymap[(int)getch()]].func();
1301 #else /* not __EMX__ */
1309 escKeyProc(int c, int esc, unsigned char *map)
1311 if (CurrentKey >= 0 && CurrentKey & K_MULTI) {
1312 unsigned char **mmap;
1313 mmap = (unsigned char **)getKeyData(MULTI_KEY(CurrentKey));
1330 esc |= (CurrentKey & ~0xFFFF);
1332 CurrentKey = esc | c;
1333 w3mFuncList[(int)map[c]].func();
1336 DEFUN(escmap, ESCMAP, "ESC map")
1341 escKeyProc((int)c, K_ESC, EscKeymap);
1344 DEFUN(escbmap, ESCBMAP, "ESC [ map")
1353 escKeyProc((int)c, K_ESCB, EscBKeymap);
1360 d = (int)c - (int)'0';
1363 d = d * 10 + (int)c - (int)'0';
1367 escKeyProc((int)d, K_ESCD, EscDKeymap);
1370 DEFUN(multimap, MULTIMAP, "multimap")
1375 CurrentKey = K_MULTI | (CurrentKey << 16) | c;
1376 escKeyProc((int)c, 0, NULL);
1381 tmpClearBuffer(Buffer *buf)
1383 if (buf->pagerSource == NULL && writeBufferCache(buf) == 0) {
1384 buf->firstLine = NULL;
1385 buf->topLine = NULL;
1386 buf->currentLine = NULL;
1387 buf->lastLine = NULL;
1391 static Str currentURL(void);
1401 if ((fp = fopen(rcFile("bufinfo"), "w")) == NULL) {
1404 fprintf(fp, "%s\n", currentURL()->ptr);
1410 pushBuffer(Buffer *buf)
1415 deleteImage(Currentbuf);
1418 tmpClearBuffer(Currentbuf);
1419 if (Firstbuf == Currentbuf) {
1420 buf->nextBuffer = Firstbuf;
1421 Firstbuf = Currentbuf = buf;
1423 else if ((b = prevBuffer(Firstbuf, Currentbuf)) != NULL) {
1424 b->nextBuffer = buf;
1425 buf->nextBuffer = Currentbuf;
1435 delBuffer(Buffer *buf)
1439 if (Currentbuf == buf)
1440 Currentbuf = buf->nextBuffer;
1441 Firstbuf = deleteBuffer(Firstbuf, buf);
1443 Currentbuf = Firstbuf;
1447 repBuffer(Buffer *oldbuf, Buffer *buf)
1449 Firstbuf = replaceBuffer(Firstbuf, oldbuf, buf);
1456 { /* Interrupt catcher */
1457 LONGJMP(IntReturn, 0);
1462 static MySignalHandler
1463 resize_hook(SIGNAL_ARG)
1465 need_resize_screen = TRUE;
1466 mySignal(SIGWINCH, resize_hook);
1473 need_resize_screen = FALSE;
1477 displayBuffer(Currentbuf, B_FORCE_REDRAW);
1479 #endif /* SIGWINCH */
1482 static MySignalHandler
1488 mySignal(SIGPIPE, SigPipe);
1494 * Command functions: These functions are called with a keystroke.
1498 nscroll(int n, int mode)
1500 Buffer *buf = Currentbuf;
1501 Line *top = buf->topLine, *cur = buf->currentLine;
1502 int lnum, tlnum, llnum, diff_n;
1504 if (buf->firstLine == NULL)
1506 lnum = cur->linenumber;
1507 buf->topLine = lineSkip(buf, top, n, FALSE);
1508 if (buf->topLine == top) {
1510 if (lnum < buf->topLine->linenumber)
1511 lnum = buf->topLine->linenumber;
1512 else if (lnum > buf->lastLine->linenumber)
1513 lnum = buf->lastLine->linenumber;
1516 tlnum = buf->topLine->linenumber;
1517 llnum = buf->topLine->linenumber + buf->LINES - 1;
1518 if (nextpage_topline)
1521 diff_n = n - (tlnum - top->linenumber);
1523 lnum = tlnum + diff_n;
1525 lnum = llnum + diff_n;
1527 gotoLine(buf, lnum);
1530 if (buf->currentLine->bpos &&
1531 buf->currentLine->bwidth >= buf->currentColumn + buf->visualpos)
1534 while (buf->currentLine->next && buf->currentLine->next->bpos &&
1535 buf->currentLine->bwidth + buf->currentLine->width <
1536 buf->currentColumn + buf->visualpos)
1537 cursorDown0(buf, 1);
1541 if (buf->currentLine->bwidth + buf->currentLine->width <
1542 buf->currentColumn + buf->visualpos)
1545 while (buf->currentLine->prev && buf->currentLine->bpos &&
1546 buf->currentLine->bwidth >=
1547 buf->currentColumn + buf->visualpos)
1551 displayBuffer(buf, mode);
1554 /* Move page forward */
1555 DEFUN(pgFore, NEXT_PAGE, "Move to next page")
1558 nscroll(searchKeyNum() * (Currentbuf->LINES - 1), B_NORMAL);
1560 nscroll(prec_num ? searchKeyNum() : searchKeyNum()
1561 * (Currentbuf->LINES - 1), prec_num ? B_SCROLL : B_NORMAL);
1564 /* Move page backward */
1565 DEFUN(pgBack, PREV_PAGE, "Move to previous page")
1568 nscroll(-searchKeyNum() * (Currentbuf->LINES - 1), B_NORMAL);
1570 nscroll(-(prec_num ? searchKeyNum() : searchKeyNum()
1571 * (Currentbuf->LINES - 1)), prec_num ? B_SCROLL : B_NORMAL);
1575 DEFUN(lup1, UP, "Scroll up one line")
1577 nscroll(searchKeyNum(), B_SCROLL);
1581 DEFUN(ldown1, DOWN, "Scroll down one line")
1583 nscroll(-searchKeyNum(), B_SCROLL);
1586 /* move cursor position to the center of screen */
1587 DEFUN(ctrCsrV, CENTER_V, "Move to the center column")
1590 if (Currentbuf->firstLine == NULL)
1592 offsety = Currentbuf->LINES / 2 - Currentbuf->cursorY;
1595 Currentbuf->currentLine = lineSkip(Currentbuf,
1596 Currentbuf->currentLine, offsety,
1599 Currentbuf->topLine =
1600 lineSkip(Currentbuf, Currentbuf->topLine, -offsety, FALSE);
1601 arrangeLine(Currentbuf);
1602 displayBuffer(Currentbuf, B_NORMAL);
1606 DEFUN(ctrCsrH, CENTER_H, "Move to the center line")
1609 if (Currentbuf->firstLine == NULL)
1611 offsetx = Currentbuf->cursorX - Currentbuf->COLS / 2;
1613 columnSkip(Currentbuf, offsetx);
1614 arrangeCursor(Currentbuf);
1615 displayBuffer(Currentbuf, B_NORMAL);
1620 DEFUN(rdrwSc, REDRAW, "Redraw screen")
1623 arrangeCursor(Currentbuf);
1624 displayBuffer(Currentbuf, B_FORCE_REDRAW);
1633 for (pos = 0; pos < l->size; pos++)
1634 l->propBuf[pos] &= ~PE_MARK;
1637 /* search by regular expression */
1639 srchcore(char *volatile str, int (*func) (Buffer *, char *))
1641 MySignalHandler(*prevtrap) ();
1642 volatile int i, result = SR_NOTFOUND;
1644 if (str != NULL && str != SearchString)
1646 if (SearchString == NULL || *SearchString == '\0')
1649 str = conv_search_string(SearchString, DisplayCharset);
1650 prevtrap = mySignal(SIGINT, intTrap);
1652 if (SETJMP(IntReturn) == 0) {
1653 for (i = 0; i < PREC_NUM; i++) {
1654 result = func(Currentbuf, str);
1655 if (i < PREC_NUM - 1 && result & SR_FOUND)
1656 clear_mark(Currentbuf->currentLine);
1659 mySignal(SIGINT, prevtrap);
1665 disp_srchresult(int result, char *prompt, char *str)
1669 if (result & SR_NOTFOUND)
1670 disp_message(Sprintf("Not found: %s", str)->ptr, TRUE);
1671 else if (result & SR_WRAPPED)
1672 disp_message(Sprintf("Search wrapped: %s", str)->ptr, TRUE);
1673 else if (show_srch_str)
1674 disp_message(Sprintf("%s%s", prompt, str)->ptr, TRUE);
1678 dispincsrch(int ch, Str buf, Lineprop *prop)
1681 static Line *currentLine;
1684 int do_next_search = FALSE;
1686 if (ch == 0 && buf == NULL) {
1687 SAVE_BUFPOSITION(&sbuf); /* search starting point */
1688 currentLine = sbuf.currentLine;
1696 searchRoutine = backwardSearch;
1697 do_next_search = TRUE;
1700 searchRoutine = forwardSearch;
1701 do_next_search = TRUE;
1706 migemo_active = -migemo_active;
1712 return ch; /* use InputKeymap */
1715 if (do_next_search) {
1717 if (searchRoutine == forwardSearch)
1718 Currentbuf->pos += 1;
1719 SAVE_BUFPOSITION(&sbuf);
1720 if (srchcore(str, searchRoutine) == SR_NOTFOUND
1721 && searchRoutine == forwardSearch) {
1722 Currentbuf->pos -= 1;
1723 SAVE_BUFPOSITION(&sbuf);
1725 arrangeCursor(Currentbuf);
1726 displayBuffer(Currentbuf, B_FORCE_REDRAW);
1727 clear_mark(Currentbuf->currentLine);
1731 return 020; /* _prev completion for C-s C-s */
1734 RESTORE_BUFPOSITION(&sbuf);
1735 arrangeCursor(Currentbuf);
1736 srchcore(str, searchRoutine);
1737 arrangeCursor(Currentbuf);
1738 currentLine = Currentbuf->currentLine;
1739 pos = Currentbuf->pos;
1741 displayBuffer(Currentbuf, B_FORCE_REDRAW);
1742 clear_mark(Currentbuf->currentLine);
1745 while (*str++ != '\0') {
1746 if (migemo_active > 0)
1747 *prop++ |= PE_UNDER;
1749 *prop++ &= ~PE_UNDER;
1756 isrch(int (*func) (Buffer *, char *), char *prompt)
1760 SAVE_BUFPOSITION(&sbuf);
1761 dispincsrch(0, NULL, NULL); /* initialize incremental search state */
1763 searchRoutine = func;
1764 str = inputLineHistSearch(prompt, NULL, IN_STRING, TextHist, dispincsrch);
1766 RESTORE_BUFPOSITION(&sbuf);
1768 displayBuffer(Currentbuf, B_FORCE_REDRAW);
1772 srch(int (*func) (Buffer *, char *), char *prompt)
1779 str = searchKeyData();
1780 if (str == NULL || *str == '\0') {
1781 str = inputStrHist(prompt, NULL, TextHist);
1782 if (str != NULL && *str == '\0')
1785 displayBuffer(Currentbuf, B_NORMAL);
1790 pos = Currentbuf->pos;
1791 if (func == forwardSearch)
1792 Currentbuf->pos += 1;
1793 result = srchcore(str, func);
1794 if (result & SR_FOUND)
1795 clear_mark(Currentbuf->currentLine);
1797 Currentbuf->pos = pos;
1798 displayBuffer(Currentbuf, B_NORMAL);
1800 disp_srchresult(result, prompt, str);
1801 searchRoutine = func;
1804 /* Search regular expression forward */
1806 DEFUN(srchfor, SEARCH SEARCH_FORE WHEREIS, "Search forward")
1808 srch(forwardSearch, "Forward: ");
1811 DEFUN(isrchfor, ISEARCH, "Incremental search forward")
1813 isrch(forwardSearch, "I-search: ");
1816 /* Search regular expression backward */
1818 DEFUN(srchbak, SEARCH_BACK, "Search backward")
1820 srch(backwardSearch, "Backward: ");
1823 DEFUN(isrchbak, ISEARCH_BACK, "Incremental search backward")
1825 isrch(backwardSearch, "I-search backward: ");
1829 srch_nxtprv(int reverse)
1833 static int (*routine[2]) (Buffer *, char *) = {
1834 forwardSearch, backwardSearch
1838 if (searchRoutine == NULL) {
1839 /* FIXME: gettextize? */
1840 disp_message("No previous regular expression", TRUE);
1845 if (searchRoutine == backwardSearch)
1848 Currentbuf->pos += 1;
1849 result = srchcore(SearchString, routine[reverse]);
1850 if (result & SR_FOUND)
1851 clear_mark(Currentbuf->currentLine);
1852 displayBuffer(Currentbuf, B_NORMAL);
1853 disp_srchresult(result, (reverse ? "Backward: " : "Forward: "),
1857 /* Search next matching */
1858 DEFUN(srchnxt, SEARCH_NEXT, "Search next regexp")
1863 /* Search previous matching */
1864 DEFUN(srchprv, SEARCH_PREV, "Search previous regexp")
1870 shiftvisualpos(Buffer *buf, int shift)
1872 Line *l = buf->currentLine;
1873 buf->visualpos -= shift;
1874 if (buf->visualpos - l->bwidth >= buf->COLS)
1875 buf->visualpos = l->bwidth + buf->COLS - 1;
1876 else if (buf->visualpos - l->bwidth < 0)
1877 buf->visualpos = l->bwidth;
1879 if (buf->visualpos - l->bwidth == -shift && buf->cursorX == 0)
1880 buf->visualpos = l->bwidth;
1883 /* Shift screen left */
1884 DEFUN(shiftl, SHIFT_LEFT, "Shift screen left")
1888 if (Currentbuf->firstLine == NULL)
1890 column = Currentbuf->currentColumn;
1891 columnSkip(Currentbuf, searchKeyNum() * (-Currentbuf->COLS + 1) + 1);
1892 shiftvisualpos(Currentbuf, Currentbuf->currentColumn - column);
1893 displayBuffer(Currentbuf, B_NORMAL);
1896 /* Shift screen right */
1897 DEFUN(shiftr, SHIFT_RIGHT, "Shift screen right")
1901 if (Currentbuf->firstLine == NULL)
1903 column = Currentbuf->currentColumn;
1904 columnSkip(Currentbuf, searchKeyNum() * (Currentbuf->COLS - 1) - 1);
1905 shiftvisualpos(Currentbuf, Currentbuf->currentColumn - column);
1906 displayBuffer(Currentbuf, B_NORMAL);
1909 DEFUN(col1R, RIGHT, "Shift screen one column right")
1911 Buffer *buf = Currentbuf;
1912 Line *l = buf->currentLine;
1913 int j, column, n = searchKeyNum();
1917 for (j = 0; j < n; j++) {
1918 column = buf->currentColumn;
1919 columnSkip(Currentbuf, 1);
1920 if (column == buf->currentColumn)
1922 shiftvisualpos(Currentbuf, 1);
1924 displayBuffer(Currentbuf, B_NORMAL);
1927 DEFUN(col1L, LEFT, "Shift screen one column")
1929 Buffer *buf = Currentbuf;
1930 Line *l = buf->currentLine;
1931 int j, n = searchKeyNum();
1935 for (j = 0; j < n; j++) {
1936 if (buf->currentColumn == 0)
1938 columnSkip(Currentbuf, -1);
1939 shiftvisualpos(Currentbuf, -1);
1941 displayBuffer(Currentbuf, B_NORMAL);
1944 DEFUN(setEnv, SETENV, "Set environment variable")
1949 CurrentKeyData = NULL; /* not allowed in w3m-control: */
1950 env = searchKeyData();
1951 if (env == NULL || *env == '\0' || strchr(env, '=') == NULL) {
1952 if (env != NULL && *env != '\0')
1953 env = Sprintf("%s=", env)->ptr;
1954 env = inputStrHist("Set environ: ", env, TextHist);
1955 if (env == NULL || *env == '\0') {
1956 displayBuffer(Currentbuf, B_NORMAL);
1960 if ((value = strchr(env, '=')) != NULL && value > env) {
1961 var = allocStr(env, value - env);
1963 set_environ(var, value);
1965 displayBuffer(Currentbuf, B_NORMAL);
1968 DEFUN(pipeBuf, PIPE_BUF, "Send rendered document to pipe")
1974 CurrentKeyData = NULL; /* not allowed in w3m-control: */
1975 cmd = searchKeyData();
1976 if (cmd == NULL || *cmd == '\0') {
1977 /* FIXME: gettextize? */
1978 cmd = inputLineHist("Pipe buffer to: ", "", IN_COMMAND, ShellHist);
1981 cmd = conv_to_system(cmd);
1982 if (cmd == NULL || *cmd == '\0') {
1983 displayBuffer(Currentbuf, B_NORMAL);
1986 tmpf = tmpfname(TMPF_DFL, NULL)->ptr;
1987 f = fopen(tmpf, "w");
1989 /* FIXME: gettextize? */
1990 disp_message(Sprintf("Can't save buffer to %s", cmd)->ptr, TRUE);
1993 saveBuffer(Currentbuf, f, TRUE);
1995 buf = getpipe(myExtCommand(cmd, shell_quote(tmpf), TRUE)->ptr);
1997 disp_message("Execution failed", TRUE);
2001 buf->filename = cmd;
2002 buf->buffername = Sprintf("%s %s", PIPEBUFFERNAME,
2003 conv_from_system(cmd))->ptr;
2004 buf->bufferprop |= (BP_INTERNAL | BP_NO_URL);
2005 if (buf->type == NULL)
2006 buf->type = "text/plain";
2007 buf->currentURL.file = "-";
2010 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2013 /* Execute shell command and read output ac pipe. */
2014 DEFUN(pipesh, PIPE_SHELL, "Execute shell command and browse")
2019 CurrentKeyData = NULL; /* not allowed in w3m-control: */
2020 cmd = searchKeyData();
2021 if (cmd == NULL || *cmd == '\0') {
2022 cmd = inputLineHist("(read shell[pipe])!", "", IN_COMMAND, ShellHist);
2025 cmd = conv_to_system(cmd);
2026 if (cmd == NULL || *cmd == '\0') {
2027 displayBuffer(Currentbuf, B_NORMAL);
2032 disp_message("Execution failed", TRUE);
2036 buf->bufferprop |= (BP_INTERNAL | BP_NO_URL);
2037 if (buf->type == NULL)
2038 buf->type = "text/plain";
2041 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2044 /* Execute shell command and load entire output to buffer */
2045 DEFUN(readsh, READ_SHELL, "Execute shell command and load")
2048 MySignalHandler(*prevtrap) ();
2051 CurrentKeyData = NULL; /* not allowed in w3m-control: */
2052 cmd = searchKeyData();
2053 if (cmd == NULL || *cmd == '\0') {
2054 cmd = inputLineHist("(read shell)!", "", IN_COMMAND, ShellHist);
2057 cmd = conv_to_system(cmd);
2058 if (cmd == NULL || *cmd == '\0') {
2059 displayBuffer(Currentbuf, B_NORMAL);
2062 prevtrap = mySignal(SIGINT, intTrap);
2064 buf = getshell(cmd);
2065 mySignal(SIGINT, prevtrap);
2068 /* FIXME: gettextize? */
2069 disp_message("Execution failed", TRUE);
2073 buf->bufferprop |= (BP_INTERNAL | BP_NO_URL);
2074 if (buf->type == NULL)
2075 buf->type = "text/plain";
2078 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2081 /* Execute shell command */
2082 DEFUN(execsh, EXEC_SHELL SHELL, "Execute shell command")
2086 CurrentKeyData = NULL; /* not allowed in w3m-control: */
2087 cmd = searchKeyData();
2088 if (cmd == NULL || *cmd == '\0') {
2089 cmd = inputLineHist("(exec shell)!", "", IN_COMMAND, ShellHist);
2092 cmd = conv_to_system(cmd);
2093 if (cmd != NULL && *cmd != '\0') {
2097 /* FIXME: gettextize? */
2098 printf("\n[Hit any key]");
2103 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2107 DEFUN(ldfile, LOAD, "Load local file")
2111 fn = searchKeyData();
2112 if (fn == NULL || *fn == '\0') {
2113 /* FIXME: gettextize? */
2114 fn = inputFilenameHist("(Load)Filename? ", NULL, LoadHist);
2117 fn = conv_to_system(fn);
2118 if (fn == NULL || *fn == '\0') {
2119 displayBuffer(Currentbuf, B_NORMAL);
2125 /* Load help file */
2126 DEFUN(ldhelp, HELP, "View help")
2134 n = strcspn(lang, ";, \t");
2135 tmp = Sprintf("file:///$LIB/" HELP_CGI CGI_EXTENSION "?version=%s&lang=%s",
2136 Str_form_quote(Strnew_charp(w3m_version))->ptr,
2137 Str_form_quote(Strnew_charp_n(lang, n))->ptr);
2138 cmd_loadURL(tmp->ptr, NULL, NO_REFERER, NULL);
2140 cmd_loadURL(helpFile(HELP_FILE), NULL, NO_REFERER, NULL);
2145 cmd_loadfile(char *fn)
2149 buf = loadGeneralFile(file_to_url(fn), NULL, NO_REFERER, 0, NULL);
2151 /* FIXME: gettextize? */
2152 char *emsg = Sprintf("%s not found", conv_from_system(fn))->ptr;
2153 disp_err_message(emsg, FALSE);
2155 else if (buf != NO_BUFFER) {
2157 if (RenderFrame && Currentbuf->frameset != NULL)
2160 displayBuffer(Currentbuf, B_NORMAL);
2163 /* Move cursor left */
2167 int i, m = searchKeyNum();
2168 if (Currentbuf->firstLine == NULL)
2170 for (i = 0; i < m; i++)
2171 cursorLeft(Currentbuf, n);
2172 displayBuffer(Currentbuf, B_NORMAL);
2175 DEFUN(movL, MOVE_LEFT,
2176 "Move cursor left (a half screen shift at the left edge)")
2178 _movL(Currentbuf->COLS / 2);
2181 DEFUN(movL1, MOVE_LEFT1, "Move cursor left (1 columns shift at the left edge)")
2186 /* Move cursor downward */
2190 int i, m = searchKeyNum();
2191 if (Currentbuf->firstLine == NULL)
2193 for (i = 0; i < m; i++)
2194 cursorDown(Currentbuf, n);
2195 displayBuffer(Currentbuf, B_NORMAL);
2198 DEFUN(movD, MOVE_DOWN,
2199 "Move cursor down (a half screen scroll at the end of screen)")
2201 _movD((Currentbuf->LINES + 1) / 2);
2204 DEFUN(movD1, MOVE_DOWN1,
2205 "Move cursor down (1 line scroll at the end of screen)")
2210 /* move cursor upward */
2214 int i, m = searchKeyNum();
2215 if (Currentbuf->firstLine == NULL)
2217 for (i = 0; i < m; i++)
2218 cursorUp(Currentbuf, n);
2219 displayBuffer(Currentbuf, B_NORMAL);
2222 DEFUN(movU, MOVE_UP,
2223 "Move cursor up (a half screen scroll at the top of screen)")
2225 _movU((Currentbuf->LINES + 1) / 2);
2228 DEFUN(movU1, MOVE_UP1, "Move cursor up (1 line scrol at the top of screen)")
2233 /* Move cursor right */
2237 int i, m = searchKeyNum();
2238 if (Currentbuf->firstLine == NULL)
2240 for (i = 0; i < m; i++)
2241 cursorRight(Currentbuf, n);
2242 displayBuffer(Currentbuf, B_NORMAL);
2245 DEFUN(movR, MOVE_RIGHT,
2246 "Move cursor right (a half screen shift at the right edge)")
2248 _movR(Currentbuf->COLS / 2);
2251 DEFUN(movR1, MOVE_RIGHT1,
2252 "Move cursor right (1 columns shift at the right edge)")
2259 * From: Takashi Nishimoto <g96p0935@mse.waseda.ac.jp> Date: Mon, 14 Jun
2260 * 1999 09:29:56 +0900
2262 #define IS_WORD_CHAR(c,p) (IS_ALNUM(c) && CharType(p) == PC_ASCII)
2265 prev_nonnull_line(Line *line)
2269 for (l = line; l != NULL && l->len == 0; l = l->prev) ;
2270 if (l == NULL || l->len == 0)
2273 Currentbuf->currentLine = l;
2275 Currentbuf->pos = Currentbuf->currentLine->len;
2279 DEFUN(movLW, PREV_WORD, "Move to previous word")
2285 int i, n = searchKeyNum();
2287 if (Currentbuf->firstLine == NULL)
2290 for (i = 0; i < n; i++) {
2291 pline = Currentbuf->currentLine;
2292 ppos = Currentbuf->pos;
2294 if (prev_nonnull_line(Currentbuf->currentLine) < 0)
2298 lb = Currentbuf->currentLine->lineBuf;
2299 pb = Currentbuf->currentLine->propBuf;
2300 while (Currentbuf->pos > 0 &&
2301 !IS_WORD_CHAR(lb[Currentbuf->pos - 1],
2302 pb[Currentbuf->pos - 1])) {
2305 if (Currentbuf->pos > 0)
2307 if (prev_nonnull_line(Currentbuf->currentLine->prev) < 0) {
2308 Currentbuf->currentLine = pline;
2309 Currentbuf->pos = ppos;
2312 Currentbuf->pos = Currentbuf->currentLine->len;
2315 lb = Currentbuf->currentLine->lineBuf;
2316 pb = Currentbuf->currentLine->propBuf;
2317 while (Currentbuf->pos > 0 &&
2318 IS_WORD_CHAR(lb[Currentbuf->pos - 1],
2319 pb[Currentbuf->pos - 1])) {
2324 arrangeCursor(Currentbuf);
2325 displayBuffer(Currentbuf, B_NORMAL);
2329 next_nonnull_line(Line *line)
2333 for (l = line; l != NULL && l->len == 0; l = l->next) ;
2335 if (l == NULL || l->len == 0)
2338 Currentbuf->currentLine = l;
2340 Currentbuf->pos = 0;
2344 DEFUN(movRW, NEXT_WORD, "Move to next word")
2350 int i, n = searchKeyNum();
2352 if (Currentbuf->firstLine == NULL)
2355 for (i = 0; i < n; i++) {
2356 pline = Currentbuf->currentLine;
2357 ppos = Currentbuf->pos;
2359 if (next_nonnull_line(Currentbuf->currentLine) < 0)
2362 lb = Currentbuf->currentLine->lineBuf;
2363 pb = Currentbuf->currentLine->propBuf;
2365 while (lb[Currentbuf->pos] &&
2366 IS_WORD_CHAR(lb[Currentbuf->pos], pb[Currentbuf->pos]))
2370 while (lb[Currentbuf->pos] &&
2371 !IS_WORD_CHAR(lb[Currentbuf->pos], pb[Currentbuf->pos]))
2373 if (lb[Currentbuf->pos])
2375 if (next_nonnull_line(Currentbuf->currentLine->next) < 0) {
2376 Currentbuf->currentLine = pline;
2377 Currentbuf->pos = ppos;
2380 Currentbuf->pos = 0;
2381 lb = Currentbuf->currentLine->lineBuf;
2382 pb = Currentbuf->currentLine->propBuf;
2386 arrangeCursor(Currentbuf);
2387 displayBuffer(Currentbuf, B_NORMAL);
2391 _quitfm(int confirm)
2395 if (checkDownloadList())
2396 /* FIXME: gettextize? */
2397 ans = inputChar("Download process retains. "
2398 "Do you want to exit w3m? (y/n)");
2400 /* FIXME: gettextize? */
2401 ans = inputChar("Do you want to exit w3m? (y/n)");
2402 if (!(ans && TOLOWER(*ans) == 'y')) {
2403 displayBuffer(Currentbuf, B_NORMAL);
2407 term_title(""); /* XXX */
2415 #endif /* USE_COOKIE */
2417 if (UseHistory && SaveURLHist)
2418 saveHistory(URLHist, URLHistSize);
2419 #endif /* USE_HISTORY */
2424 DEFUN(quitfm, ABORT EXIT, "Quit w3m without confirmation")
2429 /* Question and Quit */
2430 DEFUN(qquitfm, QUIT, "Quit w3m")
2432 _quitfm(confirm_on_quit);
2436 DEFUN(selBuf, SELECT, "Go to buffer selection panel")
2444 buf = selectBuffer(Firstbuf, Currentbuf, &cmd);
2456 if (Firstbuf == NULL) {
2457 /* No more buffer */
2458 Firstbuf = nullBuffer();
2459 Currentbuf = Firstbuf;
2471 for (buf = Firstbuf; buf != NULL; buf = buf->nextBuffer) {
2472 if (buf == Currentbuf)
2478 tmpClearBuffer(buf);
2480 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2483 /* Suspend (on BSD), or run interactive shell (on SysV) */
2484 DEFUN(susp, INTERRUPT SUSPEND, "Stop loading document")
2488 #endif /* not SIGSTOP */
2494 shell = getenv("SHELL");
2499 kill((pid_t) 0, SIGSTOP);
2500 #endif /* SIGSTOP */
2502 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2505 /* Go to specified line */
2509 if (l == NULL || *l == '\0' || Currentbuf->currentLine == NULL) {
2510 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2513 Currentbuf->pos = 0;
2514 if (((*l == '^') || (*l == '$')) && prec_num) {
2515 gotoRealLine(Currentbuf, prec_num);
2517 else if (*l == '^') {
2518 Currentbuf->topLine = Currentbuf->currentLine = Currentbuf->firstLine;
2520 else if (*l == '$') {
2521 Currentbuf->topLine =
2522 lineSkip(Currentbuf, Currentbuf->lastLine,
2523 -(Currentbuf->LINES + 1) / 2, TRUE);
2524 Currentbuf->currentLine = Currentbuf->lastLine;
2527 gotoRealLine(Currentbuf, atoi(l));
2528 arrangeCursor(Currentbuf);
2529 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2532 DEFUN(goLine, GOTO_LINE, "Go to specified line")
2535 char *str = searchKeyData();
2541 /* FIXME: gettextize? */
2542 _goLine(inputStr("Goto line: ", ""));
2546 DEFUN(goLineF, BEGIN, "Go to the first line")
2551 DEFUN(goLineL, END, "Go to the last line")
2556 /* Go to the beginning of the line */
2557 DEFUN(linbeg, LINE_BEGIN, "Go to the beginning of line")
2559 if (Currentbuf->firstLine == NULL)
2561 while (Currentbuf->currentLine->prev && Currentbuf->currentLine->bpos)
2562 cursorUp0(Currentbuf, 1);
2563 Currentbuf->pos = 0;
2564 arrangeCursor(Currentbuf);
2565 displayBuffer(Currentbuf, B_NORMAL);
2568 /* Go to the bottom of the line */
2569 DEFUN(linend, LINE_END, "Go to the end of line")
2571 if (Currentbuf->firstLine == NULL)
2573 while (Currentbuf->currentLine->next
2574 && Currentbuf->currentLine->next->bpos)
2575 cursorDown0(Currentbuf, 1);
2576 Currentbuf->pos = Currentbuf->currentLine->len - 1;
2577 arrangeCursor(Currentbuf);
2578 displayBuffer(Currentbuf, B_NORMAL);
2582 cur_real_linenumber(Buffer *buf)
2584 Line *l, *cur = buf->currentLine;
2589 n = cur->real_linenumber ? cur->real_linenumber : 1;
2590 for (l = buf->firstLine; l && l != cur && l->real_linenumber == 0; l = l->next) { /* header */
2597 /* Run editor on the current buffer */
2598 DEFUN(editBf, EDIT, "Edit current document")
2600 char *fn = Currentbuf->filename;
2603 if (fn == NULL || Currentbuf->pagerSource != NULL || /* Behaving as a pager */
2604 (Currentbuf->type == NULL && Currentbuf->edit == NULL) || /* Reading shell */
2605 Currentbuf->real_scheme != SCM_LOCAL || !strcmp(Currentbuf->currentURL.file, "-") || /* file is std input */
2606 Currentbuf->bufferprop & BP_FRAME) { /* Frame */
2607 disp_err_message("Can't edit other than local file", TRUE);
2610 if (Currentbuf->edit)
2611 cmd = unquote_mailcap(Currentbuf->edit, Currentbuf->real_type, fn,
2612 checkHeader(Currentbuf, "Content-Type:"), NULL);
2614 cmd = myEditor(Editor, shell_quote(fn),
2615 cur_real_linenumber(Currentbuf));
2620 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2624 /* Run editor on the current screen */
2625 DEFUN(editScr, EDIT_SCREEN, "Edit currently rendered document")
2630 tmpf = tmpfname(TMPF_DFL, NULL)->ptr;
2631 f = fopen(tmpf, "w");
2633 /* FIXME: gettextize? */
2634 disp_err_message(Sprintf("Can't open %s", tmpf)->ptr, TRUE);
2637 saveBuffer(Currentbuf, f, TRUE);
2640 system(myEditor(Editor, shell_quote(tmpf),
2641 cur_real_linenumber(Currentbuf))->ptr);
2644 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2649 /* Set / unset mark */
2650 DEFUN(_mark, MARK, "Set/unset mark")
2655 if (Currentbuf->firstLine == NULL)
2657 l = Currentbuf->currentLine;
2658 l->propBuf[Currentbuf->pos] ^= PE_MARK;
2659 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2662 /* Go to next mark */
2663 DEFUN(nextMk, NEXT_MARK, "Move to next word")
2670 if (Currentbuf->firstLine == NULL)
2672 i = Currentbuf->pos + 1;
2673 l = Currentbuf->currentLine;
2679 for (; i < l->len; i++) {
2680 if (l->propBuf[i] & PE_MARK) {
2681 Currentbuf->currentLine = l;
2682 Currentbuf->pos = i;
2683 arrangeCursor(Currentbuf);
2684 displayBuffer(Currentbuf, B_NORMAL);
2691 /* FIXME: gettextize? */
2692 disp_message("No mark exist after here", TRUE);
2695 /* Go to previous mark */
2696 DEFUN(prevMk, PREV_MARK, "Move to previous mark")
2703 if (Currentbuf->firstLine == NULL)
2705 i = Currentbuf->pos - 1;
2706 l = Currentbuf->currentLine;
2713 for (; i >= 0; i--) {
2714 if (l->propBuf[i] & PE_MARK) {
2715 Currentbuf->currentLine = l;
2716 Currentbuf->pos = i;
2717 arrangeCursor(Currentbuf);
2718 displayBuffer(Currentbuf, B_NORMAL);
2726 /* FIXME: gettextize? */
2727 disp_message("No mark exist before here", TRUE);
2730 /* Mark place to which the regular expression matches */
2731 DEFUN(reMark, REG_MARK, "Set mark using regexp")
2739 str = searchKeyData();
2740 if (str == NULL || *str == '\0') {
2741 str = inputStrHist("(Mark)Regexp: ", MarkString, TextHist);
2742 if (str == NULL || *str == '\0') {
2743 displayBuffer(Currentbuf, B_NORMAL);
2747 str = conv_search_string(str, DisplayCharset);
2748 if ((str = regexCompile(str, 1)) != NULL) {
2749 disp_message(str, TRUE);
2753 for (l = Currentbuf->firstLine; l != NULL; l = l->next) {
2756 if (regexMatch(p, &l->lineBuf[l->len] - p, p == l->lineBuf) == 1) {
2757 matchedPosition(&p1, &p2);
2758 l->propBuf[p1 - l->lineBuf] |= PE_MARK;
2766 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2768 #endif /* USE_MARK */
2771 loadNormalBuf(Buffer *buf, int renderframe)
2774 if (renderframe && RenderFrame && Currentbuf->frameset != NULL)
2780 loadLink(char *url, char *target, char *referer, FormList *request)
2782 Buffer *buf, *nfbuf;
2783 union frameset_element *f_element = NULL;
2785 ParsedURL *base, pu;
2787 message(Sprintf("loading %s", url)->ptr, 0, 0);
2790 base = baseURL(Currentbuf);
2792 base->scheme == SCM_LOCAL || base->scheme == SCM_LOCAL_CGI)
2793 referer = NO_REFERER;
2794 if (referer == NULL)
2795 referer = parsedURL2Str(&Currentbuf->currentURL)->ptr;
2796 buf = loadGeneralFile(url, baseURL(Currentbuf), referer, flag, request);
2798 char *emsg = Sprintf("Can't load %s", url)->ptr;
2799 disp_err_message(emsg, FALSE);
2803 parseURL2(url, &pu, base);
2804 pushHashHist(URLHist, parsedURL2Str(&pu)->ptr);
2806 if (buf == NO_BUFFER) {
2809 if (!on_target) /* open link as an indivisual page */
2810 return loadNormalBuf(buf, TRUE);
2812 if (do_download) /* download (thus no need to render frame) */
2813 return loadNormalBuf(buf, FALSE);
2815 if (target == NULL || /* no target specified (that means this page is not a frame page) */
2816 !strcmp(target, "_top") || /* this link is specified to be opened as an indivisual * page */
2817 !(Currentbuf->bufferprop & BP_FRAME) /* This page is not a frame page */
2819 return loadNormalBuf(buf, TRUE);
2821 nfbuf = Currentbuf->linkBuffer[LB_N_FRAME];
2822 if (nfbuf == NULL) {
2823 /* original page (that contains <frameset> tag) doesn't exist */
2824 return loadNormalBuf(buf, TRUE);
2827 f_element = search_frame(nfbuf->frameset, target);
2828 if (f_element == NULL) {
2829 /* specified target doesn't exist in this frameset */
2830 return loadNormalBuf(buf, TRUE);
2835 /* stack current frameset */
2836 pushFrameTree(&(nfbuf->frameQ), copyFrameSet(nfbuf->frameset), Currentbuf);
2837 /* delete frame view buffer */
2838 delBuffer(Currentbuf);
2840 /* nfbuf->frameset = copyFrameSet(nfbuf->frameset); */
2841 resetFrameElement(f_element, buf, referer, request);
2846 char *label = pu.label;
2848 if (label && f_element->element->attr == F_BODY) {
2849 al = searchAnchor(f_element->body->nameList, label);
2852 label = Strnew_m_charp("_", target, NULL)->ptr;
2853 al = searchURLLabel(Currentbuf, label);
2856 gotoLine(Currentbuf, al->start.line);
2858 Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->topLine,
2859 Currentbuf->currentLine->
2861 Currentbuf->topLine->linenumber,
2863 Currentbuf->pos = al->start.pos;
2864 arrangeCursor(Currentbuf);
2867 displayBuffer(Currentbuf, B_NORMAL);
2872 gotoLabel(char *label)
2878 al = searchURLLabel(Currentbuf, label);
2880 /* FIXME: gettextize? */
2881 disp_message(Sprintf("%s is not found", label)->ptr, TRUE);
2884 buf = newBuffer(Currentbuf->width);
2885 copyBuffer(buf, Currentbuf);
2886 for (i = 0; i < MAX_LB; i++)
2887 buf->linkBuffer[i] = NULL;
2888 buf->currentURL.label = allocStr(label, -1);
2889 pushHashHist(URLHist, parsedURL2Str(&buf->currentURL)->ptr);
2892 gotoLine(Currentbuf, al->start.line);
2894 Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->topLine,
2895 Currentbuf->currentLine->linenumber
2896 - Currentbuf->topLine->linenumber,
2898 Currentbuf->pos = al->start.pos;
2899 arrangeCursor(Currentbuf);
2900 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2904 /* follow HREF link */
2905 DEFUN(followA, GOTO_LINK, "Go to current link")
2911 int x = 0, y = 0, map = 0;
2915 if (Currentbuf->firstLine == NULL)
2917 l = Currentbuf->currentLine;
2920 a = retrieveCurrentImg(Currentbuf);
2921 if (a && a->image && a->image->map) {
2925 if (a && a->image && a->image->ismap) {
2926 getMapXY(Currentbuf, a, &x, &y);
2930 a = retrieveCurrentMap(Currentbuf);
2936 a = retrieveCurrentAnchor(Currentbuf);
2941 if (*a->url == '#') { /* index within this buffer */
2942 gotoLabel(a->url + 1);
2945 parseURL2(a->url, &u, baseURL(Currentbuf));
2946 if (Strcmp(parsedURL2Str(&u), parsedURL2Str(&Currentbuf->currentURL)) == 0) {
2947 /* index within this buffer */
2953 if (!strncasecmp(a->url, "mailto:", 7)
2954 #ifdef USE_W3MMAILER
2955 && non_null(Mailer) && strchr(a->url, '?') == NULL
2958 /* invoke external mailer */
2959 Str to = Strnew_charp(a->url + 7);
2960 #ifndef USE_W3MMAILER
2962 if (!non_null(Mailer)) {
2963 /* FIXME: gettextize? */
2964 disp_err_message("no mailer is specified", TRUE);
2967 if ((pos = strchr(to->ptr, '?')) != NULL)
2968 Strtruncate(to, pos - to->ptr);
2971 system(myExtCommand(Mailer, shell_quote(file_unquote(to->ptr)),
2974 displayBuffer(Currentbuf, B_FORCE_REDRAW);
2975 pushHashHist(URLHist, a->url);
2979 else if (!strncasecmp(a->url, "news:", 5) && strchr(a->url, '@') == NULL) {
2980 /* news:newsgroup is not supported */
2981 /* FIXME: gettextize? */
2982 disp_err_message("news:newsgroup_name is not supported", TRUE);
2985 #endif /* USE_NNTP */
2989 url = Sprintf("%s?%d,%d", a->url, x, y)->ptr;
2992 if (check_target && open_tab_blank && a->target &&
2993 (!strcasecmp(a->target, "_new") || !strcasecmp(a->target, "_blank"))) {
2998 loadLink(url, a->target, a->referer, NULL);
2999 if (buf != Currentbuf)
3002 deleteTab(CurrentTab);
3003 displayBuffer(Currentbuf, B_FORCE_REDRAW);
3006 loadLink(url, a->target, a->referer, NULL);
3007 displayBuffer(Currentbuf, B_NORMAL);
3010 /* follow HREF link in the buffer */
3019 /* view inline image */
3020 DEFUN(followI, VIEW_IMAGE, "View image")
3026 if (Currentbuf->firstLine == NULL)
3028 l = Currentbuf->currentLine;
3030 a = retrieveCurrentImg(Currentbuf);
3033 /* FIXME: gettextize? */
3034 message(Sprintf("loading %s", a->url)->ptr, 0, 0);
3036 buf = loadGeneralFile(a->url, baseURL(Currentbuf), NULL, 0, NULL);
3038 /* FIXME: gettextize? */
3039 char *emsg = Sprintf("Can't load %s", a->url)->ptr;
3040 disp_err_message(emsg, FALSE);
3042 else if (buf != NO_BUFFER) {
3045 displayBuffer(Currentbuf, B_NORMAL);
3048 static FormItemList *
3049 save_submit_formlist(FormItemList *src)
3053 FormItemList *srcitem;
3055 FormItemList *ret = NULL;
3057 FormSelectOptionItem *opt;
3058 FormSelectOptionItem *curopt;
3059 FormSelectOptionItem *srcopt;
3060 #endif /* MENU_SELECT */
3064 srclist = src->parent;
3065 list = New(FormList);
3066 list->method = srclist->method;
3067 list->action = Strdup(srclist->action);
3069 list->charset = srclist->charset;
3071 list->enctype = srclist->enctype;
3072 list->nitems = srclist->nitems;
3073 list->body = srclist->body;
3074 list->boundary = srclist->boundary;
3075 list->length = srclist->length;
3077 for (srcitem = srclist->item; srcitem; srcitem = srcitem->next) {
3078 item = New(FormItemList);
3079 item->type = srcitem->type;
3080 item->name = Strdup(srcitem->name);
3081 item->value = Strdup(srcitem->value);
3082 item->checked = srcitem->checked;
3083 item->accept = srcitem->accept;
3084 item->size = srcitem->size;
3085 item->rows = srcitem->rows;
3086 item->maxlength = srcitem->maxlength;
3087 item->readonly = srcitem->readonly;
3089 opt = curopt = NULL;
3090 for (srcopt = srcitem->select_option; srcopt; srcopt = srcopt->next) {
3091 if (!srcopt->checked)
3093 opt = New(FormSelectOptionItem);
3094 opt->value = Strdup(srcopt->value);
3095 opt->label = Strdup(srcopt->label);
3096 opt->checked = srcopt->checked;
3097 if (item->select_option == NULL) {
3098 item->select_option = curopt = opt;
3102 curopt = curopt->next;
3105 item->select_option = opt;
3107 item->label = Strdup(srcitem->label);
3108 #endif /* MENU_SELECT */
3109 item->parent = list;
3112 if (list->lastitem == NULL) {
3113 list->item = list->lastitem = item;
3116 list->lastitem->next = item;
3117 list->lastitem = item;
3129 conv_form_encoding(Str val, FormItemList *fi, Buffer *buf)
3131 wc_ces charset = SystemCharset;
3133 if (fi->parent->charset)
3134 charset = fi->parent->charset;
3135 else if (buf->document_charset && buf->document_charset != WC_CES_US_ASCII)
3136 charset = buf->document_charset;
3137 return wc_Str_conv_strict(val, InnerCharset, charset);
3140 #define conv_form_encoding(val, fi, buf) (val)
3144 query_from_followform(Str *query, FormItemList *fi, int multipart)
3150 *query = tmpfname(TMPF_DFL, NULL);
3151 body = fopen((*query)->ptr, "w");
3155 fi->parent->body = (*query)->ptr;
3156 fi->parent->boundary =
3157 Sprintf("------------------------------%d%ld%ld%ld", CurrentPid,
3158 fi->parent, fi->parent->body, fi->parent->boundary)->ptr;
3161 for (f2 = fi->parent->item; f2; f2 = f2->next) {
3162 if (f2->name == NULL)
3164 /* <ISINDEX> is translated into single text form */
3165 if (f2->name->length == 0 &&
3166 (multipart || f2->type != FORM_INPUT_TEXT))
3169 case FORM_INPUT_RESET:
3172 case FORM_INPUT_SUBMIT:
3173 case FORM_INPUT_IMAGE:
3174 if (f2 != fi || f2->value == NULL)
3177 case FORM_INPUT_RADIO:
3178 case FORM_INPUT_CHECKBOX:
3183 if (f2->type == FORM_INPUT_IMAGE) {
3186 getMapXY(Currentbuf, retrieveCurrentImg(Currentbuf), &x, &y);
3188 *query = Strdup(conv_form_encoding(f2->name, fi, Currentbuf));
3189 Strcat_charp(*query, ".x");
3190 form_write_data(body, fi->parent->boundary, (*query)->ptr,
3191 Sprintf("%d", x)->ptr);
3192 *query = Strdup(conv_form_encoding(f2->name, fi, Currentbuf));
3193 Strcat_charp(*query, ".y");
3194 form_write_data(body, fi->parent->boundary, (*query)->ptr,
3195 Sprintf("%d", y)->ptr);
3197 else if (f2->name && f2->name->length > 0 && f2->value != NULL) {
3199 *query = conv_form_encoding(f2->value, fi, Currentbuf);
3200 if (f2->type == FORM_INPUT_FILE)
3201 form_write_from_file(body, fi->parent->boundary,
3202 conv_form_encoding(f2->name, fi,
3205 Str_conv_to_system(f2->value)->ptr);
3207 form_write_data(body, fi->parent->boundary,
3208 conv_form_encoding(f2->name, fi,
3215 if (f2->type == FORM_INPUT_IMAGE) {
3218 getMapXY(Currentbuf, retrieveCurrentImg(Currentbuf), &x, &y);
3221 Str_form_quote(conv_form_encoding
3222 (f2->name, fi, Currentbuf)));
3223 Strcat(*query, Sprintf(".x=%d&", x));
3225 Str_form_quote(conv_form_encoding
3226 (f2->name, fi, Currentbuf)));
3227 Strcat(*query, Sprintf(".y=%d", y));
3231 if (f2->name && f2->name->length > 0) {
3233 Str_form_quote(conv_form_encoding
3234 (f2->name, fi, Currentbuf)));
3235 Strcat_char(*query, '=');
3237 if (f2->value != NULL) {
3238 if (fi->parent->method == FORM_METHOD_INTERNAL)
3239 Strcat(*query, Str_form_quote(f2->value));
3242 Str_form_quote(conv_form_encoding
3243 (f2->value, fi, Currentbuf)));
3248 Strcat_char(*query, '&');
3252 fprintf(body, "--%s--\r\n", fi->parent->boundary);
3256 /* remove trailing & */
3257 while (Strlastchar(*query) == '&')
3258 Strshrink(*query, 1);
3263 DEFUN(submitForm, SUBMIT, "Submit form")
3276 _followForm(int submit)
3281 FormItemList *fi, *f2;
3283 int multipart = 0, i;
3285 if (Currentbuf->firstLine == NULL)
3287 l = Currentbuf->currentLine;
3289 a = retrieveCurrentForm(Currentbuf);
3292 fi = (FormItemList *)a->url;
3294 case FORM_INPUT_TEXT:
3298 /* FIXME: gettextize? */
3299 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE);
3300 /* FIXME: gettextize? */
3301 p = inputStrHist("TEXT:", fi->value ? fi->value->ptr : NULL, TextHist);
3302 if (p == NULL || fi->readonly)
3304 fi->value = Strnew_charp(p);
3305 formUpdateBuffer(a, Currentbuf, fi);
3306 if (fi->accept || fi->parent->nitems == 1)
3309 case FORM_INPUT_FILE:
3313 /* FIXME: gettextize? */
3314 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE);
3315 /* FIXME: gettextize? */
3316 p = inputFilenameHist("Filename:", fi->value ? fi->value->ptr : NULL,
3318 if (p == NULL || fi->readonly)
3320 fi->value = Strnew_charp(p);
3321 formUpdateBuffer(a, Currentbuf, fi);
3322 if (fi->accept || fi->parent->nitems == 1)
3325 case FORM_INPUT_PASSWORD:
3329 /* FIXME: gettextize? */
3330 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE);
3333 /* FIXME: gettextize? */
3334 p = inputLine("Password:", fi->value ? fi->value->ptr : NULL,
3338 fi->value = Strnew_charp(p);
3339 formUpdateBuffer(a, Currentbuf, fi);
3347 /* FIXME: gettextize? */
3348 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE);
3350 formUpdateBuffer(a, Currentbuf, fi);
3352 case FORM_INPUT_RADIO:
3356 /* FIXME: gettextize? */
3357 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE);
3360 formRecheckRadio(a, Currentbuf, fi);
3362 case FORM_INPUT_CHECKBOX:
3366 /* FIXME: gettextize? */
3367 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE);
3370 fi->checked = !fi->checked;
3371 formUpdateBuffer(a, Currentbuf, fi);
3377 if (!formChooseOptionByMenu(fi,
3378 Currentbuf->cursorX - Currentbuf->pos +
3379 a->start.pos + Currentbuf->rootX,
3380 Currentbuf->cursorY + Currentbuf->rootY))
3382 formUpdateBuffer(a, Currentbuf, fi);
3383 if (fi->parent->nitems == 1)
3386 #endif /* MENU_SELECT */
3387 case FORM_INPUT_IMAGE:
3388 case FORM_INPUT_SUBMIT:
3389 case FORM_INPUT_BUTTON:
3393 multipart = (fi->parent->method == FORM_METHOD_POST &&
3394 fi->parent->enctype == FORM_ENCTYPE_MULTIPART);
3395 query_from_followform(&tmp, fi, multipart);
3397 tmp2 = Strdup(fi->parent->action);
3398 if (!Strcmp_charp(tmp2, "!CURRENT_URL!")) {
3399 /* It means "current URL" */
3400 tmp2 = parsedURL2Str(&Currentbuf->currentURL);
3401 if ((p = strchr(tmp2->ptr, '?')) != NULL)
3402 Strshrink(tmp2, (tmp2->ptr + tmp2->length) - p);
3405 if (fi->parent->method == FORM_METHOD_GET) {
3406 if ((p = strchr(tmp2->ptr, '?')) != NULL)
3407 Strshrink(tmp2, (tmp2->ptr + tmp2->length) - p);
3408 Strcat_charp(tmp2, "?");
3410 loadLink(tmp2->ptr, a->target, NULL, NULL);
3412 else if (fi->parent->method == FORM_METHOD_POST) {
3416 stat(fi->parent->body, &st);
3417 fi->parent->length = st.st_size;
3420 fi->parent->body = tmp->ptr;
3421 fi->parent->length = tmp->length;
3423 buf = loadLink(tmp2->ptr, a->target, NULL, fi->parent);
3425 unlink(fi->parent->body);
3427 if (buf && !(buf->bufferprop & BP_REDIRECTED)) { /* buf must be Currentbuf */
3428 /* BP_REDIRECTED means that the buffer is obtained through
3429 * Location: header. In this case, buf->form_submit must not be set
3430 * because the page is not loaded by POST method but GET method.
3432 buf->form_submit = save_submit_formlist(fi);
3435 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 */
3436 do_internal(tmp2->ptr, tmp->ptr);
3439 disp_err_message("Can't send form because of illegal method.",
3443 case FORM_INPUT_RESET:
3444 for (i = 0; i < Currentbuf->formitem->nanchor; i++) {
3445 a2 = &Currentbuf->formitem->anchors[i];
3446 f2 = (FormItemList *)a2->url;
3447 if (f2->parent == fi->parent &&
3448 f2->name && f2->value &&
3449 f2->type != FORM_INPUT_SUBMIT &&
3450 f2->type != FORM_INPUT_HIDDEN &&
3451 f2->type != FORM_INPUT_RESET) {
3452 f2->value = f2->init_value;
3453 f2->checked = f2->init_checked;
3455 f2->label = f2->init_label;
3456 f2->selected = f2->init_selected;
3457 #endif /* MENU_SELECT */
3458 formUpdateBuffer(a2, Currentbuf, f2);
3462 case FORM_INPUT_HIDDEN:
3466 displayBuffer(Currentbuf, B_FORCE_REDRAW);
3469 /* go to the top anchor */
3470 DEFUN(topA, LINK_BEGIN, "Go to the first link")
3472 HmarkerList *hl = Currentbuf->hmarklist;
3477 if (Currentbuf->firstLine == NULL)
3479 if (!hl || hl->nmark == 0)
3482 if (prec_num > hl->nmark)
3483 hseq = hl->nmark - 1;
3484 else if (prec_num > 0)
3485 hseq = prec_num - 1;
3487 if (hseq >= hl->nmark)
3489 po = hl->marks + hseq;
3490 an = retrieveAnchor(Currentbuf->href, po->line, po->pos);
3492 an = retrieveAnchor(Currentbuf->formitem, po->line, po->pos);
3494 } while (an == NULL);
3496 gotoLine(Currentbuf, po->line);
3497 Currentbuf->pos = po->pos;
3498 arrangeCursor(Currentbuf);
3499 displayBuffer(Currentbuf, B_NORMAL);
3502 /* go to the last anchor */
3503 DEFUN(lastA, LINK_END, "Go to the last link")
3505 HmarkerList *hl = Currentbuf->hmarklist;
3510 if (Currentbuf->firstLine == NULL)
3512 if (!hl || hl->nmark == 0)
3515 if (prec_num >= hl->nmark)
3517 else if (prec_num > 0)
3518 hseq = hl->nmark - prec_num;
3520 hseq = hl->nmark - 1;
3524 po = hl->marks + hseq;
3525 an = retrieveAnchor(Currentbuf->href, po->line, po->pos);
3527 an = retrieveAnchor(Currentbuf->formitem, po->line, po->pos);
3529 } while (an == NULL);
3531 gotoLine(Currentbuf, po->line);
3532 Currentbuf->pos = po->pos;
3533 arrangeCursor(Currentbuf);
3534 displayBuffer(Currentbuf, B_NORMAL);
3537 /* go to the next anchor */
3538 DEFUN(nextA, NEXT_LINK, "Move to next link")
3543 /* go to the previous anchor */
3544 DEFUN(prevA, PREV_LINK, "Move to previous link")
3549 /* go to the next visited anchor */
3550 DEFUN(nextVA, NEXT_VISITED, "Move to next visited link")
3555 /* go to the previous visited anchor */
3556 DEFUN(prevVA, PREV_VISITED, "Move to previous visited link")
3561 /* go to the next [visited] anchor */
3565 HmarkerList *hl = Currentbuf->hmarklist;
3568 int i, x, y, n = searchKeyNum();
3571 if (Currentbuf->firstLine == NULL)
3573 if (!hl || hl->nmark == 0)
3576 an = retrieveCurrentAnchor(Currentbuf);
3577 if (visited != TRUE && an == NULL)
3578 an = retrieveCurrentForm(Currentbuf);
3580 y = Currentbuf->currentLine->linenumber;
3581 x = Currentbuf->pos;
3583 if (visited == TRUE) {
3587 for (i = 0; i < n; i++) {
3589 if (an && an->hseq >= 0) {
3590 int hseq = an->hseq + 1;
3592 if (hseq >= hl->nmark) {
3593 if (visited == TRUE)
3598 po = &hl->marks[hseq];
3599 an = retrieveAnchor(Currentbuf->href, po->line, po->pos);
3600 if (visited != TRUE && an == NULL)
3601 an = retrieveAnchor(Currentbuf->formitem, po->line,
3604 if (visited == TRUE && an) {
3605 parseURL2(an->url, &url, baseURL(Currentbuf));
3606 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) {
3610 } while (an == NULL || an == pan);
3613 an = closest_next_anchor(Currentbuf->href, NULL, x, y);
3614 if (visited != TRUE)
3615 an = closest_next_anchor(Currentbuf->formitem, an, x, y);
3617 if (visited == TRUE)
3624 if (visited == TRUE) {
3625 parseURL2(an->url, &url, baseURL(Currentbuf));
3626 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) {
3632 if (visited == TRUE)
3636 if (an == NULL || an->hseq < 0)
3638 po = &hl->marks[an->hseq];
3639 gotoLine(Currentbuf, po->line);
3640 Currentbuf->pos = po->pos;
3641 arrangeCursor(Currentbuf);
3642 displayBuffer(Currentbuf, B_NORMAL);
3645 /* go to the previous anchor */
3649 HmarkerList *hl = Currentbuf->hmarklist;
3652 int i, x, y, n = searchKeyNum();
3655 if (Currentbuf->firstLine == NULL)
3657 if (!hl || hl->nmark == 0)
3660 an = retrieveCurrentAnchor(Currentbuf);
3661 if (visited != TRUE && an == NULL)
3662 an = retrieveCurrentForm(Currentbuf);
3664 y = Currentbuf->currentLine->linenumber;
3665 x = Currentbuf->pos;
3667 if (visited == TRUE) {
3671 for (i = 0; i < n; i++) {
3673 if (an && an->hseq >= 0) {
3674 int hseq = an->hseq - 1;
3677 if (visited == TRUE)
3682 po = hl->marks + hseq;
3683 an = retrieveAnchor(Currentbuf->href, po->line, po->pos);
3684 if (visited != TRUE && an == NULL)
3685 an = retrieveAnchor(Currentbuf->formitem, po->line,
3688 if (visited == TRUE && an) {
3689 parseURL2(an->url, &url, baseURL(Currentbuf));
3690 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) {
3694 } while (an == NULL || an == pan);
3697 an = closest_prev_anchor(Currentbuf->href, NULL, x, y);
3698 if (visited != TRUE)
3699 an = closest_prev_anchor(Currentbuf->formitem, an, x, y);
3701 if (visited == TRUE)
3708 if (visited == TRUE && an) {
3709 parseURL2(an->url, &url, baseURL(Currentbuf));
3710 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) {
3716 if (visited == TRUE)
3720 if (an == NULL || an->hseq < 0)
3722 po = hl->marks + an->hseq;
3723 gotoLine(Currentbuf, po->line);
3724 Currentbuf->pos = po->pos;
3725 arrangeCursor(Currentbuf);
3726 displayBuffer(Currentbuf, B_NORMAL);
3729 /* go to the next left/right anchor */
3731 nextX(int d, int dy)
3733 HmarkerList *hl = Currentbuf->hmarklist;
3736 int i, x, y, n = searchKeyNum();
3738 if (Currentbuf->firstLine == NULL)
3740 if (!hl || hl->nmark == 0)
3743 an = retrieveCurrentAnchor(Currentbuf);
3745 an = retrieveCurrentForm(Currentbuf);
3747 l = Currentbuf->currentLine;
3748 x = Currentbuf->pos;
3751 for (i = 0; i < n; i++) {
3753 x = (d > 0) ? an->end.pos : an->start.pos - 1;
3756 for (; x >= 0 && x < l->len; x += d) {
3757 an = retrieveAnchor(Currentbuf->href, y, x);
3759 an = retrieveAnchor(Currentbuf->formitem, y, x);
3767 l = (dy > 0) ? l->next : l->prev;
3770 x = (d > 0) ? 0 : l->len - 1;
3779 gotoLine(Currentbuf, y);
3780 Currentbuf->pos = pan->start.pos;
3781 arrangeCursor(Currentbuf);
3782 displayBuffer(Currentbuf, B_NORMAL);
3785 /* go to the next downward/upward anchor */
3789 HmarkerList *hl = Currentbuf->hmarklist;
3791 int i, x, y, n = searchKeyNum();
3794 if (Currentbuf->firstLine == NULL)
3796 if (!hl || hl->nmark == 0)
3799 an = retrieveCurrentAnchor(Currentbuf);
3801 an = retrieveCurrentForm(Currentbuf);
3803 x = Currentbuf->pos;
3804 y = Currentbuf->currentLine->linenumber + d;
3807 for (i = 0; i < n; i++) {
3809 hseq = abs(an->hseq);
3811 for (; y >= 0 && y <= Currentbuf->lastLine->linenumber; y += d) {
3812 an = retrieveAnchor(Currentbuf->href, y, x);
3814 an = retrieveAnchor(Currentbuf->formitem, y, x);
3815 if (an && hseq != abs(an->hseq)) {
3826 gotoLine(Currentbuf, pan->start.line);
3827 arrangeLine(Currentbuf);
3828 displayBuffer(Currentbuf, B_NORMAL);
3831 /* go to the next left anchor */
3832 DEFUN(nextL, NEXT_LEFT, "Move to next left link")
3837 /* go to the next left-up anchor */
3838 DEFUN(nextLU, NEXT_LEFT_UP, "Move to next left (or upward) link")
3843 /* go to the next right anchor */
3844 DEFUN(nextR, NEXT_RIGHT, "Move to next right link")
3849 /* go to the next right-down anchor */
3850 DEFUN(nextRD, NEXT_RIGHT_DOWN, "Move to next right (or downward) link")
3855 /* go to the next downward anchor */
3856 DEFUN(nextD, NEXT_DOWN, "Move to next downward link")
3861 /* go to the next upward anchor */
3862 DEFUN(nextU, NEXT_UP, "Move to next upward link")
3867 /* go to the next bufferr */
3868 DEFUN(nextBf, NEXT, "Move to next buffer")
3873 for (i = 0; i < PREC_NUM; i++) {
3874 buf = prevBuffer(Firstbuf, Currentbuf);
3882 displayBuffer(Currentbuf, B_FORCE_REDRAW);
3885 /* go to the previous bufferr */
3886 DEFUN(prevBf, PREV, "Move to previous buffer")
3891 for (i = 0; i < PREC_NUM; i++) {
3892 buf = Currentbuf->nextBuffer;
3900 displayBuffer(Currentbuf, B_FORCE_REDRAW);
3904 checkBackBuffer(Buffer *buf)
3906 Buffer *fbuf = buf->linkBuffer[LB_N_FRAME];
3910 return TRUE; /* Currentbuf has stacked frames */
3911 /* when no frames stacked and next is frame source, try next's
3913 if (RenderFrame && fbuf == buf->nextBuffer) {
3914 if (fbuf->nextBuffer != NULL)
3921 if (buf->nextBuffer)
3927 /* delete current buffer and back to the previous buffer */
3928 DEFUN(backBf, BACK, "Back to previous buffer")
3930 Buffer *buf = Currentbuf->linkBuffer[LB_N_FRAME];
3932 if (!checkBackBuffer(Currentbuf)) {
3933 if (close_tab_back && nTab >= 1) {
3934 deleteTab(CurrentTab);
3935 displayBuffer(Currentbuf, B_FORCE_REDRAW);
3938 /* FIXME: gettextize? */
3939 disp_message("Can't back...", TRUE);
3943 delBuffer(Currentbuf);
3947 struct frameset *fs;
3948 long linenumber = buf->frameQ->linenumber;
3949 long top = buf->frameQ->top_linenumber;
3950 int pos = buf->frameQ->pos;
3951 int currentColumn = buf->frameQ->currentColumn;
3952 AnchorList *formitem = buf->frameQ->formitem;
3954 fs = popFrameTree(&(buf->frameQ));
3955 deleteFrameSet(buf->frameset);
3958 if (buf == Currentbuf) {
3960 Currentbuf->topLine = lineSkip(Currentbuf,
3961 Currentbuf->firstLine, top - 1,
3963 gotoLine(Currentbuf, linenumber);
3964 Currentbuf->pos = pos;
3965 Currentbuf->currentColumn = currentColumn;
3966 arrangeCursor(Currentbuf);
3967 formResetBuffer(Currentbuf, formitem);
3970 else if (RenderFrame && buf == Currentbuf) {
3971 delBuffer(Currentbuf);
3974 displayBuffer(Currentbuf, B_FORCE_REDRAW);
3977 DEFUN(deletePrevBuf, DELETE_PREVBUF,
3978 "Delete previous buffer (mainly for local-CGI)")
3980 Buffer *buf = Currentbuf->nextBuffer;
3986 cmd_loadURL(char *url, ParsedURL *current, char *referer, FormList *request)
3990 if (!strncasecmp(url, "mailto:", 7)
3991 #ifdef USE_W3MMAILER
3992 && non_null(Mailer) && strchr(url, '?') == NULL
3995 /* invoke external mailer */
3996 Str to = Strnew_charp(url + 7);
3997 #ifndef USE_W3MMAILER
3999 if (!non_null(Mailer)) {
4000 /* FIXME: gettextize? */
4001 disp_err_message("no mailer is specified", TRUE);
4004 if ((pos = strchr(to->ptr, '?')) != NULL)
4005 Strtruncate(to, pos - to->ptr);
4008 system(myExtCommand(Mailer, shell_quote(file_unquote(to->ptr)),
4011 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4012 pushHashHist(URLHist, url);
4016 if (!strncasecmp(url, "news:", 5) && strchr(url, '@') == NULL) {
4017 /* news:newsgroup is not supported */
4018 /* FIXME: gettextize? */
4019 disp_err_message("news:newsgroup_name is not supported", TRUE);
4022 #endif /* USE_NNTP */
4025 buf = loadGeneralFile(url, current, referer, 0, request);
4027 /* FIXME: gettextize? */
4028 char *emsg = Sprintf("Can't load %s", conv_from_system(url))->ptr;
4029 disp_err_message(emsg, FALSE);
4031 else if (buf != NO_BUFFER) {
4033 if (RenderFrame && Currentbuf->frameset != NULL)
4036 displayBuffer(Currentbuf, B_NORMAL);
4040 /* go to specified URL */
4042 goURL0(char *prompt, int relative)
4044 char *url, *referer;
4045 ParsedURL p_url, *current;
4046 Buffer *cur_buf = Currentbuf;
4048 url = searchKeyData();
4050 Hist *hist = copyHist(URLHist);
4053 current = baseURL(Currentbuf);
4055 char *c_url = parsedURL2Str(current)->ptr;
4056 if (DefaultURLString == DEFAULT_URL_CURRENT) {
4059 url = url_unquote_conv(url, 0);
4062 pushHist(hist, c_url);
4064 a = retrieveCurrentAnchor(Currentbuf);
4067 parseURL2(a->url, &p_url, current);
4068 a_url = parsedURL2Str(&p_url)->ptr;
4069 if (DefaultURLString == DEFAULT_URL_LINK) {
4072 url = url_unquote_conv(url, Currentbuf->document_charset);
4075 pushHist(hist, a_url);
4077 url = inputLineHist(prompt, url, IN_URL, hist);
4083 if ((relative || *url == '#') && Currentbuf->document_charset)
4084 url = wc_conv_strict(url, InnerCharset,
4085 Currentbuf->document_charset)->ptr;
4087 url = conv_to_system(url);
4090 if (url == NULL || *url == '\0') {
4091 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4099 current = baseURL(Currentbuf);
4100 referer = parsedURL2Str(&Currentbuf->currentURL)->ptr;
4106 parseURL2(url, &p_url, current);
4107 pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr);
4108 cmd_loadURL(url, current, referer, NULL);
4109 if (Currentbuf != cur_buf) /* success */
4110 pushHashHist(URLHist, parsedURL2Str(&Currentbuf->currentURL)->ptr);
4113 DEFUN(goURL, GOTO, "Go to URL")
4115 goURL0("Goto URL: ", FALSE);
4118 DEFUN(gorURL, GOTO_RELATIVE, "Go to relative URL")
4120 goURL0("Goto relative URL: ", TRUE);
4124 cmd_loadBuffer(Buffer *buf, int prop, int linkid)
4127 disp_err_message("Can't load string", FALSE);
4129 else if (buf != NO_BUFFER) {
4130 buf->bufferprop |= (BP_INTERNAL | prop);
4131 if (!(buf->bufferprop & BP_NO_URL))
4132 copyParsedURL(&buf->currentURL, &Currentbuf->currentURL);
4133 if (linkid != LB_NOLINK) {
4134 buf->linkBuffer[REV_LB[linkid]] = Currentbuf;
4135 Currentbuf->linkBuffer[linkid] = buf;
4139 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4143 DEFUN(ldBmark, BOOKMARK VIEW_BOOKMARK, "Read bookmark")
4145 cmd_loadURL(BookmarkFile, NULL, NO_REFERER, NULL);
4149 /* Add current to bookmark */
4150 DEFUN(adBmark, ADD_BOOKMARK, "Add current page to bookmark")
4155 tmp = Sprintf("mode=panel&cookie=%s&bmark=%s&url=%s&title=%s"
4160 (Str_form_quote(localCookie()))->ptr,
4161 (Str_form_quote(Strnew_charp(BookmarkFile)))->ptr,
4162 (Str_form_quote(parsedURL2Str(&Currentbuf->currentURL)))->
4165 (Str_form_quote(wc_conv_strict(Currentbuf->buffername,
4167 BookmarkCharset)))->ptr,
4168 wc_ces_to_charset(BookmarkCharset));
4170 (Str_form_quote(Strnew_charp(Currentbuf->buffername)))->ptr);
4172 request = newFormList(NULL, "post", NULL, NULL, NULL, NULL, NULL);
4173 request->body = tmp->ptr;
4174 request->length = tmp->length;
4175 cmd_loadURL("file:///$LIB/" W3MBOOKMARK_CMDNAME, NULL, NO_REFERER,
4179 /* option setting */
4180 DEFUN(ldOpt, OPTIONS, "Option setting panel")
4182 cmd_loadBuffer(load_option_panel(), BP_NO_URL, LB_NOLINK);
4186 DEFUN(setOpt, SET_OPTION, "Set option")
4190 CurrentKeyData = NULL; /* not allowed in w3m-control: */
4191 opt = searchKeyData();
4192 if (opt == NULL || *opt == '\0' || strchr(opt, '=') == NULL) {
4193 if (opt != NULL && *opt != '\0') {
4194 char *v = get_param_option(opt);
4195 opt = Sprintf("%s=%s", opt, v ? v : "")->ptr;
4197 opt = inputStrHist("Set option: ", opt, TextHist);
4198 if (opt == NULL || *opt == '\0') {
4199 displayBuffer(Currentbuf, B_NORMAL);
4203 if (set_param_option(opt))
4205 displayBuffer(Currentbuf, B_REDRAW_IMAGE);
4208 /* error message list */
4209 DEFUN(msgs, MSGS, "Display error messages")
4211 cmd_loadBuffer(message_list_panel(), BP_NO_URL, LB_NOLINK);
4215 DEFUN(pginfo, INFO, "View info of current document")
4219 if ((buf = Currentbuf->linkBuffer[LB_N_INFO]) != NULL) {
4221 displayBuffer(Currentbuf, B_NORMAL);
4224 if ((buf = Currentbuf->linkBuffer[LB_INFO]) != NULL)
4226 buf = page_info_panel(Currentbuf);
4227 cmd_loadBuffer(buf, BP_NORMAL, LB_INFO);
4231 follow_map(struct parsed_tagarg *arg)
4233 char *name = tag_get_value(arg, "link");
4234 #if defined(MENU_MAP) || defined(USE_IMAGE)
4240 an = retrieveCurrentImg(Currentbuf);
4241 x = Currentbuf->cursorX + Currentbuf->rootX;
4242 y = Currentbuf->cursorY + Currentbuf->rootY;
4243 a = follow_map_menu(Currentbuf, name, an, x, y);
4244 if (a == NULL || a->url == NULL || *(a->url) == '\0') {
4247 Buffer *buf = follow_map_panel(Currentbuf, name);
4250 cmd_loadBuffer(buf, BP_NORMAL, LB_NOLINK);
4252 #if defined(MENU_MAP) || defined(USE_IMAGE)
4255 if (*(a->url) == '#') {
4256 gotoLabel(a->url + 1);
4259 parseURL2(a->url, &p_url, baseURL(Currentbuf));
4260 pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr);
4261 if (check_target && open_tab_blank && a->target &&
4262 (!strcasecmp(a->target, "_new") || !strcasecmp(a->target, "_blank"))) {
4267 cmd_loadURL(a->url, baseURL(Currentbuf),
4268 parsedURL2Str(&Currentbuf->currentURL)->ptr, NULL);
4269 if (buf != Currentbuf)
4272 deleteTab(CurrentTab);
4273 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4276 cmd_loadURL(a->url, baseURL(Currentbuf),
4277 parsedURL2Str(&Currentbuf->currentURL)->ptr, NULL);
4283 DEFUN(linkMn, LINK_MENU, "Popup link element menu")
4285 LinkList *l = link_menu(Currentbuf);
4290 if (*(l->url) == '#') {
4291 gotoLabel(l->url + 1);
4294 parseURL2(l->url, &p_url, baseURL(Currentbuf));
4295 pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr);
4296 cmd_loadURL(l->url, baseURL(Currentbuf),
4297 parsedURL2Str(&Currentbuf->currentURL)->ptr, NULL);
4301 anchorMn(Anchor *(*menu_func) (Buffer *), int go)
4306 if (!Currentbuf->href || !Currentbuf->hmarklist)
4308 a = menu_func(Currentbuf);
4309 if (!a || a->hseq < 0)
4311 po = &Currentbuf->hmarklist->marks[a->hseq];
4312 gotoLine(Currentbuf, po->line);
4313 Currentbuf->pos = po->pos;
4314 arrangeCursor(Currentbuf);
4315 displayBuffer(Currentbuf, B_NORMAL);
4321 DEFUN(accessKey, ACCESSKEY, "Popup acceskey menu")
4323 anchorMn(accesskey_menu, TRUE);
4327 DEFUN(listMn, LIST_MENU, "Popup link list menu and go to selected link")
4329 anchorMn(list_menu, TRUE);
4332 DEFUN(movlistMn, MOVE_LIST_MENU,
4333 "Popup link list menu and move cursor to selected link")
4335 anchorMn(list_menu, FALSE);
4339 /* link,anchor,image list */
4340 DEFUN(linkLst, LIST, "Show all links and images")
4344 buf = link_list_panel(Currentbuf);
4347 buf->document_charset = Currentbuf->document_charset;
4349 cmd_loadBuffer(buf, BP_NORMAL, LB_NOLINK);
4355 DEFUN(cooLst, COOKIE, "View cookie list")
4359 buf = cookie_list_panel();
4361 cmd_loadBuffer(buf, BP_NO_URL, LB_NOLINK);
4363 #endif /* USE_COOKIE */
4367 DEFUN(ldHist, HISTORY, "View history of URL")
4369 cmd_loadBuffer(historyBuffer(URLHist), BP_NO_URL, LB_NOLINK);
4371 #endif /* USE_HISTORY */
4373 /* download HREF link */
4374 DEFUN(svA, SAVE_LINK, "Save link to file")
4376 CurrentKeyData = NULL; /* not allowed in w3m-control: */
4379 do_download = FALSE;
4382 /* download IMG link */
4383 DEFUN(svI, SAVE_IMAGE, "Save image to file")
4385 CurrentKeyData = NULL; /* not allowed in w3m-control: */
4388 do_download = FALSE;
4392 DEFUN(svBuf, PRINT SAVE_SCREEN, "Save rendered document to file")
4394 char *qfile = NULL, *file;
4398 CurrentKeyData = NULL; /* not allowed in w3m-control: */
4399 file = searchKeyData();
4400 if (file == NULL || *file == '\0') {
4401 /* FIXME: gettextize? */
4402 qfile = inputLineHist("Save buffer to: ", NULL, IN_COMMAND, SaveHist);
4403 if (qfile == NULL || *qfile == '\0') {
4404 displayBuffer(Currentbuf, B_NORMAL);
4408 file = conv_to_system(qfile ? qfile : file);
4411 f = popen(file + 1, "w");
4415 file = unescape_spaces(Strnew_charp(qfile))->ptr;
4416 file = conv_to_system(file);
4418 file = expandPath(file);
4419 if (checkOverWrite(file) < 0) {
4420 displayBuffer(Currentbuf, B_NORMAL);
4423 f = fopen(file, "w");
4427 /* FIXME: gettextize? */
4428 char *emsg = Sprintf("Can't open %s", conv_from_system(file))->ptr;
4429 disp_err_message(emsg, TRUE);
4432 saveBuffer(Currentbuf, f, TRUE);
4437 displayBuffer(Currentbuf, B_NORMAL);
4441 DEFUN(svSrc, DOWNLOAD SAVE, "Save document source to file")
4445 if (Currentbuf->sourcefile == NULL)
4447 CurrentKeyData = NULL; /* not allowed in w3m-control: */
4448 PermitSaveToPipe = TRUE;
4449 if (Currentbuf->real_scheme == SCM_LOCAL)
4450 file = conv_from_system(guess_save_name(NULL,
4451 Currentbuf->currentURL.
4454 file = guess_save_name(Currentbuf, Currentbuf->currentURL.file);
4455 doFileCopy(Currentbuf->sourcefile, file);
4456 PermitSaveToPipe = FALSE;
4457 displayBuffer(Currentbuf, B_NORMAL);
4461 _peekURL(int only_img)
4466 static Str s = NULL;
4468 static Lineprop *p = NULL;
4471 static int offset = 0, n;
4473 if (Currentbuf->firstLine == NULL)
4475 if (CurrentKey == prev_key && s != NULL) {
4476 if (s->length - offset >= COLS)
4478 else if (s->length <= offset) /* bug ? */
4486 a = (only_img ? NULL : retrieveCurrentAnchor(Currentbuf));
4488 a = (only_img ? NULL : retrieveCurrentForm(Currentbuf));
4490 a = retrieveCurrentImg(Currentbuf);
4495 s = Strnew_charp(form2str((FormItemList *)a->url));
4498 parseURL2(a->url, &pu, baseURL(Currentbuf));
4499 s = parsedURL2Str(&pu);
4502 s = Strnew_charp(url_unquote_conv
4503 (s->ptr, Currentbuf->document_charset));
4505 s = checkType(s, &pp, NULL);
4506 p = NewAtom_N(Lineprop, s->length);
4507 bcopy((void *)pp, (void *)p, s->length * sizeof(Lineprop));
4511 if (n > 1 && s->length > (n - 1) * (COLS - 1))
4512 offset = (n - 1) * (COLS - 1);
4514 while (offset < s->length && p[offset] & PC_WCHAR2)
4517 disp_message_nomouse(&s->ptr[offset], TRUE);
4521 DEFUN(peekURL, PEEK_LINK, "Peek link URL")
4526 /* peek URL of image */
4527 DEFUN(peekIMG, PEEK_IMG, "Peek image URL")
4532 /* show current URL */
4536 if (Currentbuf->bufferprop & BP_INTERNAL)
4537 return Strnew_size(0);
4538 return parsedURL2Str(&Currentbuf->currentURL);
4541 DEFUN(curURL, PEEK, "Peek current URL")
4543 static Str s = NULL;
4545 static Lineprop *p = NULL;
4548 static int offset = 0, n;
4550 if (Currentbuf->bufferprop & BP_INTERNAL)
4552 if (CurrentKey == prev_key && s != NULL) {
4553 if (s->length - offset >= COLS)
4555 else if (s->length <= offset) /* bug ? */
4562 s = Strnew_charp(url_unquote_conv(s->ptr, 0));
4564 s = checkType(s, &pp, NULL);
4565 p = NewAtom_N(Lineprop, s->length);
4566 bcopy((void *)pp, (void *)p, s->length * sizeof(Lineprop));
4570 if (n > 1 && s->length > (n - 1) * (COLS - 1))
4571 offset = (n - 1) * (COLS - 1);
4573 while (offset < s->length && p[offset] & PC_WCHAR2)
4576 disp_message_nomouse(&s->ptr[offset], TRUE);
4578 /* view HTML source */
4580 DEFUN(vwSrc, SOURCE VIEW, "View HTML source")
4584 if (Currentbuf->type == NULL || Currentbuf->bufferprop & BP_FRAME)
4586 if ((buf = Currentbuf->linkBuffer[LB_SOURCE]) != NULL ||
4587 (buf = Currentbuf->linkBuffer[LB_N_SOURCE]) != NULL) {
4589 displayBuffer(Currentbuf, B_NORMAL);
4592 if (Currentbuf->sourcefile == NULL) {
4593 if (Currentbuf->pagerSource &&
4594 !strcasecmp(Currentbuf->type, "text/plain")) {
4597 wc_bool old_fix_width_conv;
4600 Str tmpf = tmpfname(TMPF_SRC, NULL);
4601 f = fopen(tmpf->ptr, "w");
4605 old_charset = DisplayCharset;
4606 old_fix_width_conv = WcOption.fix_width_conv;
4607 DisplayCharset = (Currentbuf->document_charset != WC_CES_US_ASCII)
4608 ? Currentbuf->document_charset : 0;
4609 WcOption.fix_width_conv = WC_FALSE;
4611 saveBufferBody(Currentbuf, f, TRUE);
4613 DisplayCharset = old_charset;
4614 WcOption.fix_width_conv = old_fix_width_conv;
4617 Currentbuf->sourcefile = tmpf->ptr;
4624 buf = newBuffer(INIT_BUFFER_WIDTH);
4626 if (!strcasecmp(Currentbuf->type, "text/html")) {
4627 buf->type = "text/plain";
4628 if (Currentbuf->real_type &&
4629 !strcasecmp(Currentbuf->real_type, "text/html"))
4630 buf->real_type = "text/plain";
4632 buf->real_type = Currentbuf->real_type;
4633 buf->buffername = Sprintf("source of %s", Currentbuf->buffername)->ptr;
4634 buf->linkBuffer[LB_N_SOURCE] = Currentbuf;
4635 Currentbuf->linkBuffer[LB_SOURCE] = buf;
4637 else if (!strcasecmp(Currentbuf->type, "text/plain")) {
4638 buf->type = "text/html";
4639 if (Currentbuf->real_type &&
4640 !strcasecmp(Currentbuf->real_type, "text/plain"))
4641 buf->real_type = "text/html";
4643 buf->real_type = Currentbuf->real_type;
4644 buf->buffername = Sprintf("HTML view of %s",
4645 Currentbuf->buffername)->ptr;
4646 buf->linkBuffer[LB_SOURCE] = Currentbuf;
4647 Currentbuf->linkBuffer[LB_N_SOURCE] = buf;
4652 buf->currentURL = Currentbuf->currentURL;
4653 buf->real_scheme = Currentbuf->real_scheme;
4654 buf->filename = Currentbuf->filename;
4655 buf->sourcefile = Currentbuf->sourcefile;
4656 buf->header_source = Currentbuf->header_source;
4657 buf->search_header = Currentbuf->search_header;
4659 buf->document_charset = Currentbuf->document_charset;
4661 buf->clone = Currentbuf->clone;
4664 buf->need_reshape = TRUE;
4667 displayBuffer(Currentbuf, B_NORMAL);
4671 DEFUN(reload, RELOAD, "Reload buffer")
4673 Buffer *buf, *fbuf = NULL, sbuf;
4681 if (Currentbuf->bufferprop & BP_INTERNAL) {
4682 if (!strcmp(Currentbuf->buffername, DOWNLOAD_LIST_TITLE)) {
4686 /* FIXME: gettextize? */
4687 disp_err_message("Can't reload...", TRUE);
4690 if (Currentbuf->currentURL.scheme == SCM_LOCAL &&
4691 !strcmp(Currentbuf->currentURL.file, "-")) {
4692 /* file is std input */
4693 /* FIXME: gettextize? */
4694 disp_err_message("Can't reload stdin", TRUE);
4697 copyBuffer(&sbuf, Currentbuf);
4698 if (Currentbuf->bufferprop & BP_FRAME &&
4699 (fbuf = Currentbuf->linkBuffer[LB_N_FRAME])) {
4700 if (fmInitialized) {
4701 message("Rendering frame", 0, 0);
4704 if (!(buf = renderFrame(fbuf, 1))) {
4705 displayBuffer(Currentbuf, B_NORMAL);
4708 if (fbuf->linkBuffer[LB_FRAME]) {
4709 if (buf->sourcefile &&
4710 fbuf->linkBuffer[LB_FRAME]->sourcefile &&
4711 !strcmp(buf->sourcefile,
4712 fbuf->linkBuffer[LB_FRAME]->sourcefile))
4713 fbuf->linkBuffer[LB_FRAME]->sourcefile = NULL;
4714 delBuffer(fbuf->linkBuffer[LB_FRAME]);
4716 fbuf->linkBuffer[LB_FRAME] = buf;
4717 buf->linkBuffer[LB_N_FRAME] = fbuf;
4720 if (Currentbuf->firstLine) {
4721 COPY_BUFROOT(Currentbuf, &sbuf);
4722 restorePosition(Currentbuf, &sbuf);
4724 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4727 else if (Currentbuf->frameset != NULL)
4728 fbuf = Currentbuf->linkBuffer[LB_FRAME];
4730 if (Currentbuf->form_submit) {
4731 request = Currentbuf->form_submit->parent;
4732 if (request->method == FORM_METHOD_POST
4733 && request->enctype == FORM_ENCTYPE_MULTIPART) {
4737 query_from_followform(&query, Currentbuf->form_submit, multipart);
4738 stat(request->body, &st);
4739 request->length = st.st_size;
4745 url = parsedURL2Str(&Currentbuf->currentURL);
4746 /* FIXME: gettextize? */
4747 message("Reloading...", 0, 0);
4750 old_charset = DocumentCharset;
4751 if (Currentbuf->document_charset != WC_CES_US_ASCII)
4752 DocumentCharset = Currentbuf->document_charset;
4754 SearchHeader = Currentbuf->search_header;
4755 DefaultType = Currentbuf->real_type;
4756 buf = loadGeneralFile(url->ptr, NULL, NO_REFERER, RG_NOCACHE, request);
4758 DocumentCharset = old_charset;
4760 SearchHeader = FALSE;
4764 unlink(request->body);
4766 /* FIXME: gettextize? */
4767 disp_err_message("Can't reload...", TRUE);
4770 else if (buf == NO_BUFFER) {
4771 displayBuffer(Currentbuf, B_NORMAL);
4775 Firstbuf = deleteBuffer(Firstbuf, fbuf);
4776 repBuffer(Currentbuf, buf);
4777 if ((buf->type != NULL) && (sbuf.type != NULL) &&
4778 ((!strcasecmp(buf->type, "text/plain") &&
4779 !strcasecmp(sbuf.type, "text/html")) ||
4780 (!strcasecmp(buf->type, "text/html") &&
4781 !strcasecmp(sbuf.type, "text/plain")))) {
4783 if (Currentbuf != buf)
4784 Firstbuf = deleteBuffer(Firstbuf, buf);
4786 Currentbuf->search_header = sbuf.search_header;
4787 Currentbuf->form_submit = sbuf.form_submit;
4788 if (Currentbuf->firstLine) {
4789 COPY_BUFROOT(Currentbuf, &sbuf);
4790 restorePosition(Currentbuf, &sbuf);
4792 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4796 DEFUN(reshape, RESHAPE, "Re-render buffer")
4798 Currentbuf->need_reshape = TRUE;
4799 reshapeBuffer(Currentbuf);
4800 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4805 _docCSet(wc_ces charset)
4807 if (Currentbuf->bufferprop & BP_INTERNAL)
4809 if (Currentbuf->sourcefile == NULL) {
4810 disp_message("Can't reload...", FALSE);
4813 Currentbuf->document_charset = charset;
4814 Currentbuf->need_reshape = TRUE;
4815 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4819 change_charset(struct parsed_tagarg *arg)
4821 Buffer *buf = Currentbuf->linkBuffer[LB_N_INFO];
4826 delBuffer(Currentbuf);
4828 if (Currentbuf->bufferprop & BP_INTERNAL)
4830 charset = Currentbuf->document_charset;
4831 for (; arg; arg = arg->next) {
4832 if (!strcmp(arg->arg, "charset"))
4833 charset = atoi(arg->value);
4838 DEFUN(docCSet, CHARSET, "Change the current document charset")
4843 cs = searchKeyData();
4844 if (cs == NULL || *cs == '\0')
4845 /* FIXME: gettextize? */
4846 cs = inputStr("Document charset: ",
4847 wc_ces_to_charset(Currentbuf->document_charset));
4848 charset = wc_guess_charset_short(cs, 0);
4850 displayBuffer(Currentbuf, B_NORMAL);
4856 DEFUN(defCSet, DEFAULT_CHARSET, "Change the default document charset")
4861 cs = searchKeyData();
4862 if (cs == NULL || *cs == '\0')
4863 /* FIXME: gettextize? */
4864 cs = inputStr("Default document charset: ",
4865 wc_ces_to_charset(DocumentCharset));
4866 charset = wc_guess_charset_short(cs, 0);
4868 DocumentCharset = charset;
4869 displayBuffer(Currentbuf, B_NORMAL);
4873 /* mark URL-like patterns as anchors */
4875 chkURLBuffer(Buffer *buf)
4877 static char *url_like_pat[] = {
4878 "https?://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./?=~_\\&+@#,\\$;]*[a-zA-Z0-9_/=\\-]",
4879 "file:/[a-zA-Z0-9:%\\-\\./=_\\+@#,\\$;]*",
4881 "gopher://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./_]*",
4882 #endif /* USE_GOPHER */
4883 "ftp://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./=_+@#,\\$]*[a-zA-Z0-9_/]",
4885 "news:[^<> ][^<> ]*",
4886 "nntp://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./_]*",
4887 #endif /* USE_NNTP */
4888 #ifndef USE_W3MMAILER /* see also chkExternalURIBuffer() */
4889 "mailto:[^<> ][^<> ]*@[a-zA-Z0-9][a-zA-Z0-9\\-\\._]*[a-zA-Z0-9]",
4892 "https?://[a-zA-Z0-9:%\\-\\./_@]*\\[[a-fA-F0-9:][a-fA-F0-9:\\.]*\\][a-zA-Z0-9:%\\-\\./?=~_\\&+@#,\\$;]*",
4893 "ftp://[a-zA-Z0-9:%\\-\\./_@]*\\[[a-fA-F0-9:][a-fA-F0-9:\\.]*\\][a-zA-Z0-9:%\\-\\./=_+@#,\\$]*",
4898 for (i = 0; url_like_pat[i]; i++) {
4899 reAnchor(buf, url_like_pat[i]);
4901 #ifdef USE_EXTERNAL_URI_LOADER
4902 chkExternalURIBuffer(buf);
4904 buf->check_url |= CHK_URL;
4907 DEFUN(chkURL, MARK_URL, "Mark URL-like strings as anchors")
4909 chkURLBuffer(Currentbuf);
4910 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4913 DEFUN(chkWORD, MARK_WORD, "Mark current word as anchor")
4917 p = getCurWord(Currentbuf, &spos, &epos, ":\"\'`<>()[]{}&|;*?$");
4920 reAnchorWord(Currentbuf, Currentbuf->currentLine, spos, epos);
4921 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4925 /* mark Message-ID-like patterns as NEWS anchors */
4927 chkNMIDBuffer(Buffer *buf)
4929 static char *url_like_pat[] = {
4930 "<[!-;=?-~]+@[a-zA-Z0-9\\.\\-_]+>",
4934 for (i = 0; url_like_pat[i]; i++) {
4935 reAnchorNews(buf, url_like_pat[i]);
4937 buf->check_url |= CHK_NMID;
4940 DEFUN(chkNMID, MARK_MID, "Mark Message-ID-like strings as anchors")
4942 chkNMIDBuffer(Currentbuf);
4943 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4945 #endif /* USE_NNTP */
4948 DEFUN(rFrame, FRAME, "Render frame")
4952 if ((buf = Currentbuf->linkBuffer[LB_FRAME]) != NULL) {
4954 displayBuffer(Currentbuf, B_NORMAL);
4957 if (Currentbuf->frameset == NULL) {
4958 if ((buf = Currentbuf->linkBuffer[LB_N_FRAME]) != NULL) {
4960 displayBuffer(Currentbuf, B_NORMAL);
4964 if (fmInitialized) {
4965 message("Rendering frame", 0, 0);
4968 buf = renderFrame(Currentbuf, 0);
4970 displayBuffer(Currentbuf, B_NORMAL);
4973 buf->linkBuffer[LB_N_FRAME] = Currentbuf;
4974 Currentbuf->linkBuffer[LB_FRAME] = buf;
4976 if (fmInitialized && display_ok)
4977 displayBuffer(Currentbuf, B_FORCE_REDRAW);
4980 /* spawn external browser */
4982 invoke_browser(char *url)
4985 char *browser = NULL;
4988 CurrentKeyData = NULL; /* not allowed in w3m-control: */
4989 browser = searchKeyData();
4990 if (browser == NULL || *browser == '\0') {
4994 browser = ExtBrowser;
4997 browser = ExtBrowser2;
5000 browser = ExtBrowser3;
5003 if (browser == NULL || *browser == '\0') {
5004 browser = inputStr("Browse command: ", NULL);
5005 if (browser != NULL)
5006 browser = conv_to_system(browser);
5010 browser = conv_to_system(browser);
5012 if (browser == NULL || *browser == '\0') {
5013 displayBuffer(Currentbuf, B_NORMAL);
5017 if ((len = strlen(browser)) >= 2 && browser[len - 1] == '&' &&
5018 browser[len - 2] != '\\') {
5019 browser = allocStr(browser, len - 2);
5022 cmd = myExtCommand(browser, shell_quote(url), FALSE);
5023 Strremovetrailingspaces(cmd);
5025 mySystem(cmd->ptr, bg);
5027 displayBuffer(Currentbuf, B_FORCE_REDRAW);
5030 DEFUN(extbrz, EXTERN, "Execute external browser")
5032 if (Currentbuf->bufferprop & BP_INTERNAL) {
5033 /* FIXME: gettextize? */
5034 disp_err_message("Can't browse...", TRUE);
5037 if (Currentbuf->currentURL.scheme == SCM_LOCAL &&
5038 !strcmp(Currentbuf->currentURL.file, "-")) {
5039 /* file is std input */
5040 /* FIXME: gettextize? */
5041 disp_err_message("Can't browse stdin", TRUE);
5044 invoke_browser(parsedURL2Str(&Currentbuf->currentURL)->ptr);
5047 DEFUN(linkbrz, EXTERN_LINK, "View current link using external browser")
5052 if (Currentbuf->firstLine == NULL)
5054 a = retrieveCurrentAnchor(Currentbuf);
5057 parseURL2(a->url, &pu, baseURL(Currentbuf));
5058 invoke_browser(parsedURL2Str(&pu)->ptr);
5061 /* show current line number and number of lines in the entire document */
5062 DEFUN(curlno, LINE_INFO, "Show current line number")
5064 Line *l = Currentbuf->currentLine;
5066 int cur = 0, all = 0, col = 0, len = 0;
5069 cur = l->real_linenumber;
5070 col = l->bwidth + Currentbuf->currentColumn + Currentbuf->cursorX + 1;
5071 while (l->next && l->next->bpos)
5074 l->width = COLPOS(l, l->len);
5075 len = l->bwidth + l->width;
5077 if (Currentbuf->lastLine)
5078 all = Currentbuf->lastLine->real_linenumber;
5079 if (Currentbuf->pagerSource && !(Currentbuf->bufferprop & BP_CLOSE))
5080 tmp = Sprintf("line %d col %d/%d", cur, col, len);
5082 tmp = Sprintf("line %d/%d (%d%%) col %d/%d", cur, all,
5083 (int)((double)cur * 100.0 / (double)(all ? all : 1)
5086 Strcat_charp(tmp, " ");
5087 Strcat_charp(tmp, wc_ces_to_charset_desc(Currentbuf->document_charset));
5090 disp_message(tmp->ptr, FALSE);
5094 DEFUN(dispI, DISPLAY_IMAGE, "Restart loading and drawing of images")
5100 displayImage = TRUE;
5102 * if (!(Currentbuf->type && !strcmp(Currentbuf->type, "text/html")))
5105 Currentbuf->image_flag = IMG_FLAG_AUTO;
5106 Currentbuf->need_reshape = TRUE;
5107 displayBuffer(Currentbuf, B_REDRAW_IMAGE);
5110 DEFUN(stopI, STOP_IMAGE, "Stop loading and drawing of images")
5115 * if (!(Currentbuf->type && !strcmp(Currentbuf->type, "text/html")))
5118 Currentbuf->image_flag = IMG_FLAG_SKIP;
5119 displayBuffer(Currentbuf, B_REDRAW_IMAGE);
5126 mouse_scroll_line(void)
5128 if (relative_wheel_scroll)
5129 return (relative_wheel_scroll_ratio * LASTLINE + 99) / 100;
5131 return fixed_wheel_scroll_count;
5135 posTab(int x, int y)
5139 if (mouse_action.menu_str && x < mouse_action.menu_width && y == 0)
5140 return NO_TABBUFFER;
5143 for (tab = FirstTab; tab; tab = tab->nextTab) {
5144 if (tab->x1 <= x && x <= tab->x2 && tab->y == y)
5151 do_mouse_action(int btn, int x, int y)
5153 MouseActionMap *map = NULL;
5156 if (nTab > 1 || mouse_action.menu_str)
5157 ny = LastTab->y + 1;
5160 case MOUSE_BTN1_DOWN:
5163 case MOUSE_BTN2_DOWN:
5166 case MOUSE_BTN3_DOWN:
5173 if (mouse_action.menu_str && x >= 0 && x < mouse_action.menu_width) {
5174 if (mouse_action.menu_map[btn])
5175 map = &mouse_action.menu_map[btn][x];
5178 map = &mouse_action.tab_map[btn];
5180 else if (y == LASTLINE) {
5181 if (mouse_action.lastline_str && x >= 0 &&
5182 x < mouse_action.lastline_width) {
5183 if (mouse_action.lastline_map[btn])
5184 map = &mouse_action.lastline_map[btn][x];
5188 if (y == Currentbuf->cursorY + Currentbuf->rootY &&
5189 (x == Currentbuf->cursorX + Currentbuf->rootX
5191 || (WcOption.use_wide && Currentbuf->currentLine != NULL &&
5192 (CharType(Currentbuf->currentLine->propBuf[Currentbuf->pos])
5194 && x == Currentbuf->cursorX + Currentbuf->rootX + 1)
5197 if (retrieveCurrentAnchor(Currentbuf) ||
5198 retrieveCurrentForm(Currentbuf)) {
5199 map = &mouse_action.active_map[btn];
5200 if (!(map && map->func))
5201 map = &mouse_action.anchor_map[btn];
5205 int cx = Currentbuf->cursorX, cy = Currentbuf->cursorY;
5206 cursorXY(Currentbuf, x - Currentbuf->rootX, y - Currentbuf->rootY);
5207 if (y == Currentbuf->cursorY + Currentbuf->rootY &&
5208 (x == Currentbuf->cursorX + Currentbuf->rootX
5210 || (WcOption.use_wide && Currentbuf->currentLine != NULL &&
5211 (CharType(Currentbuf->currentLine->
5212 propBuf[Currentbuf->pos]) == PC_KANJI1)
5213 && x == Currentbuf->cursorX + Currentbuf->rootX + 1)
5216 (retrieveCurrentAnchor(Currentbuf) ||
5217 retrieveCurrentForm(Currentbuf)))
5218 map = &mouse_action.anchor_map[btn];
5219 cursorXY(Currentbuf, cx, cy);
5225 if (!(map && map->func))
5226 map = &mouse_action.default_map[btn];
5227 if (map && map->func) {
5228 mouse_action.in_action = TRUE;
5229 mouse_action.cursorX = x;
5230 mouse_action.cursorY = y;
5232 CurrentKeyData = NULL;
5233 CurrentCmdData = map->data;
5235 CurrentCmdData = NULL;
5240 process_mouse(int btn, int x, int y)
5242 int delta_x, delta_y, i;
5243 static int press_btn = MOUSE_BTN_RESET, press_x, press_y;
5247 if (nTab > 1 || mouse_action.menu_str)
5248 ny = LastTab->y + 1;
5249 if (btn == MOUSE_BTN_UP) {
5250 switch (press_btn) {
5251 case MOUSE_BTN1_DOWN:
5252 if (press_y == y && press_x == x)
5253 do_mouse_action(press_btn, x, y);
5254 else if (ny > 0 && y < ny) {
5256 moveTab(posTab(press_x, press_y), posTab(x, y),
5257 (press_y == y) ? (press_x < x) : (press_y < y));
5260 else if (press_x >= Currentbuf->rootX) {
5261 Buffer *buf = Currentbuf;
5262 int cx = Currentbuf->cursorX, cy = Currentbuf->cursorY;
5267 if (t == NO_TABBUFFER)
5268 t = NULL; /* open new tab */
5269 cursorXY(Currentbuf, press_x - Currentbuf->rootX,
5270 press_y - Currentbuf->rootY);
5271 if (Currentbuf->cursorY == press_y - Currentbuf->rootY &&
5272 (Currentbuf->cursorX == press_x - Currentbuf->rootX
5274 || (WcOption.use_wide &&
5275 Currentbuf->currentLine != NULL &&
5276 (CharType(Currentbuf->currentLine->
5277 propBuf[Currentbuf->pos]) == PC_KANJI1)
5278 && Currentbuf->cursorX == press_x
5279 - Currentbuf->rootX - 1)
5282 displayBuffer(Currentbuf, B_NORMAL);
5285 if (buf == Currentbuf)
5286 cursorXY(Currentbuf, cx, cy);
5291 delta_x = x - press_x;
5292 delta_y = y - press_y;
5294 if (abs(delta_x) < abs(delta_y) / 3)
5296 if (abs(delta_y) < abs(delta_x) / 3)
5298 if (reverse_mouse) {
5306 else if (delta_y < 0) {
5307 prec_num = -delta_y;
5314 else if (delta_x < 0) {
5315 prec_num = -delta_x;
5320 case MOUSE_BTN2_DOWN:
5321 case MOUSE_BTN3_DOWN:
5322 if (press_y == y && press_x == x)
5323 do_mouse_action(press_btn, x, y);
5325 case MOUSE_BTN4_DOWN_RXVT:
5326 for (i = 0; i < mouse_scroll_line(); i++)
5329 case MOUSE_BTN5_DOWN_RXVT:
5330 for (i = 0; i < mouse_scroll_line(); i++)
5335 else if (btn == MOUSE_BTN4_DOWN_XTERM) {
5336 for (i = 0; i < mouse_scroll_line(); i++)
5339 else if (btn == MOUSE_BTN5_DOWN_XTERM) {
5340 for (i = 0; i < mouse_scroll_line(); i++)
5344 if (btn != MOUSE_BTN4_DOWN_RXVT || press_btn == MOUSE_BTN_RESET) {
5350 press_btn = MOUSE_BTN_RESET;
5354 DEFUN(msToggle, MOUSE_TOGGLE, "Toggle activity of mouse")
5362 displayBuffer(Currentbuf, B_FORCE_REDRAW);
5365 DEFUN(mouse, MOUSE, "mouse operation")
5369 btn = (unsigned char)getch() - 32;
5370 #if defined(__CYGWIN__) && CYGWIN_VERSION_DLL_MAJOR < 1005
5371 if (cygwin_mouse_btn_swapped) {
5372 if (btn == MOUSE_BTN2_DOWN)
5373 btn = MOUSE_BTN3_DOWN;
5374 else if (btn == MOUSE_BTN3_DOWN)
5375 btn = MOUSE_BTN2_DOWN;
5378 x = (unsigned char)getch() - 33;
5381 y = (unsigned char)getch() - 33;
5385 if (x < 0 || x >= COLS || y < 0 || y > LASTLINE)
5387 process_mouse(btn, x, y);
5392 gpm_process_mouse(Gpm_Event * event, void *data)
5394 int btn = MOUSE_BTN_RESET, x, y;
5395 if (event->type & GPM_UP)
5397 else if (event->type & GPM_DOWN) {
5398 switch (event->buttons) {
5400 btn = MOUSE_BTN1_DOWN;
5403 btn = MOUSE_BTN2_DOWN;
5406 btn = MOUSE_BTN3_DOWN;
5411 GPM_DRAWPOINTER(event);
5416 process_mouse(btn, x - 1, y - 1);
5419 #endif /* USE_GPM */
5423 sysm_process_mouse(int x, int y, int nbs, int obs)
5430 else if (nbs & ~obs) {
5432 btn = bits & 0x1 ? MOUSE_BTN1_DOWN :
5433 (bits & 0x2 ? MOUSE_BTN2_DOWN :
5434 (bits & 0x4 ? MOUSE_BTN3_DOWN : 0));
5436 else /* nbs == obs */
5438 process_mouse(btn, x, y);
5441 #endif /* USE_SYSMOUSE */
5443 DEFUN(movMs, MOVE_MOUSE, "Move cursor to mouse cursor (for mouse action)")
5445 if (!mouse_action.in_action)
5447 if ((nTab > 1 || mouse_action.menu_str) &&
5448 mouse_action.cursorY < LastTab->y + 1)
5450 else if (mouse_action.cursorX >= Currentbuf->rootX &&
5451 mouse_action.cursorY < LASTLINE) {
5452 cursorXY(Currentbuf, mouse_action.cursorX - Currentbuf->rootX,
5453 mouse_action.cursorY - Currentbuf->rootY);
5455 displayBuffer(Currentbuf, B_NORMAL);
5459 #ifdef KANJI_SYMBOLS
5460 #define FRAME_WIDTH 2
5462 #define FRAME_WIDTH 1
5465 DEFUN(menuMs, MENU_MOUSE, "Popup menu at mouse cursor (for mouse action)")
5467 if (!mouse_action.in_action)
5469 if ((nTab > 1 || mouse_action.menu_str) &&
5470 mouse_action.cursorY < LastTab->y + 1)
5471 mouse_action.cursorX -= FRAME_WIDTH + 1;
5472 else if (mouse_action.cursorX >= Currentbuf->rootX &&
5473 mouse_action.cursorY < LASTLINE) {
5474 cursorXY(Currentbuf, mouse_action.cursorX - Currentbuf->rootX,
5475 mouse_action.cursorY - Currentbuf->rootY);
5476 displayBuffer(Currentbuf, B_NORMAL);
5482 DEFUN(tabMs, TAB_MOUSE, "Move to tab on mouse cursor (for mouse action)")
5486 if (!mouse_action.in_action)
5488 tab = posTab(mouse_action.cursorX, mouse_action.cursorY);
5489 if (!tab || tab == NO_TABBUFFER)
5492 displayBuffer(Currentbuf, B_FORCE_REDRAW);
5495 DEFUN(closeTMs, CLOSE_TAB_MOUSE,
5496 "Close tab on mouse cursor (for mouse action)")
5500 if (!mouse_action.in_action)
5502 tab = posTab(mouse_action.cursorX, mouse_action.cursorY);
5503 if (!tab || tab == NO_TABBUFFER)
5506 displayBuffer(Currentbuf, B_FORCE_REDRAW);
5508 #endif /* USE_MOUSE */
5510 DEFUN(dispVer, VERSION, "Display version of w3m")
5512 disp_message(Sprintf("w3m version %s", w3m_version)->ptr, TRUE);
5515 DEFUN(wrapToggle, WRAP_TOGGLE, "Toggle wrap search mode")
5519 /* FIXME: gettextize? */
5520 disp_message("Wrap search off", TRUE);
5524 /* FIXME: gettextize? */
5525 disp_message("Wrap search on", TRUE);
5530 is_wordchar(int c, const char *badchars)
5533 return !(IS_SPACE(c) || strchr(badchars, c));
5539 getCurWord(Buffer *buf, int *spos, int *epos, const char *badchars)
5542 Line *l = buf->currentLine;
5551 while (e > 0 && !is_wordchar(p[e], badchars))
5553 if (!is_wordchar(p[e], badchars))
5556 while (b > 0 && is_wordchar(p[b - 1], badchars))
5558 while (e < l->len && is_wordchar(p[e], badchars))
5566 GetWord(Buffer *buf)
5571 if ((p = getCurWord(buf, &b, &e, 0)) != NULL) {
5572 return Strnew_charp_n(p, e - b)->ptr;
5579 execdict(char *word)
5584 if (!UseDictCommand || word == NULL || *word == '\0') {
5585 displayBuffer(Currentbuf, B_NORMAL);
5588 w = conv_to_system(word);
5590 displayBuffer(Currentbuf, B_NORMAL);
5593 dictcmd = Sprintf("%s?%s", DictCommand,
5594 Str_form_quote(Strnew_charp(w))->ptr)->ptr;
5595 buf = loadGeneralFile(dictcmd, NULL, NO_REFERER, 0, NULL);
5597 disp_message("Execution failed", TRUE);
5602 buf->buffername = Sprintf("%s %s", DICTBUFFERNAME, word)->ptr;
5603 if (buf->type == NULL)
5604 buf->type = "text/plain";
5607 displayBuffer(Currentbuf, B_FORCE_REDRAW);
5610 DEFUN(dictword, DICT_WORD, "Execute dictionary command (see README.dict)")
5612 execdict(inputStr("(dictionary)!", ""));
5615 DEFUN(dictwordat, DICT_WORD_AT,
5616 "Execute dictionary command for word at cursor")
5618 execdict(GetWord(Currentbuf));
5620 #endif /* USE_DICT */
5623 set_buffer_environ(Buffer *buf)
5625 static Buffer *prev_buf = NULL;
5626 static Line *prev_line = NULL;
5627 static int prev_pos = -1;
5632 if (buf != prev_buf) {
5633 set_environ("W3M_SOURCEFILE", buf->sourcefile);
5634 set_environ("W3M_FILENAME", buf->filename);
5635 set_environ("W3M_TITLE", buf->buffername);
5636 set_environ("W3M_URL", parsedURL2Str(&buf->currentURL)->ptr);
5637 set_environ("W3M_TYPE", buf->real_type ? buf->real_type : "unknown");
5639 set_environ("W3M_CHARSET", wc_ces_to_charset(buf->document_charset));
5642 l = buf->currentLine;
5643 if (l && (buf != prev_buf || l != prev_line || buf->pos != prev_pos)) {
5646 char *s = GetWord(buf);
5647 set_environ("W3M_CURRENT_WORD", s ? s : "");
5648 a = retrieveCurrentAnchor(buf);
5650 parseURL2(a->url, &pu, baseURL(buf));
5651 set_environ("W3M_CURRENT_LINK", parsedURL2Str(&pu)->ptr);
5654 set_environ("W3M_CURRENT_LINK", "");
5655 a = retrieveCurrentImg(buf);
5657 parseURL2(a->url, &pu, baseURL(buf));
5658 set_environ("W3M_CURRENT_IMG", parsedURL2Str(&pu)->ptr);
5661 set_environ("W3M_CURRENT_IMG", "");
5662 a = retrieveCurrentForm(buf);
5664 set_environ("W3M_CURRENT_FORM", form2str((FormItemList *)a->url));
5666 set_environ("W3M_CURRENT_FORM", "");
5667 set_environ("W3M_CURRENT_LINE", Sprintf("%d",
5668 l->real_linenumber)->ptr);
5669 set_environ("W3M_CURRENT_COLUMN", Sprintf("%d",
5670 buf->currentColumn +
5671 buf->cursorX + 1)->ptr);
5674 set_environ("W3M_CURRENT_WORD", "");
5675 set_environ("W3M_CURRENT_LINK", "");
5676 set_environ("W3M_CURRENT_IMG", "");
5677 set_environ("W3M_CURRENT_FORM", "");
5678 set_environ("W3M_CURRENT_LINE", "0");
5679 set_environ("W3M_CURRENT_COLUMN", "0");
5683 prev_pos = buf->pos;
5691 if (CurrentKeyData != NULL && *CurrentKeyData != '\0')
5692 data = CurrentKeyData;
5693 else if (CurrentCmdData != NULL && *CurrentCmdData != '\0')
5694 data = CurrentCmdData;
5695 else if (CurrentKey >= 0)
5696 data = getKeyData(CurrentKey);
5697 CurrentKeyData = NULL;
5698 CurrentCmdData = NULL;
5699 if (data == NULL || *data == '\0')
5701 return allocStr(data, -1);
5710 d = searchKeyData();
5713 return n * PREC_NUM;
5721 unsigned long CpList[8], CpSize;
5723 if (!getenv("WINDOWID") && !DosQueryCp(sizeof(CpList), CpList, &CpSize))
5724 return Sprintf("CP%d", *CpList)->ptr;
5736 for (CurrentTab = FirstTab; CurrentTab; CurrentTab = CurrentTab->nextTab) {
5737 while (Firstbuf && Firstbuf != NO_BUFFER) {
5738 buf = Firstbuf->nextBuffer;
5739 discardBuffer(Firstbuf);
5743 while ((f = popText(fileToDelete)) != NULL)
5751 init_migemo(); /* close pipe to migemo */
5762 #ifdef __MINGW32_VERSION
5768 DEFUN(execCmd, COMMAND, "Execute w3m command(s)")
5773 CurrentKeyData = NULL; /* not allowed in w3m-control: */
5774 data = searchKeyData();
5775 if (data == NULL || *data == '\0') {
5776 data = inputStrHist("command [; ...]: ", "", TextHist);
5778 displayBuffer(Currentbuf, B_NORMAL);
5782 /* data: FUNC [DATA] [; FUNC [DATA] ...] */
5790 cmd = getFuncList(p);
5793 p = getQWord(&data);
5795 CurrentKeyData = NULL;
5796 CurrentCmdData = *p ? p : NULL;
5801 w3mFuncList[cmd].func();
5806 CurrentCmdData = NULL;
5808 displayBuffer(Currentbuf, B_NORMAL);
5812 static MySignalHandler
5813 SigAlarm(SIGNAL_ARG)
5817 if (CurrentAlarm->sec > 0) {
5819 CurrentKeyData = NULL;
5820 CurrentCmdData = data = (char *)CurrentAlarm->data;
5825 w3mFuncList[CurrentAlarm->cmd].func();
5830 CurrentCmdData = NULL;
5831 if (CurrentAlarm->status == AL_IMPLICIT_ONCE) {
5832 CurrentAlarm->sec = 0;
5833 CurrentAlarm->status = AL_UNSET;
5835 if (Currentbuf->event) {
5836 if (Currentbuf->event->status != AL_UNSET)
5837 CurrentAlarm = Currentbuf->event;
5839 Currentbuf->event = NULL;
5841 if (!Currentbuf->event)
5842 CurrentAlarm = &DefaultAlarm;
5843 if (CurrentAlarm->sec > 0) {
5844 mySignal(SIGALRM, SigAlarm);
5845 alarm(CurrentAlarm->sec);
5852 DEFUN(setAlarm, ALARM, "Set alarm")
5855 int sec = 0, cmd = -1;
5857 CurrentKeyData = NULL; /* not allowed in w3m-control: */
5858 data = searchKeyData();
5859 if (data == NULL || *data == '\0') {
5860 data = inputStrHist("(Alarm)sec command: ", "", TextHist);
5862 displayBuffer(Currentbuf, B_NORMAL);
5866 if (*data != '\0') {
5867 sec = atoi(getWord(&data));
5869 cmd = getFuncList(getWord(&data));
5872 data = getQWord(&data);
5873 setAlarmEvent(&DefaultAlarm, sec, AL_EXPLICIT, cmd, data);
5874 disp_message_nsec(Sprintf("%dsec %s %s", sec, w3mFuncList[cmd].id,
5875 data)->ptr, FALSE, 1, FALSE, TRUE);
5878 setAlarmEvent(&DefaultAlarm, 0, AL_UNSET, FUNCNAME_nulcmd, NULL);
5880 displayBuffer(Currentbuf, B_NORMAL);
5884 setAlarmEvent(AlarmEvent * event, int sec, short status, int cmd, void *data)
5887 event = New(AlarmEvent);
5889 event->status = status;
5896 DEFUN(reinit, REINIT, "Reload configuration files")
5898 char *resource = searchKeyData();
5900 if (resource == NULL) {
5906 displayBuffer(Currentbuf, B_REDRAW_IMAGE);
5910 if (!strcasecmp(resource, "CONFIG") || !strcasecmp(resource, "RC")) {
5913 displayBuffer(Currentbuf, B_REDRAW_IMAGE);
5918 if (!strcasecmp(resource, "COOKIE")) {
5924 if (!strcasecmp(resource, "KEYMAP")) {
5929 if (!strcasecmp(resource, "MAILCAP")) {
5935 if (!strcasecmp(resource, "MOUSE")) {
5937 displayBuffer(Currentbuf, B_REDRAW_IMAGE);
5943 if (!strcasecmp(resource, "MENU")) {
5949 if (!strcasecmp(resource, "MIMETYPES")) {
5954 #ifdef USE_EXTERNAL_URI_LOADER
5955 if (!strcasecmp(resource, "URIMETHODS")) {
5961 disp_err_message(Sprintf("Don't know how to reinitialize '%s'", resource)->
5965 DEFUN(defKey, DEFINE_KEY,
5966 "Define a binding between a key stroke and a user command")
5970 CurrentKeyData = NULL; /* not allowed in w3m-control: */
5971 data = searchKeyData();
5972 if (data == NULL || *data == '\0') {
5973 data = inputStrHist("Key definition: ", "", TextHist);
5974 if (data == NULL || *data == '\0') {
5975 displayBuffer(Currentbuf, B_NORMAL);
5979 setKeymap(allocStr(data, -1), -1, TRUE);
5980 displayBuffer(Currentbuf, B_NORMAL);
5992 n->currentBuffer = NULL;
5993 n->firstBuffer = NULL;
6008 buf = newBuffer(Currentbuf->width);
6009 copyBuffer(buf, Currentbuf);
6010 buf->nextBuffer = NULL;
6011 for (i = 0; i < MAX_LB; i++)
6012 buf->linkBuffer[i] = NULL;
6014 tag->firstBuffer = tag->currentBuffer = buf;
6016 tag->nextTab = CurrentTab->nextTab;
6017 tag->prevTab = CurrentTab;
6018 if (CurrentTab->nextTab)
6019 CurrentTab->nextTab->prevTab = tag;
6022 CurrentTab->nextTab = tag;
6027 DEFUN(newT, NEW_TAB, "Open new tab")
6030 displayBuffer(Currentbuf, B_REDRAW_IMAGE);
6045 for (tab = FirstTab, i = 1; tab && i < n; tab = tab->nextTab, i++) ;
6054 int lcol = 0, rcol = 2, col;
6056 int lcol = 0, rcol = 0, col;
6058 int n1, n2, na, nx, ny, ix, iy;
6061 lcol = mouse_action.menu_str ? mouse_action.menu_width : 0;
6066 n1 = (COLS - rcol - lcol) / TabCols;
6074 n2 = COLS / TabCols;
6077 ny = (nTab - n1 - 1) / n2 + 2;
6079 na = n1 + n2 * (ny - 1);
6080 n1 -= (na - nTab) / ny;
6083 na = n1 + n2 * (ny - 1);
6085 for (iy = 0; iy < ny && tab; iy++) {
6088 col = COLS - rcol - lcol;
6091 nx = n2 - (na - nTab + (iy - 1)) / (ny - 1);
6094 for (ix = 0; ix < nx && tab; ix++, tab = tab->nextTab) {
6095 tab->x1 = col * ix / nx;
6096 tab->x2 = col * (ix + 1) / nx - 1;
6107 deleteTab(TabBuffer * tab)
6115 tab->nextTab->prevTab = tab->prevTab;
6117 LastTab = tab->prevTab;
6118 tab->prevTab->nextTab = tab->nextTab;
6119 if (tab == CurrentTab)
6120 CurrentTab = tab->prevTab;
6122 else { /* tab == FirstTab */
6123 tab->nextTab->prevTab = NULL;
6124 FirstTab = tab->nextTab;
6125 if (tab == CurrentTab)
6126 CurrentTab = tab->nextTab;
6129 buf = tab->firstBuffer;
6130 while (buf && buf != NO_BUFFER) {
6131 next = buf->nextBuffer;
6138 DEFUN(closeT, CLOSE_TAB, "Close current tab")
6145 tab = numTab(PREC_NUM);
6150 displayBuffer(Currentbuf, B_REDRAW_IMAGE);
6153 DEFUN(nextT, NEXT_TAB, "Move to next tab")
6159 for (i = 0; i < PREC_NUM; i++) {
6160 if (CurrentTab->nextTab)
6161 CurrentTab = CurrentTab->nextTab;
6163 CurrentTab = FirstTab;
6165 displayBuffer(Currentbuf, B_REDRAW_IMAGE);
6168 DEFUN(prevT, PREV_TAB, "Move to previous tab")
6174 for (i = 0; i < PREC_NUM; i++) {
6175 if (CurrentTab->prevTab)
6176 CurrentTab = CurrentTab->prevTab;
6178 CurrentTab = LastTab;
6180 displayBuffer(Currentbuf, B_REDRAW_IMAGE);
6184 followTab(TabBuffer * tab)
6190 a = retrieveCurrentImg(Currentbuf);
6191 if (!(a && a->image && a->image->map))
6193 a = retrieveCurrentAnchor(Currentbuf);
6197 if (tab == CurrentTab) {
6198 check_target = FALSE;
6200 check_target = TRUE;
6205 check_target = FALSE;
6207 check_target = TRUE;
6209 if (buf != Currentbuf)
6212 deleteTab(CurrentTab);
6214 else if (buf != Currentbuf) {
6215 /* buf <- p <- ... <- Currentbuf = c */
6219 p = prevBuffer(c, buf);
6220 p->nextBuffer = NULL;
6222 deleteTab(CurrentTab);
6224 for (buf = p; buf; buf = p) {
6225 p = prevBuffer(c, buf);
6229 displayBuffer(Currentbuf, B_FORCE_REDRAW);
6232 DEFUN(tabA, TAB_LINK, "Open current link on new tab")
6234 followTab(prec_num ? numTab(PREC_NUM) : NULL);
6238 tabURL0(TabBuffer * tab, char *prompt, int relative)
6242 if (tab == CurrentTab) {
6243 goURL0(prompt, relative);
6248 goURL0(prompt, relative);
6250 if (buf != Currentbuf)
6253 deleteTab(CurrentTab);
6255 else if (buf != Currentbuf) {
6256 /* buf <- p <- ... <- Currentbuf = c */
6260 p = prevBuffer(c, buf);
6261 p->nextBuffer = NULL;
6263 deleteTab(CurrentTab);
6265 for (buf = p; buf; buf = p) {
6266 p = prevBuffer(c, buf);
6270 displayBuffer(Currentbuf, B_FORCE_REDRAW);
6273 DEFUN(tabURL, TAB_GOTO, "Open URL on new tab")
6275 tabURL0(prec_num ? numTab(PREC_NUM) : NULL,
6276 "Goto URL on new tab: ", FALSE);
6279 DEFUN(tabrURL, TAB_GOTO_RELATIVE, "Open relative URL on new tab")
6281 tabURL0(prec_num ? numTab(PREC_NUM) : NULL,
6282 "Goto relative URL on new tab: ", TRUE);
6286 moveTab(TabBuffer * t, TabBuffer * t2, int right)
6288 if (t2 == NO_TABBUFFER)
6290 if (!t || !t2 || t == t2 || t == NO_TABBUFFER)
6294 t->nextTab->prevTab = t->prevTab;
6296 LastTab = t->prevTab;
6297 t->prevTab->nextTab = t->nextTab;
6300 t->nextTab->prevTab = NULL;
6301 FirstTab = t->nextTab;
6304 t->nextTab = t2->nextTab;
6307 t2->nextTab->prevTab = t;
6313 t->prevTab = t2->prevTab;
6316 t2->prevTab->nextTab = t;
6321 displayBuffer(Currentbuf, B_FORCE_REDRAW);
6324 DEFUN(tabR, TAB_RIGHT, "Move current tab right")
6329 for (tab = CurrentTab, i = 0; tab && i < PREC_NUM;
6330 tab = tab->nextTab, i++) ;
6331 moveTab(CurrentTab, tab ? tab : LastTab, TRUE);
6334 DEFUN(tabL, TAB_LEFT, "Move current tab left")
6339 for (tab = CurrentTab, i = 0; tab && i < PREC_NUM;
6340 tab = tab->prevTab, i++) ;
6341 moveTab(CurrentTab, tab ? tab : FirstTab, FALSE);
6345 addDownloadList(pid_t pid, char *url, char *save, char *lock, clen_t size)
6349 d = New(DownloadList);
6352 if (save[0] != '/' && save[0] != '~')
6353 save = Strnew_m_charp(CurrentDir, "/", save, NULL)->ptr;
6354 d->save = expandPath(save);
6366 add_download_list = TRUE;
6370 checkDownloadList(void)
6377 for (d = FirstDL; d != NULL; d = d->next) {
6378 if (!d->ok && !lstat(d->lock, &st))
6385 convert_size3(clen_t size)
6393 tmp = Sprintf(size ? ",%.3d%s" : "%d%s", n, tmp->ptr);
6399 DownloadListBuffer(void)
6405 int duration, rate, eta;
6411 /* FIXME: gettextize? */
6412 src = Strnew_charp("<html><head><title>" DOWNLOAD_LIST_TITLE
6413 "</title></head>\n<body><h1 align=center>"
6414 DOWNLOAD_LIST_TITLE "</h1>\n"
6415 "<form method=internal action=download><hr>\n");
6416 for (d = LastDL; d != NULL; d = d->prev) {
6417 if (lstat(d->lock, &st))
6419 Strcat_charp(src, "<pre>\n");
6420 Strcat(src, Sprintf("%s\n --> %s\n ", html_quote(d->url),
6421 html_quote(conv_from_system(d->save))));
6422 duration = cur_time - d->time;
6423 if (!stat(d->save, &st)) {
6427 duration = st.st_mtime - d->time;
6433 int i, l = COLS - 6;
6435 i = 1.0 * l * size / d->size;
6440 Strcat_char(src, '#');
6442 Strcat_char(src, '_');
6443 Strcat_char(src, '\n');
6445 if (!d->ok && size < d->size)
6446 Strcat(src, Sprintf(" %s / %s bytes (%d%%)",
6447 convert_size3(size), convert_size3(d->size),
6448 (int)(100.0 * size / d->size)));
6450 Strcat(src, Sprintf(" %s bytes loaded", convert_size3(size)));
6452 rate = size / duration;
6453 Strcat(src, Sprintf(" %02d:%02d:%02d rate %s/sec",
6454 duration / (60 * 60), (duration / 60) % 60,
6455 duration % 60, convert_size(rate, 1)));
6456 if (!d->ok && size < d->size && rate) {
6457 eta = (d->size - size) / rate;
6458 Strcat(src, Sprintf(" eta %02d:%02d:%02d", eta / (60 * 60),
6459 (eta / 60) % 60, eta % 60));
6462 Strcat_char(src, '\n');
6464 Strcat(src, Sprintf("<input type=submit name=ok%d value=OK>",
6467 Strcat_charp(src, " Download incompleted");
6469 Strcat_charp(src, " Download completed");
6472 Strcat(src, Sprintf("<input type=submit name=stop%d value=STOP>",
6474 Strcat_charp(src, "\n</pre><hr>\n");
6476 Strcat_charp(src, "</form></body></html>");
6477 return loadHTMLString(src);
6481 download_action(struct parsed_tagarg *arg)
6486 for (; arg; arg = arg->next) {
6487 if (!strncmp(arg->arg, "stop", 4)) {
6488 pid = (pid_t) atoi(&arg->arg[4]);
6489 #ifndef __MINGW32_VERSION
6493 else if (!strncmp(arg->arg, "ok", 2))
6494 pid = (pid_t) atoi(&arg->arg[2]);
6497 for (d = FirstDL; d; d = d->next) {
6498 if (d->pid == pid) {
6501 d->prev->next = d->next;
6505 d->next->prev = d->prev;
6522 for (d = FirstDL; d != NULL; d = d->next) {
6525 #ifndef __MINGW32_VERSION
6526 kill(d->pid, SIGKILL);
6532 /* download panel */
6533 DEFUN(ldDL, DOWNLOAD_LIST, "Display download list panel")
6536 int replace = FALSE, new_tab = FALSE;
6541 if (Currentbuf->bufferprop & BP_INTERNAL &&
6542 !strcmp(Currentbuf->buffername, DOWNLOAD_LIST_TITLE))
6546 if (Currentbuf == Firstbuf && Currentbuf->nextBuffer == NULL) {
6548 deleteTab(CurrentTab);
6551 delBuffer(Currentbuf);
6552 displayBuffer(Currentbuf, B_FORCE_REDRAW);
6557 reload = checkDownloadList();
6559 buf = DownloadListBuffer();
6561 displayBuffer(Currentbuf, B_NORMAL);
6564 buf->bufferprop |= (BP_INTERNAL | BP_NO_URL);
6566 COPY_BUFROOT(buf, Currentbuf);
6567 restorePosition(buf, Currentbuf);
6569 if (!replace && open_tab_dl_list) {
6574 if (replace || new_tab)
6578 Currentbuf->event = setAlarmEvent(Currentbuf->event, 1, AL_IMPLICIT,
6579 FUNCNAME_reload, NULL);
6581 displayBuffer(Currentbuf, B_FORCE_REDRAW);
6585 save_buffer_position(Buffer *buf)
6587 BufferPos *b = buf->undo;
6589 if (!buf->firstLine)
6591 if (b && b->top_linenumber == TOP_LINENUMBER(buf) &&
6592 b->cur_linenumber == CUR_LINENUMBER(buf) &&
6593 b->currentColumn == buf->currentColumn && b->pos == buf->pos)
6596 b->top_linenumber = TOP_LINENUMBER(buf);
6597 b->cur_linenumber = CUR_LINENUMBER(buf);
6598 b->currentColumn = buf->currentColumn;
6600 b->bpos = buf->currentLine ? buf->currentLine->bpos : 0;
6602 b->prev = buf->undo;
6604 buf->undo->next = b;
6609 resetPos(BufferPos * b)
6614 top.linenumber = b->top_linenumber;
6615 cur.linenumber = b->cur_linenumber;
6618 buf.currentLine = &cur;
6620 buf.currentColumn = b->currentColumn;
6621 restorePosition(Currentbuf, &buf);
6622 Currentbuf->undo = b;
6623 displayBuffer(Currentbuf, B_FORCE_REDRAW);
6626 DEFUN(undoPos, UNDO, "Cancel the last cursor movement")
6628 BufferPos *b = Currentbuf->undo;
6631 if (!Currentbuf->firstLine)
6635 for (i = 0; i < PREC_NUM && b->prev; i++, b = b->prev) ;
6639 DEFUN(redoPos, REDO, "Cancel the last undo")
6641 BufferPos *b = Currentbuf->undo;
6644 if (!Currentbuf->firstLine)
6648 for (i = 0; i < PREC_NUM && b->next; i++, b = b->next) ;