~ubuntu-branches/ubuntu/utopic/w3m/utopic

« back to all changes in this revision

Viewing changes to .pc/240_win64gc.patch/main.c

  • Committer: Package Import Robot
  • Author(s): Tatsuya Kinoshita
  • Date: 2013-12-17 19:57:42 UTC
  • mfrom: (3.1.24 sid)
  • Revision ID: package-import@ubuntu.com-20131217195742-2mdqsjidjuwj3xz5
Tags: 0.5.3-13
* New patch 240_win64gc.patch for GC on Cygwin64
* New patch 250_schemebug.patch to fix scheme bug (closes: #650747)
* New patch 260_openssl.patch from openSUSE for OpenSSL issues
* New patch 270_refresh-url.patch to accept single quoted URL
* New patch 280_search-next.patch to fix crash after SEARCH_NEXT
* New patch 290_closedir.patch to fix a directory descriptor leak
* Update 230_cygwin-lang.patch to really fix
* Update 090_parallel-make.patch to fix scripts and w3mimg (closes: #726188)
* Update 040_link_gcc45.patch to 040_link-gtk2.patch
* Update 050_autotools-config.patch with autotools-dev 20130810.1
* Drop 050_autotools-config.patch (comment out)
* Update 900_ChangeLog.patch
* Update 015_debian-version.patch to 0.5.3+debian-13
* Use LFS_CFLAGS to support large file (closes: #493956)
* Use autotools-dev dh addon again (closes: #732086)
* Update gitlog2changelog to fix paren handling
* debian/rules: builddir fixes
* Use dpkg-maintscript-helper to remove obsolete conffile
* Update Standards-Version to 3.9.5

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