main.c (155402B)
1 /* $Id$ */ 2 #define MAINPROGRAM 3 #include "fm.h" 4 #include <signal.h> 5 #include <setjmp.h> 6 #include <sys/stat.h> 7 #include <sys/types.h> 8 #include <unistd.h> 9 #include <fcntl.h> 10 #if defined(HAVE_WAITPID) || defined(HAVE_WAIT3) 11 #include <sys/wait.h> 12 #endif 13 #include <time.h> 14 #include "terms.h" 15 #include "myctype.h" 16 #include "regex.h" 17 #ifdef USE_M17N 18 #include "wc.h" 19 #include "wtf.h" 20 #ifdef USE_UNICODE 21 #include "ucs.h" 22 #endif 23 #endif 24 #ifdef USE_MOUSE 25 #ifdef USE_GPM 26 #include <gpm.h> 27 #endif /* USE_GPM */ 28 #if defined(USE_GPM) || defined(USE_SYSMOUSE) 29 extern int do_getch(); 30 #define getch() do_getch() 31 #endif /* defined(USE_GPM) || defined(USE_SYSMOUSE) */ 32 #endif 33 34 #ifdef __MINGW32_VERSION 35 #include <winsock.h> 36 37 WSADATA WSAData; 38 #endif 39 40 #define DSTR_LEN 256 41 42 Hist *LoadHist; 43 Hist *SaveHist; 44 Hist *URLHist; 45 Hist *ShellHist; 46 Hist *TextHist; 47 48 typedef struct _Event { 49 int cmd; 50 void *data; 51 struct _Event *next; 52 } Event; 53 static Event *CurrentEvent = NULL; 54 static Event *LastEvent = NULL; 55 56 #ifdef USE_ALARM 57 static AlarmEvent DefaultAlarm = { 58 0, AL_UNSET, FUNCNAME_nulcmd, NULL 59 }; 60 static AlarmEvent *CurrentAlarm = &DefaultAlarm; 61 static MySignalHandler SigAlarm(SIGNAL_ARG); 62 #endif 63 64 #ifdef SIGWINCH 65 static int need_resize_screen = FALSE; 66 static MySignalHandler resize_hook(SIGNAL_ARG); 67 static void resize_screen(void); 68 #endif 69 70 #ifdef SIGPIPE 71 static MySignalHandler SigPipe(SIGNAL_ARG); 72 #endif 73 74 #ifdef USE_MARK 75 static char *MarkString = NULL; 76 #endif 77 static char *SearchString = NULL; 78 int (*searchRoutine) (Buffer *, char *); 79 80 #ifndef __MINGW32_VERSION 81 JMP_BUF IntReturn; 82 #else 83 _JBTYPE IntReturn[_JBLEN]; 84 #endif /* __MINGW32_VERSION */ 85 86 static void delBuffer(Buffer *buf); 87 static void cmd_loadfile(char *path); 88 static void cmd_loadURL(char *url, ParsedURL *current, char *referer, 89 FormList *request); 90 static void cmd_loadBuffer(Buffer *buf, int prop, int linkid); 91 static void keyPressEventProc(int c); 92 int show_params_p = 0; 93 void show_params(FILE * fp); 94 95 static char *getCurWord(Buffer *buf, int *spos, int *epos); 96 97 static int display_ok = FALSE; 98 static void do_dump(Buffer *); 99 int prec_num = 0; 100 int prev_key = -1; 101 int on_target = 1; 102 static int add_download_list = FALSE; 103 104 void set_buffer_environ(Buffer *); 105 static void save_buffer_position(Buffer *buf); 106 107 static void _followForm(int); 108 static void _goLine(char *); 109 static void _newT(void); 110 static void followTab(TabBuffer * tab); 111 static void moveTab(TabBuffer * t, TabBuffer * t2, int right); 112 static void _nextA(int); 113 static void _prevA(int); 114 static int check_target = TRUE; 115 #define PREC_NUM (prec_num ? prec_num : 1) 116 #define PREC_LIMIT 10000 117 static int searchKeyNum(void); 118 119 #define help() fusage(stdout, 0) 120 #define usage() fusage(stderr, 1) 121 122 static void 123 fversion(FILE * f) 124 { 125 fprintf(f, "w3m version %s, options %s\n", w3m_version, 126 #if LANG == JA 127 "lang=ja" 128 #else 129 "lang=en" 130 #endif 131 #ifdef USE_M17N 132 ",m17n" 133 #endif 134 #ifdef USE_IMAGE 135 ",image" 136 #endif 137 #ifdef USE_COLOR 138 ",color" 139 #ifdef USE_ANSI_COLOR 140 ",ansi-color" 141 #endif 142 #endif 143 #ifdef USE_MOUSE 144 ",mouse" 145 #ifdef USE_GPM 146 ",gpm" 147 #endif 148 #ifdef USE_SYSMOUSE 149 ",sysmouse" 150 #endif 151 #endif 152 #ifdef USE_MENU 153 ",menu" 154 #endif 155 #ifdef USE_COOKIE 156 ",cookie" 157 #endif 158 #ifdef USE_SSL 159 ",ssl" 160 #ifdef USE_SSL_VERIFY 161 ",ssl-verify" 162 #endif 163 #endif 164 #ifdef USE_EXTERNAL_URI_LOADER 165 ",external-uri-loader" 166 #endif 167 #ifdef USE_W3MMAILER 168 ",w3mmailer" 169 #endif 170 #ifdef USE_NNTP 171 ",nntp" 172 #endif 173 #ifdef USE_GOPHER 174 ",gopher" 175 #endif 176 #ifdef INET6 177 ",ipv6" 178 #endif 179 #ifdef USE_ALARM 180 ",alarm" 181 #endif 182 #ifdef USE_MARK 183 ",mark" 184 #endif 185 #ifdef USE_MIGEMO 186 ",migemo" 187 #endif 188 ); 189 } 190 191 static void 192 fusage(FILE * f, int err) 193 { 194 fversion(f); 195 /* FIXME: gettextize? */ 196 fprintf(f, "usage: w3m [options] [URL or filename]\noptions:\n"); 197 fprintf(f, " -t tab set tab width\n"); 198 fprintf(f, " -r ignore backspace effect\n"); 199 fprintf(f, " -l line # of preserved line (default 10000)\n"); 200 #ifdef USE_M17N 201 fprintf(f, " -I charset document charset\n"); 202 fprintf(f, " -O charset display/output charset\n"); 203 fprintf(f, " -e EUC-JP\n"); 204 fprintf(f, " -s Shift_JIS\n"); 205 fprintf(f, " -j JIS\n"); 206 #endif 207 fprintf(f, " -B load bookmark\n"); 208 fprintf(f, " -bookmark file specify bookmark file\n"); 209 fprintf(f, " -T type specify content-type\n"); 210 fprintf(f, " -m internet message mode\n"); 211 fprintf(f, " -v visual startup mode\n"); 212 #ifdef USE_COLOR 213 fprintf(f, " -M monochrome display\n"); 214 #endif /* USE_COLOR */ 215 fprintf(f, 216 " -N open URL of command line on each new tab\n"); 217 fprintf(f, " -F automatically render frame\n"); 218 fprintf(f, 219 " -cols width specify column width (used with -dump)\n"); 220 fprintf(f, 221 " -ppc count specify the number of pixels per character (4.0...32.0)\n"); 222 #ifdef USE_IMAGE 223 fprintf(f, 224 " -ppl count specify the number of pixels per line (4.0...64.0)\n"); 225 #endif 226 fprintf(f, " -dump dump formatted page into stdout\n"); 227 fprintf(f, 228 " -dump_head dump response of HEAD request into stdout\n"); 229 fprintf(f, " -dump_source dump page source into stdout\n"); 230 fprintf(f, " -dump_both dump HEAD and source into stdout\n"); 231 fprintf(f, 232 " -dump_extra dump HEAD, source, and extra information into stdout\n"); 233 fprintf(f, " -post file use POST method with file content\n"); 234 fprintf(f, " -header string insert string as a header\n"); 235 fprintf(f, " +<num> goto <num> line\n"); 236 fprintf(f, " -num show line number\n"); 237 fprintf(f, " -no-proxy don't use proxy\n"); 238 #ifdef INET6 239 fprintf(f, " -4 IPv4 only (-o dns_order=4)\n"); 240 fprintf(f, " -6 IPv6 only (-o dns_order=6)\n"); 241 #endif 242 #ifdef USE_MOUSE 243 fprintf(f, " -no-mouse don't use mouse\n"); 244 #endif /* USE_MOUSE */ 245 #ifdef USE_COOKIE 246 fprintf(f, 247 " -cookie use cookie (-no-cookie: don't use cookie)\n"); 248 #endif /* USE_COOKIE */ 249 fprintf(f, " -graph use DEC special graphics for border of table and menu\n"); 250 fprintf(f, " -no-graph use ACII character for border of table and menu\n"); 251 fprintf(f, " -S squeeze multiple blank lines\n"); 252 fprintf(f, " -W toggle wrap search mode\n"); 253 fprintf(f, " -X don't use termcap init/deinit\n"); 254 fprintf(f, 255 " -title[=TERM] set buffer name to terminal title string\n"); 256 fprintf(f, " -o opt=value assign value to config option\n"); 257 fprintf(f, " -show-option print all config options\n"); 258 fprintf(f, " -config file specify config file\n"); 259 fprintf(f, " -help print this usage message\n"); 260 fprintf(f, " -version print w3m version\n"); 261 fprintf(f, " -reqlog write request logfile\n"); 262 fprintf(f, " -debug DO NOT USE\n"); 263 if (show_params_p) 264 show_params(f); 265 exit(err); 266 } 267 268 #ifdef USE_M17N 269 #ifdef __EMX__ 270 static char *getCodePage(void); 271 #endif 272 #endif 273 274 static GC_warn_proc orig_GC_warn_proc = NULL; 275 #define GC_WARN_KEEP_MAX (20) 276 277 static void 278 wrap_GC_warn_proc(char *msg, GC_word arg) 279 { 280 if (fmInitialized) { 281 /* *INDENT-OFF* */ 282 static struct { 283 char *msg; 284 GC_word arg; 285 } msg_ring[GC_WARN_KEEP_MAX]; 286 /* *INDENT-ON* */ 287 static int i = 0; 288 static int n = 0; 289 static int lock = 0; 290 int j; 291 292 j = (i + n) % (sizeof(msg_ring) / sizeof(msg_ring[0])); 293 msg_ring[j].msg = msg; 294 msg_ring[j].arg = arg; 295 296 if (n < sizeof(msg_ring) / sizeof(msg_ring[0])) 297 ++n; 298 else 299 ++i; 300 301 if (!lock) { 302 lock = 1; 303 304 for (; n > 0; --n, ++i) { 305 i %= sizeof(msg_ring) / sizeof(msg_ring[0]); 306 307 printf(msg_ring[i].msg, (unsigned long)msg_ring[i].arg); 308 sleep_till_anykey(1, 1); 309 } 310 311 lock = 0; 312 } 313 } 314 else if (orig_GC_warn_proc) 315 orig_GC_warn_proc(msg, arg); 316 else 317 fprintf(stderr, msg, (unsigned long)arg); 318 } 319 320 #ifdef SIGCHLD 321 static void 322 sig_chld(int signo) 323 { 324 int p_stat; 325 pid_t pid; 326 327 #ifdef HAVE_WAITPID 328 while ((pid = waitpid(-1, &p_stat, WNOHANG)) > 0) 329 #elif HAVE_WAIT3 330 while ((pid = wait3(&p_stat, WNOHANG, NULL)) > 0) 331 #else 332 if ((pid = wait(&p_stat)) > 0) 333 #endif 334 { 335 DownloadList *d; 336 337 if (WIFEXITED(p_stat)) { 338 for (d = FirstDL; d != NULL; d = d->next) { 339 if (d->pid == pid) { 340 d->err = WEXITSTATUS(p_stat); 341 break; 342 } 343 } 344 } 345 } 346 mySignal(SIGCHLD, sig_chld); 347 return; 348 } 349 #endif 350 351 Str 352 make_optional_header_string(char *s) 353 { 354 char *p; 355 Str hs; 356 357 if (strchr(s, '\n') || strchr(s, '\r')) 358 return NULL; 359 for (p = s; *p && *p != ':'; p++) ; 360 if (*p != ':' || p == s) 361 return NULL; 362 hs = Strnew_size(strlen(s) + 3); 363 Strcopy_charp_n(hs, s, p - s); 364 if (!Strcasecmp_charp(hs, "content-type")) 365 override_content_type = TRUE; 366 Strcat_charp(hs, ": "); 367 if (*(++p)) { /* not null header */ 368 SKIP_BLANKS(p); /* skip white spaces */ 369 Strcat_charp(hs, p); 370 } 371 Strcat_charp(hs, "\r\n"); 372 return hs; 373 } 374 375 int 376 main(int argc, char **argv, char **envp) 377 { 378 Buffer *newbuf = NULL; 379 char *p, c; 380 int i; 381 InputStream redin; 382 char *line_str = NULL; 383 char **load_argv; 384 FormList *request; 385 int load_argc = 0; 386 int load_bookmark = FALSE; 387 int visual_start = FALSE; 388 int open_new_tab = FALSE; 389 char search_header = FALSE; 390 char *default_type = NULL; 391 char *post_file = NULL; 392 Str err_msg; 393 #ifdef USE_M17N 394 char *Locale = NULL; 395 wc_uint8 auto_detect; 396 #ifdef __EMX__ 397 wc_ces CodePage; 398 #endif 399 #endif 400 GC_INIT(); 401 #if defined(ENABLE_NLS) || (defined(USE_M17N) && defined(HAVE_LANGINFO_CODESET)) 402 setlocale(LC_ALL, ""); 403 #endif 404 #ifdef ENABLE_NLS 405 bindtextdomain(PACKAGE, LOCALEDIR); 406 textdomain(PACKAGE); 407 #endif 408 409 #ifndef HAVE_SYS_ERRLIST 410 prepare_sys_errlist(); 411 #endif /* not HAVE_SYS_ERRLIST */ 412 413 NO_proxy_domains = newTextList(); 414 fileToDelete = newTextList(); 415 416 load_argv = New_N(char *, argc - 1); 417 load_argc = 0; 418 419 CurrentDir = currentdir(); 420 CurrentPid = (int)getpid(); 421 BookmarkFile = NULL; 422 config_file = NULL; 423 424 /* argument search 1 */ 425 for (i = 1; i < argc; i++) { 426 if (*argv[i] == '-') { 427 if (!strcmp("-config", argv[i])) { 428 argv[i] = "-dummy"; 429 if (++i >= argc) 430 usage(); 431 config_file = argv[i]; 432 argv[i] = "-dummy"; 433 } 434 else if (!strcmp("-h", argv[i]) || !strcmp("-help", argv[i])) 435 help(); 436 else if (!strcmp("-V", argv[i]) || !strcmp("-version", argv[i])) { 437 fversion(stdout); 438 exit(0); 439 } 440 } 441 } 442 443 #ifdef USE_M17N 444 if (non_null(Locale = getenv("LC_ALL")) || 445 non_null(Locale = getenv("LC_CTYPE")) || 446 non_null(Locale = getenv("LANG"))) { 447 DisplayCharset = wc_guess_locale_charset(Locale, DisplayCharset); 448 DocumentCharset = wc_guess_locale_charset(Locale, DocumentCharset); 449 SystemCharset = wc_guess_locale_charset(Locale, SystemCharset); 450 } 451 #ifdef __EMX__ 452 CodePage = wc_guess_charset(getCodePage(), 0); 453 if (CodePage) 454 DisplayCharset = DocumentCharset = SystemCharset = CodePage; 455 #endif 456 #endif 457 458 /* initializations */ 459 init_rc(); 460 461 LoadHist = newHist(); 462 SaveHist = newHist(); 463 ShellHist = newHist(); 464 TextHist = newHist(); 465 URLHist = newHist(); 466 467 #ifdef USE_M17N 468 if (FollowLocale && Locale) { 469 DisplayCharset = wc_guess_locale_charset(Locale, DisplayCharset); 470 SystemCharset = wc_guess_locale_charset(Locale, SystemCharset); 471 } 472 auto_detect = WcOption.auto_detect; 473 BookmarkCharset = DocumentCharset; 474 #endif 475 476 if (!non_null(HTTP_proxy) && 477 ((p = getenv("HTTP_PROXY")) || 478 (p = getenv("http_proxy")) || (p = getenv("HTTP_proxy")))) 479 HTTP_proxy = p; 480 #ifdef USE_SSL 481 if (!non_null(HTTPS_proxy) && 482 ((p = getenv("HTTPS_PROXY")) || 483 (p = getenv("https_proxy")) || (p = getenv("HTTPS_proxy")))) 484 HTTPS_proxy = p; 485 if (HTTPS_proxy == NULL && non_null(HTTP_proxy)) 486 HTTPS_proxy = HTTP_proxy; 487 #endif /* USE_SSL */ 488 #ifdef USE_GOPHER 489 if (!non_null(GOPHER_proxy) && 490 ((p = getenv("GOPHER_PROXY")) || 491 (p = getenv("gopher_proxy")) || (p = getenv("GOPHER_proxy")))) 492 GOPHER_proxy = p; 493 #endif /* USE_GOPHER */ 494 if (!non_null(FTP_proxy) && 495 ((p = getenv("FTP_PROXY")) || 496 (p = getenv("ftp_proxy")) || (p = getenv("FTP_proxy")))) 497 FTP_proxy = p; 498 if (!non_null(NO_proxy) && 499 ((p = getenv("NO_PROXY")) || 500 (p = getenv("no_proxy")) || (p = getenv("NO_proxy")))) 501 NO_proxy = p; 502 #ifdef USE_NNTP 503 if (!non_null(NNTP_server) && (p = getenv("NNTPSERVER")) != NULL) 504 NNTP_server = p; 505 if (!non_null(NNTP_mode) && (p = getenv("NNTPMODE")) != NULL) 506 NNTP_mode = p; 507 #endif 508 509 if (!non_null(Editor) && (p = getenv("EDITOR")) != NULL) 510 Editor = p; 511 if (!non_null(Mailer) && (p = getenv("MAILER")) != NULL) 512 Mailer = p; 513 514 /* argument search 2 */ 515 i = 1; 516 while (i < argc) { 517 if (*argv[i] == '-') { 518 if (!strcmp("-t", argv[i])) { 519 if (++i >= argc) 520 usage(); 521 if (atoi(argv[i]) > 0) 522 Tabstop = atoi(argv[i]); 523 } 524 else if (!strcmp("-r", argv[i])) 525 ShowEffect = FALSE; 526 else if (!strcmp("-l", argv[i])) { 527 if (++i >= argc) 528 usage(); 529 if (atoi(argv[i]) > 0) 530 PagerMax = atoi(argv[i]); 531 } 532 #ifdef USE_M17N 533 else if (!strcmp("-s", argv[i])) 534 DisplayCharset = WC_CES_SHIFT_JIS; 535 else if (!strcmp("-j", argv[i])) 536 DisplayCharset = WC_CES_ISO_2022_JP; 537 else if (!strcmp("-e", argv[i])) 538 DisplayCharset = WC_CES_EUC_JP; 539 else if (!strncmp("-I", argv[i], 2)) { 540 if (argv[i][2] != '\0') 541 p = argv[i] + 2; 542 else { 543 if (++i >= argc) 544 usage(); 545 p = argv[i]; 546 } 547 DocumentCharset = wc_guess_charset_short(p, DocumentCharset); 548 WcOption.auto_detect = WC_OPT_DETECT_OFF; 549 UseContentCharset = FALSE; 550 } 551 else if (!strncmp("-O", argv[i], 2)) { 552 if (argv[i][2] != '\0') 553 p = argv[i] + 2; 554 else { 555 if (++i >= argc) 556 usage(); 557 p = argv[i]; 558 } 559 DisplayCharset = wc_guess_charset_short(p, DisplayCharset); 560 } 561 #endif 562 else if (!strcmp("-graph", argv[i])) 563 UseGraphicChar = GRAPHIC_CHAR_DEC; 564 else if (!strcmp("-no-graph", argv[i])) 565 UseGraphicChar = GRAPHIC_CHAR_ASCII; 566 else if (!strcmp("-T", argv[i])) { 567 if (++i >= argc) 568 usage(); 569 DefaultType = default_type = argv[i]; 570 } 571 else if (!strcmp("-m", argv[i])) 572 SearchHeader = search_header = TRUE; 573 else if (!strcmp("-v", argv[i])) 574 visual_start = TRUE; 575 else if (!strcmp("-N", argv[i])) 576 open_new_tab = TRUE; 577 #ifdef USE_COLOR 578 else if (!strcmp("-M", argv[i])) 579 useColor = FALSE; 580 #endif /* USE_COLOR */ 581 else if (!strcmp("-B", argv[i])) 582 load_bookmark = TRUE; 583 else if (!strcmp("-bookmark", argv[i])) { 584 if (++i >= argc) 585 usage(); 586 BookmarkFile = argv[i]; 587 if (BookmarkFile[0] != '~' && BookmarkFile[0] != '/') { 588 Str tmp = Strnew_charp(CurrentDir); 589 if (Strlastchar(tmp) != '/') 590 Strcat_char(tmp, '/'); 591 Strcat_charp(tmp, BookmarkFile); 592 BookmarkFile = cleanupName(tmp->ptr); 593 } 594 } 595 else if (!strcmp("-F", argv[i])) 596 RenderFrame = TRUE; 597 else if (!strcmp("-W", argv[i])) { 598 if (WrapDefault) 599 WrapDefault = FALSE; 600 else 601 WrapDefault = TRUE; 602 } 603 else if (!strcmp("-dump", argv[i])) 604 w3m_dump = DUMP_BUFFER; 605 else if (!strcmp("-dump_source", argv[i])) 606 w3m_dump = DUMP_SOURCE; 607 else if (!strcmp("-dump_head", argv[i])) 608 w3m_dump = DUMP_HEAD; 609 else if (!strcmp("-dump_both", argv[i])) 610 w3m_dump = (DUMP_HEAD | DUMP_SOURCE); 611 else if (!strcmp("-dump_extra", argv[i])) 612 w3m_dump = (DUMP_HEAD | DUMP_SOURCE | DUMP_EXTRA); 613 else if (!strcmp("-halfdump", argv[i])) 614 w3m_dump = DUMP_HALFDUMP; 615 else if (!strcmp("-halfload", argv[i])) { 616 w3m_dump = 0; 617 w3m_halfload = TRUE; 618 DefaultType = default_type = "text/html"; 619 } 620 else if (!strcmp("-backend", argv[i])) { 621 w3m_backend = TRUE; 622 } 623 else if (!strcmp("-backend_batch", argv[i])) { 624 w3m_backend = TRUE; 625 if (++i >= argc) 626 usage(); 627 if (!backend_batch_commands) 628 backend_batch_commands = newTextList(); 629 pushText(backend_batch_commands, argv[i]); 630 } 631 else if (!strcmp("-cols", argv[i])) { 632 if (++i >= argc) 633 usage(); 634 COLS = atoi(argv[i]); 635 if (COLS > MAXIMUM_COLS) { 636 COLS = MAXIMUM_COLS; 637 } 638 } 639 else if (!strcmp("-ppc", argv[i])) { 640 double ppc; 641 if (++i >= argc) 642 usage(); 643 ppc = atof(argv[i]); 644 if (ppc >= MINIMUM_PIXEL_PER_CHAR && 645 ppc <= MAXIMUM_PIXEL_PER_CHAR) { 646 pixel_per_char = ppc; 647 set_pixel_per_char = TRUE; 648 } 649 } 650 #ifdef USE_IMAGE 651 else if (!strcmp("-ppl", argv[i])) { 652 double ppc; 653 if (++i >= argc) 654 usage(); 655 ppc = atof(argv[i]); 656 if (ppc >= MINIMUM_PIXEL_PER_CHAR && 657 ppc <= MAXIMUM_PIXEL_PER_CHAR * 2) { 658 pixel_per_line = ppc; 659 set_pixel_per_line = TRUE; 660 } 661 } 662 #endif 663 else if (!strcmp("-num", argv[i])) 664 showLineNum = TRUE; 665 else if (!strcmp("-no-proxy", argv[i])) 666 use_proxy = FALSE; 667 #ifdef INET6 668 else if (!strcmp("-4", argv[i]) || !strcmp("-6", argv[i])) 669 set_param_option(Sprintf("dns_order=%c", argv[i][1])->ptr); 670 #endif 671 else if (!strcmp("-post", argv[i])) { 672 if (++i >= argc) 673 usage(); 674 post_file = argv[i]; 675 } 676 else if (!strcmp("-header", argv[i])) { 677 Str hs; 678 if (++i >= argc) 679 usage(); 680 if ((hs = make_optional_header_string(argv[i])) != NULL) { 681 if (header_string == NULL) 682 header_string = hs; 683 else 684 Strcat(header_string, hs); 685 } 686 while (argv[i][0]) { 687 argv[i][0] = '\0'; 688 argv[i]++; 689 } 690 } 691 #ifdef USE_MOUSE 692 else if (!strcmp("-no-mouse", argv[i])) { 693 use_mouse = FALSE; 694 } 695 #endif /* USE_MOUSE */ 696 #ifdef USE_COOKIE 697 else if (!strcmp("-no-cookie", argv[i])) { 698 use_cookie = FALSE; 699 accept_cookie = FALSE; 700 } 701 else if (!strcmp("-cookie", argv[i])) { 702 use_cookie = TRUE; 703 accept_cookie = TRUE; 704 } 705 #endif /* USE_COOKIE */ 706 else if (!strcmp("-S", argv[i])) 707 squeezeBlankLine = TRUE; 708 else if (!strcmp("-X", argv[i])) 709 Do_not_use_ti_te = TRUE; 710 else if (!strcmp("-title", argv[i])) 711 displayTitleTerm = getenv("TERM"); 712 else if (!strncmp("-title=", argv[i], 7)) 713 displayTitleTerm = argv[i] + 7; 714 else if (!strcmp("-o", argv[i]) || 715 !strcmp("-show-option", argv[i])) { 716 if (!strcmp("-show-option", argv[i]) || ++i >= argc || 717 !strcmp(argv[i], "?")) { 718 show_params(stdout); 719 exit(0); 720 } 721 if (!set_param_option(argv[i])) { 722 /* option set failed */ 723 /* FIXME: gettextize? */ 724 fprintf(stderr, "%s: bad option\n", argv[i]); 725 show_params_p = 1; 726 usage(); 727 } 728 } 729 else if (!strcmp("-dummy", argv[i])) { 730 /* do nothing */ 731 } 732 else if (!strcmp("-debug", argv[i])) { 733 w3m_debug = TRUE; 734 } 735 else if (!strcmp("-reqlog",argv[i])) { 736 w3m_reqlog=rcFile("request.log"); 737 } 738 else { 739 usage(); 740 } 741 } 742 else if (*argv[i] == '+') { 743 line_str = argv[i] + 1; 744 } 745 else { 746 load_argv[load_argc++] = argv[i]; 747 } 748 i++; 749 } 750 751 #ifdef __WATT32__ 752 if (w3m_debug) 753 dbug_init(); 754 sock_init(); 755 #endif 756 757 #ifdef __MINGW32_VERSION 758 { 759 int err; 760 WORD wVerReq; 761 762 wVerReq = MAKEWORD(1, 1); 763 764 err = WSAStartup(wVerReq, &WSAData); 765 if (err != 0) 766 { 767 fprintf(stderr, "Can't find winsock\n"); 768 return 1; 769 } 770 _fmode = _O_BINARY; 771 } 772 #endif 773 774 FirstTab = NULL; 775 LastTab = NULL; 776 nTab = 0; 777 CurrentTab = NULL; 778 CurrentKey = -1; 779 if (BookmarkFile == NULL) 780 BookmarkFile = rcFile(BOOKMARK); 781 782 if (!isatty(1) && !w3m_dump) { 783 /* redirected output */ 784 w3m_dump = DUMP_BUFFER; 785 } 786 if (w3m_dump) { 787 if (COLS == 0) 788 COLS = DEFAULT_COLS; 789 } 790 791 #ifdef USE_BINMODE_STREAM 792 setmode(fileno(stdout), O_BINARY); 793 #endif 794 if (!w3m_dump && !w3m_backend) { 795 fmInit(); 796 #ifdef SIGWINCH 797 mySignal(SIGWINCH, resize_hook); 798 #else /* not SIGWINCH */ 799 setlinescols(); 800 setupscreen(); 801 #endif /* not SIGWINCH */ 802 } 803 #ifdef USE_IMAGE 804 else if (w3m_halfdump && displayImage) 805 activeImage = TRUE; 806 #endif 807 808 sync_with_option(); 809 #ifdef USE_COOKIE 810 initCookie(); 811 #endif /* USE_COOKIE */ 812 #ifdef USE_HISTORY 813 if (UseHistory) 814 loadHistory(URLHist); 815 #endif /* not USE_HISTORY */ 816 817 #ifdef USE_M17N 818 wtf_init(DocumentCharset, DisplayCharset); 819 /* if (w3m_dump) 820 * WcOption.pre_conv = WC_TRUE; 821 */ 822 #endif 823 824 if (w3m_backend) 825 backend(); 826 827 if (w3m_dump) 828 mySignal(SIGINT, SIG_IGN); 829 #ifdef SIGCHLD 830 mySignal(SIGCHLD, sig_chld); 831 #endif 832 #ifdef SIGPIPE 833 mySignal(SIGPIPE, SigPipe); 834 #endif 835 836 orig_GC_warn_proc = GC_set_warn_proc(wrap_GC_warn_proc); 837 err_msg = Strnew(); 838 if (load_argc == 0) { 839 /* no URL specified */ 840 if (!isatty(0)) { 841 redin = newFileStream(fdopen(dup(0), "rb"), (void (*)())pclose); 842 newbuf = openGeneralPagerBuffer(redin); 843 dup2(1, 0); 844 } 845 else if (load_bookmark) { 846 newbuf = loadGeneralFile(BookmarkFile, NULL, NO_REFERER, 0, NULL); 847 if (newbuf == NULL) 848 Strcat_charp(err_msg, "w3m: Can't load bookmark.\n"); 849 } 850 else if (visual_start) { 851 /* FIXME: gettextize? */ 852 Str s_page; 853 s_page = 854 Strnew_charp 855 ("<title>W3M startup page</title><center><b>Welcome to "); 856 Strcat_charp(s_page, "<a href='http://w3m.sourceforge.net/'>"); 857 Strcat_m_charp(s_page, 858 "w3m</a>!<p><p>This is w3m version ", 859 w3m_version, 860 "<br>Written by <a href='mailto:aito@fw.ipsj.or.jp'>Akinori Ito</a>", 861 NULL); 862 newbuf = loadHTMLString(s_page); 863 if (newbuf == NULL) 864 Strcat_charp(err_msg, "w3m: Can't load string.\n"); 865 else if (newbuf != NO_BUFFER) 866 newbuf->bufferprop |= (BP_INTERNAL | BP_NO_URL); 867 } 868 else if ((p = getenv("HTTP_HOME")) != NULL || 869 (p = getenv("WWW_HOME")) != NULL) { 870 newbuf = loadGeneralFile(p, NULL, NO_REFERER, 0, NULL); 871 if (newbuf == NULL) 872 Strcat(err_msg, Sprintf("w3m: Can't load %s.\n", p)); 873 else if (newbuf != NO_BUFFER) 874 pushHashHist(URLHist, parsedURL2Str(&newbuf->currentURL)->ptr); 875 } 876 else { 877 if (fmInitialized) 878 fmTerm(); 879 usage(); 880 } 881 if (newbuf == NULL) { 882 if (fmInitialized) 883 fmTerm(); 884 if (err_msg->length) 885 fprintf(stderr, "%s", err_msg->ptr); 886 w3m_exit(2); 887 } 888 i = -1; 889 } 890 else { 891 i = 0; 892 } 893 for (; i < load_argc; i++) { 894 if (i >= 0) { 895 SearchHeader = search_header; 896 DefaultType = default_type; 897 if (w3m_dump == DUMP_HEAD) { 898 request = New(FormList); 899 request->method = FORM_METHOD_HEAD; 900 newbuf = 901 loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0, 902 request); 903 } 904 else { 905 if (post_file && i == 0) { 906 FILE *fp; 907 Str body; 908 if (!strcmp(post_file, "-")) 909 fp = stdin; 910 else 911 fp = fopen(post_file, "r"); 912 if (fp == NULL) { 913 /* FIXME: gettextize? */ 914 Strcat(err_msg, 915 Sprintf("w3m: Can't open %s.\n", post_file)); 916 continue; 917 } 918 body = Strfgetall(fp); 919 if (fp != stdin) 920 fclose(fp); 921 request = 922 newFormList(NULL, "post", NULL, NULL, NULL, NULL, 923 NULL); 924 request->body = body->ptr; 925 request->boundary = NULL; 926 request->length = body->length; 927 } 928 else { 929 request = NULL; 930 } 931 newbuf = 932 loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0, 933 request); 934 } 935 if (newbuf == NULL) { 936 /* FIXME: gettextize? */ 937 Strcat(err_msg, 938 Sprintf("w3m: Can't load %s.\n", load_argv[i])); 939 continue; 940 } 941 else if (newbuf == NO_BUFFER) 942 continue; 943 switch (newbuf->real_scheme) { 944 case SCM_MAILTO: 945 break; 946 case SCM_LOCAL: 947 case SCM_LOCAL_CGI: 948 unshiftHist(LoadHist, conv_from_system(load_argv[i])); 949 default: 950 pushHashHist(URLHist, parsedURL2Str(&newbuf->currentURL)->ptr); 951 break; 952 } 953 } 954 else if (newbuf == NO_BUFFER) 955 continue; 956 if (newbuf->pagerSource || 957 (newbuf->real_scheme == SCM_LOCAL && newbuf->header_source && 958 newbuf->currentURL.file && strcmp(newbuf->currentURL.file, "-"))) 959 newbuf->search_header = search_header; 960 if (CurrentTab == NULL) { 961 FirstTab = LastTab = CurrentTab = newTab(); 962 nTab = 1; 963 Firstbuf = Currentbuf = newbuf; 964 } 965 else if (open_new_tab) { 966 _newT(); 967 Currentbuf->nextBuffer = newbuf; 968 delBuffer(Currentbuf); 969 } 970 else { 971 Currentbuf->nextBuffer = newbuf; 972 Currentbuf = newbuf; 973 } 974 if (!w3m_dump || w3m_dump == DUMP_BUFFER) { 975 if (Currentbuf->frameset != NULL && RenderFrame) 976 rFrame(); 977 } 978 if (w3m_dump) 979 do_dump(Currentbuf); 980 else { 981 Currentbuf = newbuf; 982 #ifdef USE_BUFINFO 983 saveBufferInfo(); 984 #endif 985 } 986 } 987 if (w3m_dump) { 988 if (err_msg->length) 989 fprintf(stderr, "%s", err_msg->ptr); 990 #ifdef USE_COOKIE 991 save_cookies(); 992 #endif /* USE_COOKIE */ 993 w3m_exit(0); 994 } 995 996 if (add_download_list) { 997 add_download_list = FALSE; 998 CurrentTab = LastTab; 999 if (!FirstTab) { 1000 FirstTab = LastTab = CurrentTab = newTab(); 1001 nTab = 1; 1002 } 1003 if (!Firstbuf || Firstbuf == NO_BUFFER) { 1004 Firstbuf = Currentbuf = newBuffer(INIT_BUFFER_WIDTH); 1005 Currentbuf->bufferprop = BP_INTERNAL | BP_NO_URL; 1006 Currentbuf->buffername = DOWNLOAD_LIST_TITLE; 1007 } 1008 else 1009 Currentbuf = Firstbuf; 1010 ldDL(); 1011 } 1012 else 1013 CurrentTab = FirstTab; 1014 if (!FirstTab || !Firstbuf || Firstbuf == NO_BUFFER) { 1015 if (newbuf == NO_BUFFER) { 1016 if (fmInitialized) 1017 /* FIXME: gettextize? */ 1018 inputChar("Hit any key to quit w3m:"); 1019 } 1020 if (fmInitialized) 1021 fmTerm(); 1022 if (err_msg->length) 1023 fprintf(stderr, "%s", err_msg->ptr); 1024 if (newbuf == NO_BUFFER) { 1025 #ifdef USE_COOKIE 1026 save_cookies(); 1027 #endif /* USE_COOKIE */ 1028 if (!err_msg->length) 1029 w3m_exit(0); 1030 } 1031 w3m_exit(2); 1032 } 1033 if (err_msg->length) 1034 disp_message_nsec(err_msg->ptr, FALSE, 1, TRUE, FALSE); 1035 1036 SearchHeader = FALSE; 1037 DefaultType = NULL; 1038 #ifdef USE_M17N 1039 UseContentCharset = TRUE; 1040 WcOption.auto_detect = auto_detect; 1041 #endif 1042 1043 Currentbuf = Firstbuf; 1044 displayBuffer(Currentbuf, B_FORCE_REDRAW); 1045 if (line_str) { 1046 _goLine(line_str); 1047 } 1048 for (;;) { 1049 if (add_download_list) { 1050 add_download_list = FALSE; 1051 ldDL(); 1052 } 1053 if (Currentbuf->submit) { 1054 Anchor *a = Currentbuf->submit; 1055 Currentbuf->submit = NULL; 1056 gotoLine(Currentbuf, a->start.line); 1057 Currentbuf->pos = a->start.pos; 1058 _followForm(TRUE); 1059 continue; 1060 } 1061 /* event processing */ 1062 if (CurrentEvent) { 1063 CurrentKey = -1; 1064 CurrentKeyData = NULL; 1065 CurrentCmdData = (char *)CurrentEvent->data; 1066 w3mFuncList[CurrentEvent->cmd].func(); 1067 CurrentCmdData = NULL; 1068 CurrentEvent = CurrentEvent->next; 1069 continue; 1070 } 1071 /* get keypress event */ 1072 #ifdef USE_ALARM 1073 if (Currentbuf->event) { 1074 if (Currentbuf->event->status != AL_UNSET) { 1075 CurrentAlarm = Currentbuf->event; 1076 if (CurrentAlarm->sec == 0) { /* refresh (0sec) */ 1077 Currentbuf->event = NULL; 1078 CurrentKey = -1; 1079 CurrentKeyData = NULL; 1080 CurrentCmdData = (char *)CurrentAlarm->data; 1081 w3mFuncList[CurrentAlarm->cmd].func(); 1082 CurrentCmdData = NULL; 1083 continue; 1084 } 1085 } 1086 else 1087 Currentbuf->event = NULL; 1088 } 1089 if (!Currentbuf->event) 1090 CurrentAlarm = &DefaultAlarm; 1091 #endif 1092 #ifdef USE_MOUSE 1093 mouse_action.in_action = FALSE; 1094 if (use_mouse) 1095 mouse_active(); 1096 #endif /* USE_MOUSE */ 1097 #ifdef USE_ALARM 1098 if (CurrentAlarm->sec > 0) { 1099 mySignal(SIGALRM, SigAlarm); 1100 alarm(CurrentAlarm->sec); 1101 } 1102 #endif 1103 #ifdef SIGWINCH 1104 mySignal(SIGWINCH, resize_hook); 1105 #endif 1106 #ifdef USE_IMAGE 1107 if (activeImage && displayImage && Currentbuf->img && 1108 !Currentbuf->image_loaded) { 1109 do { 1110 #ifdef SIGWINCH 1111 if (need_resize_screen) 1112 resize_screen(); 1113 #endif 1114 loadImage(Currentbuf, IMG_FLAG_NEXT); 1115 } while (sleep_till_anykey(1, 0) <= 0); 1116 } 1117 #ifdef SIGWINCH 1118 else 1119 #endif 1120 #endif 1121 #ifdef SIGWINCH 1122 { 1123 do { 1124 if (need_resize_screen) 1125 resize_screen(); 1126 } while (sleep_till_anykey(1, 0) <= 0); 1127 } 1128 #endif 1129 c = getch(); 1130 #ifdef USE_ALARM 1131 if (CurrentAlarm->sec > 0) { 1132 alarm(0); 1133 } 1134 #endif 1135 #ifdef USE_MOUSE 1136 if (use_mouse) 1137 mouse_inactive(); 1138 #endif /* USE_MOUSE */ 1139 if (IS_ASCII(c)) { /* Ascii */ 1140 if (('0' <= c) && (c <= '9') && 1141 (prec_num || (GlobalKeymap[c] == FUNCNAME_nulcmd))) { 1142 prec_num = prec_num * 10 + (int)(c - '0'); 1143 if (prec_num > PREC_LIMIT) 1144 prec_num = PREC_LIMIT; 1145 } 1146 else { 1147 set_buffer_environ(Currentbuf); 1148 save_buffer_position(Currentbuf); 1149 keyPressEventProc((int)c); 1150 prec_num = 0; 1151 } 1152 } 1153 prev_key = CurrentKey; 1154 CurrentKey = -1; 1155 CurrentKeyData = NULL; 1156 } 1157 } 1158 1159 static void 1160 keyPressEventProc(int c) 1161 { 1162 CurrentKey = c; 1163 w3mFuncList[(int)GlobalKeymap[c]].func(); 1164 } 1165 1166 void 1167 pushEvent(int cmd, void *data) 1168 { 1169 Event *event; 1170 1171 event = New(Event); 1172 event->cmd = cmd; 1173 event->data = data; 1174 event->next = NULL; 1175 if (CurrentEvent) 1176 LastEvent->next = event; 1177 else 1178 CurrentEvent = event; 1179 LastEvent = event; 1180 } 1181 1182 static void 1183 dump_source(Buffer *buf) 1184 { 1185 FILE *f; 1186 char c; 1187 if (buf->sourcefile == NULL) 1188 return; 1189 f = fopen(buf->sourcefile, "r"); 1190 if (f == NULL) 1191 return; 1192 while (c = fgetc(f), !feof(f)) { 1193 putchar(c); 1194 } 1195 fclose(f); 1196 } 1197 1198 static void 1199 dump_head(Buffer *buf) 1200 { 1201 TextListItem *ti; 1202 1203 if (buf->document_header == NULL) { 1204 if (w3m_dump & DUMP_EXTRA) 1205 printf("\n"); 1206 return; 1207 } 1208 for (ti = buf->document_header->first; ti; ti = ti->next) { 1209 #ifdef USE_M17N 1210 printf("%s", 1211 wc_conv_strict(ti->ptr, InnerCharset, 1212 buf->document_charset)->ptr); 1213 #else 1214 printf("%s", ti->ptr); 1215 #endif 1216 } 1217 puts(""); 1218 } 1219 1220 static void 1221 dump_extra(Buffer *buf) 1222 { 1223 printf("W3m-current-url: %s\n", parsedURL2Str(&buf->currentURL)->ptr); 1224 if (buf->baseURL) 1225 printf("W3m-base-url: %s\n", parsedURL2Str(buf->baseURL)->ptr); 1226 #ifdef USE_M17N 1227 printf("W3m-document-charset: %s\n", 1228 wc_ces_to_charset(buf->document_charset)); 1229 #endif 1230 #ifdef USE_SSL 1231 if (buf->ssl_certificate) { 1232 Str tmp = Strnew(); 1233 char *p; 1234 for (p = buf->ssl_certificate; *p; p++) { 1235 Strcat_char(tmp, *p); 1236 if (*p == '\n') { 1237 for (; *(p + 1) == '\n'; p++) ; 1238 if (*(p + 1)) 1239 Strcat_char(tmp, '\t'); 1240 } 1241 } 1242 if (Strlastchar(tmp) != '\n') 1243 Strcat_char(tmp, '\n'); 1244 printf("W3m-ssl-certificate: %s", tmp->ptr); 1245 } 1246 #endif 1247 } 1248 1249 static void 1250 do_dump(Buffer *buf) 1251 { 1252 MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL; 1253 1254 prevtrap = mySignal(SIGINT, intTrap); 1255 if (SETJMP(IntReturn) != 0) { 1256 mySignal(SIGINT, prevtrap); 1257 return; 1258 } 1259 if (w3m_dump & DUMP_EXTRA) 1260 dump_extra(buf); 1261 if (w3m_dump & DUMP_HEAD) 1262 dump_head(buf); 1263 if (w3m_dump & DUMP_SOURCE) 1264 dump_source(buf); 1265 if (w3m_dump == DUMP_BUFFER) { 1266 int i; 1267 saveBuffer(buf, stdout, FALSE); 1268 if (displayLinkNumber && buf->href) { 1269 printf("\nReferences:\n\n"); 1270 for (i = 0; i < buf->href->nanchor; i++) { 1271 ParsedURL pu; 1272 static Str s = NULL; 1273 if (buf->href->anchors[i].slave) 1274 continue; 1275 parseURL2(buf->href->anchors[i].url, &pu, baseURL(buf)); 1276 s = parsedURL2Str(&pu); 1277 if (DecodeURL) 1278 s = Strnew_charp(url_unquote_conv 1279 (s->ptr, Currentbuf->document_charset)); 1280 printf("[%d] %s\n", buf->href->anchors[i].hseq + 1, s->ptr); 1281 } 1282 } 1283 } 1284 mySignal(SIGINT, prevtrap); 1285 } 1286 1287 DEFUN(nulcmd, NOTHING NULL @@@, "Do nothing") 1288 { /* do nothing */ 1289 } 1290 1291 #ifdef __EMX__ 1292 DEFUN(pcmap, PCMAP, "pcmap") 1293 { 1294 w3mFuncList[(int)PcKeymap[(int)getch()]].func(); 1295 } 1296 #else /* not __EMX__ */ 1297 void 1298 pcmap(void) 1299 { 1300 } 1301 #endif 1302 1303 static void 1304 escKeyProc(int c, int esc, unsigned char *map) 1305 { 1306 if (CurrentKey >= 0 && CurrentKey & K_MULTI) { 1307 unsigned char **mmap; 1308 mmap = (unsigned char **)getKeyData(MULTI_KEY(CurrentKey)); 1309 if (!mmap) 1310 return; 1311 switch (esc) { 1312 case K_ESCD: 1313 map = mmap[3]; 1314 break; 1315 case K_ESCB: 1316 map = mmap[2]; 1317 break; 1318 case K_ESC: 1319 map = mmap[1]; 1320 break; 1321 default: 1322 map = mmap[0]; 1323 break; 1324 } 1325 esc |= (CurrentKey & ~0xFFFF); 1326 } 1327 CurrentKey = esc | c; 1328 w3mFuncList[(int)map[c]].func(); 1329 } 1330 1331 DEFUN(escmap, ESCMAP, "ESC map") 1332 { 1333 char c; 1334 c = getch(); 1335 if (IS_ASCII(c)) 1336 escKeyProc((int)c, K_ESC, EscKeymap); 1337 } 1338 1339 DEFUN(escbmap, ESCBMAP, "ESC [ map") 1340 { 1341 char c; 1342 c = getch(); 1343 if (IS_DIGIT(c)) { 1344 escdmap(c); 1345 return; 1346 } 1347 if (IS_ASCII(c)) 1348 escKeyProc((int)c, K_ESCB, EscBKeymap); 1349 } 1350 1351 void 1352 escdmap(char c) 1353 { 1354 int d; 1355 d = (int)c - (int)'0'; 1356 c = getch(); 1357 if (IS_DIGIT(c)) { 1358 d = d * 10 + (int)c - (int)'0'; 1359 c = getch(); 1360 } 1361 if (c == '~') 1362 escKeyProc((int)d, K_ESCD, EscDKeymap); 1363 } 1364 1365 DEFUN(multimap, MULTIMAP, "multimap") 1366 { 1367 char c; 1368 c = getch(); 1369 if (IS_ASCII(c)) { 1370 CurrentKey = K_MULTI | (CurrentKey << 16) | c; 1371 escKeyProc((int)c, 0, NULL); 1372 } 1373 } 1374 1375 void 1376 tmpClearBuffer(Buffer *buf) 1377 { 1378 if (buf->pagerSource == NULL && writeBufferCache(buf) == 0) { 1379 buf->firstLine = NULL; 1380 buf->topLine = NULL; 1381 buf->currentLine = NULL; 1382 buf->lastLine = NULL; 1383 } 1384 } 1385 1386 static Str currentURL(void); 1387 1388 #ifdef USE_BUFINFO 1389 void 1390 saveBufferInfo() 1391 { 1392 FILE *fp; 1393 1394 if (w3m_dump) 1395 return; 1396 if ((fp = fopen(rcFile("bufinfo"), "w")) == NULL) { 1397 return; 1398 } 1399 fprintf(fp, "%s\n", currentURL()->ptr); 1400 fclose(fp); 1401 } 1402 #endif 1403 1404 static void 1405 pushBuffer(Buffer *buf) 1406 { 1407 Buffer *b; 1408 1409 #ifdef USE_IMAGE 1410 deleteImage(Currentbuf); 1411 #endif 1412 if (clear_buffer) 1413 tmpClearBuffer(Currentbuf); 1414 if (Firstbuf == Currentbuf) { 1415 buf->nextBuffer = Firstbuf; 1416 Firstbuf = Currentbuf = buf; 1417 } 1418 else if ((b = prevBuffer(Firstbuf, Currentbuf)) != NULL) { 1419 b->nextBuffer = buf; 1420 buf->nextBuffer = Currentbuf; 1421 Currentbuf = buf; 1422 } 1423 #ifdef USE_BUFINFO 1424 saveBufferInfo(); 1425 #endif 1426 1427 } 1428 1429 static void 1430 delBuffer(Buffer *buf) 1431 { 1432 if (buf == NULL) 1433 return; 1434 if (Currentbuf == buf) 1435 Currentbuf = buf->nextBuffer; 1436 Firstbuf = deleteBuffer(Firstbuf, buf); 1437 if (!Currentbuf) 1438 Currentbuf = Firstbuf; 1439 } 1440 1441 static void 1442 repBuffer(Buffer *oldbuf, Buffer *buf) 1443 { 1444 Firstbuf = replaceBuffer(Firstbuf, oldbuf, buf); 1445 Currentbuf = buf; 1446 } 1447 1448 1449 MySignalHandler 1450 intTrap(SIGNAL_ARG) 1451 { /* Interrupt catcher */ 1452 LONGJMP(IntReturn, 0); 1453 SIGNAL_RETURN; 1454 } 1455 1456 #ifdef SIGWINCH 1457 static MySignalHandler 1458 resize_hook(SIGNAL_ARG) 1459 { 1460 need_resize_screen = TRUE; 1461 mySignal(SIGWINCH, resize_hook); 1462 SIGNAL_RETURN; 1463 } 1464 1465 static void 1466 resize_screen(void) 1467 { 1468 need_resize_screen = FALSE; 1469 setlinescols(); 1470 setupscreen(); 1471 if (CurrentTab) 1472 displayBuffer(Currentbuf, B_FORCE_REDRAW); 1473 } 1474 #endif /* SIGWINCH */ 1475 1476 #ifdef SIGPIPE 1477 static MySignalHandler 1478 SigPipe(SIGNAL_ARG) 1479 { 1480 #ifdef USE_MIGEMO 1481 init_migemo(); 1482 #endif 1483 mySignal(SIGPIPE, SigPipe); 1484 SIGNAL_RETURN; 1485 } 1486 #endif 1487 1488 /* 1489 * Command functions: These functions are called with a keystroke. 1490 */ 1491 1492 static void 1493 nscroll(int n, int mode) 1494 { 1495 Buffer *buf = Currentbuf; 1496 Line *top = buf->topLine, *cur = buf->currentLine; 1497 int lnum, tlnum, llnum, diff_n; 1498 1499 if (buf->firstLine == NULL) 1500 return; 1501 lnum = cur->linenumber; 1502 buf->topLine = lineSkip(buf, top, n, FALSE); 1503 if (buf->topLine == top) { 1504 lnum += n; 1505 if (lnum < buf->topLine->linenumber) 1506 lnum = buf->topLine->linenumber; 1507 else if (lnum > buf->lastLine->linenumber) 1508 lnum = buf->lastLine->linenumber; 1509 } 1510 else { 1511 tlnum = buf->topLine->linenumber; 1512 llnum = buf->topLine->linenumber + buf->LINES - 1; 1513 if (nextpage_topline) 1514 diff_n = 0; 1515 else 1516 diff_n = n - (tlnum - top->linenumber); 1517 if (lnum < tlnum) 1518 lnum = tlnum + diff_n; 1519 if (lnum > llnum) 1520 lnum = llnum + diff_n; 1521 } 1522 gotoLine(buf, lnum); 1523 arrangeLine(buf); 1524 if (n > 0) { 1525 if (buf->currentLine->bpos && 1526 buf->currentLine->bwidth >= buf->currentColumn + buf->visualpos) 1527 cursorDown(buf, 1); 1528 else { 1529 while (buf->currentLine->next && buf->currentLine->next->bpos && 1530 buf->currentLine->bwidth + buf->currentLine->width < 1531 buf->currentColumn + buf->visualpos) 1532 cursorDown0(buf, 1); 1533 } 1534 } 1535 else { 1536 if (buf->currentLine->bwidth + buf->currentLine->width < 1537 buf->currentColumn + buf->visualpos) 1538 cursorUp(buf, 1); 1539 else { 1540 while (buf->currentLine->prev && buf->currentLine->bpos && 1541 buf->currentLine->bwidth >= 1542 buf->currentColumn + buf->visualpos) 1543 cursorUp0(buf, 1); 1544 } 1545 } 1546 displayBuffer(buf, mode); 1547 } 1548 1549 /* Move page forward */ 1550 DEFUN(pgFore, NEXT_PAGE, "Move to next page") 1551 { 1552 if (vi_prec_num) 1553 nscroll(searchKeyNum() * (Currentbuf->LINES - 1), B_NORMAL); 1554 else 1555 nscroll(prec_num ? searchKeyNum() : searchKeyNum() 1556 * (Currentbuf->LINES - 1), prec_num ? B_SCROLL : B_NORMAL); 1557 } 1558 1559 /* Move page backward */ 1560 DEFUN(pgBack, PREV_PAGE, "Move to previous page") 1561 { 1562 if (vi_prec_num) 1563 nscroll(-searchKeyNum() * (Currentbuf->LINES - 1), B_NORMAL); 1564 else 1565 nscroll(-(prec_num ? searchKeyNum() : searchKeyNum() 1566 * (Currentbuf->LINES - 1)), prec_num ? B_SCROLL : B_NORMAL); 1567 } 1568 1569 /* 1 line up */ 1570 DEFUN(lup1, UP, "Scroll up one line") 1571 { 1572 nscroll(searchKeyNum(), B_SCROLL); 1573 } 1574 1575 /* 1 line down */ 1576 DEFUN(ldown1, DOWN, "Scroll down one line") 1577 { 1578 nscroll(-searchKeyNum(), B_SCROLL); 1579 } 1580 1581 /* move cursor position to the center of screen */ 1582 DEFUN(ctrCsrV, CENTER_V, "Move to the center column") 1583 { 1584 int offsety; 1585 if (Currentbuf->firstLine == NULL) 1586 return; 1587 offsety = Currentbuf->LINES / 2 - Currentbuf->cursorY; 1588 if (offsety != 0) { 1589 #if 0 1590 Currentbuf->currentLine = lineSkip(Currentbuf, 1591 Currentbuf->currentLine, offsety, 1592 FALSE); 1593 #endif 1594 Currentbuf->topLine = 1595 lineSkip(Currentbuf, Currentbuf->topLine, -offsety, FALSE); 1596 arrangeLine(Currentbuf); 1597 displayBuffer(Currentbuf, B_NORMAL); 1598 } 1599 } 1600 1601 DEFUN(ctrCsrH, CENTER_H, "Move to the center line") 1602 { 1603 int offsetx; 1604 if (Currentbuf->firstLine == NULL) 1605 return; 1606 offsetx = Currentbuf->cursorX - Currentbuf->COLS / 2; 1607 if (offsetx != 0) { 1608 columnSkip(Currentbuf, offsetx); 1609 arrangeCursor(Currentbuf); 1610 displayBuffer(Currentbuf, B_NORMAL); 1611 } 1612 } 1613 1614 /* Redraw screen */ 1615 DEFUN(rdrwSc, REDRAW, "Redraw screen") 1616 { 1617 clear(); 1618 arrangeCursor(Currentbuf); 1619 displayBuffer(Currentbuf, B_FORCE_REDRAW); 1620 } 1621 1622 static void 1623 clear_mark(Line *l) 1624 { 1625 int pos; 1626 if (!l) 1627 return; 1628 for (pos = 0; pos < l->size; pos++) 1629 l->propBuf[pos] &= ~PE_MARK; 1630 } 1631 1632 /* search by regular expression */ 1633 static int 1634 srchcore(char *volatile str, int (*func) (Buffer *, char *)) 1635 { 1636 MySignalHandler(*prevtrap) (); 1637 volatile int i, result = SR_NOTFOUND; 1638 1639 if (str != NULL && str != SearchString) 1640 SearchString = str; 1641 if (SearchString == NULL || *SearchString == '\0') 1642 return SR_NOTFOUND; 1643 1644 str = conv_search_string(SearchString, DisplayCharset); 1645 prevtrap = mySignal(SIGINT, intTrap); 1646 crmode(); 1647 if (SETJMP(IntReturn) == 0) { 1648 for (i = 0; i < PREC_NUM; i++) { 1649 result = func(Currentbuf, str); 1650 if (i < PREC_NUM - 1 && result & SR_FOUND) 1651 clear_mark(Currentbuf->currentLine); 1652 } 1653 } 1654 mySignal(SIGINT, prevtrap); 1655 term_raw(); 1656 return result; 1657 } 1658 1659 static void 1660 disp_srchresult(int result, char *prompt, char *str) 1661 { 1662 if (str == NULL) 1663 str = ""; 1664 if (result & SR_NOTFOUND) 1665 disp_message(Sprintf("Not found: %s", str)->ptr, TRUE); 1666 else if (result & SR_WRAPPED) 1667 disp_message(Sprintf("Search wrapped: %s", str)->ptr, TRUE); 1668 else if (show_srch_str) 1669 disp_message(Sprintf("%s%s", prompt, str)->ptr, TRUE); 1670 } 1671 1672 static int 1673 dispincsrch(int ch, Str buf, Lineprop *prop) 1674 { 1675 static Buffer sbuf; 1676 static Line *currentLine; 1677 static int pos; 1678 char *str; 1679 int do_next_search = FALSE; 1680 1681 if (ch == 0 && buf == NULL) { 1682 SAVE_BUFPOSITION(&sbuf); /* search starting point */ 1683 currentLine = sbuf.currentLine; 1684 pos = sbuf.pos; 1685 return -1; 1686 } 1687 1688 str = buf->ptr; 1689 switch (ch) { 1690 case 022: /* C-r */ 1691 searchRoutine = backwardSearch; 1692 do_next_search = TRUE; 1693 break; 1694 case 023: /* C-s */ 1695 searchRoutine = forwardSearch; 1696 do_next_search = TRUE; 1697 break; 1698 1699 #ifdef USE_MIGEMO 1700 case 034: 1701 migemo_active = -migemo_active; 1702 goto done; 1703 #endif 1704 1705 default: 1706 if (ch >= 0) 1707 return ch; /* use InputKeymap */ 1708 } 1709 1710 if (do_next_search) { 1711 if (*str) { 1712 if (searchRoutine == forwardSearch) 1713 Currentbuf->pos += 1; 1714 SAVE_BUFPOSITION(&sbuf); 1715 if (srchcore(str, searchRoutine) == SR_NOTFOUND 1716 && searchRoutine == forwardSearch) { 1717 Currentbuf->pos -= 1; 1718 SAVE_BUFPOSITION(&sbuf); 1719 } 1720 arrangeCursor(Currentbuf); 1721 displayBuffer(Currentbuf, B_FORCE_REDRAW); 1722 clear_mark(Currentbuf->currentLine); 1723 return -1; 1724 } 1725 else 1726 return 020; /* _prev completion for C-s C-s */ 1727 } 1728 else if (*str) { 1729 RESTORE_BUFPOSITION(&sbuf); 1730 arrangeCursor(Currentbuf); 1731 srchcore(str, searchRoutine); 1732 arrangeCursor(Currentbuf); 1733 currentLine = Currentbuf->currentLine; 1734 pos = Currentbuf->pos; 1735 } 1736 displayBuffer(Currentbuf, B_FORCE_REDRAW); 1737 clear_mark(Currentbuf->currentLine); 1738 #ifdef USE_MIGEMO 1739 done: 1740 while (*str++ != '\0') { 1741 if (migemo_active > 0) 1742 *prop++ |= PE_UNDER; 1743 else 1744 *prop++ &= ~PE_UNDER; 1745 } 1746 #endif 1747 return -1; 1748 } 1749 1750 void 1751 isrch(int (*func) (Buffer *, char *), char *prompt) 1752 { 1753 char *str; 1754 Buffer sbuf; 1755 SAVE_BUFPOSITION(&sbuf); 1756 dispincsrch(0, NULL, NULL); /* initialize incremental search state */ 1757 1758 searchRoutine = func; 1759 str = inputLineHistSearch(prompt, NULL, IN_STRING, TextHist, dispincsrch); 1760 if (str == NULL) { 1761 RESTORE_BUFPOSITION(&sbuf); 1762 } 1763 displayBuffer(Currentbuf, B_FORCE_REDRAW); 1764 } 1765 1766 void 1767 srch(int (*func) (Buffer *, char *), char *prompt) 1768 { 1769 char *str; 1770 int result; 1771 int disp = FALSE; 1772 int pos; 1773 1774 str = searchKeyData(); 1775 if (str == NULL || *str == '\0') { 1776 str = inputStrHist(prompt, NULL, TextHist); 1777 if (str != NULL && *str == '\0') 1778 str = SearchString; 1779 if (str == NULL) { 1780 displayBuffer(Currentbuf, B_NORMAL); 1781 return; 1782 } 1783 disp = TRUE; 1784 } 1785 pos = Currentbuf->pos; 1786 if (func == forwardSearch) 1787 Currentbuf->pos += 1; 1788 result = srchcore(str, func); 1789 if (result & SR_FOUND) 1790 clear_mark(Currentbuf->currentLine); 1791 else 1792 Currentbuf->pos = pos; 1793 displayBuffer(Currentbuf, B_NORMAL); 1794 if (disp) 1795 disp_srchresult(result, prompt, str); 1796 searchRoutine = func; 1797 } 1798 1799 /* Search regular expression forward */ 1800 1801 DEFUN(srchfor, SEARCH SEARCH_FORE WHEREIS, "Search forward") 1802 { 1803 srch(forwardSearch, "Forward: "); 1804 } 1805 1806 DEFUN(isrchfor, ISEARCH, "Incremental search forward") 1807 { 1808 isrch(forwardSearch, "I-search: "); 1809 } 1810 1811 /* Search regular expression backward */ 1812 1813 DEFUN(srchbak, SEARCH_BACK, "Search backward") 1814 { 1815 srch(backwardSearch, "Backward: "); 1816 } 1817 1818 DEFUN(isrchbak, ISEARCH_BACK, "Incremental search backward") 1819 { 1820 isrch(backwardSearch, "I-search backward: "); 1821 } 1822 1823 static void 1824 srch_nxtprv(int reverse) 1825 { 1826 int result; 1827 /* *INDENT-OFF* */ 1828 static int (*routine[2]) (Buffer *, char *) = { 1829 forwardSearch, backwardSearch 1830 }; 1831 /* *INDENT-ON* */ 1832 1833 if (searchRoutine == NULL) { 1834 /* FIXME: gettextize? */ 1835 disp_message("No previous regular expression", TRUE); 1836 return; 1837 } 1838 if (reverse != 0) 1839 reverse = 1; 1840 if (searchRoutine == backwardSearch) 1841 reverse ^= 1; 1842 if (reverse == 0) 1843 Currentbuf->pos += 1; 1844 result = srchcore(SearchString, routine[reverse]); 1845 if (result & SR_FOUND) 1846 clear_mark(Currentbuf->currentLine); 1847 displayBuffer(Currentbuf, B_NORMAL); 1848 disp_srchresult(result, (reverse ? "Backward: " : "Forward: "), 1849 SearchString); 1850 } 1851 1852 /* Search next matching */ 1853 DEFUN(srchnxt, SEARCH_NEXT, "Search next regexp") 1854 { 1855 srch_nxtprv(0); 1856 } 1857 1858 /* Search previous matching */ 1859 DEFUN(srchprv, SEARCH_PREV, "Search previous regexp") 1860 { 1861 srch_nxtprv(1); 1862 } 1863 1864 static void 1865 shiftvisualpos(Buffer *buf, int shift) 1866 { 1867 Line *l = buf->currentLine; 1868 buf->visualpos -= shift; 1869 if (buf->visualpos - l->bwidth >= buf->COLS) 1870 buf->visualpos = l->bwidth + buf->COLS - 1; 1871 else if (buf->visualpos - l->bwidth < 0) 1872 buf->visualpos = l->bwidth; 1873 arrangeLine(buf); 1874 if (buf->visualpos - l->bwidth == -shift && buf->cursorX == 0) 1875 buf->visualpos = l->bwidth; 1876 } 1877 1878 /* Shift screen left */ 1879 DEFUN(shiftl, SHIFT_LEFT, "Shift screen left") 1880 { 1881 int column; 1882 1883 if (Currentbuf->firstLine == NULL) 1884 return; 1885 column = Currentbuf->currentColumn; 1886 columnSkip(Currentbuf, searchKeyNum() * (-Currentbuf->COLS + 1) + 1); 1887 shiftvisualpos(Currentbuf, Currentbuf->currentColumn - column); 1888 displayBuffer(Currentbuf, B_NORMAL); 1889 } 1890 1891 /* Shift screen right */ 1892 DEFUN(shiftr, SHIFT_RIGHT, "Shift screen right") 1893 { 1894 int column; 1895 1896 if (Currentbuf->firstLine == NULL) 1897 return; 1898 column = Currentbuf->currentColumn; 1899 columnSkip(Currentbuf, searchKeyNum() * (Currentbuf->COLS - 1) - 1); 1900 shiftvisualpos(Currentbuf, Currentbuf->currentColumn - column); 1901 displayBuffer(Currentbuf, B_NORMAL); 1902 } 1903 1904 DEFUN(col1R, RIGHT, "Shift screen one column right") 1905 { 1906 Buffer *buf = Currentbuf; 1907 Line *l = buf->currentLine; 1908 int j, column, n = searchKeyNum(); 1909 1910 if (l == NULL) 1911 return; 1912 for (j = 0; j < n; j++) { 1913 column = buf->currentColumn; 1914 columnSkip(Currentbuf, 1); 1915 if (column == buf->currentColumn) 1916 break; 1917 shiftvisualpos(Currentbuf, 1); 1918 } 1919 displayBuffer(Currentbuf, B_NORMAL); 1920 } 1921 1922 DEFUN(col1L, LEFT, "Shift screen one column") 1923 { 1924 Buffer *buf = Currentbuf; 1925 Line *l = buf->currentLine; 1926 int j, n = searchKeyNum(); 1927 1928 if (l == NULL) 1929 return; 1930 for (j = 0; j < n; j++) { 1931 if (buf->currentColumn == 0) 1932 break; 1933 columnSkip(Currentbuf, -1); 1934 shiftvisualpos(Currentbuf, -1); 1935 } 1936 displayBuffer(Currentbuf, B_NORMAL); 1937 } 1938 1939 DEFUN(setEnv, SETENV, "Set environment variable") 1940 { 1941 char *env; 1942 char *var, *value; 1943 1944 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 1945 env = searchKeyData(); 1946 if (env == NULL || *env == '\0' || strchr(env, '=') == NULL) { 1947 if (env != NULL && *env != '\0') 1948 env = Sprintf("%s=", env)->ptr; 1949 env = inputStrHist("Set environ: ", env, TextHist); 1950 if (env == NULL || *env == '\0') { 1951 displayBuffer(Currentbuf, B_NORMAL); 1952 return; 1953 } 1954 } 1955 if ((value = strchr(env, '=')) != NULL && value > env) { 1956 var = allocStr(env, value - env); 1957 value++; 1958 set_environ(var, value); 1959 } 1960 displayBuffer(Currentbuf, B_NORMAL); 1961 } 1962 1963 DEFUN(pipeBuf, PIPE_BUF, "Send rendered document to pipe") 1964 { 1965 Buffer *buf; 1966 char *cmd, *tmpf; 1967 FILE *f; 1968 1969 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 1970 cmd = searchKeyData(); 1971 if (cmd == NULL || *cmd == '\0') { 1972 /* FIXME: gettextize? */ 1973 cmd = inputLineHist("Pipe buffer to: ", "", IN_COMMAND, ShellHist); 1974 } 1975 if (cmd != NULL) 1976 cmd = conv_to_system(cmd); 1977 if (cmd == NULL || *cmd == '\0') { 1978 displayBuffer(Currentbuf, B_NORMAL); 1979 return; 1980 } 1981 tmpf = tmpfname(TMPF_DFL, NULL)->ptr; 1982 f = fopen(tmpf, "w"); 1983 if (f == NULL) { 1984 /* FIXME: gettextize? */ 1985 disp_message(Sprintf("Can't save buffer to %s", cmd)->ptr, TRUE); 1986 return; 1987 } 1988 saveBuffer(Currentbuf, f, TRUE); 1989 fclose(f); 1990 buf = getpipe(myExtCommand(cmd, shell_quote(tmpf), TRUE)->ptr); 1991 if (buf == NULL) { 1992 disp_message("Execution failed", TRUE); 1993 return; 1994 } 1995 else { 1996 buf->filename = cmd; 1997 buf->buffername = Sprintf("%s %s", PIPEBUFFERNAME, 1998 conv_from_system(cmd))->ptr; 1999 buf->bufferprop |= (BP_INTERNAL | BP_NO_URL); 2000 if (buf->type == NULL) 2001 buf->type = "text/plain"; 2002 buf->currentURL.file = "-"; 2003 pushBuffer(buf); 2004 } 2005 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2006 } 2007 2008 /* Execute shell command and read output ac pipe. */ 2009 DEFUN(pipesh, PIPE_SHELL, "Execute shell command and browse") 2010 { 2011 Buffer *buf; 2012 char *cmd; 2013 2014 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 2015 cmd = searchKeyData(); 2016 if (cmd == NULL || *cmd == '\0') { 2017 cmd = inputLineHist("(read shell[pipe])!", "", IN_COMMAND, ShellHist); 2018 } 2019 if (cmd != NULL) 2020 cmd = conv_to_system(cmd); 2021 if (cmd == NULL || *cmd == '\0') { 2022 displayBuffer(Currentbuf, B_NORMAL); 2023 return; 2024 } 2025 buf = getpipe(cmd); 2026 if (buf == NULL) { 2027 disp_message("Execution failed", TRUE); 2028 return; 2029 } 2030 else { 2031 buf->bufferprop |= (BP_INTERNAL | BP_NO_URL); 2032 if (buf->type == NULL) 2033 buf->type = "text/plain"; 2034 pushBuffer(buf); 2035 } 2036 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2037 } 2038 2039 /* Execute shell command and load entire output to buffer */ 2040 DEFUN(readsh, READ_SHELL, "Execute shell command and load") 2041 { 2042 Buffer *buf; 2043 MySignalHandler(*prevtrap) (); 2044 char *cmd; 2045 2046 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 2047 cmd = searchKeyData(); 2048 if (cmd == NULL || *cmd == '\0') { 2049 cmd = inputLineHist("(read shell)!", "", IN_COMMAND, ShellHist); 2050 } 2051 if (cmd != NULL) 2052 cmd = conv_to_system(cmd); 2053 if (cmd == NULL || *cmd == '\0') { 2054 displayBuffer(Currentbuf, B_NORMAL); 2055 return; 2056 } 2057 prevtrap = mySignal(SIGINT, intTrap); 2058 crmode(); 2059 buf = getshell(cmd); 2060 mySignal(SIGINT, prevtrap); 2061 term_raw(); 2062 if (buf == NULL) { 2063 /* FIXME: gettextize? */ 2064 disp_message("Execution failed", TRUE); 2065 return; 2066 } 2067 else { 2068 buf->bufferprop |= (BP_INTERNAL | BP_NO_URL); 2069 if (buf->type == NULL) 2070 buf->type = "text/plain"; 2071 pushBuffer(buf); 2072 } 2073 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2074 } 2075 2076 /* Execute shell command */ 2077 DEFUN(execsh, EXEC_SHELL SHELL, "Execute shell command") 2078 { 2079 char *cmd; 2080 2081 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 2082 cmd = searchKeyData(); 2083 if (cmd == NULL || *cmd == '\0') { 2084 cmd = inputLineHist("(exec shell)!", "", IN_COMMAND, ShellHist); 2085 } 2086 if (cmd != NULL) 2087 cmd = conv_to_system(cmd); 2088 if (cmd != NULL && *cmd != '\0') { 2089 fmTerm(); 2090 printf("\n"); 2091 system(cmd); 2092 /* FIXME: gettextize? */ 2093 printf("\n[Hit any key]"); 2094 fflush(stdout); 2095 fmInit(); 2096 getch(); 2097 } 2098 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2099 } 2100 2101 /* Load file */ 2102 DEFUN(ldfile, LOAD, "Load local file") 2103 { 2104 char *fn; 2105 2106 fn = searchKeyData(); 2107 if (fn == NULL || *fn == '\0') { 2108 /* FIXME: gettextize? */ 2109 fn = inputFilenameHist("(Load)Filename? ", NULL, LoadHist); 2110 } 2111 if (fn != NULL) 2112 fn = conv_to_system(fn); 2113 if (fn == NULL || *fn == '\0') { 2114 displayBuffer(Currentbuf, B_NORMAL); 2115 return; 2116 } 2117 cmd_loadfile(fn); 2118 } 2119 2120 /* Load help file */ 2121 DEFUN(ldhelp, HELP, "View help") 2122 { 2123 #ifdef USE_HELP_CGI 2124 char *lang; 2125 int n; 2126 Str tmp; 2127 2128 lang = AcceptLang; 2129 n = strcspn(lang, ";, \t"); 2130 tmp = Sprintf("file:///$LIB/" HELP_CGI CGI_EXTENSION "?version=%s&lang=%s", 2131 Str_form_quote(Strnew_charp(w3m_version))->ptr, 2132 Str_form_quote(Strnew_charp_n(lang, n))->ptr); 2133 cmd_loadURL(tmp->ptr, NULL, NO_REFERER, NULL); 2134 #else 2135 cmd_loadURL(helpFile(HELP_FILE), NULL, NO_REFERER, NULL); 2136 #endif 2137 } 2138 2139 static void 2140 cmd_loadfile(char *fn) 2141 { 2142 Buffer *buf; 2143 2144 buf = loadGeneralFile(file_to_url(fn), NULL, NO_REFERER, 0, NULL); 2145 if (buf == NULL) { 2146 /* FIXME: gettextize? */ 2147 char *emsg = Sprintf("%s not found", conv_from_system(fn))->ptr; 2148 disp_err_message(emsg, FALSE); 2149 } 2150 else if (buf != NO_BUFFER) { 2151 pushBuffer(buf); 2152 if (RenderFrame && Currentbuf->frameset != NULL) 2153 rFrame(); 2154 } 2155 displayBuffer(Currentbuf, B_NORMAL); 2156 } 2157 2158 /* Move cursor left */ 2159 static void 2160 _movL(int n) 2161 { 2162 int i, m = searchKeyNum(); 2163 if (Currentbuf->firstLine == NULL) 2164 return; 2165 for (i = 0; i < m; i++) 2166 cursorLeft(Currentbuf, n); 2167 displayBuffer(Currentbuf, B_NORMAL); 2168 } 2169 2170 DEFUN(movL, MOVE_LEFT, 2171 "Move cursor left (a half screen shift at the left edge)") 2172 { 2173 _movL(Currentbuf->COLS / 2); 2174 } 2175 2176 DEFUN(movL1, MOVE_LEFT1, "Move cursor left (1 columns shift at the left edge)") 2177 { 2178 _movL(1); 2179 } 2180 2181 /* Move cursor downward */ 2182 static void 2183 _movD(int n) 2184 { 2185 int i, m = searchKeyNum(); 2186 if (Currentbuf->firstLine == NULL) 2187 return; 2188 for (i = 0; i < m; i++) 2189 cursorDown(Currentbuf, n); 2190 displayBuffer(Currentbuf, B_NORMAL); 2191 } 2192 2193 DEFUN(movD, MOVE_DOWN, 2194 "Move cursor down (a half screen scroll at the end of screen)") 2195 { 2196 _movD((Currentbuf->LINES + 1) / 2); 2197 } 2198 2199 DEFUN(movD1, MOVE_DOWN1, 2200 "Move cursor down (1 line scroll at the end of screen)") 2201 { 2202 _movD(1); 2203 } 2204 2205 /* move cursor upward */ 2206 static void 2207 _movU(int n) 2208 { 2209 int i, m = searchKeyNum(); 2210 if (Currentbuf->firstLine == NULL) 2211 return; 2212 for (i = 0; i < m; i++) 2213 cursorUp(Currentbuf, n); 2214 displayBuffer(Currentbuf, B_NORMAL); 2215 } 2216 2217 DEFUN(movU, MOVE_UP, 2218 "Move cursor up (a half screen scroll at the top of screen)") 2219 { 2220 _movU((Currentbuf->LINES + 1) / 2); 2221 } 2222 2223 DEFUN(movU1, MOVE_UP1, "Move cursor up (1 line scrol at the top of screen)") 2224 { 2225 _movU(1); 2226 } 2227 2228 /* Move cursor right */ 2229 static void 2230 _movR(int n) 2231 { 2232 int i, m = searchKeyNum(); 2233 if (Currentbuf->firstLine == NULL) 2234 return; 2235 for (i = 0; i < m; i++) 2236 cursorRight(Currentbuf, n); 2237 displayBuffer(Currentbuf, B_NORMAL); 2238 } 2239 2240 DEFUN(movR, MOVE_RIGHT, 2241 "Move cursor right (a half screen shift at the right edge)") 2242 { 2243 _movR(Currentbuf->COLS / 2); 2244 } 2245 2246 DEFUN(movR1, MOVE_RIGHT1, 2247 "Move cursor right (1 columns shift at the right edge)") 2248 { 2249 _movR(1); 2250 } 2251 2252 /* movLW, movRW */ 2253 /* 2254 * From: Takashi Nishimoto <g96p0935@mse.waseda.ac.jp> Date: Mon, 14 Jun 2255 * 1999 09:29:56 +0900 2256 */ 2257 #if defined(USE_M17N) && defined(USE_UNICODE) 2258 #define nextChar(s, l) do { (s)++; } while ((s) < (l)->len && (l)->propBuf[s] & PC_WCHAR2) 2259 #define prevChar(s, l) do { (s)--; } while ((s) > 0 && (l)->propBuf[s] & PC_WCHAR2) 2260 2261 static wc_uint32 2262 getChar(char *p) 2263 { 2264 return wc_any_to_ucs(wtf_parse1(&p)); 2265 } 2266 2267 static int 2268 is_wordchar(wc_uint32 c) 2269 { 2270 return wc_is_ucs_alnum(c); 2271 } 2272 #else 2273 #define nextChar(s, l) (s)++ 2274 #define prevChar(s, l) (s)-- 2275 #define getChar(p) ((int)*(p)) 2276 2277 static int 2278 is_wordchar(int c) 2279 { 2280 return IS_ALNUM(c); 2281 } 2282 #endif 2283 2284 static int 2285 prev_nonnull_line(Line *line) 2286 { 2287 Line *l; 2288 2289 for (l = line; l != NULL && l->len == 0; l = l->prev) ; 2290 if (l == NULL || l->len == 0) 2291 return -1; 2292 2293 Currentbuf->currentLine = l; 2294 if (l != line) 2295 Currentbuf->pos = Currentbuf->currentLine->len; 2296 return 0; 2297 } 2298 2299 DEFUN(movLW, PREV_WORD, "Move to previous word") 2300 { 2301 char *lb; 2302 Line *pline, *l; 2303 int ppos; 2304 int i, n = searchKeyNum(); 2305 2306 if (Currentbuf->firstLine == NULL) 2307 return; 2308 2309 for (i = 0; i < n; i++) { 2310 pline = Currentbuf->currentLine; 2311 ppos = Currentbuf->pos; 2312 2313 if (prev_nonnull_line(Currentbuf->currentLine) < 0) 2314 goto end; 2315 2316 while (1) { 2317 l = Currentbuf->currentLine; 2318 lb = l->lineBuf; 2319 while (Currentbuf->pos > 0) { 2320 int tmp = Currentbuf->pos; 2321 prevChar(tmp, l); 2322 if (is_wordchar(getChar(&lb[tmp]))) 2323 break; 2324 Currentbuf->pos = tmp; 2325 } 2326 if (Currentbuf->pos > 0) 2327 break; 2328 if (prev_nonnull_line(Currentbuf->currentLine->prev) < 0) { 2329 Currentbuf->currentLine = pline; 2330 Currentbuf->pos = ppos; 2331 goto end; 2332 } 2333 Currentbuf->pos = Currentbuf->currentLine->len; 2334 } 2335 2336 l = Currentbuf->currentLine; 2337 lb = l->lineBuf; 2338 while (Currentbuf->pos > 0) { 2339 int tmp = Currentbuf->pos; 2340 prevChar(tmp, l); 2341 if (!is_wordchar(getChar(&lb[tmp]))) 2342 break; 2343 Currentbuf->pos = tmp; 2344 } 2345 } 2346 end: 2347 arrangeCursor(Currentbuf); 2348 displayBuffer(Currentbuf, B_NORMAL); 2349 } 2350 2351 static int 2352 next_nonnull_line(Line *line) 2353 { 2354 Line *l; 2355 2356 for (l = line; l != NULL && l->len == 0; l = l->next) ; 2357 2358 if (l == NULL || l->len == 0) 2359 return -1; 2360 2361 Currentbuf->currentLine = l; 2362 if (l != line) 2363 Currentbuf->pos = 0; 2364 return 0; 2365 } 2366 2367 DEFUN(movRW, NEXT_WORD, "Move to next word") 2368 { 2369 char *lb; 2370 Line *pline, *l; 2371 int ppos; 2372 int i, n = searchKeyNum(); 2373 2374 if (Currentbuf->firstLine == NULL) 2375 return; 2376 2377 for (i = 0; i < n; i++) { 2378 pline = Currentbuf->currentLine; 2379 ppos = Currentbuf->pos; 2380 2381 if (next_nonnull_line(Currentbuf->currentLine) < 0) 2382 goto end; 2383 2384 l = Currentbuf->currentLine; 2385 lb = l->lineBuf; 2386 while (Currentbuf->pos < l->len && 2387 is_wordchar(getChar(&lb[Currentbuf->pos]))) 2388 nextChar(Currentbuf->pos, l); 2389 2390 while (1) { 2391 while (Currentbuf->pos < l->len && 2392 !is_wordchar(getChar(&lb[Currentbuf->pos]))) 2393 nextChar(Currentbuf->pos, l); 2394 if (Currentbuf->pos < l->len) 2395 break; 2396 if (next_nonnull_line(Currentbuf->currentLine->next) < 0) { 2397 Currentbuf->currentLine = pline; 2398 Currentbuf->pos = ppos; 2399 goto end; 2400 } 2401 Currentbuf->pos = 0; 2402 l = Currentbuf->currentLine; 2403 lb = l->lineBuf; 2404 } 2405 } 2406 end: 2407 arrangeCursor(Currentbuf); 2408 displayBuffer(Currentbuf, B_NORMAL); 2409 } 2410 2411 static void 2412 _quitfm(int confirm) 2413 { 2414 char *ans = "y"; 2415 2416 if (checkDownloadList()) 2417 /* FIXME: gettextize? */ 2418 ans = inputChar("Download process retains. " 2419 "Do you want to exit w3m? (y/n)"); 2420 else if (confirm) 2421 /* FIXME: gettextize? */ 2422 ans = inputChar("Do you want to exit w3m? (y/n)"); 2423 if (!(ans && TOLOWER(*ans) == 'y')) { 2424 displayBuffer(Currentbuf, B_NORMAL); 2425 return; 2426 } 2427 2428 term_title(""); /* XXX */ 2429 #ifdef USE_IMAGE 2430 if (activeImage) 2431 termImage(); 2432 #endif 2433 fmTerm(); 2434 #ifdef USE_COOKIE 2435 save_cookies(); 2436 #endif /* USE_COOKIE */ 2437 #ifdef USE_HISTORY 2438 if (UseHistory && SaveURLHist) 2439 saveHistory(URLHist, URLHistSize); 2440 #endif /* USE_HISTORY */ 2441 w3m_exit(0); 2442 } 2443 2444 /* Quit */ 2445 DEFUN(quitfm, ABORT EXIT, "Quit w3m without confirmation") 2446 { 2447 _quitfm(FALSE); 2448 } 2449 2450 /* Question and Quit */ 2451 DEFUN(qquitfm, QUIT, "Quit w3m") 2452 { 2453 _quitfm(confirm_on_quit); 2454 } 2455 2456 /* Select buffer */ 2457 DEFUN(selBuf, SELECT, "Go to buffer selection panel") 2458 { 2459 Buffer *buf; 2460 int ok; 2461 char cmd; 2462 2463 ok = FALSE; 2464 do { 2465 buf = selectBuffer(Firstbuf, Currentbuf, &cmd); 2466 switch (cmd) { 2467 case 'B': 2468 ok = TRUE; 2469 break; 2470 case '\n': 2471 case ' ': 2472 Currentbuf = buf; 2473 ok = TRUE; 2474 break; 2475 case 'D': 2476 delBuffer(buf); 2477 if (Firstbuf == NULL) { 2478 /* No more buffer */ 2479 Firstbuf = nullBuffer(); 2480 Currentbuf = Firstbuf; 2481 } 2482 break; 2483 case 'q': 2484 qquitfm(); 2485 break; 2486 case 'Q': 2487 quitfm(); 2488 break; 2489 } 2490 } while (!ok); 2491 2492 for (buf = Firstbuf; buf != NULL; buf = buf->nextBuffer) { 2493 if (buf == Currentbuf) 2494 continue; 2495 #ifdef USE_IMAGE 2496 deleteImage(buf); 2497 #endif 2498 if (clear_buffer) 2499 tmpClearBuffer(buf); 2500 } 2501 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2502 } 2503 2504 /* Suspend (on BSD), or run interactive shell (on SysV) */ 2505 DEFUN(susp, INTERRUPT SUSPEND, "Stop loading document") 2506 { 2507 #ifndef SIGSTOP 2508 char *shell; 2509 #endif /* not SIGSTOP */ 2510 move(LASTLINE, 0); 2511 clrtoeolx(); 2512 refresh(); 2513 fmTerm(); 2514 #ifndef SIGSTOP 2515 shell = getenv("SHELL"); 2516 if (shell == NULL) 2517 shell = "/bin/sh"; 2518 system(shell); 2519 #else /* SIGSTOP */ 2520 kill((pid_t) 0, SIGSTOP); 2521 #endif /* SIGSTOP */ 2522 fmInit(); 2523 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2524 } 2525 2526 /* Go to specified line */ 2527 static void 2528 _goLine(char *l) 2529 { 2530 if (l == NULL || *l == '\0' || Currentbuf->currentLine == NULL) { 2531 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2532 return; 2533 } 2534 Currentbuf->pos = 0; 2535 if (((*l == '^') || (*l == '$')) && prec_num) { 2536 gotoRealLine(Currentbuf, prec_num); 2537 } 2538 else if (*l == '^') { 2539 Currentbuf->topLine = Currentbuf->currentLine = Currentbuf->firstLine; 2540 } 2541 else if (*l == '$') { 2542 Currentbuf->topLine = 2543 lineSkip(Currentbuf, Currentbuf->lastLine, 2544 -(Currentbuf->LINES + 1) / 2, TRUE); 2545 Currentbuf->currentLine = Currentbuf->lastLine; 2546 } 2547 else 2548 gotoRealLine(Currentbuf, atoi(l)); 2549 arrangeCursor(Currentbuf); 2550 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2551 } 2552 2553 DEFUN(goLine, GOTO_LINE, "Go to specified line") 2554 { 2555 2556 char *str = searchKeyData(); 2557 if (prec_num) 2558 _goLine("^"); 2559 else if (str) 2560 _goLine(str); 2561 else 2562 /* FIXME: gettextize? */ 2563 _goLine(inputStr("Goto line: ", "")); 2564 } 2565 2566 2567 DEFUN(goLineF, BEGIN, "Go to the first line") 2568 { 2569 _goLine("^"); 2570 } 2571 2572 DEFUN(goLineL, END, "Go to the last line") 2573 { 2574 _goLine("$"); 2575 } 2576 2577 /* Go to the beginning of the line */ 2578 DEFUN(linbeg, LINE_BEGIN, "Go to the beginning of line") 2579 { 2580 if (Currentbuf->firstLine == NULL) 2581 return; 2582 while (Currentbuf->currentLine->prev && Currentbuf->currentLine->bpos) 2583 cursorUp0(Currentbuf, 1); 2584 Currentbuf->pos = 0; 2585 arrangeCursor(Currentbuf); 2586 displayBuffer(Currentbuf, B_NORMAL); 2587 } 2588 2589 /* Go to the bottom of the line */ 2590 DEFUN(linend, LINE_END, "Go to the end of line") 2591 { 2592 if (Currentbuf->firstLine == NULL) 2593 return; 2594 while (Currentbuf->currentLine->next 2595 && Currentbuf->currentLine->next->bpos) 2596 cursorDown0(Currentbuf, 1); 2597 Currentbuf->pos = Currentbuf->currentLine->len - 1; 2598 arrangeCursor(Currentbuf); 2599 displayBuffer(Currentbuf, B_NORMAL); 2600 } 2601 2602 static int 2603 cur_real_linenumber(Buffer *buf) 2604 { 2605 Line *l, *cur = buf->currentLine; 2606 int n; 2607 2608 if (!cur) 2609 return 1; 2610 n = cur->real_linenumber ? cur->real_linenumber : 1; 2611 for (l = buf->firstLine; l && l != cur && l->real_linenumber == 0; l = l->next) { /* header */ 2612 if (l->bpos == 0) 2613 n++; 2614 } 2615 return n; 2616 } 2617 2618 /* Run editor on the current buffer */ 2619 DEFUN(editBf, EDIT, "Edit current document") 2620 { 2621 char *fn = Currentbuf->filename; 2622 Str cmd; 2623 2624 if (fn == NULL || Currentbuf->pagerSource != NULL || /* Behaving as a pager */ 2625 (Currentbuf->type == NULL && Currentbuf->edit == NULL) || /* Reading shell */ 2626 Currentbuf->real_scheme != SCM_LOCAL || !strcmp(Currentbuf->currentURL.file, "-") || /* file is std input */ 2627 Currentbuf->bufferprop & BP_FRAME) { /* Frame */ 2628 disp_err_message("Can't edit other than local file", TRUE); 2629 return; 2630 } 2631 if (Currentbuf->edit) 2632 cmd = unquote_mailcap(Currentbuf->edit, Currentbuf->real_type, fn, 2633 checkHeader(Currentbuf, "Content-Type:"), NULL); 2634 else 2635 cmd = myEditor(Editor, shell_quote(fn), 2636 cur_real_linenumber(Currentbuf)); 2637 fmTerm(); 2638 system(cmd->ptr); 2639 fmInit(); 2640 2641 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2642 reload(); 2643 } 2644 2645 /* Run editor on the current screen */ 2646 DEFUN(editScr, EDIT_SCREEN, "Edit currently rendered document") 2647 { 2648 char *tmpf; 2649 FILE *f; 2650 2651 tmpf = tmpfname(TMPF_DFL, NULL)->ptr; 2652 f = fopen(tmpf, "w"); 2653 if (f == NULL) { 2654 /* FIXME: gettextize? */ 2655 disp_err_message(Sprintf("Can't open %s", tmpf)->ptr, TRUE); 2656 return; 2657 } 2658 saveBuffer(Currentbuf, f, TRUE); 2659 fclose(f); 2660 fmTerm(); 2661 system(myEditor(Editor, shell_quote(tmpf), 2662 cur_real_linenumber(Currentbuf))->ptr); 2663 fmInit(); 2664 unlink(tmpf); 2665 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2666 } 2667 2668 #ifdef USE_MARK 2669 2670 /* Set / unset mark */ 2671 DEFUN(_mark, MARK, "Set/unset mark") 2672 { 2673 Line *l; 2674 if (!use_mark) 2675 return; 2676 if (Currentbuf->firstLine == NULL) 2677 return; 2678 l = Currentbuf->currentLine; 2679 l->propBuf[Currentbuf->pos] ^= PE_MARK; 2680 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2681 } 2682 2683 /* Go to next mark */ 2684 DEFUN(nextMk, NEXT_MARK, "Move to next word") 2685 { 2686 Line *l; 2687 int i; 2688 2689 if (!use_mark) 2690 return; 2691 if (Currentbuf->firstLine == NULL) 2692 return; 2693 i = Currentbuf->pos + 1; 2694 l = Currentbuf->currentLine; 2695 if (i >= l->len) { 2696 i = 0; 2697 l = l->next; 2698 } 2699 while (l != NULL) { 2700 for (; i < l->len; i++) { 2701 if (l->propBuf[i] & PE_MARK) { 2702 Currentbuf->currentLine = l; 2703 Currentbuf->pos = i; 2704 arrangeCursor(Currentbuf); 2705 displayBuffer(Currentbuf, B_NORMAL); 2706 return; 2707 } 2708 } 2709 l = l->next; 2710 i = 0; 2711 } 2712 /* FIXME: gettextize? */ 2713 disp_message("No mark exist after here", TRUE); 2714 } 2715 2716 /* Go to previous mark */ 2717 DEFUN(prevMk, PREV_MARK, "Move to previous mark") 2718 { 2719 Line *l; 2720 int i; 2721 2722 if (!use_mark) 2723 return; 2724 if (Currentbuf->firstLine == NULL) 2725 return; 2726 i = Currentbuf->pos - 1; 2727 l = Currentbuf->currentLine; 2728 if (i < 0) { 2729 l = l->prev; 2730 if (l != NULL) 2731 i = l->len - 1; 2732 } 2733 while (l != NULL) { 2734 for (; i >= 0; i--) { 2735 if (l->propBuf[i] & PE_MARK) { 2736 Currentbuf->currentLine = l; 2737 Currentbuf->pos = i; 2738 arrangeCursor(Currentbuf); 2739 displayBuffer(Currentbuf, B_NORMAL); 2740 return; 2741 } 2742 } 2743 l = l->prev; 2744 if (l != NULL) 2745 i = l->len - 1; 2746 } 2747 /* FIXME: gettextize? */ 2748 disp_message("No mark exist before here", TRUE); 2749 } 2750 2751 /* Mark place to which the regular expression matches */ 2752 DEFUN(reMark, REG_MARK, "Set mark using regexp") 2753 { 2754 Line *l; 2755 char *str; 2756 char *p, *p1, *p2; 2757 2758 if (!use_mark) 2759 return; 2760 str = searchKeyData(); 2761 if (str == NULL || *str == '\0') { 2762 str = inputStrHist("(Mark)Regexp: ", MarkString, TextHist); 2763 if (str == NULL || *str == '\0') { 2764 displayBuffer(Currentbuf, B_NORMAL); 2765 return; 2766 } 2767 } 2768 str = conv_search_string(str, DisplayCharset); 2769 if ((str = regexCompile(str, 1)) != NULL) { 2770 disp_message(str, TRUE); 2771 return; 2772 } 2773 MarkString = str; 2774 for (l = Currentbuf->firstLine; l != NULL; l = l->next) { 2775 p = l->lineBuf; 2776 for (;;) { 2777 if (regexMatch(p, &l->lineBuf[l->len] - p, p == l->lineBuf) == 1) { 2778 matchedPosition(&p1, &p2); 2779 l->propBuf[p1 - l->lineBuf] |= PE_MARK; 2780 p = p2; 2781 } 2782 else 2783 break; 2784 } 2785 } 2786 2787 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2788 } 2789 #endif /* USE_MARK */ 2790 2791 static Buffer * 2792 loadNormalBuf(Buffer *buf, int renderframe) 2793 { 2794 pushBuffer(buf); 2795 if (renderframe && RenderFrame && Currentbuf->frameset != NULL) 2796 rFrame(); 2797 return buf; 2798 } 2799 2800 static Buffer * 2801 loadLink(char *url, char *target, char *referer, FormList *request) 2802 { 2803 Buffer *buf, *nfbuf; 2804 union frameset_element *f_element = NULL; 2805 int flag = 0; 2806 ParsedURL *base, pu; 2807 2808 message(Sprintf("loading %s", url)->ptr, 0, 0); 2809 refresh(); 2810 2811 base = baseURL(Currentbuf); 2812 if (base == NULL || 2813 base->scheme == SCM_LOCAL || base->scheme == SCM_LOCAL_CGI) 2814 referer = NO_REFERER; 2815 if (referer == NULL) 2816 referer = parsedURL2Str(&Currentbuf->currentURL)->ptr; 2817 buf = loadGeneralFile(url, baseURL(Currentbuf), referer, flag, request); 2818 if (buf == NULL) { 2819 char *emsg = Sprintf("Can't load %s", url)->ptr; 2820 disp_err_message(emsg, FALSE); 2821 return NULL; 2822 } 2823 2824 parseURL2(url, &pu, base); 2825 pushHashHist(URLHist, parsedURL2Str(&pu)->ptr); 2826 2827 if (buf == NO_BUFFER) { 2828 return NULL; 2829 } 2830 if (!on_target) /* open link as an indivisual page */ 2831 return loadNormalBuf(buf, TRUE); 2832 2833 if (do_download) /* download (thus no need to render frame) */ 2834 return loadNormalBuf(buf, FALSE); 2835 2836 if (target == NULL || /* no target specified (that means this page is not a frame page) */ 2837 !strcmp(target, "_top") || /* this link is specified to be opened as an indivisual * page */ 2838 !(Currentbuf->bufferprop & BP_FRAME) /* This page is not a frame page */ 2839 ) { 2840 return loadNormalBuf(buf, TRUE); 2841 } 2842 nfbuf = Currentbuf->linkBuffer[LB_N_FRAME]; 2843 if (nfbuf == NULL) { 2844 /* original page (that contains <frameset> tag) doesn't exist */ 2845 return loadNormalBuf(buf, TRUE); 2846 } 2847 2848 f_element = search_frame(nfbuf->frameset, target); 2849 if (f_element == NULL) { 2850 /* specified target doesn't exist in this frameset */ 2851 return loadNormalBuf(buf, TRUE); 2852 } 2853 2854 /* frame page */ 2855 2856 /* stack current frameset */ 2857 pushFrameTree(&(nfbuf->frameQ), copyFrameSet(nfbuf->frameset), Currentbuf); 2858 /* delete frame view buffer */ 2859 delBuffer(Currentbuf); 2860 Currentbuf = nfbuf; 2861 /* nfbuf->frameset = copyFrameSet(nfbuf->frameset); */ 2862 resetFrameElement(f_element, buf, referer, request); 2863 discardBuffer(buf); 2864 rFrame(); 2865 { 2866 Anchor *al = NULL; 2867 char *label = pu.label; 2868 2869 if (label && f_element->element->attr == F_BODY) { 2870 al = searchAnchor(f_element->body->nameList, label); 2871 } 2872 if (!al) { 2873 label = Strnew_m_charp("_", target, NULL)->ptr; 2874 al = searchURLLabel(Currentbuf, label); 2875 } 2876 if (al) { 2877 gotoLine(Currentbuf, al->start.line); 2878 if (label_topline) 2879 Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->topLine, 2880 Currentbuf->currentLine-> 2881 linenumber - 2882 Currentbuf->topLine->linenumber, 2883 FALSE); 2884 Currentbuf->pos = al->start.pos; 2885 arrangeCursor(Currentbuf); 2886 } 2887 } 2888 displayBuffer(Currentbuf, B_NORMAL); 2889 return buf; 2890 } 2891 2892 static void 2893 gotoLabel(char *label) 2894 { 2895 Buffer *buf; 2896 Anchor *al; 2897 int i; 2898 2899 al = searchURLLabel(Currentbuf, label); 2900 if (al == NULL) { 2901 /* FIXME: gettextize? */ 2902 disp_message(Sprintf("%s is not found", label)->ptr, TRUE); 2903 return; 2904 } 2905 buf = newBuffer(Currentbuf->width); 2906 copyBuffer(buf, Currentbuf); 2907 for (i = 0; i < MAX_LB; i++) 2908 buf->linkBuffer[i] = NULL; 2909 buf->currentURL.label = allocStr(label, -1); 2910 pushHashHist(URLHist, parsedURL2Str(&buf->currentURL)->ptr); 2911 (*buf->clone)++; 2912 pushBuffer(buf); 2913 gotoLine(Currentbuf, al->start.line); 2914 if (label_topline) 2915 Currentbuf->topLine = lineSkip(Currentbuf, Currentbuf->topLine, 2916 Currentbuf->currentLine->linenumber 2917 - Currentbuf->topLine->linenumber, 2918 FALSE); 2919 Currentbuf->pos = al->start.pos; 2920 arrangeCursor(Currentbuf); 2921 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2922 return; 2923 } 2924 2925 static int 2926 handleMailto(char *url) 2927 { 2928 Str to; 2929 char *pos; 2930 2931 if (strncasecmp(url, "mailto:", 7)) 2932 return 0; 2933 #ifdef USE_W3MMAILER 2934 if (! non_null(Mailer) || MailtoOptions == MAILTO_OPTIONS_USE_W3MMAILER) 2935 return 0; 2936 #else 2937 if (!non_null(Mailer)) { 2938 /* FIXME: gettextize? */ 2939 disp_err_message("no mailer is specified", TRUE); 2940 return 1; 2941 } 2942 #endif 2943 2944 /* invoke external mailer */ 2945 if (MailtoOptions == MAILTO_OPTIONS_USE_MAILTO_URL) { 2946 to = Strnew_charp(html_unquote(url)); 2947 } else { 2948 to = Strnew_charp(url + 7); 2949 if ((pos = strchr(to->ptr, '?')) != NULL) 2950 Strtruncate(to, pos - to->ptr); 2951 } 2952 fmTerm(); 2953 system(myExtCommand(Mailer, shell_quote(file_unquote(to->ptr)), 2954 FALSE)->ptr); 2955 fmInit(); 2956 displayBuffer(Currentbuf, B_FORCE_REDRAW); 2957 pushHashHist(URLHist, url); 2958 return 1; 2959 } 2960 2961 /* follow HREF link */ 2962 DEFUN(followA, GOTO_LINK, "Go to current link") 2963 { 2964 Line *l; 2965 Anchor *a; 2966 ParsedURL u; 2967 #ifdef USE_IMAGE 2968 int x = 0, y = 0, map = 0; 2969 #endif 2970 char *url; 2971 2972 if (Currentbuf->firstLine == NULL) 2973 return; 2974 l = Currentbuf->currentLine; 2975 2976 #ifdef USE_IMAGE 2977 a = retrieveCurrentImg(Currentbuf); 2978 if (a && a->image && a->image->map) { 2979 _followForm(FALSE); 2980 return; 2981 } 2982 if (a && a->image && a->image->ismap) { 2983 getMapXY(Currentbuf, a, &x, &y); 2984 map = 1; 2985 } 2986 #else 2987 a = retrieveCurrentMap(Currentbuf); 2988 if (a) { 2989 _followForm(FALSE); 2990 return; 2991 } 2992 #endif 2993 a = retrieveCurrentAnchor(Currentbuf); 2994 if (a == NULL) { 2995 _followForm(FALSE); 2996 return; 2997 } 2998 if (*a->url == '#') { /* index within this buffer */ 2999 gotoLabel(a->url + 1); 3000 return; 3001 } 3002 parseURL2(a->url, &u, baseURL(Currentbuf)); 3003 if (Strcmp(parsedURL2Str(&u), parsedURL2Str(&Currentbuf->currentURL)) == 0) { 3004 /* index within this buffer */ 3005 if (u.label) { 3006 gotoLabel(u.label); 3007 return; 3008 } 3009 } 3010 if (handleMailto(a->url)) 3011 return; 3012 #if 0 3013 else if (!strncasecmp(a->url, "news:", 5) && strchr(a->url, '@') == NULL) { 3014 /* news:newsgroup is not supported */ 3015 /* FIXME: gettextize? */ 3016 disp_err_message("news:newsgroup_name is not supported", TRUE); 3017 return; 3018 } 3019 #endif /* USE_NNTP */ 3020 url = a->url; 3021 #ifdef USE_IMAGE 3022 if (map) 3023 url = Sprintf("%s?%d,%d", a->url, x, y)->ptr; 3024 #endif 3025 3026 if (check_target && open_tab_blank && a->target && 3027 (!strcasecmp(a->target, "_new") || !strcasecmp(a->target, "_blank"))) { 3028 Buffer *buf; 3029 3030 _newT(); 3031 buf = Currentbuf; 3032 loadLink(url, a->target, a->referer, NULL); 3033 if (buf != Currentbuf) 3034 delBuffer(buf); 3035 else 3036 deleteTab(CurrentTab); 3037 displayBuffer(Currentbuf, B_FORCE_REDRAW); 3038 return; 3039 } 3040 loadLink(url, a->target, a->referer, NULL); 3041 displayBuffer(Currentbuf, B_NORMAL); 3042 } 3043 3044 /* follow HREF link in the buffer */ 3045 void 3046 bufferA(void) 3047 { 3048 on_target = FALSE; 3049 followA(); 3050 on_target = TRUE; 3051 } 3052 3053 /* view inline image */ 3054 DEFUN(followI, VIEW_IMAGE, "View image") 3055 { 3056 Line *l; 3057 Anchor *a; 3058 Buffer *buf; 3059 3060 if (Currentbuf->firstLine == NULL) 3061 return; 3062 l = Currentbuf->currentLine; 3063 3064 a = retrieveCurrentImg(Currentbuf); 3065 if (a == NULL) 3066 return; 3067 /* FIXME: gettextize? */ 3068 message(Sprintf("loading %s", a->url)->ptr, 0, 0); 3069 refresh(); 3070 buf = loadGeneralFile(a->url, baseURL(Currentbuf), NULL, 0, NULL); 3071 if (buf == NULL) { 3072 /* FIXME: gettextize? */ 3073 char *emsg = Sprintf("Can't load %s", a->url)->ptr; 3074 disp_err_message(emsg, FALSE); 3075 } 3076 else if (buf != NO_BUFFER) { 3077 pushBuffer(buf); 3078 } 3079 displayBuffer(Currentbuf, B_NORMAL); 3080 } 3081 3082 static FormItemList * 3083 save_submit_formlist(FormItemList *src) 3084 { 3085 FormList *list; 3086 FormList *srclist; 3087 FormItemList *srcitem; 3088 FormItemList *item; 3089 FormItemList *ret = NULL; 3090 #ifdef MENU_SELECT 3091 FormSelectOptionItem *opt; 3092 FormSelectOptionItem *curopt; 3093 FormSelectOptionItem *srcopt; 3094 #endif /* MENU_SELECT */ 3095 3096 if (src == NULL) 3097 return NULL; 3098 srclist = src->parent; 3099 list = New(FormList); 3100 list->method = srclist->method; 3101 list->action = Strdup(srclist->action); 3102 #ifdef USE_M17N 3103 list->charset = srclist->charset; 3104 #endif 3105 list->enctype = srclist->enctype; 3106 list->nitems = srclist->nitems; 3107 list->body = srclist->body; 3108 list->boundary = srclist->boundary; 3109 list->length = srclist->length; 3110 3111 for (srcitem = srclist->item; srcitem; srcitem = srcitem->next) { 3112 item = New(FormItemList); 3113 item->type = srcitem->type; 3114 item->name = Strdup(srcitem->name); 3115 item->value = Strdup(srcitem->value); 3116 item->checked = srcitem->checked; 3117 item->accept = srcitem->accept; 3118 item->size = srcitem->size; 3119 item->rows = srcitem->rows; 3120 item->maxlength = srcitem->maxlength; 3121 item->readonly = srcitem->readonly; 3122 #ifdef MENU_SELECT 3123 opt = curopt = NULL; 3124 for (srcopt = srcitem->select_option; srcopt; srcopt = srcopt->next) { 3125 if (!srcopt->checked) 3126 continue; 3127 opt = New(FormSelectOptionItem); 3128 opt->value = Strdup(srcopt->value); 3129 opt->label = Strdup(srcopt->label); 3130 opt->checked = srcopt->checked; 3131 if (item->select_option == NULL) { 3132 item->select_option = curopt = opt; 3133 } 3134 else { 3135 curopt->next = opt; 3136 curopt = curopt->next; 3137 } 3138 } 3139 item->select_option = opt; 3140 if (srcitem->label) 3141 item->label = Strdup(srcitem->label); 3142 #endif /* MENU_SELECT */ 3143 item->parent = list; 3144 item->next = NULL; 3145 3146 if (list->lastitem == NULL) { 3147 list->item = list->lastitem = item; 3148 } 3149 else { 3150 list->lastitem->next = item; 3151 list->lastitem = item; 3152 } 3153 3154 if (srcitem == src) 3155 ret = item; 3156 } 3157 3158 return ret; 3159 } 3160 3161 #ifdef USE_M17N 3162 static Str 3163 conv_form_encoding(Str val, FormItemList *fi, Buffer *buf) 3164 { 3165 wc_ces charset = SystemCharset; 3166 3167 if (fi->parent->charset) 3168 charset = fi->parent->charset; 3169 else if (buf->document_charset && buf->document_charset != WC_CES_US_ASCII) 3170 charset = buf->document_charset; 3171 return wc_Str_conv_strict(val, InnerCharset, charset); 3172 } 3173 #else 3174 #define conv_form_encoding(val, fi, buf) (val) 3175 #endif 3176 3177 static void 3178 query_from_followform(Str *query, FormItemList *fi, int multipart) 3179 { 3180 FormItemList *f2; 3181 FILE *body = NULL; 3182 3183 if (multipart) { 3184 *query = tmpfname(TMPF_DFL, NULL); 3185 body = fopen((*query)->ptr, "w"); 3186 if (body == NULL) { 3187 return; 3188 } 3189 fi->parent->body = (*query)->ptr; 3190 fi->parent->boundary = 3191 Sprintf("------------------------------%d%ld%ld%ld", CurrentPid, 3192 fi->parent, fi->parent->body, fi->parent->boundary)->ptr; 3193 } 3194 *query = Strnew(); 3195 for (f2 = fi->parent->item; f2; f2 = f2->next) { 3196 if (f2->name == NULL) 3197 continue; 3198 /* <ISINDEX> is translated into single text form */ 3199 if (f2->name->length == 0 && 3200 (multipart || f2->type != FORM_INPUT_TEXT)) 3201 continue; 3202 switch (f2->type) { 3203 case FORM_INPUT_RESET: 3204 /* do nothing */ 3205 continue; 3206 case FORM_INPUT_SUBMIT: 3207 case FORM_INPUT_IMAGE: 3208 if (f2 != fi || f2->value == NULL) 3209 continue; 3210 break; 3211 case FORM_INPUT_RADIO: 3212 case FORM_INPUT_CHECKBOX: 3213 if (!f2->checked) 3214 continue; 3215 } 3216 if (multipart) { 3217 if (f2->type == FORM_INPUT_IMAGE) { 3218 int x = 0, y = 0; 3219 #ifdef USE_IMAGE 3220 getMapXY(Currentbuf, retrieveCurrentImg(Currentbuf), &x, &y); 3221 #endif 3222 *query = Strdup(conv_form_encoding(f2->name, fi, Currentbuf)); 3223 Strcat_charp(*query, ".x"); 3224 form_write_data(body, fi->parent->boundary, (*query)->ptr, 3225 Sprintf("%d", x)->ptr); 3226 *query = Strdup(conv_form_encoding(f2->name, fi, Currentbuf)); 3227 Strcat_charp(*query, ".y"); 3228 form_write_data(body, fi->parent->boundary, (*query)->ptr, 3229 Sprintf("%d", y)->ptr); 3230 } 3231 else if (f2->name && f2->name->length > 0 && f2->value != NULL) { 3232 /* not IMAGE */ 3233 *query = conv_form_encoding(f2->value, fi, Currentbuf); 3234 if (f2->type == FORM_INPUT_FILE) 3235 form_write_from_file(body, fi->parent->boundary, 3236 conv_form_encoding(f2->name, fi, 3237 Currentbuf)->ptr, 3238 (*query)->ptr, 3239 Str_conv_to_system(f2->value)->ptr); 3240 else 3241 form_write_data(body, fi->parent->boundary, 3242 conv_form_encoding(f2->name, fi, 3243 Currentbuf)->ptr, 3244 (*query)->ptr); 3245 } 3246 } 3247 else { 3248 /* not multipart */ 3249 if (f2->type == FORM_INPUT_IMAGE) { 3250 int x = 0, y = 0; 3251 #ifdef USE_IMAGE 3252 getMapXY(Currentbuf, retrieveCurrentImg(Currentbuf), &x, &y); 3253 #endif 3254 Strcat(*query, 3255 Str_form_quote(conv_form_encoding 3256 (f2->name, fi, Currentbuf))); 3257 Strcat(*query, Sprintf(".x=%d&", x)); 3258 Strcat(*query, 3259 Str_form_quote(conv_form_encoding 3260 (f2->name, fi, Currentbuf))); 3261 Strcat(*query, Sprintf(".y=%d", y)); 3262 } 3263 else { 3264 /* not IMAGE */ 3265 if (f2->name && f2->name->length > 0) { 3266 Strcat(*query, 3267 Str_form_quote(conv_form_encoding 3268 (f2->name, fi, Currentbuf))); 3269 Strcat_char(*query, '='); 3270 } 3271 if (f2->value != NULL) { 3272 if (fi->parent->method == FORM_METHOD_INTERNAL) 3273 Strcat(*query, Str_form_quote(f2->value)); 3274 else { 3275 Strcat(*query, 3276 Str_form_quote(conv_form_encoding 3277 (f2->value, fi, Currentbuf))); 3278 } 3279 } 3280 } 3281 if (f2->next) 3282 Strcat_char(*query, '&'); 3283 } 3284 } 3285 if (multipart) { 3286 fprintf(body, "--%s--\r\n", fi->parent->boundary); 3287 fclose(body); 3288 } 3289 else { 3290 /* remove trailing & */ 3291 while (Strlastchar(*query) == '&') 3292 Strshrink(*query, 1); 3293 } 3294 } 3295 3296 /* submit form */ 3297 DEFUN(submitForm, SUBMIT, "Submit form") 3298 { 3299 _followForm(TRUE); 3300 } 3301 3302 /* process form */ 3303 void 3304 followForm(void) 3305 { 3306 _followForm(FALSE); 3307 } 3308 3309 static void 3310 _followForm(int submit) 3311 { 3312 Line *l; 3313 Anchor *a, *a2; 3314 char *p; 3315 FormItemList *fi, *f2; 3316 Str tmp, tmp2; 3317 int multipart = 0, i; 3318 3319 if (Currentbuf->firstLine == NULL) 3320 return; 3321 l = Currentbuf->currentLine; 3322 3323 a = retrieveCurrentForm(Currentbuf); 3324 if (a == NULL) 3325 return; 3326 fi = (FormItemList *)a->url; 3327 switch (fi->type) { 3328 case FORM_INPUT_TEXT: 3329 if (submit) 3330 goto do_submit; 3331 if (fi->readonly) 3332 /* FIXME: gettextize? */ 3333 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); 3334 /* FIXME: gettextize? */ 3335 p = inputStrHist("TEXT:", fi->value ? fi->value->ptr : NULL, TextHist); 3336 if (p == NULL || fi->readonly) 3337 break; 3338 fi->value = Strnew_charp(p); 3339 formUpdateBuffer(a, Currentbuf, fi); 3340 if (fi->accept || fi->parent->nitems == 1) 3341 goto do_submit; 3342 break; 3343 case FORM_INPUT_FILE: 3344 if (submit) 3345 goto do_submit; 3346 if (fi->readonly) 3347 /* FIXME: gettextize? */ 3348 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); 3349 /* FIXME: gettextize? */ 3350 p = inputFilenameHist("Filename:", fi->value ? fi->value->ptr : NULL, 3351 NULL); 3352 if (p == NULL || fi->readonly) 3353 break; 3354 fi->value = Strnew_charp(p); 3355 formUpdateBuffer(a, Currentbuf, fi); 3356 if (fi->accept || fi->parent->nitems == 1) 3357 goto do_submit; 3358 break; 3359 case FORM_INPUT_PASSWORD: 3360 if (submit) 3361 goto do_submit; 3362 if (fi->readonly) { 3363 /* FIXME: gettextize? */ 3364 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); 3365 break; 3366 } 3367 /* FIXME: gettextize? */ 3368 p = inputLine("Password:", fi->value ? fi->value->ptr : NULL, 3369 IN_PASSWORD); 3370 if (p == NULL) 3371 break; 3372 fi->value = Strnew_charp(p); 3373 formUpdateBuffer(a, Currentbuf, fi); 3374 if (fi->accept) 3375 goto do_submit; 3376 break; 3377 case FORM_TEXTAREA: 3378 if (submit) 3379 goto do_submit; 3380 if (fi->readonly) 3381 /* FIXME: gettextize? */ 3382 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); 3383 input_textarea(fi); 3384 formUpdateBuffer(a, Currentbuf, fi); 3385 break; 3386 case FORM_INPUT_RADIO: 3387 if (submit) 3388 goto do_submit; 3389 if (fi->readonly) { 3390 /* FIXME: gettextize? */ 3391 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); 3392 break; 3393 } 3394 formRecheckRadio(a, Currentbuf, fi); 3395 break; 3396 case FORM_INPUT_CHECKBOX: 3397 if (submit) 3398 goto do_submit; 3399 if (fi->readonly) { 3400 /* FIXME: gettextize? */ 3401 disp_message_nsec("Read only field!", FALSE, 1, TRUE, FALSE); 3402 break; 3403 } 3404 fi->checked = !fi->checked; 3405 formUpdateBuffer(a, Currentbuf, fi); 3406 break; 3407 #ifdef MENU_SELECT 3408 case FORM_SELECT: 3409 if (submit) 3410 goto do_submit; 3411 if (!formChooseOptionByMenu(fi, 3412 Currentbuf->cursorX - Currentbuf->pos + 3413 a->start.pos + Currentbuf->rootX, 3414 Currentbuf->cursorY + Currentbuf->rootY)) 3415 break; 3416 formUpdateBuffer(a, Currentbuf, fi); 3417 if (fi->parent->nitems == 1) 3418 goto do_submit; 3419 break; 3420 #endif /* MENU_SELECT */ 3421 case FORM_INPUT_IMAGE: 3422 case FORM_INPUT_SUBMIT: 3423 case FORM_INPUT_BUTTON: 3424 do_submit: 3425 tmp = Strnew(); 3426 tmp2 = Strnew(); 3427 multipart = (fi->parent->method == FORM_METHOD_POST && 3428 fi->parent->enctype == FORM_ENCTYPE_MULTIPART); 3429 query_from_followform(&tmp, fi, multipart); 3430 3431 tmp2 = Strdup(fi->parent->action); 3432 if (!Strcmp_charp(tmp2, "!CURRENT_URL!")) { 3433 /* It means "current URL" */ 3434 tmp2 = parsedURL2Str(&Currentbuf->currentURL); 3435 if ((p = strchr(tmp2->ptr, '?')) != NULL) 3436 Strshrink(tmp2, (tmp2->ptr + tmp2->length) - p); 3437 } 3438 3439 if (fi->parent->method == FORM_METHOD_GET) { 3440 if ((p = strchr(tmp2->ptr, '?')) != NULL) 3441 Strshrink(tmp2, (tmp2->ptr + tmp2->length) - p); 3442 Strcat_charp(tmp2, "?"); 3443 Strcat(tmp2, tmp); 3444 loadLink(tmp2->ptr, a->target, NULL, NULL); 3445 } 3446 else if (fi->parent->method == FORM_METHOD_POST) { 3447 Buffer *buf; 3448 if (multipart) { 3449 struct stat st; 3450 stat(fi->parent->body, &st); 3451 fi->parent->length = st.st_size; 3452 } 3453 else { 3454 fi->parent->body = tmp->ptr; 3455 fi->parent->length = tmp->length; 3456 } 3457 buf = loadLink(tmp2->ptr, a->target, NULL, fi->parent); 3458 if (multipart) { 3459 unlink(fi->parent->body); 3460 } 3461 if (buf && !(buf->bufferprop & BP_REDIRECTED)) { /* buf must be Currentbuf */ 3462 /* BP_REDIRECTED means that the buffer is obtained through 3463 * Location: header. In this case, buf->form_submit must not be set 3464 * because the page is not loaded by POST method but GET method. 3465 */ 3466 buf->form_submit = save_submit_formlist(fi); 3467 } 3468 } 3469 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 */ 3470 do_internal(tmp2->ptr, tmp->ptr); 3471 } 3472 else { 3473 disp_err_message("Can't send form because of illegal method.", 3474 FALSE); 3475 } 3476 break; 3477 case FORM_INPUT_RESET: 3478 for (i = 0; i < Currentbuf->formitem->nanchor; i++) { 3479 a2 = &Currentbuf->formitem->anchors[i]; 3480 f2 = (FormItemList *)a2->url; 3481 if (f2->parent == fi->parent && 3482 f2->name && f2->value && 3483 f2->type != FORM_INPUT_SUBMIT && 3484 f2->type != FORM_INPUT_HIDDEN && 3485 f2->type != FORM_INPUT_RESET) { 3486 f2->value = f2->init_value; 3487 f2->checked = f2->init_checked; 3488 #ifdef MENU_SELECT 3489 f2->label = f2->init_label; 3490 f2->selected = f2->init_selected; 3491 #endif /* MENU_SELECT */ 3492 formUpdateBuffer(a2, Currentbuf, f2); 3493 } 3494 } 3495 break; 3496 case FORM_INPUT_HIDDEN: 3497 default: 3498 break; 3499 } 3500 displayBuffer(Currentbuf, B_FORCE_REDRAW); 3501 } 3502 3503 /* go to the top anchor */ 3504 DEFUN(topA, LINK_BEGIN, "Go to the first link") 3505 { 3506 HmarkerList *hl = Currentbuf->hmarklist; 3507 BufferPoint *po; 3508 Anchor *an; 3509 int hseq = 0; 3510 3511 if (Currentbuf->firstLine == NULL) 3512 return; 3513 if (!hl || hl->nmark == 0) 3514 return; 3515 3516 if (prec_num > hl->nmark) 3517 hseq = hl->nmark - 1; 3518 else if (prec_num > 0) 3519 hseq = prec_num - 1; 3520 do { 3521 if (hseq >= hl->nmark) 3522 return; 3523 po = hl->marks + hseq; 3524 an = retrieveAnchor(Currentbuf->href, po->line, po->pos); 3525 if (an == NULL) 3526 an = retrieveAnchor(Currentbuf->formitem, po->line, po->pos); 3527 hseq++; 3528 } while (an == NULL); 3529 3530 gotoLine(Currentbuf, po->line); 3531 Currentbuf->pos = po->pos; 3532 arrangeCursor(Currentbuf); 3533 displayBuffer(Currentbuf, B_NORMAL); 3534 } 3535 3536 /* go to the last anchor */ 3537 DEFUN(lastA, LINK_END, "Go to the last link") 3538 { 3539 HmarkerList *hl = Currentbuf->hmarklist; 3540 BufferPoint *po; 3541 Anchor *an; 3542 int hseq; 3543 3544 if (Currentbuf->firstLine == NULL) 3545 return; 3546 if (!hl || hl->nmark == 0) 3547 return; 3548 3549 if (prec_num >= hl->nmark) 3550 hseq = 0; 3551 else if (prec_num > 0) 3552 hseq = hl->nmark - prec_num; 3553 else 3554 hseq = hl->nmark - 1; 3555 do { 3556 if (hseq < 0) 3557 return; 3558 po = hl->marks + hseq; 3559 an = retrieveAnchor(Currentbuf->href, po->line, po->pos); 3560 if (an == NULL) 3561 an = retrieveAnchor(Currentbuf->formitem, po->line, po->pos); 3562 hseq--; 3563 } while (an == NULL); 3564 3565 gotoLine(Currentbuf, po->line); 3566 Currentbuf->pos = po->pos; 3567 arrangeCursor(Currentbuf); 3568 displayBuffer(Currentbuf, B_NORMAL); 3569 } 3570 3571 /* go to the next anchor */ 3572 DEFUN(nextA, NEXT_LINK, "Move to next link") 3573 { 3574 _nextA(FALSE); 3575 } 3576 3577 /* go to the previous anchor */ 3578 DEFUN(prevA, PREV_LINK, "Move to previous link") 3579 { 3580 _prevA(FALSE); 3581 } 3582 3583 /* go to the next visited anchor */ 3584 DEFUN(nextVA, NEXT_VISITED, "Move to next visited link") 3585 { 3586 _nextA(TRUE); 3587 } 3588 3589 /* go to the previous visited anchor */ 3590 DEFUN(prevVA, PREV_VISITED, "Move to previous visited link") 3591 { 3592 _prevA(TRUE); 3593 } 3594 3595 /* go to the next [visited] anchor */ 3596 static void 3597 _nextA(int visited) 3598 { 3599 HmarkerList *hl = Currentbuf->hmarklist; 3600 BufferPoint *po; 3601 Anchor *an, *pan; 3602 int i, x, y, n = searchKeyNum(); 3603 ParsedURL url; 3604 3605 if (Currentbuf->firstLine == NULL) 3606 return; 3607 if (!hl || hl->nmark == 0) 3608 return; 3609 3610 an = retrieveCurrentAnchor(Currentbuf); 3611 if (visited != TRUE && an == NULL) 3612 an = retrieveCurrentForm(Currentbuf); 3613 3614 y = Currentbuf->currentLine->linenumber; 3615 x = Currentbuf->pos; 3616 3617 if (visited == TRUE) { 3618 n = hl->nmark; 3619 } 3620 3621 for (i = 0; i < n; i++) { 3622 pan = an; 3623 if (an && an->hseq >= 0) { 3624 int hseq = an->hseq + 1; 3625 do { 3626 if (hseq >= hl->nmark) { 3627 if (visited == TRUE) 3628 return; 3629 an = pan; 3630 goto _end; 3631 } 3632 po = &hl->marks[hseq]; 3633 an = retrieveAnchor(Currentbuf->href, po->line, po->pos); 3634 if (visited != TRUE && an == NULL) 3635 an = retrieveAnchor(Currentbuf->formitem, po->line, 3636 po->pos); 3637 hseq++; 3638 if (visited == TRUE && an) { 3639 parseURL2(an->url, &url, baseURL(Currentbuf)); 3640 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) { 3641 goto _end; 3642 } 3643 } 3644 } while (an == NULL || an == pan); 3645 } 3646 else { 3647 an = closest_next_anchor(Currentbuf->href, NULL, x, y); 3648 if (visited != TRUE) 3649 an = closest_next_anchor(Currentbuf->formitem, an, x, y); 3650 if (an == NULL) { 3651 if (visited == TRUE) 3652 return; 3653 an = pan; 3654 break; 3655 } 3656 x = an->start.pos; 3657 y = an->start.line; 3658 if (visited == TRUE) { 3659 parseURL2(an->url, &url, baseURL(Currentbuf)); 3660 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) { 3661 goto _end; 3662 } 3663 } 3664 } 3665 } 3666 if (visited == TRUE) 3667 return; 3668 3669 _end: 3670 if (an == NULL || an->hseq < 0) 3671 return; 3672 po = &hl->marks[an->hseq]; 3673 gotoLine(Currentbuf, po->line); 3674 Currentbuf->pos = po->pos; 3675 arrangeCursor(Currentbuf); 3676 displayBuffer(Currentbuf, B_NORMAL); 3677 } 3678 3679 /* go to the previous anchor */ 3680 static void 3681 _prevA(int visited) 3682 { 3683 HmarkerList *hl = Currentbuf->hmarklist; 3684 BufferPoint *po; 3685 Anchor *an, *pan; 3686 int i, x, y, n = searchKeyNum(); 3687 ParsedURL url; 3688 3689 if (Currentbuf->firstLine == NULL) 3690 return; 3691 if (!hl || hl->nmark == 0) 3692 return; 3693 3694 an = retrieveCurrentAnchor(Currentbuf); 3695 if (visited != TRUE && an == NULL) 3696 an = retrieveCurrentForm(Currentbuf); 3697 3698 y = Currentbuf->currentLine->linenumber; 3699 x = Currentbuf->pos; 3700 3701 if (visited == TRUE) { 3702 n = hl->nmark; 3703 } 3704 3705 for (i = 0; i < n; i++) { 3706 pan = an; 3707 if (an && an->hseq >= 0) { 3708 int hseq = an->hseq - 1; 3709 do { 3710 if (hseq < 0) { 3711 if (visited == TRUE) 3712 return; 3713 an = pan; 3714 goto _end; 3715 } 3716 po = hl->marks + hseq; 3717 an = retrieveAnchor(Currentbuf->href, po->line, po->pos); 3718 if (visited != TRUE && an == NULL) 3719 an = retrieveAnchor(Currentbuf->formitem, po->line, 3720 po->pos); 3721 hseq--; 3722 if (visited == TRUE && an) { 3723 parseURL2(an->url, &url, baseURL(Currentbuf)); 3724 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) { 3725 goto _end; 3726 } 3727 } 3728 } while (an == NULL || an == pan); 3729 } 3730 else { 3731 an = closest_prev_anchor(Currentbuf->href, NULL, x, y); 3732 if (visited != TRUE) 3733 an = closest_prev_anchor(Currentbuf->formitem, an, x, y); 3734 if (an == NULL) { 3735 if (visited == TRUE) 3736 return; 3737 an = pan; 3738 break; 3739 } 3740 x = an->start.pos; 3741 y = an->start.line; 3742 if (visited == TRUE && an) { 3743 parseURL2(an->url, &url, baseURL(Currentbuf)); 3744 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) { 3745 goto _end; 3746 } 3747 } 3748 } 3749 } 3750 if (visited == TRUE) 3751 return; 3752 3753 _end: 3754 if (an == NULL || an->hseq < 0) 3755 return; 3756 po = hl->marks + an->hseq; 3757 gotoLine(Currentbuf, po->line); 3758 Currentbuf->pos = po->pos; 3759 arrangeCursor(Currentbuf); 3760 displayBuffer(Currentbuf, B_NORMAL); 3761 } 3762 3763 /* go to the next left/right anchor */ 3764 static void 3765 nextX(int d, int dy) 3766 { 3767 HmarkerList *hl = Currentbuf->hmarklist; 3768 Anchor *an, *pan; 3769 Line *l; 3770 int i, x, y, n = searchKeyNum(); 3771 3772 if (Currentbuf->firstLine == NULL) 3773 return; 3774 if (!hl || hl->nmark == 0) 3775 return; 3776 3777 an = retrieveCurrentAnchor(Currentbuf); 3778 if (an == NULL) 3779 an = retrieveCurrentForm(Currentbuf); 3780 3781 l = Currentbuf->currentLine; 3782 x = Currentbuf->pos; 3783 y = l->linenumber; 3784 pan = NULL; 3785 for (i = 0; i < n; i++) { 3786 if (an) 3787 x = (d > 0) ? an->end.pos : an->start.pos - 1; 3788 an = NULL; 3789 while (1) { 3790 for (; x >= 0 && x < l->len; x += d) { 3791 an = retrieveAnchor(Currentbuf->href, y, x); 3792 if (!an) 3793 an = retrieveAnchor(Currentbuf->formitem, y, x); 3794 if (an) { 3795 pan = an; 3796 break; 3797 } 3798 } 3799 if (!dy || an) 3800 break; 3801 l = (dy > 0) ? l->next : l->prev; 3802 if (!l) 3803 break; 3804 x = (d > 0) ? 0 : l->len - 1; 3805 y = l->linenumber; 3806 } 3807 if (!an) 3808 break; 3809 } 3810 3811 if (pan == NULL) 3812 return; 3813 gotoLine(Currentbuf, y); 3814 Currentbuf->pos = pan->start.pos; 3815 arrangeCursor(Currentbuf); 3816 displayBuffer(Currentbuf, B_NORMAL); 3817 } 3818 3819 /* go to the next downward/upward anchor */ 3820 static void 3821 nextY(int d) 3822 { 3823 HmarkerList *hl = Currentbuf->hmarklist; 3824 Anchor *an, *pan; 3825 int i, x, y, n = searchKeyNum(); 3826 int hseq; 3827 3828 if (Currentbuf->firstLine == NULL) 3829 return; 3830 if (!hl || hl->nmark == 0) 3831 return; 3832 3833 an = retrieveCurrentAnchor(Currentbuf); 3834 if (an == NULL) 3835 an = retrieveCurrentForm(Currentbuf); 3836 3837 x = Currentbuf->pos; 3838 y = Currentbuf->currentLine->linenumber + d; 3839 pan = NULL; 3840 hseq = -1; 3841 for (i = 0; i < n; i++) { 3842 if (an) 3843 hseq = abs(an->hseq); 3844 an = NULL; 3845 for (; y >= 0 && y <= Currentbuf->lastLine->linenumber; y += d) { 3846 an = retrieveAnchor(Currentbuf->href, y, x); 3847 if (!an) 3848 an = retrieveAnchor(Currentbuf->formitem, y, x); 3849 if (an && hseq != abs(an->hseq)) { 3850 pan = an; 3851 break; 3852 } 3853 } 3854 if (!an) 3855 break; 3856 } 3857 3858 if (pan == NULL) 3859 return; 3860 gotoLine(Currentbuf, pan->start.line); 3861 arrangeLine(Currentbuf); 3862 displayBuffer(Currentbuf, B_NORMAL); 3863 } 3864 3865 /* go to the next left anchor */ 3866 DEFUN(nextL, NEXT_LEFT, "Move to next left link") 3867 { 3868 nextX(-1, 0); 3869 } 3870 3871 /* go to the next left-up anchor */ 3872 DEFUN(nextLU, NEXT_LEFT_UP, "Move to next left (or upward) link") 3873 { 3874 nextX(-1, -1); 3875 } 3876 3877 /* go to the next right anchor */ 3878 DEFUN(nextR, NEXT_RIGHT, "Move to next right link") 3879 { 3880 nextX(1, 0); 3881 } 3882 3883 /* go to the next right-down anchor */ 3884 DEFUN(nextRD, NEXT_RIGHT_DOWN, "Move to next right (or downward) link") 3885 { 3886 nextX(1, 1); 3887 } 3888 3889 /* go to the next downward anchor */ 3890 DEFUN(nextD, NEXT_DOWN, "Move to next downward link") 3891 { 3892 nextY(1); 3893 } 3894 3895 /* go to the next upward anchor */ 3896 DEFUN(nextU, NEXT_UP, "Move to next upward link") 3897 { 3898 nextY(-1); 3899 } 3900 3901 /* go to the next bufferr */ 3902 DEFUN(nextBf, NEXT, "Move to next buffer") 3903 { 3904 Buffer *buf; 3905 int i; 3906 3907 for (i = 0; i < PREC_NUM; i++) { 3908 buf = prevBuffer(Firstbuf, Currentbuf); 3909 if (!buf) { 3910 if (i == 0) 3911 return; 3912 break; 3913 } 3914 Currentbuf = buf; 3915 } 3916 displayBuffer(Currentbuf, B_FORCE_REDRAW); 3917 } 3918 3919 /* go to the previous bufferr */ 3920 DEFUN(prevBf, PREV, "Move to previous buffer") 3921 { 3922 Buffer *buf; 3923 int i; 3924 3925 for (i = 0; i < PREC_NUM; i++) { 3926 buf = Currentbuf->nextBuffer; 3927 if (!buf) { 3928 if (i == 0) 3929 return; 3930 break; 3931 } 3932 Currentbuf = buf; 3933 } 3934 displayBuffer(Currentbuf, B_FORCE_REDRAW); 3935 } 3936 3937 static int 3938 checkBackBuffer(Buffer *buf) 3939 { 3940 Buffer *fbuf = buf->linkBuffer[LB_N_FRAME]; 3941 3942 if (fbuf) { 3943 if (fbuf->frameQ) 3944 return TRUE; /* Currentbuf has stacked frames */ 3945 /* when no frames stacked and next is frame source, try next's 3946 * nextBuffer */ 3947 if (RenderFrame && fbuf == buf->nextBuffer) { 3948 if (fbuf->nextBuffer != NULL) 3949 return TRUE; 3950 else 3951 return FALSE; 3952 } 3953 } 3954 3955 if (buf->nextBuffer) 3956 return TRUE; 3957 3958 return FALSE; 3959 } 3960 3961 /* delete current buffer and back to the previous buffer */ 3962 DEFUN(backBf, BACK, "Back to previous buffer") 3963 { 3964 Buffer *buf = Currentbuf->linkBuffer[LB_N_FRAME]; 3965 3966 if (!checkBackBuffer(Currentbuf)) { 3967 if (close_tab_back && nTab >= 1) { 3968 deleteTab(CurrentTab); 3969 displayBuffer(Currentbuf, B_FORCE_REDRAW); 3970 } 3971 else 3972 /* FIXME: gettextize? */ 3973 disp_message("Can't back...", TRUE); 3974 return; 3975 } 3976 3977 delBuffer(Currentbuf); 3978 3979 if (buf) { 3980 if (buf->frameQ) { 3981 struct frameset *fs; 3982 long linenumber = buf->frameQ->linenumber; 3983 long top = buf->frameQ->top_linenumber; 3984 int pos = buf->frameQ->pos; 3985 int currentColumn = buf->frameQ->currentColumn; 3986 AnchorList *formitem = buf->frameQ->formitem; 3987 3988 fs = popFrameTree(&(buf->frameQ)); 3989 deleteFrameSet(buf->frameset); 3990 buf->frameset = fs; 3991 3992 if (buf == Currentbuf) { 3993 rFrame(); 3994 Currentbuf->topLine = lineSkip(Currentbuf, 3995 Currentbuf->firstLine, top - 1, 3996 FALSE); 3997 gotoLine(Currentbuf, linenumber); 3998 Currentbuf->pos = pos; 3999 Currentbuf->currentColumn = currentColumn; 4000 arrangeCursor(Currentbuf); 4001 formResetBuffer(Currentbuf, formitem); 4002 } 4003 } 4004 else if (RenderFrame && buf == Currentbuf) { 4005 delBuffer(Currentbuf); 4006 } 4007 } 4008 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4009 } 4010 4011 DEFUN(deletePrevBuf, DELETE_PREVBUF, 4012 "Delete previous buffer (mainly for local-CGI)") 4013 { 4014 Buffer *buf = Currentbuf->nextBuffer; 4015 if (buf) 4016 delBuffer(buf); 4017 } 4018 4019 static void 4020 cmd_loadURL(char *url, ParsedURL *current, char *referer, FormList *request) 4021 { 4022 Buffer *buf; 4023 4024 if (handleMailto(url)) 4025 return; 4026 #if 0 4027 if (!strncasecmp(url, "news:", 5) && strchr(url, '@') == NULL) { 4028 /* news:newsgroup is not supported */ 4029 /* FIXME: gettextize? */ 4030 disp_err_message("news:newsgroup_name is not supported", TRUE); 4031 return; 4032 } 4033 #endif /* USE_NNTP */ 4034 4035 refresh(); 4036 buf = loadGeneralFile(url, current, referer, 0, request); 4037 if (buf == NULL) { 4038 /* FIXME: gettextize? */ 4039 char *emsg = Sprintf("Can't load %s", conv_from_system(url))->ptr; 4040 disp_err_message(emsg, FALSE); 4041 } 4042 else if (buf != NO_BUFFER) { 4043 pushBuffer(buf); 4044 if (RenderFrame && Currentbuf->frameset != NULL) 4045 rFrame(); 4046 } 4047 displayBuffer(Currentbuf, B_NORMAL); 4048 } 4049 4050 4051 /* go to specified URL */ 4052 static void 4053 goURL0(char *prompt, int relative) 4054 { 4055 char *url, *referer; 4056 ParsedURL p_url, *current; 4057 Buffer *cur_buf = Currentbuf; 4058 4059 url = searchKeyData(); 4060 if (url == NULL) { 4061 Hist *hist = copyHist(URLHist); 4062 Anchor *a; 4063 4064 current = baseURL(Currentbuf); 4065 if (current) { 4066 char *c_url = parsedURL2Str(current)->ptr; 4067 if (DefaultURLString == DEFAULT_URL_CURRENT) { 4068 url = c_url; 4069 if (DecodeURL) 4070 url = url_unquote_conv(url, 0); 4071 } 4072 else 4073 pushHist(hist, c_url); 4074 } 4075 a = retrieveCurrentAnchor(Currentbuf); 4076 if (a) { 4077 char *a_url; 4078 parseURL2(a->url, &p_url, current); 4079 a_url = parsedURL2Str(&p_url)->ptr; 4080 if (DefaultURLString == DEFAULT_URL_LINK) { 4081 url = a_url; 4082 if (DecodeURL) 4083 url = url_unquote_conv(url, Currentbuf->document_charset); 4084 } 4085 else 4086 pushHist(hist, a_url); 4087 } 4088 url = inputLineHist(prompt, url, IN_URL, hist); 4089 if (url != NULL) 4090 SKIP_BLANKS(url); 4091 } 4092 #ifdef USE_M17N 4093 if (url != NULL) { 4094 if ((relative || *url == '#') && Currentbuf->document_charset) 4095 url = wc_conv_strict(url, InnerCharset, 4096 Currentbuf->document_charset)->ptr; 4097 else 4098 url = conv_to_system(url); 4099 } 4100 #endif 4101 if (url == NULL || *url == '\0') { 4102 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4103 return; 4104 } 4105 if (*url == '#') { 4106 gotoLabel(url + 1); 4107 return; 4108 } 4109 if (relative) { 4110 current = baseURL(Currentbuf); 4111 referer = parsedURL2Str(&Currentbuf->currentURL)->ptr; 4112 } 4113 else { 4114 current = NULL; 4115 referer = NULL; 4116 } 4117 parseURL2(url, &p_url, current); 4118 pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr); 4119 cmd_loadURL(url, current, referer, NULL); 4120 if (Currentbuf != cur_buf) /* success */ 4121 pushHashHist(URLHist, parsedURL2Str(&Currentbuf->currentURL)->ptr); 4122 } 4123 4124 DEFUN(goURL, GOTO, "Go to URL") 4125 { 4126 goURL0("Goto URL: ", FALSE); 4127 } 4128 4129 DEFUN(gorURL, GOTO_RELATIVE, "Go to relative URL") 4130 { 4131 goURL0("Goto relative URL: ", TRUE); 4132 } 4133 4134 static void 4135 cmd_loadBuffer(Buffer *buf, int prop, int linkid) 4136 { 4137 if (buf == NULL) { 4138 disp_err_message("Can't load string", FALSE); 4139 } 4140 else if (buf != NO_BUFFER) { 4141 buf->bufferprop |= (BP_INTERNAL | prop); 4142 if (!(buf->bufferprop & BP_NO_URL)) 4143 copyParsedURL(&buf->currentURL, &Currentbuf->currentURL); 4144 if (linkid != LB_NOLINK) { 4145 buf->linkBuffer[REV_LB[linkid]] = Currentbuf; 4146 Currentbuf->linkBuffer[linkid] = buf; 4147 } 4148 pushBuffer(buf); 4149 } 4150 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4151 } 4152 4153 /* load bookmark */ 4154 DEFUN(ldBmark, BOOKMARK VIEW_BOOKMARK, "Read bookmark") 4155 { 4156 cmd_loadURL(BookmarkFile, NULL, NO_REFERER, NULL); 4157 } 4158 4159 4160 /* Add current to bookmark */ 4161 DEFUN(adBmark, ADD_BOOKMARK, "Add current page to bookmark") 4162 { 4163 Str tmp; 4164 FormList *request; 4165 4166 tmp = Sprintf("mode=panel&cookie=%s&bmark=%s&url=%s&title=%s" 4167 #ifdef USE_M17N 4168 "&charset=%s" 4169 #endif 4170 , 4171 (Str_form_quote(localCookie()))->ptr, 4172 (Str_form_quote(Strnew_charp(BookmarkFile)))->ptr, 4173 (Str_form_quote(parsedURL2Str(&Currentbuf->currentURL)))-> 4174 ptr, 4175 #ifdef USE_M17N 4176 (Str_form_quote(wc_conv_strict(Currentbuf->buffername, 4177 InnerCharset, 4178 BookmarkCharset)))->ptr, 4179 wc_ces_to_charset(BookmarkCharset)); 4180 #else 4181 (Str_form_quote(Strnew_charp(Currentbuf->buffername)))->ptr); 4182 #endif 4183 request = newFormList(NULL, "post", NULL, NULL, NULL, NULL, NULL); 4184 request->body = tmp->ptr; 4185 request->length = tmp->length; 4186 cmd_loadURL("file:///$LIB/" W3MBOOKMARK_CMDNAME, NULL, NO_REFERER, 4187 request); 4188 } 4189 4190 /* option setting */ 4191 DEFUN(ldOpt, OPTIONS, "Option setting panel") 4192 { 4193 cmd_loadBuffer(load_option_panel(), BP_NO_URL, LB_NOLINK); 4194 } 4195 4196 /* set an option */ 4197 DEFUN(setOpt, SET_OPTION, "Set option") 4198 { 4199 char *opt; 4200 4201 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 4202 opt = searchKeyData(); 4203 if (opt == NULL || *opt == '\0' || strchr(opt, '=') == NULL) { 4204 if (opt != NULL && *opt != '\0') { 4205 char *v = get_param_option(opt); 4206 opt = Sprintf("%s=%s", opt, v ? v : "")->ptr; 4207 } 4208 opt = inputStrHist("Set option: ", opt, TextHist); 4209 if (opt == NULL || *opt == '\0') { 4210 displayBuffer(Currentbuf, B_NORMAL); 4211 return; 4212 } 4213 } 4214 if (set_param_option(opt)) 4215 sync_with_option(); 4216 displayBuffer(Currentbuf, B_REDRAW_IMAGE); 4217 } 4218 4219 /* error message list */ 4220 DEFUN(msgs, MSGS, "Display error messages") 4221 { 4222 cmd_loadBuffer(message_list_panel(), BP_NO_URL, LB_NOLINK); 4223 } 4224 4225 /* page info */ 4226 DEFUN(pginfo, INFO, "View info of current document") 4227 { 4228 Buffer *buf; 4229 4230 if ((buf = Currentbuf->linkBuffer[LB_N_INFO]) != NULL) { 4231 Currentbuf = buf; 4232 displayBuffer(Currentbuf, B_NORMAL); 4233 return; 4234 } 4235 if ((buf = Currentbuf->linkBuffer[LB_INFO]) != NULL) 4236 delBuffer(buf); 4237 buf = page_info_panel(Currentbuf); 4238 cmd_loadBuffer(buf, BP_NORMAL, LB_INFO); 4239 } 4240 4241 void 4242 follow_map(struct parsed_tagarg *arg) 4243 { 4244 char *name = tag_get_value(arg, "link"); 4245 #if defined(MENU_MAP) || defined(USE_IMAGE) 4246 Anchor *an; 4247 MapArea *a; 4248 int x, y; 4249 ParsedURL p_url; 4250 4251 an = retrieveCurrentImg(Currentbuf); 4252 x = Currentbuf->cursorX + Currentbuf->rootX; 4253 y = Currentbuf->cursorY + Currentbuf->rootY; 4254 a = follow_map_menu(Currentbuf, name, an, x, y); 4255 if (a == NULL || a->url == NULL || *(a->url) == '\0') { 4256 #endif 4257 #ifndef MENU_MAP 4258 Buffer *buf = follow_map_panel(Currentbuf, name); 4259 4260 if (buf != NULL) 4261 cmd_loadBuffer(buf, BP_NORMAL, LB_NOLINK); 4262 #endif 4263 #if defined(MENU_MAP) || defined(USE_IMAGE) 4264 return; 4265 } 4266 if (*(a->url) == '#') { 4267 gotoLabel(a->url + 1); 4268 return; 4269 } 4270 parseURL2(a->url, &p_url, baseURL(Currentbuf)); 4271 pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr); 4272 if (check_target && open_tab_blank && a->target && 4273 (!strcasecmp(a->target, "_new") || !strcasecmp(a->target, "_blank"))) { 4274 Buffer *buf; 4275 4276 _newT(); 4277 buf = Currentbuf; 4278 cmd_loadURL(a->url, baseURL(Currentbuf), 4279 parsedURL2Str(&Currentbuf->currentURL)->ptr, NULL); 4280 if (buf != Currentbuf) 4281 delBuffer(buf); 4282 else 4283 deleteTab(CurrentTab); 4284 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4285 return; 4286 } 4287 cmd_loadURL(a->url, baseURL(Currentbuf), 4288 parsedURL2Str(&Currentbuf->currentURL)->ptr, NULL); 4289 #endif 4290 } 4291 4292 #ifdef USE_MENU 4293 /* link menu */ 4294 DEFUN(linkMn, LINK_MENU, "Popup link element menu") 4295 { 4296 LinkList *l = link_menu(Currentbuf); 4297 ParsedURL p_url; 4298 4299 if (!l || !l->url) 4300 return; 4301 if (*(l->url) == '#') { 4302 gotoLabel(l->url + 1); 4303 return; 4304 } 4305 parseURL2(l->url, &p_url, baseURL(Currentbuf)); 4306 pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr); 4307 cmd_loadURL(l->url, baseURL(Currentbuf), 4308 parsedURL2Str(&Currentbuf->currentURL)->ptr, NULL); 4309 } 4310 4311 static void 4312 anchorMn(Anchor *(*menu_func) (Buffer *), int go) 4313 { 4314 Anchor *a; 4315 BufferPoint *po; 4316 4317 if (!Currentbuf->href || !Currentbuf->hmarklist) 4318 return; 4319 a = menu_func(Currentbuf); 4320 if (!a || a->hseq < 0) 4321 return; 4322 po = &Currentbuf->hmarklist->marks[a->hseq]; 4323 gotoLine(Currentbuf, po->line); 4324 Currentbuf->pos = po->pos; 4325 arrangeCursor(Currentbuf); 4326 displayBuffer(Currentbuf, B_NORMAL); 4327 if (go) 4328 followA(); 4329 } 4330 4331 /* accesskey */ 4332 DEFUN(accessKey, ACCESSKEY, "Popup acceskey menu") 4333 { 4334 anchorMn(accesskey_menu, TRUE); 4335 } 4336 4337 /* list menu */ 4338 DEFUN(listMn, LIST_MENU, "Popup link list menu and go to selected link") 4339 { 4340 anchorMn(list_menu, TRUE); 4341 } 4342 4343 DEFUN(movlistMn, MOVE_LIST_MENU, 4344 "Popup link list menu and move cursor to selected link") 4345 { 4346 anchorMn(list_menu, FALSE); 4347 } 4348 #endif 4349 4350 /* link,anchor,image list */ 4351 DEFUN(linkLst, LIST, "Show all links and images") 4352 { 4353 Buffer *buf; 4354 4355 buf = link_list_panel(Currentbuf); 4356 if (buf != NULL) { 4357 #ifdef USE_M17N 4358 buf->document_charset = Currentbuf->document_charset; 4359 #endif 4360 cmd_loadBuffer(buf, BP_NORMAL, LB_NOLINK); 4361 } 4362 } 4363 4364 #ifdef USE_COOKIE 4365 /* cookie list */ 4366 DEFUN(cooLst, COOKIE, "View cookie list") 4367 { 4368 Buffer *buf; 4369 4370 buf = cookie_list_panel(); 4371 if (buf != NULL) 4372 cmd_loadBuffer(buf, BP_NO_URL, LB_NOLINK); 4373 } 4374 #endif /* USE_COOKIE */ 4375 4376 #ifdef USE_HISTORY 4377 /* History page */ 4378 DEFUN(ldHist, HISTORY, "View history of URL") 4379 { 4380 cmd_loadBuffer(historyBuffer(URLHist), BP_NO_URL, LB_NOLINK); 4381 } 4382 #endif /* USE_HISTORY */ 4383 4384 /* download HREF link */ 4385 DEFUN(svA, SAVE_LINK, "Save link to file") 4386 { 4387 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 4388 do_download = TRUE; 4389 followA(); 4390 do_download = FALSE; 4391 } 4392 4393 /* download IMG link */ 4394 DEFUN(svI, SAVE_IMAGE, "Save image to file") 4395 { 4396 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 4397 do_download = TRUE; 4398 followI(); 4399 do_download = FALSE; 4400 } 4401 4402 /* save buffer */ 4403 DEFUN(svBuf, PRINT SAVE_SCREEN, "Save rendered document to file") 4404 { 4405 char *qfile = NULL, *file; 4406 FILE *f; 4407 int is_pipe; 4408 4409 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 4410 file = searchKeyData(); 4411 if (file == NULL || *file == '\0') { 4412 /* FIXME: gettextize? */ 4413 qfile = inputLineHist("Save buffer to: ", NULL, IN_COMMAND, SaveHist); 4414 if (qfile == NULL || *qfile == '\0') { 4415 displayBuffer(Currentbuf, B_NORMAL); 4416 return; 4417 } 4418 } 4419 file = conv_to_system(qfile ? qfile : file); 4420 if (*file == '|') { 4421 is_pipe = TRUE; 4422 f = popen(file + 1, "w"); 4423 } 4424 else { 4425 if (qfile) { 4426 file = unescape_spaces(Strnew_charp(qfile))->ptr; 4427 file = conv_to_system(file); 4428 } 4429 file = expandPath(file); 4430 if (checkOverWrite(file) < 0) { 4431 displayBuffer(Currentbuf, B_NORMAL); 4432 return; 4433 } 4434 f = fopen(file, "w"); 4435 is_pipe = FALSE; 4436 } 4437 if (f == NULL) { 4438 /* FIXME: gettextize? */ 4439 char *emsg = Sprintf("Can't open %s", conv_from_system(file))->ptr; 4440 disp_err_message(emsg, TRUE); 4441 return; 4442 } 4443 saveBuffer(Currentbuf, f, TRUE); 4444 if (is_pipe) 4445 pclose(f); 4446 else 4447 fclose(f); 4448 displayBuffer(Currentbuf, B_NORMAL); 4449 } 4450 4451 /* save source */ 4452 DEFUN(svSrc, DOWNLOAD SAVE, "Save document source to file") 4453 { 4454 char *file; 4455 4456 if (Currentbuf->sourcefile == NULL) 4457 return; 4458 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 4459 PermitSaveToPipe = TRUE; 4460 if (Currentbuf->real_scheme == SCM_LOCAL) 4461 file = conv_from_system(guess_save_name(NULL, 4462 Currentbuf->currentURL. 4463 real_file)); 4464 else 4465 file = guess_save_name(Currentbuf, Currentbuf->currentURL.file); 4466 doFileCopy(Currentbuf->sourcefile, file); 4467 PermitSaveToPipe = FALSE; 4468 displayBuffer(Currentbuf, B_NORMAL); 4469 } 4470 4471 static void 4472 _peekURL(int only_img) 4473 { 4474 4475 Anchor *a; 4476 ParsedURL pu; 4477 static Str s = NULL; 4478 #ifdef USE_M17N 4479 static Lineprop *p = NULL; 4480 Lineprop *pp; 4481 #endif 4482 static int offset = 0, n; 4483 4484 if (Currentbuf->firstLine == NULL) 4485 return; 4486 if (CurrentKey == prev_key && s != NULL) { 4487 if (s->length - offset >= COLS) 4488 offset++; 4489 else if (s->length <= offset) /* bug ? */ 4490 offset = 0; 4491 goto disp; 4492 } 4493 else { 4494 offset = 0; 4495 } 4496 s = NULL; 4497 a = (only_img ? NULL : retrieveCurrentAnchor(Currentbuf)); 4498 if (a == NULL) { 4499 a = (only_img ? NULL : retrieveCurrentForm(Currentbuf)); 4500 if (a == NULL) { 4501 a = retrieveCurrentImg(Currentbuf); 4502 if (a == NULL) 4503 return; 4504 } 4505 else 4506 s = Strnew_charp(form2str((FormItemList *)a->url)); 4507 } 4508 if (s == NULL) { 4509 parseURL2(a->url, &pu, baseURL(Currentbuf)); 4510 s = parsedURL2Str(&pu); 4511 } 4512 if (DecodeURL) 4513 s = Strnew_charp(url_unquote_conv 4514 (s->ptr, Currentbuf->document_charset)); 4515 #ifdef USE_M17N 4516 s = checkType(s, &pp, NULL); 4517 p = NewAtom_N(Lineprop, s->length); 4518 bcopy((void *)pp, (void *)p, s->length * sizeof(Lineprop)); 4519 #endif 4520 disp: 4521 n = searchKeyNum(); 4522 if (n > 1 && s->length > (n - 1) * (COLS - 1)) 4523 offset = (n - 1) * (COLS - 1); 4524 #ifdef USE_M17N 4525 while (offset < s->length && p[offset] & PC_WCHAR2) 4526 offset++; 4527 #endif 4528 disp_message_nomouse(&s->ptr[offset], TRUE); 4529 } 4530 4531 /* peek URL */ 4532 DEFUN(peekURL, PEEK_LINK, "Peek link URL") 4533 { 4534 _peekURL(0); 4535 } 4536 4537 /* peek URL of image */ 4538 DEFUN(peekIMG, PEEK_IMG, "Peek image URL") 4539 { 4540 _peekURL(1); 4541 } 4542 4543 /* show current URL */ 4544 static Str 4545 currentURL(void) 4546 { 4547 if (Currentbuf->bufferprop & BP_INTERNAL) 4548 return Strnew_size(0); 4549 return parsedURL2Str(&Currentbuf->currentURL); 4550 } 4551 4552 DEFUN(curURL, PEEK, "Peek current URL") 4553 { 4554 static Str s = NULL; 4555 #ifdef USE_M17N 4556 static Lineprop *p = NULL; 4557 Lineprop *pp; 4558 #endif 4559 static int offset = 0, n; 4560 4561 if (Currentbuf->bufferprop & BP_INTERNAL) 4562 return; 4563 if (CurrentKey == prev_key && s != NULL) { 4564 if (s->length - offset >= COLS) 4565 offset++; 4566 else if (s->length <= offset) /* bug ? */ 4567 offset = 0; 4568 } 4569 else { 4570 offset = 0; 4571 s = currentURL(); 4572 if (DecodeURL) 4573 s = Strnew_charp(url_unquote_conv(s->ptr, 0)); 4574 #ifdef USE_M17N 4575 s = checkType(s, &pp, NULL); 4576 p = NewAtom_N(Lineprop, s->length); 4577 bcopy((void *)pp, (void *)p, s->length * sizeof(Lineprop)); 4578 #endif 4579 } 4580 n = searchKeyNum(); 4581 if (n > 1 && s->length > (n - 1) * (COLS - 1)) 4582 offset = (n - 1) * (COLS - 1); 4583 #ifdef USE_M17N 4584 while (offset < s->length && p[offset] & PC_WCHAR2) 4585 offset++; 4586 #endif 4587 disp_message_nomouse(&s->ptr[offset], TRUE); 4588 } 4589 /* view HTML source */ 4590 4591 DEFUN(vwSrc, SOURCE VIEW, "View HTML source") 4592 { 4593 Buffer *buf; 4594 4595 if (Currentbuf->type == NULL || Currentbuf->bufferprop & BP_FRAME) 4596 return; 4597 if ((buf = Currentbuf->linkBuffer[LB_SOURCE]) != NULL || 4598 (buf = Currentbuf->linkBuffer[LB_N_SOURCE]) != NULL) { 4599 Currentbuf = buf; 4600 displayBuffer(Currentbuf, B_NORMAL); 4601 return; 4602 } 4603 if (Currentbuf->sourcefile == NULL) { 4604 if (Currentbuf->pagerSource && 4605 !strcasecmp(Currentbuf->type, "text/plain")) { 4606 #ifdef USE_M17N 4607 wc_ces old_charset; 4608 wc_bool old_fix_width_conv; 4609 #endif 4610 FILE *f; 4611 Str tmpf = tmpfname(TMPF_SRC, NULL); 4612 f = fopen(tmpf->ptr, "w"); 4613 if (f == NULL) 4614 return; 4615 #ifdef USE_M17N 4616 old_charset = DisplayCharset; 4617 old_fix_width_conv = WcOption.fix_width_conv; 4618 DisplayCharset = (Currentbuf->document_charset != WC_CES_US_ASCII) 4619 ? Currentbuf->document_charset : 0; 4620 WcOption.fix_width_conv = WC_FALSE; 4621 #endif 4622 saveBufferBody(Currentbuf, f, TRUE); 4623 #ifdef USE_M17N 4624 DisplayCharset = old_charset; 4625 WcOption.fix_width_conv = old_fix_width_conv; 4626 #endif 4627 fclose(f); 4628 Currentbuf->sourcefile = tmpf->ptr; 4629 } 4630 else { 4631 return; 4632 } 4633 } 4634 4635 buf = newBuffer(INIT_BUFFER_WIDTH); 4636 4637 if (is_html_type(Currentbuf->type)) { 4638 buf->type = "text/plain"; 4639 if (Currentbuf->real_type && 4640 is_html_type(Currentbuf->real_type)) 4641 buf->real_type = "text/plain"; 4642 else 4643 buf->real_type = Currentbuf->real_type; 4644 buf->buffername = Sprintf("source of %s", Currentbuf->buffername)->ptr; 4645 buf->linkBuffer[LB_N_SOURCE] = Currentbuf; 4646 Currentbuf->linkBuffer[LB_SOURCE] = buf; 4647 } 4648 else if (!strcasecmp(Currentbuf->type, "text/plain")) { 4649 buf->type = "text/html"; 4650 if (Currentbuf->real_type && 4651 !strcasecmp(Currentbuf->real_type, "text/plain")) 4652 buf->real_type = "text/html"; 4653 else 4654 buf->real_type = Currentbuf->real_type; 4655 buf->buffername = Sprintf("HTML view of %s", 4656 Currentbuf->buffername)->ptr; 4657 buf->linkBuffer[LB_SOURCE] = Currentbuf; 4658 Currentbuf->linkBuffer[LB_N_SOURCE] = buf; 4659 } 4660 else { 4661 return; 4662 } 4663 buf->currentURL = Currentbuf->currentURL; 4664 buf->real_scheme = Currentbuf->real_scheme; 4665 buf->filename = Currentbuf->filename; 4666 buf->sourcefile = Currentbuf->sourcefile; 4667 buf->header_source = Currentbuf->header_source; 4668 buf->search_header = Currentbuf->search_header; 4669 #ifdef USE_M17N 4670 buf->document_charset = Currentbuf->document_charset; 4671 #endif 4672 buf->clone = Currentbuf->clone; 4673 (*buf->clone)++; 4674 4675 buf->need_reshape = TRUE; 4676 reshapeBuffer(buf); 4677 pushBuffer(buf); 4678 displayBuffer(Currentbuf, B_NORMAL); 4679 } 4680 4681 /* reload */ 4682 DEFUN(reload, RELOAD, "Reload buffer") 4683 { 4684 Buffer *buf, *fbuf = NULL, sbuf; 4685 #ifdef USE_M17N 4686 wc_ces old_charset; 4687 #endif 4688 Str url; 4689 FormList *request; 4690 int multipart; 4691 4692 if (Currentbuf->bufferprop & BP_INTERNAL) { 4693 if (!strcmp(Currentbuf->buffername, DOWNLOAD_LIST_TITLE)) { 4694 ldDL(); 4695 return; 4696 } 4697 /* FIXME: gettextize? */ 4698 disp_err_message("Can't reload...", TRUE); 4699 return; 4700 } 4701 if (Currentbuf->currentURL.scheme == SCM_LOCAL && 4702 !strcmp(Currentbuf->currentURL.file, "-")) { 4703 /* file is std input */ 4704 /* FIXME: gettextize? */ 4705 disp_err_message("Can't reload stdin", TRUE); 4706 return; 4707 } 4708 copyBuffer(&sbuf, Currentbuf); 4709 if (Currentbuf->bufferprop & BP_FRAME && 4710 (fbuf = Currentbuf->linkBuffer[LB_N_FRAME])) { 4711 if (fmInitialized) { 4712 message("Rendering frame", 0, 0); 4713 refresh(); 4714 } 4715 if (!(buf = renderFrame(fbuf, 1))) { 4716 displayBuffer(Currentbuf, B_NORMAL); 4717 return; 4718 } 4719 if (fbuf->linkBuffer[LB_FRAME]) { 4720 if (buf->sourcefile && 4721 fbuf->linkBuffer[LB_FRAME]->sourcefile && 4722 !strcmp(buf->sourcefile, 4723 fbuf->linkBuffer[LB_FRAME]->sourcefile)) 4724 fbuf->linkBuffer[LB_FRAME]->sourcefile = NULL; 4725 delBuffer(fbuf->linkBuffer[LB_FRAME]); 4726 } 4727 fbuf->linkBuffer[LB_FRAME] = buf; 4728 buf->linkBuffer[LB_N_FRAME] = fbuf; 4729 pushBuffer(buf); 4730 Currentbuf = buf; 4731 if (Currentbuf->firstLine) { 4732 COPY_BUFROOT(Currentbuf, &sbuf); 4733 restorePosition(Currentbuf, &sbuf); 4734 } 4735 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4736 return; 4737 } 4738 else if (Currentbuf->frameset != NULL) 4739 fbuf = Currentbuf->linkBuffer[LB_FRAME]; 4740 multipart = 0; 4741 if (Currentbuf->form_submit) { 4742 request = Currentbuf->form_submit->parent; 4743 if (request->method == FORM_METHOD_POST 4744 && request->enctype == FORM_ENCTYPE_MULTIPART) { 4745 Str query; 4746 struct stat st; 4747 multipart = 1; 4748 query_from_followform(&query, Currentbuf->form_submit, multipart); 4749 stat(request->body, &st); 4750 request->length = st.st_size; 4751 } 4752 } 4753 else { 4754 request = NULL; 4755 } 4756 url = parsedURL2Str(&Currentbuf->currentURL); 4757 /* FIXME: gettextize? */ 4758 message("Reloading...", 0, 0); 4759 refresh(); 4760 #ifdef USE_M17N 4761 old_charset = DocumentCharset; 4762 if (Currentbuf->document_charset != WC_CES_US_ASCII) 4763 DocumentCharset = Currentbuf->document_charset; 4764 #endif 4765 SearchHeader = Currentbuf->search_header; 4766 DefaultType = Currentbuf->real_type; 4767 buf = loadGeneralFile(url->ptr, NULL, NO_REFERER, RG_NOCACHE, request); 4768 #ifdef USE_M17N 4769 DocumentCharset = old_charset; 4770 #endif 4771 SearchHeader = FALSE; 4772 DefaultType = NULL; 4773 4774 if (multipart) 4775 unlink(request->body); 4776 if (buf == NULL) { 4777 /* FIXME: gettextize? */ 4778 disp_err_message("Can't reload...", TRUE); 4779 return; 4780 } 4781 else if (buf == NO_BUFFER) { 4782 displayBuffer(Currentbuf, B_NORMAL); 4783 return; 4784 } 4785 if (fbuf != NULL) 4786 Firstbuf = deleteBuffer(Firstbuf, fbuf); 4787 repBuffer(Currentbuf, buf); 4788 if ((buf->type != NULL) && (sbuf.type != NULL) && 4789 ((!strcasecmp(buf->type, "text/plain") && 4790 is_html_type(sbuf.type)) || 4791 (is_html_type(buf->type) && 4792 !strcasecmp(sbuf.type, "text/plain")))) { 4793 vwSrc(); 4794 if (Currentbuf != buf) 4795 Firstbuf = deleteBuffer(Firstbuf, buf); 4796 } 4797 Currentbuf->search_header = sbuf.search_header; 4798 Currentbuf->form_submit = sbuf.form_submit; 4799 if (Currentbuf->firstLine) { 4800 COPY_BUFROOT(Currentbuf, &sbuf); 4801 restorePosition(Currentbuf, &sbuf); 4802 } 4803 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4804 } 4805 4806 /* reshape */ 4807 DEFUN(reshape, RESHAPE, "Re-render buffer") 4808 { 4809 Currentbuf->need_reshape = TRUE; 4810 reshapeBuffer(Currentbuf); 4811 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4812 } 4813 4814 #ifdef USE_M17N 4815 static void 4816 _docCSet(wc_ces charset) 4817 { 4818 if (Currentbuf->bufferprop & BP_INTERNAL) 4819 return; 4820 if (Currentbuf->sourcefile == NULL) { 4821 disp_message("Can't reload...", FALSE); 4822 return; 4823 } 4824 Currentbuf->document_charset = charset; 4825 Currentbuf->need_reshape = TRUE; 4826 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4827 } 4828 4829 void 4830 change_charset(struct parsed_tagarg *arg) 4831 { 4832 Buffer *buf = Currentbuf->linkBuffer[LB_N_INFO]; 4833 wc_ces charset; 4834 4835 if (buf == NULL) 4836 return; 4837 delBuffer(Currentbuf); 4838 Currentbuf = buf; 4839 if (Currentbuf->bufferprop & BP_INTERNAL) 4840 return; 4841 charset = Currentbuf->document_charset; 4842 for (; arg; arg = arg->next) { 4843 if (!strcmp(arg->arg, "charset")) 4844 charset = atoi(arg->value); 4845 } 4846 _docCSet(charset); 4847 } 4848 4849 DEFUN(docCSet, CHARSET, "Change the current document charset") 4850 { 4851 char *cs; 4852 wc_ces charset; 4853 4854 cs = searchKeyData(); 4855 if (cs == NULL || *cs == '\0') 4856 /* FIXME: gettextize? */ 4857 cs = inputStr("Document charset: ", 4858 wc_ces_to_charset(Currentbuf->document_charset)); 4859 charset = wc_guess_charset_short(cs, 0); 4860 if (charset == 0) { 4861 displayBuffer(Currentbuf, B_NORMAL); 4862 return; 4863 } 4864 _docCSet(charset); 4865 } 4866 4867 DEFUN(defCSet, DEFAULT_CHARSET, "Change the default document charset") 4868 { 4869 char *cs; 4870 wc_ces charset; 4871 4872 cs = searchKeyData(); 4873 if (cs == NULL || *cs == '\0') 4874 /* FIXME: gettextize? */ 4875 cs = inputStr("Default document charset: ", 4876 wc_ces_to_charset(DocumentCharset)); 4877 charset = wc_guess_charset_short(cs, 0); 4878 if (charset != 0) 4879 DocumentCharset = charset; 4880 displayBuffer(Currentbuf, B_NORMAL); 4881 } 4882 #endif 4883 4884 /* mark URL-like patterns as anchors */ 4885 void 4886 chkURLBuffer(Buffer *buf) 4887 { 4888 static char *url_like_pat[] = { 4889 "https?://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./?=~_\\&+@#,\\$;]*[a-zA-Z0-9_/=\\-]", 4890 "file:/[a-zA-Z0-9:%\\-\\./=_\\+@#,\\$;]*", 4891 #ifdef USE_GOPHER 4892 "gopher://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./_]*", 4893 #endif /* USE_GOPHER */ 4894 "ftp://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./=_+@#,\\$]*[a-zA-Z0-9_/]", 4895 #ifdef USE_NNTP 4896 "news:[^<> ][^<> ]*", 4897 "nntp://[a-zA-Z0-9][a-zA-Z0-9:%\\-\\./_]*", 4898 #endif /* USE_NNTP */ 4899 #ifndef USE_W3MMAILER /* see also chkExternalURIBuffer() */ 4900 "mailto:[^<> ][^<> ]*@[a-zA-Z0-9][a-zA-Z0-9\\-\\._]*[a-zA-Z0-9]", 4901 #endif 4902 #ifdef INET6 4903 "https?://[a-zA-Z0-9:%\\-\\./_@]*\\[[a-fA-F0-9:][a-fA-F0-9:\\.]*\\][a-zA-Z0-9:%\\-\\./?=~_\\&+@#,\\$;]*", 4904 "ftp://[a-zA-Z0-9:%\\-\\./_@]*\\[[a-fA-F0-9:][a-fA-F0-9:\\.]*\\][a-zA-Z0-9:%\\-\\./=_+@#,\\$]*", 4905 #endif /* INET6 */ 4906 NULL 4907 }; 4908 int i; 4909 for (i = 0; url_like_pat[i]; i++) { 4910 reAnchor(buf, url_like_pat[i]); 4911 } 4912 #ifdef USE_EXTERNAL_URI_LOADER 4913 chkExternalURIBuffer(buf); 4914 #endif 4915 buf->check_url |= CHK_URL; 4916 } 4917 4918 DEFUN(chkURL, MARK_URL, "Mark URL-like strings as anchors") 4919 { 4920 chkURLBuffer(Currentbuf); 4921 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4922 } 4923 4924 DEFUN(chkWORD, MARK_WORD, "Mark current word as anchor") 4925 { 4926 char *p; 4927 int spos, epos; 4928 p = getCurWord(Currentbuf, &spos, &epos); 4929 if (p == NULL) 4930 return; 4931 reAnchorWord(Currentbuf, Currentbuf->currentLine, spos, epos); 4932 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4933 } 4934 4935 #ifdef USE_NNTP 4936 /* mark Message-ID-like patterns as NEWS anchors */ 4937 void 4938 chkNMIDBuffer(Buffer *buf) 4939 { 4940 static char *url_like_pat[] = { 4941 "<[!-;=?-~]+@[a-zA-Z0-9\\.\\-_]+>", 4942 NULL, 4943 }; 4944 int i; 4945 for (i = 0; url_like_pat[i]; i++) { 4946 reAnchorNews(buf, url_like_pat[i]); 4947 } 4948 buf->check_url |= CHK_NMID; 4949 } 4950 4951 DEFUN(chkNMID, MARK_MID, "Mark Message-ID-like strings as anchors") 4952 { 4953 chkNMIDBuffer(Currentbuf); 4954 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4955 } 4956 #endif /* USE_NNTP */ 4957 4958 /* render frame */ 4959 DEFUN(rFrame, FRAME, "Render frame") 4960 { 4961 Buffer *buf; 4962 4963 if ((buf = Currentbuf->linkBuffer[LB_FRAME]) != NULL) { 4964 Currentbuf = buf; 4965 displayBuffer(Currentbuf, B_NORMAL); 4966 return; 4967 } 4968 if (Currentbuf->frameset == NULL) { 4969 if ((buf = Currentbuf->linkBuffer[LB_N_FRAME]) != NULL) { 4970 Currentbuf = buf; 4971 displayBuffer(Currentbuf, B_NORMAL); 4972 } 4973 return; 4974 } 4975 if (fmInitialized) { 4976 message("Rendering frame", 0, 0); 4977 refresh(); 4978 } 4979 buf = renderFrame(Currentbuf, 0); 4980 if (buf == NULL) { 4981 displayBuffer(Currentbuf, B_NORMAL); 4982 return; 4983 } 4984 buf->linkBuffer[LB_N_FRAME] = Currentbuf; 4985 Currentbuf->linkBuffer[LB_FRAME] = buf; 4986 pushBuffer(buf); 4987 if (fmInitialized && display_ok) 4988 displayBuffer(Currentbuf, B_FORCE_REDRAW); 4989 } 4990 4991 /* spawn external browser */ 4992 static void 4993 invoke_browser(char *url) 4994 { 4995 Str cmd; 4996 char *browser = NULL; 4997 int bg = 0, len; 4998 4999 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 5000 browser = searchKeyData(); 5001 if (browser == NULL || *browser == '\0') { 5002 switch (prec_num) { 5003 case 0: 5004 case 1: 5005 browser = ExtBrowser; 5006 break; 5007 case 2: 5008 browser = ExtBrowser2; 5009 break; 5010 case 3: 5011 browser = ExtBrowser3; 5012 break; 5013 } 5014 if (browser == NULL || *browser == '\0') { 5015 browser = inputStr("Browse command: ", NULL); 5016 if (browser != NULL) 5017 browser = conv_to_system(browser); 5018 } 5019 } 5020 else { 5021 browser = conv_to_system(browser); 5022 } 5023 if (browser == NULL || *browser == '\0') { 5024 displayBuffer(Currentbuf, B_NORMAL); 5025 return; 5026 } 5027 5028 if ((len = strlen(browser)) >= 2 && browser[len - 1] == '&' && 5029 browser[len - 2] != '\\') { 5030 browser = allocStr(browser, len - 2); 5031 bg = 1; 5032 } 5033 cmd = myExtCommand(browser, shell_quote(url), FALSE); 5034 Strremovetrailingspaces(cmd); 5035 fmTerm(); 5036 mySystem(cmd->ptr, bg); 5037 fmInit(); 5038 displayBuffer(Currentbuf, B_FORCE_REDRAW); 5039 } 5040 5041 DEFUN(extbrz, EXTERN, "Execute external browser") 5042 { 5043 if (Currentbuf->bufferprop & BP_INTERNAL) { 5044 /* FIXME: gettextize? */ 5045 disp_err_message("Can't browse...", TRUE); 5046 return; 5047 } 5048 if (Currentbuf->currentURL.scheme == SCM_LOCAL && 5049 !strcmp(Currentbuf->currentURL.file, "-")) { 5050 /* file is std input */ 5051 /* FIXME: gettextize? */ 5052 disp_err_message("Can't browse stdin", TRUE); 5053 return; 5054 } 5055 invoke_browser(parsedURL2Str(&Currentbuf->currentURL)->ptr); 5056 } 5057 5058 DEFUN(linkbrz, EXTERN_LINK, "View current link using external browser") 5059 { 5060 Anchor *a; 5061 ParsedURL pu; 5062 5063 if (Currentbuf->firstLine == NULL) 5064 return; 5065 a = retrieveCurrentAnchor(Currentbuf); 5066 if (a == NULL) 5067 return; 5068 parseURL2(a->url, &pu, baseURL(Currentbuf)); 5069 invoke_browser(parsedURL2Str(&pu)->ptr); 5070 } 5071 5072 /* show current line number and number of lines in the entire document */ 5073 DEFUN(curlno, LINE_INFO, "Show current line number") 5074 { 5075 Line *l = Currentbuf->currentLine; 5076 Str tmp; 5077 int cur = 0, all = 0, col = 0, len = 0; 5078 5079 if (l != NULL) { 5080 cur = l->real_linenumber; 5081 col = l->bwidth + Currentbuf->currentColumn + Currentbuf->cursorX + 1; 5082 while (l->next && l->next->bpos) 5083 l = l->next; 5084 if (l->width < 0) 5085 l->width = COLPOS(l, l->len); 5086 len = l->bwidth + l->width; 5087 } 5088 if (Currentbuf->lastLine) 5089 all = Currentbuf->lastLine->real_linenumber; 5090 if (Currentbuf->pagerSource && !(Currentbuf->bufferprop & BP_CLOSE)) 5091 tmp = Sprintf("line %d col %d/%d", cur, col, len); 5092 else 5093 tmp = Sprintf("line %d/%d (%d%%) col %d/%d", cur, all, 5094 (int)((double)cur * 100.0 / (double)(all ? all : 1) 5095 + 0.5), col, len); 5096 #ifdef USE_M17N 5097 Strcat_charp(tmp, " "); 5098 Strcat_charp(tmp, wc_ces_to_charset_desc(Currentbuf->document_charset)); 5099 #endif 5100 5101 disp_message(tmp->ptr, FALSE); 5102 } 5103 5104 #ifdef USE_IMAGE 5105 DEFUN(dispI, DISPLAY_IMAGE, "Restart loading and drawing of images") 5106 { 5107 if (!displayImage) 5108 initImage(); 5109 if (!activeImage) 5110 return; 5111 displayImage = TRUE; 5112 /* 5113 * if (!(Currentbuf->type && is_html_type(Currentbuf->type))) 5114 * return; 5115 */ 5116 Currentbuf->image_flag = IMG_FLAG_AUTO; 5117 Currentbuf->need_reshape = TRUE; 5118 displayBuffer(Currentbuf, B_REDRAW_IMAGE); 5119 } 5120 5121 DEFUN(stopI, STOP_IMAGE, "Stop loading and drawing of images") 5122 { 5123 if (!activeImage) 5124 return; 5125 /* 5126 * if (!(Currentbuf->type && is_html_type(Currentbuf->type))) 5127 * return; 5128 */ 5129 Currentbuf->image_flag = IMG_FLAG_SKIP; 5130 displayBuffer(Currentbuf, B_REDRAW_IMAGE); 5131 } 5132 #endif 5133 5134 #ifdef USE_MOUSE 5135 5136 static int 5137 mouse_scroll_line(void) 5138 { 5139 if (relative_wheel_scroll) 5140 return (relative_wheel_scroll_ratio * LASTLINE + 99) / 100; 5141 else 5142 return fixed_wheel_scroll_count; 5143 } 5144 5145 static TabBuffer * 5146 posTab(int x, int y) 5147 { 5148 TabBuffer *tab; 5149 5150 if (mouse_action.menu_str && x < mouse_action.menu_width && y == 0) 5151 return NO_TABBUFFER; 5152 if (y > LastTab->y) 5153 return NULL; 5154 for (tab = FirstTab; tab; tab = tab->nextTab) { 5155 if (tab->x1 <= x && x <= tab->x2 && tab->y == y) 5156 return tab; 5157 } 5158 return NULL; 5159 } 5160 5161 static void 5162 do_mouse_action(int btn, int x, int y) 5163 { 5164 MouseActionMap *map = NULL; 5165 int ny = -1; 5166 5167 if (nTab > 1 || mouse_action.menu_str) 5168 ny = LastTab->y + 1; 5169 5170 switch (btn) { 5171 case MOUSE_BTN1_DOWN: 5172 btn = 0; 5173 break; 5174 case MOUSE_BTN2_DOWN: 5175 btn = 1; 5176 break; 5177 case MOUSE_BTN3_DOWN: 5178 btn = 2; 5179 break; 5180 default: 5181 return; 5182 } 5183 if (y < ny) { 5184 if (mouse_action.menu_str && x >= 0 && x < mouse_action.menu_width) { 5185 if (mouse_action.menu_map[btn]) 5186 map = &mouse_action.menu_map[btn][x]; 5187 } 5188 else 5189 map = &mouse_action.tab_map[btn]; 5190 } 5191 else if (y == LASTLINE) { 5192 if (mouse_action.lastline_str && x >= 0 && 5193 x < mouse_action.lastline_width) { 5194 if (mouse_action.lastline_map[btn]) 5195 map = &mouse_action.lastline_map[btn][x]; 5196 } 5197 } 5198 else if (y > ny) { 5199 if (y == Currentbuf->cursorY + Currentbuf->rootY && 5200 (x == Currentbuf->cursorX + Currentbuf->rootX 5201 #ifdef USE_M17N 5202 || (WcOption.use_wide && Currentbuf->currentLine != NULL && 5203 (CharType(Currentbuf->currentLine->propBuf[Currentbuf->pos]) 5204 == PC_KANJI1) 5205 && x == Currentbuf->cursorX + Currentbuf->rootX + 1) 5206 #endif 5207 )) { 5208 if (retrieveCurrentAnchor(Currentbuf) || 5209 retrieveCurrentForm(Currentbuf)) { 5210 map = &mouse_action.active_map[btn]; 5211 if (!(map && map->func)) 5212 map = &mouse_action.anchor_map[btn]; 5213 } 5214 } 5215 else { 5216 int cx = Currentbuf->cursorX, cy = Currentbuf->cursorY; 5217 cursorXY(Currentbuf, x - Currentbuf->rootX, y - Currentbuf->rootY); 5218 if (y == Currentbuf->cursorY + Currentbuf->rootY && 5219 (x == Currentbuf->cursorX + Currentbuf->rootX 5220 #ifdef USE_M17N 5221 || (WcOption.use_wide && Currentbuf->currentLine != NULL && 5222 (CharType(Currentbuf->currentLine-> 5223 propBuf[Currentbuf->pos]) == PC_KANJI1) 5224 && x == Currentbuf->cursorX + Currentbuf->rootX + 1) 5225 #endif 5226 ) && 5227 (retrieveCurrentAnchor(Currentbuf) || 5228 retrieveCurrentForm(Currentbuf))) 5229 map = &mouse_action.anchor_map[btn]; 5230 cursorXY(Currentbuf, cx, cy); 5231 } 5232 } 5233 else { 5234 return; 5235 } 5236 if (!(map && map->func)) 5237 map = &mouse_action.default_map[btn]; 5238 if (map && map->func) { 5239 mouse_action.in_action = TRUE; 5240 mouse_action.cursorX = x; 5241 mouse_action.cursorY = y; 5242 CurrentKey = -1; 5243 CurrentKeyData = NULL; 5244 CurrentCmdData = map->data; 5245 (*map->func) (); 5246 CurrentCmdData = NULL; 5247 } 5248 } 5249 5250 static void 5251 process_mouse(int btn, int x, int y) 5252 { 5253 int delta_x, delta_y, i; 5254 static int press_btn = MOUSE_BTN_RESET, press_x, press_y; 5255 TabBuffer *t; 5256 int ny = -1; 5257 5258 if (nTab > 1 || mouse_action.menu_str) 5259 ny = LastTab->y + 1; 5260 if (btn == MOUSE_BTN_UP) { 5261 switch (press_btn) { 5262 case MOUSE_BTN1_DOWN: 5263 if (press_y == y && press_x == x) 5264 do_mouse_action(press_btn, x, y); 5265 else if (ny > 0 && y < ny) { 5266 if (press_y < ny) { 5267 moveTab(posTab(press_x, press_y), posTab(x, y), 5268 (press_y == y) ? (press_x < x) : (press_y < y)); 5269 return; 5270 } 5271 else if (press_x >= Currentbuf->rootX) { 5272 Buffer *buf = Currentbuf; 5273 int cx = Currentbuf->cursorX, cy = Currentbuf->cursorY; 5274 5275 t = posTab(x, y); 5276 if (t == NULL) 5277 return; 5278 if (t == NO_TABBUFFER) 5279 t = NULL; /* open new tab */ 5280 cursorXY(Currentbuf, press_x - Currentbuf->rootX, 5281 press_y - Currentbuf->rootY); 5282 if (Currentbuf->cursorY == press_y - Currentbuf->rootY && 5283 (Currentbuf->cursorX == press_x - Currentbuf->rootX 5284 #ifdef USE_M17N 5285 || (WcOption.use_wide && 5286 Currentbuf->currentLine != NULL && 5287 (CharType(Currentbuf->currentLine-> 5288 propBuf[Currentbuf->pos]) == PC_KANJI1) 5289 && Currentbuf->cursorX == press_x 5290 - Currentbuf->rootX - 1) 5291 #endif 5292 )) { 5293 displayBuffer(Currentbuf, B_NORMAL); 5294 followTab(t); 5295 } 5296 if (buf == Currentbuf) 5297 cursorXY(Currentbuf, cx, cy); 5298 } 5299 return; 5300 } 5301 else { 5302 delta_x = x - press_x; 5303 delta_y = y - press_y; 5304 5305 if (abs(delta_x) < abs(delta_y) / 3) 5306 delta_x = 0; 5307 if (abs(delta_y) < abs(delta_x) / 3) 5308 delta_y = 0; 5309 if (reverse_mouse) { 5310 delta_y = -delta_y; 5311 delta_x = -delta_x; 5312 } 5313 if (delta_y > 0) { 5314 prec_num = delta_y; 5315 ldown1(); 5316 } 5317 else if (delta_y < 0) { 5318 prec_num = -delta_y; 5319 lup1(); 5320 } 5321 if (delta_x > 0) { 5322 prec_num = delta_x; 5323 col1L(); 5324 } 5325 else if (delta_x < 0) { 5326 prec_num = -delta_x; 5327 col1R(); 5328 } 5329 } 5330 break; 5331 case MOUSE_BTN2_DOWN: 5332 case MOUSE_BTN3_DOWN: 5333 if (press_y == y && press_x == x) 5334 do_mouse_action(press_btn, x, y); 5335 break; 5336 case MOUSE_BTN4_DOWN_RXVT: 5337 for (i = 0; i < mouse_scroll_line(); i++) 5338 ldown1(); 5339 break; 5340 case MOUSE_BTN5_DOWN_RXVT: 5341 for (i = 0; i < mouse_scroll_line(); i++) 5342 lup1(); 5343 break; 5344 } 5345 } 5346 else if (btn == MOUSE_BTN4_DOWN_XTERM) { 5347 for (i = 0; i < mouse_scroll_line(); i++) 5348 ldown1(); 5349 } 5350 else if (btn == MOUSE_BTN5_DOWN_XTERM) { 5351 for (i = 0; i < mouse_scroll_line(); i++) 5352 lup1(); 5353 } 5354 5355 if (btn != MOUSE_BTN4_DOWN_RXVT || press_btn == MOUSE_BTN_RESET) { 5356 press_btn = btn; 5357 press_x = x; 5358 press_y = y; 5359 } 5360 else { 5361 press_btn = MOUSE_BTN_RESET; 5362 } 5363 } 5364 5365 DEFUN(msToggle, MOUSE_TOGGLE, "Toggle activity of mouse") 5366 { 5367 if (use_mouse) { 5368 use_mouse = FALSE; 5369 } 5370 else { 5371 use_mouse = TRUE; 5372 } 5373 displayBuffer(Currentbuf, B_FORCE_REDRAW); 5374 } 5375 5376 DEFUN(mouse, MOUSE, "mouse operation") 5377 { 5378 int btn, x, y; 5379 5380 btn = (unsigned char)getch() - 32; 5381 #if defined(__CYGWIN__) && CYGWIN_VERSION_DLL_MAJOR < 1005 5382 if (cygwin_mouse_btn_swapped) { 5383 if (btn == MOUSE_BTN2_DOWN) 5384 btn = MOUSE_BTN3_DOWN; 5385 else if (btn == MOUSE_BTN3_DOWN) 5386 btn = MOUSE_BTN2_DOWN; 5387 } 5388 #endif 5389 x = (unsigned char)getch() - 33; 5390 if (x < 0) 5391 x += 0x100; 5392 y = (unsigned char)getch() - 33; 5393 if (y < 0) 5394 y += 0x100; 5395 5396 if (x < 0 || x >= COLS || y < 0 || y > LASTLINE) 5397 return; 5398 process_mouse(btn, x, y); 5399 } 5400 5401 #ifdef USE_GPM 5402 int 5403 gpm_process_mouse(Gpm_Event * event, void *data) 5404 { 5405 int btn = MOUSE_BTN_RESET, x, y; 5406 if (event->type & GPM_UP) 5407 btn = MOUSE_BTN_UP; 5408 else if (event->type & GPM_DOWN) { 5409 switch (event->buttons) { 5410 case GPM_B_LEFT: 5411 btn = MOUSE_BTN1_DOWN; 5412 break; 5413 case GPM_B_MIDDLE: 5414 btn = MOUSE_BTN2_DOWN; 5415 break; 5416 case GPM_B_RIGHT: 5417 btn = MOUSE_BTN3_DOWN; 5418 break; 5419 } 5420 } 5421 else { 5422 GPM_DRAWPOINTER(event); 5423 return 0; 5424 } 5425 x = event->x; 5426 y = event->y; 5427 process_mouse(btn, x - 1, y - 1); 5428 return 0; 5429 } 5430 #endif /* USE_GPM */ 5431 5432 #ifdef USE_SYSMOUSE 5433 int 5434 sysm_process_mouse(int x, int y, int nbs, int obs) 5435 { 5436 int btn; 5437 int bits; 5438 5439 if (obs & ~nbs) 5440 btn = MOUSE_BTN_UP; 5441 else if (nbs & ~obs) { 5442 bits = nbs & ~obs; 5443 btn = bits & 0x1 ? MOUSE_BTN1_DOWN : 5444 (bits & 0x2 ? MOUSE_BTN2_DOWN : 5445 (bits & 0x4 ? MOUSE_BTN3_DOWN : 0)); 5446 } 5447 else /* nbs == obs */ 5448 return 0; 5449 process_mouse(btn, x, y); 5450 return 0; 5451 } 5452 #endif /* USE_SYSMOUSE */ 5453 5454 DEFUN(movMs, MOVE_MOUSE, "Move cursor to mouse cursor (for mouse action)") 5455 { 5456 if (!mouse_action.in_action) 5457 return; 5458 if ((nTab > 1 || mouse_action.menu_str) && 5459 mouse_action.cursorY < LastTab->y + 1) 5460 return; 5461 else if (mouse_action.cursorX >= Currentbuf->rootX && 5462 mouse_action.cursorY < LASTLINE) { 5463 cursorXY(Currentbuf, mouse_action.cursorX - Currentbuf->rootX, 5464 mouse_action.cursorY - Currentbuf->rootY); 5465 } 5466 displayBuffer(Currentbuf, B_NORMAL); 5467 } 5468 5469 #ifdef USE_MENU 5470 #ifdef KANJI_SYMBOLS 5471 #define FRAME_WIDTH 2 5472 #else 5473 #define FRAME_WIDTH 1 5474 #endif 5475 5476 DEFUN(menuMs, MENU_MOUSE, "Popup menu at mouse cursor (for mouse action)") 5477 { 5478 if (!mouse_action.in_action) 5479 return; 5480 if ((nTab > 1 || mouse_action.menu_str) && 5481 mouse_action.cursorY < LastTab->y + 1) 5482 mouse_action.cursorX -= FRAME_WIDTH + 1; 5483 else if (mouse_action.cursorX >= Currentbuf->rootX && 5484 mouse_action.cursorY < LASTLINE) { 5485 cursorXY(Currentbuf, mouse_action.cursorX - Currentbuf->rootX, 5486 mouse_action.cursorY - Currentbuf->rootY); 5487 displayBuffer(Currentbuf, B_NORMAL); 5488 } 5489 mainMn(); 5490 } 5491 #endif 5492 5493 DEFUN(tabMs, TAB_MOUSE, "Move to tab on mouse cursor (for mouse action)") 5494 { 5495 TabBuffer *tab; 5496 5497 if (!mouse_action.in_action) 5498 return; 5499 tab = posTab(mouse_action.cursorX, mouse_action.cursorY); 5500 if (!tab || tab == NO_TABBUFFER) 5501 return; 5502 CurrentTab = tab; 5503 displayBuffer(Currentbuf, B_FORCE_REDRAW); 5504 } 5505 5506 DEFUN(closeTMs, CLOSE_TAB_MOUSE, 5507 "Close tab on mouse cursor (for mouse action)") 5508 { 5509 TabBuffer *tab; 5510 5511 if (!mouse_action.in_action) 5512 return; 5513 tab = posTab(mouse_action.cursorX, mouse_action.cursorY); 5514 if (!tab || tab == NO_TABBUFFER) 5515 return; 5516 deleteTab(tab); 5517 displayBuffer(Currentbuf, B_FORCE_REDRAW); 5518 } 5519 #endif /* USE_MOUSE */ 5520 5521 DEFUN(dispVer, VERSION, "Display version of w3m") 5522 { 5523 disp_message(Sprintf("w3m version %s", w3m_version)->ptr, TRUE); 5524 } 5525 5526 DEFUN(wrapToggle, WRAP_TOGGLE, "Toggle wrap search mode") 5527 { 5528 if (WrapSearch) { 5529 WrapSearch = FALSE; 5530 /* FIXME: gettextize? */ 5531 disp_message("Wrap search off", TRUE); 5532 } 5533 else { 5534 WrapSearch = TRUE; 5535 /* FIXME: gettextize? */ 5536 disp_message("Wrap search on", TRUE); 5537 } 5538 } 5539 5540 static char * 5541 getCurWord(Buffer *buf, int *spos, int *epos) 5542 { 5543 char *p; 5544 Line *l = buf->currentLine; 5545 int b, e; 5546 5547 *spos = 0; 5548 *epos = 0; 5549 if (l == NULL) 5550 return NULL; 5551 p = l->lineBuf; 5552 e = buf->pos; 5553 while (e > 0 && !is_wordchar(getChar(&p[e]))) 5554 prevChar(e, l); 5555 if (!is_wordchar(getChar(&p[e]))) 5556 return NULL; 5557 b = e; 5558 while (b > 0) { 5559 int tmp = b; 5560 prevChar(tmp, l); 5561 if (!is_wordchar(getChar(&p[tmp]))) 5562 break; 5563 b = tmp; 5564 } 5565 while (e < l->len && is_wordchar(getChar(&p[e]))) 5566 nextChar(e, l); 5567 *spos = b; 5568 *epos = e; 5569 return &p[b]; 5570 } 5571 5572 static char * 5573 GetWord(Buffer *buf) 5574 { 5575 int b, e; 5576 char *p; 5577 5578 if ((p = getCurWord(buf, &b, &e)) != NULL) { 5579 return Strnew_charp_n(p, e - b)->ptr; 5580 } 5581 return NULL; 5582 } 5583 5584 #ifdef USE_DICT 5585 static void 5586 execdict(char *word) 5587 { 5588 char *w, *dictcmd; 5589 Buffer *buf; 5590 5591 if (!UseDictCommand || word == NULL || *word == '\0') { 5592 displayBuffer(Currentbuf, B_NORMAL); 5593 return; 5594 } 5595 w = conv_to_system(word); 5596 if (*w == '\0') { 5597 displayBuffer(Currentbuf, B_NORMAL); 5598 return; 5599 } 5600 dictcmd = Sprintf("%s?%s", DictCommand, 5601 Str_form_quote(Strnew_charp(w))->ptr)->ptr; 5602 buf = loadGeneralFile(dictcmd, NULL, NO_REFERER, 0, NULL); 5603 if (buf == NULL) { 5604 disp_message("Execution failed", TRUE); 5605 return; 5606 } 5607 else { 5608 buf->filename = w; 5609 buf->buffername = Sprintf("%s %s", DICTBUFFERNAME, word)->ptr; 5610 if (buf->type == NULL) 5611 buf->type = "text/plain"; 5612 pushBuffer(buf); 5613 } 5614 displayBuffer(Currentbuf, B_FORCE_REDRAW); 5615 } 5616 5617 DEFUN(dictword, DICT_WORD, "Execute dictionary command (see README.dict)") 5618 { 5619 execdict(inputStr("(dictionary)!", "")); 5620 } 5621 5622 DEFUN(dictwordat, DICT_WORD_AT, 5623 "Execute dictionary command for word at cursor") 5624 { 5625 execdict(GetWord(Currentbuf)); 5626 } 5627 #endif /* USE_DICT */ 5628 5629 void 5630 set_buffer_environ(Buffer *buf) 5631 { 5632 static Buffer *prev_buf = NULL; 5633 static Line *prev_line = NULL; 5634 static int prev_pos = -1; 5635 Line *l; 5636 5637 if (buf == NULL) 5638 return; 5639 if (buf != prev_buf) { 5640 set_environ("W3M_SOURCEFILE", buf->sourcefile); 5641 set_environ("W3M_FILENAME", buf->filename); 5642 set_environ("W3M_TITLE", buf->buffername); 5643 set_environ("W3M_URL", parsedURL2Str(&buf->currentURL)->ptr); 5644 set_environ("W3M_TYPE", buf->real_type ? buf->real_type : "unknown"); 5645 #ifdef USE_M17N 5646 set_environ("W3M_CHARSET", wc_ces_to_charset(buf->document_charset)); 5647 #endif 5648 } 5649 l = buf->currentLine; 5650 if (l && (buf != prev_buf || l != prev_line || buf->pos != prev_pos)) { 5651 Anchor *a; 5652 ParsedURL pu; 5653 char *s = GetWord(buf); 5654 set_environ("W3M_CURRENT_WORD", s ? s : ""); 5655 a = retrieveCurrentAnchor(buf); 5656 if (a) { 5657 parseURL2(a->url, &pu, baseURL(buf)); 5658 set_environ("W3M_CURRENT_LINK", parsedURL2Str(&pu)->ptr); 5659 } 5660 else 5661 set_environ("W3M_CURRENT_LINK", ""); 5662 a = retrieveCurrentImg(buf); 5663 if (a) { 5664 parseURL2(a->url, &pu, baseURL(buf)); 5665 set_environ("W3M_CURRENT_IMG", parsedURL2Str(&pu)->ptr); 5666 } 5667 else 5668 set_environ("W3M_CURRENT_IMG", ""); 5669 a = retrieveCurrentForm(buf); 5670 if (a) 5671 set_environ("W3M_CURRENT_FORM", form2str((FormItemList *)a->url)); 5672 else 5673 set_environ("W3M_CURRENT_FORM", ""); 5674 set_environ("W3M_CURRENT_LINE", Sprintf("%d", 5675 l->real_linenumber)->ptr); 5676 set_environ("W3M_CURRENT_COLUMN", Sprintf("%d", 5677 buf->currentColumn + 5678 buf->cursorX + 1)->ptr); 5679 } 5680 else if (!l) { 5681 set_environ("W3M_CURRENT_WORD", ""); 5682 set_environ("W3M_CURRENT_LINK", ""); 5683 set_environ("W3M_CURRENT_IMG", ""); 5684 set_environ("W3M_CURRENT_FORM", ""); 5685 set_environ("W3M_CURRENT_LINE", "0"); 5686 set_environ("W3M_CURRENT_COLUMN", "0"); 5687 } 5688 prev_buf = buf; 5689 prev_line = l; 5690 prev_pos = buf->pos; 5691 } 5692 5693 char * 5694 searchKeyData(void) 5695 { 5696 char *data = NULL; 5697 5698 if (CurrentKeyData != NULL && *CurrentKeyData != '\0') 5699 data = CurrentKeyData; 5700 else if (CurrentCmdData != NULL && *CurrentCmdData != '\0') 5701 data = CurrentCmdData; 5702 else if (CurrentKey >= 0) 5703 data = getKeyData(CurrentKey); 5704 CurrentKeyData = NULL; 5705 CurrentCmdData = NULL; 5706 if (data == NULL || *data == '\0') 5707 return NULL; 5708 return allocStr(data, -1); 5709 } 5710 5711 static int 5712 searchKeyNum(void) 5713 { 5714 char *d; 5715 int n = 1; 5716 5717 d = searchKeyData(); 5718 if (d != NULL) 5719 n = atoi(d); 5720 return n * PREC_NUM; 5721 } 5722 5723 #ifdef __EMX__ 5724 #ifdef USE_M17N 5725 static char * 5726 getCodePage(void) 5727 { 5728 unsigned long CpList[8], CpSize; 5729 5730 if (!getenv("WINDOWID") && !DosQueryCp(sizeof(CpList), CpList, &CpSize)) 5731 return Sprintf("CP%d", *CpList)->ptr; 5732 return NULL; 5733 } 5734 #endif 5735 #endif 5736 5737 void 5738 deleteFiles() 5739 { 5740 Buffer *buf; 5741 char *f; 5742 5743 for (CurrentTab = FirstTab; CurrentTab; CurrentTab = CurrentTab->nextTab) { 5744 while (Firstbuf && Firstbuf != NO_BUFFER) { 5745 buf = Firstbuf->nextBuffer; 5746 discardBuffer(Firstbuf); 5747 Firstbuf = buf; 5748 } 5749 } 5750 while ((f = popText(fileToDelete)) != NULL) 5751 unlink(f); 5752 } 5753 5754 void 5755 w3m_exit(int i) 5756 { 5757 #ifdef USE_MIGEMO 5758 init_migemo(); /* close pipe to migemo */ 5759 #endif 5760 stopDownload(); 5761 deleteFiles(); 5762 #ifdef USE_SSL 5763 free_ssl_ctx(); 5764 #endif 5765 disconnectFTP(); 5766 #ifdef USE_NNTP 5767 disconnectNews(); 5768 #endif 5769 #ifdef __MINGW32_VERSION 5770 WSACleanup(); 5771 #endif 5772 exit(i); 5773 } 5774 5775 DEFUN(execCmd, COMMAND, "Execute w3m command(s)") 5776 { 5777 char *data, *p; 5778 int cmd; 5779 5780 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 5781 data = searchKeyData(); 5782 if (data == NULL || *data == '\0') { 5783 data = inputStrHist("command [; ...]: ", "", TextHist); 5784 if (data == NULL) { 5785 displayBuffer(Currentbuf, B_NORMAL); 5786 return; 5787 } 5788 } 5789 /* data: FUNC [DATA] [; FUNC [DATA] ...] */ 5790 while (*data) { 5791 SKIP_BLANKS(data); 5792 if (*data == ';') { 5793 data++; 5794 continue; 5795 } 5796 p = getWord(&data); 5797 cmd = getFuncList(p); 5798 if (cmd < 0) 5799 break; 5800 p = getQWord(&data); 5801 CurrentKey = -1; 5802 CurrentKeyData = NULL; 5803 CurrentCmdData = *p ? p : NULL; 5804 #ifdef USE_MOUSE 5805 if (use_mouse) 5806 mouse_inactive(); 5807 #endif 5808 w3mFuncList[cmd].func(); 5809 #ifdef USE_MOUSE 5810 if (use_mouse) 5811 mouse_active(); 5812 #endif 5813 CurrentCmdData = NULL; 5814 } 5815 displayBuffer(Currentbuf, B_NORMAL); 5816 } 5817 5818 #ifdef USE_ALARM 5819 static MySignalHandler 5820 SigAlarm(SIGNAL_ARG) 5821 { 5822 char *data; 5823 5824 if (CurrentAlarm->sec > 0) { 5825 CurrentKey = -1; 5826 CurrentKeyData = NULL; 5827 CurrentCmdData = data = (char *)CurrentAlarm->data; 5828 #ifdef USE_MOUSE 5829 if (use_mouse) 5830 mouse_inactive(); 5831 #endif 5832 w3mFuncList[CurrentAlarm->cmd].func(); 5833 #ifdef USE_MOUSE 5834 if (use_mouse) 5835 mouse_active(); 5836 #endif 5837 CurrentCmdData = NULL; 5838 if (CurrentAlarm->status == AL_IMPLICIT_ONCE) { 5839 CurrentAlarm->sec = 0; 5840 CurrentAlarm->status = AL_UNSET; 5841 } 5842 if (Currentbuf->event) { 5843 if (Currentbuf->event->status != AL_UNSET) 5844 CurrentAlarm = Currentbuf->event; 5845 else 5846 Currentbuf->event = NULL; 5847 } 5848 if (!Currentbuf->event) 5849 CurrentAlarm = &DefaultAlarm; 5850 if (CurrentAlarm->sec > 0) { 5851 mySignal(SIGALRM, SigAlarm); 5852 alarm(CurrentAlarm->sec); 5853 } 5854 } 5855 SIGNAL_RETURN; 5856 } 5857 5858 5859 DEFUN(setAlarm, ALARM, "Set alarm") 5860 { 5861 char *data; 5862 int sec = 0, cmd = -1; 5863 5864 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 5865 data = searchKeyData(); 5866 if (data == NULL || *data == '\0') { 5867 data = inputStrHist("(Alarm)sec command: ", "", TextHist); 5868 if (data == NULL) { 5869 displayBuffer(Currentbuf, B_NORMAL); 5870 return; 5871 } 5872 } 5873 if (*data != '\0') { 5874 sec = atoi(getWord(&data)); 5875 if (sec > 0) 5876 cmd = getFuncList(getWord(&data)); 5877 } 5878 if (cmd >= 0) { 5879 data = getQWord(&data); 5880 setAlarmEvent(&DefaultAlarm, sec, AL_EXPLICIT, cmd, data); 5881 disp_message_nsec(Sprintf("%dsec %s %s", sec, w3mFuncList[cmd].id, 5882 data)->ptr, FALSE, 1, FALSE, TRUE); 5883 } 5884 else { 5885 setAlarmEvent(&DefaultAlarm, 0, AL_UNSET, FUNCNAME_nulcmd, NULL); 5886 } 5887 displayBuffer(Currentbuf, B_NORMAL); 5888 } 5889 5890 AlarmEvent * 5891 setAlarmEvent(AlarmEvent * event, int sec, short status, int cmd, void *data) 5892 { 5893 if (event == NULL) 5894 event = New(AlarmEvent); 5895 event->sec = sec; 5896 event->status = status; 5897 event->cmd = cmd; 5898 event->data = data; 5899 return event; 5900 } 5901 #endif 5902 5903 DEFUN(reinit, REINIT, "Reload configuration files") 5904 { 5905 char *resource = searchKeyData(); 5906 5907 if (resource == NULL) { 5908 init_rc(); 5909 sync_with_option(); 5910 #ifdef USE_COOKIE 5911 initCookie(); 5912 #endif 5913 displayBuffer(Currentbuf, B_REDRAW_IMAGE); 5914 return; 5915 } 5916 5917 if (!strcasecmp(resource, "CONFIG") || !strcasecmp(resource, "RC")) { 5918 init_rc(); 5919 sync_with_option(); 5920 displayBuffer(Currentbuf, B_REDRAW_IMAGE); 5921 return; 5922 } 5923 5924 #ifdef USE_COOKIE 5925 if (!strcasecmp(resource, "COOKIE")) { 5926 initCookie(); 5927 return; 5928 } 5929 #endif 5930 5931 if (!strcasecmp(resource, "KEYMAP")) { 5932 initKeymap(TRUE); 5933 return; 5934 } 5935 5936 if (!strcasecmp(resource, "MAILCAP")) { 5937 initMailcap(); 5938 return; 5939 } 5940 5941 #ifdef USE_MOUSE 5942 if (!strcasecmp(resource, "MOUSE")) { 5943 initMouseAction(); 5944 displayBuffer(Currentbuf, B_REDRAW_IMAGE); 5945 return; 5946 } 5947 #endif 5948 5949 #ifdef USE_MENU 5950 if (!strcasecmp(resource, "MENU")) { 5951 initMenu(); 5952 return; 5953 } 5954 #endif 5955 5956 if (!strcasecmp(resource, "MIMETYPES")) { 5957 initMimeTypes(); 5958 return; 5959 } 5960 5961 #ifdef USE_EXTERNAL_URI_LOADER 5962 if (!strcasecmp(resource, "URIMETHODS")) { 5963 initURIMethods(); 5964 return; 5965 } 5966 #endif 5967 5968 disp_err_message(Sprintf("Don't know how to reinitialize '%s'", resource)-> 5969 ptr, FALSE); 5970 } 5971 5972 DEFUN(defKey, DEFINE_KEY, 5973 "Define a binding between a key stroke and a user command") 5974 { 5975 char *data; 5976 5977 CurrentKeyData = NULL; /* not allowed in w3m-control: */ 5978 data = searchKeyData(); 5979 if (data == NULL || *data == '\0') { 5980 data = inputStrHist("Key definition: ", "", TextHist); 5981 if (data == NULL || *data == '\0') { 5982 displayBuffer(Currentbuf, B_NORMAL); 5983 return; 5984 } 5985 } 5986 setKeymap(allocStr(data, -1), -1, TRUE); 5987 displayBuffer(Currentbuf, B_NORMAL); 5988 } 5989 5990 TabBuffer * 5991 newTab(void) 5992 { 5993 TabBuffer *n; 5994 5995 n = New(TabBuffer); 5996 if (n == NULL) 5997 return NULL; 5998 n->nextTab = NULL; 5999 n->currentBuffer = NULL; 6000 n->firstBuffer = NULL; 6001 return n; 6002 } 6003 6004 static void 6005 _newT(void) 6006 { 6007 TabBuffer *tag; 6008 Buffer *buf; 6009 int i; 6010 6011 tag = newTab(); 6012 if (!tag) 6013 return; 6014 6015 buf = newBuffer(Currentbuf->width); 6016 copyBuffer(buf, Currentbuf); 6017 buf->nextBuffer = NULL; 6018 for (i = 0; i < MAX_LB; i++) 6019 buf->linkBuffer[i] = NULL; 6020 (*buf->clone)++; 6021 tag->firstBuffer = tag->currentBuffer = buf; 6022 6023 tag->nextTab = CurrentTab->nextTab; 6024 tag->prevTab = CurrentTab; 6025 if (CurrentTab->nextTab) 6026 CurrentTab->nextTab->prevTab = tag; 6027 else 6028 LastTab = tag; 6029 CurrentTab->nextTab = tag; 6030 CurrentTab = tag; 6031 nTab++; 6032 } 6033 6034 DEFUN(newT, NEW_TAB, "Open new tab") 6035 { 6036 _newT(); 6037 displayBuffer(Currentbuf, B_REDRAW_IMAGE); 6038 } 6039 6040 static TabBuffer * 6041 numTab(int n) 6042 { 6043 TabBuffer *tab; 6044 int i; 6045 6046 if (n == 0) 6047 return CurrentTab; 6048 if (n == 1) 6049 return FirstTab; 6050 if (nTab <= 1) 6051 return NULL; 6052 for (tab = FirstTab, i = 1; tab && i < n; tab = tab->nextTab, i++) ; 6053 return tab; 6054 } 6055 6056 void 6057 calcTabPos(void) 6058 { 6059 TabBuffer *tab; 6060 #if 0 6061 int lcol = 0, rcol = 2, col; 6062 #else 6063 int lcol = 0, rcol = 0, col; 6064 #endif 6065 int n1, n2, na, nx, ny, ix, iy; 6066 6067 #ifdef USE_MOUSE 6068 lcol = mouse_action.menu_str ? mouse_action.menu_width : 0; 6069 #endif 6070 6071 if (nTab <= 0) 6072 return; 6073 n1 = (COLS - rcol - lcol) / TabCols; 6074 if (n1 >= nTab) { 6075 n2 = 1; 6076 ny = 1; 6077 } 6078 else { 6079 if (n1 < 0) 6080 n1 = 0; 6081 n2 = COLS / TabCols; 6082 if (n2 == 0) 6083 n2 = 1; 6084 ny = (nTab - n1 - 1) / n2 + 2; 6085 } 6086 na = n1 + n2 * (ny - 1); 6087 n1 -= (na - nTab) / ny; 6088 if (n1 < 0) 6089 n1 = 0; 6090 na = n1 + n2 * (ny - 1); 6091 tab = FirstTab; 6092 for (iy = 0; iy < ny && tab; iy++) { 6093 if (iy == 0) { 6094 nx = n1; 6095 col = COLS - rcol - lcol; 6096 } 6097 else { 6098 nx = n2 - (na - nTab + (iy - 1)) / (ny - 1); 6099 col = COLS; 6100 } 6101 for (ix = 0; ix < nx && tab; ix++, tab = tab->nextTab) { 6102 tab->x1 = col * ix / nx; 6103 tab->x2 = col * (ix + 1) / nx - 1; 6104 tab->y = iy; 6105 if (iy == 0) { 6106 tab->x1 += lcol; 6107 tab->x2 += lcol; 6108 } 6109 } 6110 } 6111 } 6112 6113 TabBuffer * 6114 deleteTab(TabBuffer * tab) 6115 { 6116 Buffer *buf, *next; 6117 6118 if (nTab <= 1) 6119 return FirstTab; 6120 if (tab->prevTab) { 6121 if (tab->nextTab) 6122 tab->nextTab->prevTab = tab->prevTab; 6123 else 6124 LastTab = tab->prevTab; 6125 tab->prevTab->nextTab = tab->nextTab; 6126 if (tab == CurrentTab) 6127 CurrentTab = tab->prevTab; 6128 } 6129 else { /* tab == FirstTab */ 6130 tab->nextTab->prevTab = NULL; 6131 FirstTab = tab->nextTab; 6132 if (tab == CurrentTab) 6133 CurrentTab = tab->nextTab; 6134 } 6135 nTab--; 6136 buf = tab->firstBuffer; 6137 while (buf && buf != NO_BUFFER) { 6138 next = buf->nextBuffer; 6139 discardBuffer(buf); 6140 buf = next; 6141 } 6142 return FirstTab; 6143 } 6144 6145 DEFUN(closeT, CLOSE_TAB, "Close current tab") 6146 { 6147 TabBuffer *tab; 6148 6149 if (nTab <= 1) 6150 return; 6151 if (prec_num) 6152 tab = numTab(PREC_NUM); 6153 else 6154 tab = CurrentTab; 6155 if (tab) 6156 deleteTab(tab); 6157 displayBuffer(Currentbuf, B_REDRAW_IMAGE); 6158 } 6159 6160 DEFUN(nextT, NEXT_TAB, "Move to next tab") 6161 { 6162 int i; 6163 6164 if (nTab <= 1) 6165 return; 6166 for (i = 0; i < PREC_NUM; i++) { 6167 if (CurrentTab->nextTab) 6168 CurrentTab = CurrentTab->nextTab; 6169 else 6170 CurrentTab = FirstTab; 6171 } 6172 displayBuffer(Currentbuf, B_REDRAW_IMAGE); 6173 } 6174 6175 DEFUN(prevT, PREV_TAB, "Move to previous tab") 6176 { 6177 int i; 6178 6179 if (nTab <= 1) 6180 return; 6181 for (i = 0; i < PREC_NUM; i++) { 6182 if (CurrentTab->prevTab) 6183 CurrentTab = CurrentTab->prevTab; 6184 else 6185 CurrentTab = LastTab; 6186 } 6187 displayBuffer(Currentbuf, B_REDRAW_IMAGE); 6188 } 6189 6190 static void 6191 followTab(TabBuffer * tab) 6192 { 6193 Buffer *buf; 6194 Anchor *a; 6195 6196 #ifdef USE_IMAGE 6197 a = retrieveCurrentImg(Currentbuf); 6198 if (!(a && a->image && a->image->map)) 6199 #endif 6200 a = retrieveCurrentAnchor(Currentbuf); 6201 if (a == NULL) 6202 return; 6203 6204 if (tab == CurrentTab) { 6205 check_target = FALSE; 6206 followA(); 6207 check_target = TRUE; 6208 return; 6209 } 6210 _newT(); 6211 buf = Currentbuf; 6212 check_target = FALSE; 6213 followA(); 6214 check_target = TRUE; 6215 if (tab == NULL) { 6216 if (buf != Currentbuf) 6217 delBuffer(buf); 6218 else 6219 deleteTab(CurrentTab); 6220 } 6221 else if (buf != Currentbuf) { 6222 /* buf <- p <- ... <- Currentbuf = c */ 6223 Buffer *c, *p; 6224 6225 c = Currentbuf; 6226 p = prevBuffer(c, buf); 6227 p->nextBuffer = NULL; 6228 Firstbuf = buf; 6229 deleteTab(CurrentTab); 6230 CurrentTab = tab; 6231 for (buf = p; buf; buf = p) { 6232 p = prevBuffer(c, buf); 6233 pushBuffer(buf); 6234 } 6235 } 6236 displayBuffer(Currentbuf, B_FORCE_REDRAW); 6237 } 6238 6239 DEFUN(tabA, TAB_LINK, "Open current link on new tab") 6240 { 6241 followTab(prec_num ? numTab(PREC_NUM) : NULL); 6242 } 6243 6244 static void 6245 tabURL0(TabBuffer * tab, char *prompt, int relative) 6246 { 6247 Buffer *buf; 6248 6249 if (tab == CurrentTab) { 6250 goURL0(prompt, relative); 6251 return; 6252 } 6253 _newT(); 6254 buf = Currentbuf; 6255 goURL0(prompt, relative); 6256 if (tab == NULL) { 6257 if (buf != Currentbuf) 6258 delBuffer(buf); 6259 else 6260 deleteTab(CurrentTab); 6261 } 6262 else if (buf != Currentbuf) { 6263 /* buf <- p <- ... <- Currentbuf = c */ 6264 Buffer *c, *p; 6265 6266 c = Currentbuf; 6267 p = prevBuffer(c, buf); 6268 p->nextBuffer = NULL; 6269 Firstbuf = buf; 6270 deleteTab(CurrentTab); 6271 CurrentTab = tab; 6272 for (buf = p; buf; buf = p) { 6273 p = prevBuffer(c, buf); 6274 pushBuffer(buf); 6275 } 6276 } 6277 displayBuffer(Currentbuf, B_FORCE_REDRAW); 6278 } 6279 6280 DEFUN(tabURL, TAB_GOTO, "Open URL on new tab") 6281 { 6282 tabURL0(prec_num ? numTab(PREC_NUM) : NULL, 6283 "Goto URL on new tab: ", FALSE); 6284 } 6285 6286 DEFUN(tabrURL, TAB_GOTO_RELATIVE, "Open relative URL on new tab") 6287 { 6288 tabURL0(prec_num ? numTab(PREC_NUM) : NULL, 6289 "Goto relative URL on new tab: ", TRUE); 6290 } 6291 6292 static void 6293 moveTab(TabBuffer * t, TabBuffer * t2, int right) 6294 { 6295 if (t2 == NO_TABBUFFER) 6296 t2 = FirstTab; 6297 if (!t || !t2 || t == t2 || t == NO_TABBUFFER) 6298 return; 6299 if (t->prevTab) { 6300 if (t->nextTab) 6301 t->nextTab->prevTab = t->prevTab; 6302 else 6303 LastTab = t->prevTab; 6304 t->prevTab->nextTab = t->nextTab; 6305 } 6306 else { 6307 t->nextTab->prevTab = NULL; 6308 FirstTab = t->nextTab; 6309 } 6310 if (right) { 6311 t->nextTab = t2->nextTab; 6312 t->prevTab = t2; 6313 if (t2->nextTab) 6314 t2->nextTab->prevTab = t; 6315 else 6316 LastTab = t; 6317 t2->nextTab = t; 6318 } 6319 else { 6320 t->prevTab = t2->prevTab; 6321 t->nextTab = t2; 6322 if (t2->prevTab) 6323 t2->prevTab->nextTab = t; 6324 else 6325 FirstTab = t; 6326 t2->prevTab = t; 6327 } 6328 displayBuffer(Currentbuf, B_FORCE_REDRAW); 6329 } 6330 6331 DEFUN(tabR, TAB_RIGHT, "Move current tab right") 6332 { 6333 TabBuffer *tab; 6334 int i; 6335 6336 for (tab = CurrentTab, i = 0; tab && i < PREC_NUM; 6337 tab = tab->nextTab, i++) ; 6338 moveTab(CurrentTab, tab ? tab : LastTab, TRUE); 6339 } 6340 6341 DEFUN(tabL, TAB_LEFT, "Move current tab left") 6342 { 6343 TabBuffer *tab; 6344 int i; 6345 6346 for (tab = CurrentTab, i = 0; tab && i < PREC_NUM; 6347 tab = tab->prevTab, i++) ; 6348 moveTab(CurrentTab, tab ? tab : FirstTab, FALSE); 6349 } 6350 6351 void 6352 addDownloadList(pid_t pid, char *url, char *save, char *lock, clen_t size) 6353 { 6354 DownloadList *d; 6355 6356 d = New(DownloadList); 6357 d->pid = pid; 6358 d->url = url; 6359 if (save[0] != '/' && save[0] != '~') 6360 save = Strnew_m_charp(CurrentDir, "/", save, NULL)->ptr; 6361 d->save = expandPath(save); 6362 d->lock = lock; 6363 d->size = size; 6364 d->time = time(0); 6365 d->running = TRUE; 6366 d->err = 0; 6367 d->next = NULL; 6368 d->prev = LastDL; 6369 if (LastDL) 6370 LastDL->next = d; 6371 else 6372 FirstDL = d; 6373 LastDL = d; 6374 add_download_list = TRUE; 6375 } 6376 6377 int 6378 checkDownloadList(void) 6379 { 6380 DownloadList *d; 6381 struct stat st; 6382 6383 if (!FirstDL) 6384 return FALSE; 6385 for (d = FirstDL; d != NULL; d = d->next) { 6386 if (d->running && !lstat(d->lock, &st)) 6387 return TRUE; 6388 } 6389 return FALSE; 6390 } 6391 6392 static char * 6393 convert_size3(clen_t size) 6394 { 6395 Str tmp = Strnew(); 6396 int n; 6397 6398 do { 6399 n = size % 1000; 6400 size /= 1000; 6401 tmp = Sprintf(size ? ",%.3d%s" : "%d%s", n, tmp->ptr); 6402 } while (size); 6403 return tmp->ptr; 6404 } 6405 6406 static Buffer * 6407 DownloadListBuffer(void) 6408 { 6409 DownloadList *d; 6410 Str src = NULL; 6411 struct stat st; 6412 time_t cur_time; 6413 int duration, rate, eta; 6414 size_t size; 6415 6416 if (!FirstDL) 6417 return NULL; 6418 cur_time = time(0); 6419 /* FIXME: gettextize? */ 6420 src = Strnew_charp("<html><head><title>" DOWNLOAD_LIST_TITLE 6421 "</title></head>\n<body><h1 align=center>" 6422 DOWNLOAD_LIST_TITLE "</h1>\n" 6423 "<form method=internal action=download><hr>\n"); 6424 for (d = LastDL; d != NULL; d = d->prev) { 6425 if (lstat(d->lock, &st)) 6426 d->running = FALSE; 6427 Strcat_charp(src, "<pre>\n"); 6428 Strcat(src, Sprintf("%s\n --> %s\n ", html_quote(d->url), 6429 html_quote(conv_from_system(d->save)))); 6430 duration = cur_time - d->time; 6431 if (!stat(d->save, &st)) { 6432 size = st.st_size; 6433 if (!d->running) { 6434 if (!d->err) 6435 d->size = size; 6436 duration = st.st_mtime - d->time; 6437 } 6438 } 6439 else 6440 size = 0; 6441 if (d->size) { 6442 int i, l = COLS - 6; 6443 if (size < d->size) 6444 i = 1.0 * l * size / d->size; 6445 else 6446 i = l; 6447 l -= i; 6448 while (i-- > 0) 6449 Strcat_char(src, '#'); 6450 while (l-- > 0) 6451 Strcat_char(src, '_'); 6452 Strcat_char(src, '\n'); 6453 } 6454 if ((d->running || d->err) && size < d->size) 6455 Strcat(src, Sprintf(" %s / %s bytes (%d%%)", 6456 convert_size3(size), convert_size3(d->size), 6457 (int)(100.0 * size / d->size))); 6458 else 6459 Strcat(src, Sprintf(" %s bytes loaded", convert_size3(size))); 6460 if (duration > 0) { 6461 rate = size / duration; 6462 Strcat(src, Sprintf(" %02d:%02d:%02d rate %s/sec", 6463 duration / (60 * 60), (duration / 60) % 60, 6464 duration % 60, convert_size(rate, 1))); 6465 if (d->running && size < d->size && rate) { 6466 eta = (d->size - size) / rate; 6467 Strcat(src, Sprintf(" eta %02d:%02d:%02d", eta / (60 * 60), 6468 (eta / 60) % 60, eta % 60)); 6469 } 6470 } 6471 Strcat_char(src, '\n'); 6472 if (!d->running) { 6473 Strcat(src, Sprintf("<input type=submit name=ok%d value=OK>", 6474 d->pid)); 6475 switch (d->err) { 6476 case 0: if (size < d->size) 6477 Strcat_charp(src, " Download ended but probably not complete"); 6478 else 6479 Strcat_charp(src, " Download complete"); 6480 break; 6481 case 1: Strcat_charp(src, " Error: could not open destination file"); 6482 break; 6483 case 2: Strcat_charp(src, " Error: could not write to file (disk full)"); 6484 break; 6485 default: Strcat_charp(src, " Error: unknown reason"); 6486 } 6487 } 6488 else 6489 Strcat(src, Sprintf("<input type=submit name=stop%d value=STOP>", 6490 d->pid)); 6491 Strcat_charp(src, "\n</pre><hr>\n"); 6492 } 6493 Strcat_charp(src, "</form></body></html>"); 6494 return loadHTMLString(src); 6495 } 6496 6497 void 6498 download_action(struct parsed_tagarg *arg) 6499 { 6500 DownloadList *d; 6501 pid_t pid; 6502 6503 for (; arg; arg = arg->next) { 6504 if (!strncmp(arg->arg, "stop", 4)) { 6505 pid = (pid_t) atoi(&arg->arg[4]); 6506 #ifndef __MINGW32_VERSION 6507 kill(pid, SIGKILL); 6508 #endif 6509 } 6510 else if (!strncmp(arg->arg, "ok", 2)) 6511 pid = (pid_t) atoi(&arg->arg[2]); 6512 else 6513 continue; 6514 for (d = FirstDL; d; d = d->next) { 6515 if (d->pid == pid) { 6516 unlink(d->lock); 6517 if (d->prev) 6518 d->prev->next = d->next; 6519 else 6520 FirstDL = d->next; 6521 if (d->next) 6522 d->next->prev = d->prev; 6523 else 6524 LastDL = d->prev; 6525 break; 6526 } 6527 } 6528 } 6529 ldDL(); 6530 } 6531 6532 void 6533 stopDownload(void) 6534 { 6535 DownloadList *d; 6536 6537 if (!FirstDL) 6538 return; 6539 for (d = FirstDL; d != NULL; d = d->next) { 6540 if (!d->running) 6541 continue; 6542 #ifndef __MINGW32_VERSION 6543 kill(d->pid, SIGKILL); 6544 #endif 6545 unlink(d->lock); 6546 } 6547 } 6548 6549 /* download panel */ 6550 DEFUN(ldDL, DOWNLOAD_LIST, "Display download list panel") 6551 { 6552 Buffer *buf; 6553 int replace = FALSE, new_tab = FALSE; 6554 #ifdef USE_ALARM 6555 int reload; 6556 #endif 6557 6558 if (Currentbuf->bufferprop & BP_INTERNAL && 6559 !strcmp(Currentbuf->buffername, DOWNLOAD_LIST_TITLE)) 6560 replace = TRUE; 6561 if (!FirstDL) { 6562 if (replace) { 6563 if (Currentbuf == Firstbuf && Currentbuf->nextBuffer == NULL) { 6564 if (nTab > 1) 6565 deleteTab(CurrentTab); 6566 } 6567 else 6568 delBuffer(Currentbuf); 6569 displayBuffer(Currentbuf, B_FORCE_REDRAW); 6570 } 6571 return; 6572 } 6573 #ifdef USE_ALARM 6574 reload = checkDownloadList(); 6575 #endif 6576 buf = DownloadListBuffer(); 6577 if (!buf) { 6578 displayBuffer(Currentbuf, B_NORMAL); 6579 return; 6580 } 6581 buf->bufferprop |= (BP_INTERNAL | BP_NO_URL); 6582 if (replace) { 6583 COPY_BUFROOT(buf, Currentbuf); 6584 restorePosition(buf, Currentbuf); 6585 } 6586 if (!replace && open_tab_dl_list) { 6587 _newT(); 6588 new_tab = TRUE; 6589 } 6590 pushBuffer(buf); 6591 if (replace || new_tab) 6592 deletePrevBuf(); 6593 #ifdef USE_ALARM 6594 if (reload) 6595 Currentbuf->event = setAlarmEvent(Currentbuf->event, 1, AL_IMPLICIT, 6596 FUNCNAME_reload, NULL); 6597 #endif 6598 displayBuffer(Currentbuf, B_FORCE_REDRAW); 6599 } 6600 6601 static void 6602 save_buffer_position(Buffer *buf) 6603 { 6604 BufferPos *b = buf->undo; 6605 6606 if (!buf->firstLine) 6607 return; 6608 if (b && b->top_linenumber == TOP_LINENUMBER(buf) && 6609 b->cur_linenumber == CUR_LINENUMBER(buf) && 6610 b->currentColumn == buf->currentColumn && b->pos == buf->pos) 6611 return; 6612 b = New(BufferPos); 6613 b->top_linenumber = TOP_LINENUMBER(buf); 6614 b->cur_linenumber = CUR_LINENUMBER(buf); 6615 b->currentColumn = buf->currentColumn; 6616 b->pos = buf->pos; 6617 b->bpos = buf->currentLine ? buf->currentLine->bpos : 0; 6618 b->next = NULL; 6619 b->prev = buf->undo; 6620 if (buf->undo) 6621 buf->undo->next = b; 6622 buf->undo = b; 6623 } 6624 6625 static void 6626 resetPos(BufferPos * b) 6627 { 6628 Buffer buf; 6629 Line top, cur; 6630 6631 top.linenumber = b->top_linenumber; 6632 cur.linenumber = b->cur_linenumber; 6633 cur.bpos = b->bpos; 6634 buf.topLine = ⊤ 6635 buf.currentLine = &cur; 6636 buf.pos = b->pos; 6637 buf.currentColumn = b->currentColumn; 6638 restorePosition(Currentbuf, &buf); 6639 Currentbuf->undo = b; 6640 displayBuffer(Currentbuf, B_FORCE_REDRAW); 6641 } 6642 6643 DEFUN(undoPos, UNDO, "Cancel the last cursor movement") 6644 { 6645 BufferPos *b = Currentbuf->undo; 6646 int i; 6647 6648 if (!Currentbuf->firstLine) 6649 return; 6650 if (!b || !b->prev) 6651 return; 6652 for (i = 0; i < PREC_NUM && b->prev; i++, b = b->prev) ; 6653 resetPos(b); 6654 } 6655 6656 DEFUN(redoPos, REDO, "Cancel the last undo") 6657 { 6658 BufferPos *b = Currentbuf->undo; 6659 int i; 6660 6661 if (!Currentbuf->firstLine) 6662 return; 6663 if (!b || !b->next) 6664 return; 6665 for (i = 0; i < PREC_NUM && b->next; i++, b = b->next) ; 6666 resetPos(b); 6667 }