~ubuntu-branches/debian/sid/w3m/sid

« back to all changes in this revision

Viewing changes to .pc/030_pager-s-option.patch/main.c

  • Committer: Package Import Robot
  • Author(s): Tatsuya Kinoshita
  • Date: 2015-04-25 19:33:35 UTC
  • Revision ID: package-import@ubuntu.com-20150425193335-g4o8qj59ltroolv1
Tags: 0.5.3-20
* Integrate Debian changes into 020_debian.patch (closes: #776112)
  (debian/patches/*.patch except 010_upstream.patch are merged)
  - Improve English manpages
    (closes: #771003, #766550, #403634, #380560, #345084, #285251, #268211)
  - Fix Perl warnings (closes: #771004)
  - Update to 2015-02-03
* Add libsixel-bin to Suggests for img2sixel
* Set extbrowser to sensible-browser in w3mconfig
* Set mailer to use xdg-open in w3mconfig
* Add xdg-utils to Suggests for xdg-open
* Support committer date for gitlog2changelog
* Add dot to end of message for gitlog2changelog
* Update Vcs-Browser
* Update debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: main.c,v 1.270 2010/08/24 10:11:51 htrb Exp $ */
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  --&gt; %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 = &top;
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
 
}