~ubuntu-branches/ubuntu/edgy/lynx/edgy

« back to all changes in this revision

Viewing changes to src/LYMainLoop.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-16 12:14:10 UTC
  • Revision ID: james.westby@ubuntu.com-20040916121410-cz1gu92c4nqfeyrg
Tags: upstream-2.8.5
ImportĀ upstreamĀ versionĀ 2.8.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <HTUtils.h>
 
2
#include <HTAccess.h>
 
3
#include <HTParse.h>
 
4
#include <HTList.h>
 
5
#include <HTML.h>
 
6
#include <HTFTP.h>
 
7
#include <HTFile.h>
 
8
#include <HTTP.h>
 
9
#include <HTAABrow.h>
 
10
#include <HTNews.h>
 
11
#include <LYCurses.h>
 
12
#include <LYStyle.h>
 
13
#include <LYGlobalDefs.h>
 
14
#include <HTAlert.h>
 
15
#include <LYUtils.h>
 
16
#include <GridText.h>
 
17
#include <LYStrings.h>
 
18
#include <LYOptions.h>
 
19
#include <LYSignal.h>
 
20
#include <LYGetFile.h>
 
21
#include <HTForms.h>
 
22
#include <LYSearch.h>
 
23
#include <LYClean.h>
 
24
#include <LYHistory.h>
 
25
#include <LYPrint.h>
 
26
#include <LYMail.h>
 
27
#include <LYEdit.h>
 
28
#include <LYShowInfo.h>
 
29
#include <LYBookmark.h>
 
30
#include <LYKeymap.h>
 
31
#include <LYJump.h>
 
32
#include <LYDownload.h>
 
33
#include <LYList.h>
 
34
#include <LYMap.h>
 
35
#include <LYTraversal.h>
 
36
#include <LYCharSets.h>
 
37
#include <LYCharUtils.h>
 
38
#include <LYCookie.h>
 
39
#include <LYMainLoop.h>
 
40
#include <LYPrettySrc.h>
 
41
 
 
42
#ifdef KANJI_CODE_OVERRIDE
 
43
#include <HTCJK.h>
 
44
#endif
 
45
 
 
46
#ifdef KANJI_CODE_OVERRIDE
 
47
PUBLIC char *str_kcode(HTkcode code)
 
48
{
 
49
    char *p;
 
50
    static char buff[8];
 
51
 
 
52
    if (current_char_set == TRANSPARENT) {
 
53
        p = "THRU";
 
54
    } else if (!LYRawMode) {
 
55
        p = "RAW";
 
56
    } else {
 
57
        switch (code) {
 
58
        case NOKANJI:
 
59
            p = "AUTO";
 
60
            break;
 
61
 
 
62
        case EUC:
 
63
            p = "EUC+";
 
64
            break;
 
65
 
 
66
        case SJIS:
 
67
            p = "SJIS";
 
68
            break;
 
69
 
 
70
        case JIS:
 
71
            p = " JIS";
 
72
            break;
 
73
 
 
74
        default:
 
75
            p = " ???";
 
76
            break;
 
77
        }
 
78
    }
 
79
 
 
80
    if (no_table_center) {
 
81
        buff[0] = '!';
 
82
        strcpy(buff + 1, p);
 
83
    } else {
 
84
        strcpy(buff, p);
 
85
    }
 
86
 
 
87
    return buff;
 
88
}
 
89
#endif
 
90
 
 
91
#ifdef WIN_EX
 
92
 
 
93
PRIVATE char *str_sjis(char *to, char *from)
 
94
{
 
95
    if (!LYRawMode) {
 
96
        strcpy(to, from);
 
97
#ifdef KANJI_CODE_OVERRIDE
 
98
    } else if (last_kcode == EUC) {
 
99
        EUC_TO_SJIS(from, to);
 
100
    } else if (last_kcode == SJIS) {
 
101
        strcpy(to, from);
 
102
#endif
 
103
    } else {
 
104
        TO_SJIS(from, to);
 
105
    }
 
106
    return to;
 
107
}
 
108
 
 
109
PRIVATE void set_ws_title(char * str)
 
110
{
 
111
    SetConsoleTitle(str);
 
112
}
 
113
 
 
114
#endif /* WIN_EX */
 
115
 
 
116
 
 
117
#ifdef SH_EX  /* 1998/10/30 (Fri) 10:06:47 */
 
118
 
 
119
#define NOT_EQU 1
 
120
 
 
121
PRIVATE int str_n_cmp(const char *p, const char *q, int n)
 
122
{
 
123
    if (n == 0)
 
124
        return 0;
 
125
 
 
126
    if (p == NULL)
 
127
        return NOT_EQU;
 
128
 
 
129
    if (q == NULL)
 
130
        return NOT_EQU;
 
131
 
 
132
    return strncmp(p, q, n);
 
133
}
 
134
 
 
135
#undef strncmp
 
136
#define strncmp(p, q, r)        str_n_cmp(p, q, r)
 
137
 
 
138
#endif  /* SH_EX */
 
139
 
 
140
#if defined(USE_EXTERNALS) || defined(WIN_EX)
 
141
#include <LYExtern.h>
 
142
#endif
 
143
 
 
144
#ifdef __EMX__
 
145
#include <io.h>
 
146
#endif
 
147
 
 
148
#ifdef DIRED_SUPPORT
 
149
#include <LYLocal.h>
 
150
#include <LYUpload.h>
 
151
#endif /* DIRED_SUPPORT */
 
152
 
 
153
#include <LYexit.h>
 
154
#include <LYLeaks.h>
 
155
 
 
156
/* two constants: */
 
157
PUBLIC HTLinkType * HTInternalLink = 0;
 
158
PUBLIC HTAtom * WWW_SOURCE = 0;
 
159
 
 
160
#ifndef DONT_TRACK_INTERNAL_LINKS
 
161
#define NO_INTERNAL_OR_DIFFERENT(c,n) TRUE
 
162
#define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) (!curdoc.internal_link || \
 
163
                           are_phys_different(p,n))
 
164
#else /* TRACK_INTERNAL_LINKS */
 
165
#define NO_INTERNAL_OR_DIFFERENT(c,n) are_different(c,n)
 
166
#define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) are_different(p,n)
 
167
#endif /* TRACK_INTERNAL_LINKS */
 
168
 
 
169
 
 
170
PRIVATE void exit_immediately_with_error_message PARAMS((int state, BOOLEAN first_file));
 
171
PRIVATE void status_link PARAMS((char *curlink_name, BOOLEAN show_more, BOOLEAN show_indx));
 
172
PRIVATE void show_main_statusline PARAMS((CONST LinkInfo curlink, int for_what));
 
173
PRIVATE void form_noviceline PARAMS((int));
 
174
PRIVATE int are_different PARAMS((DocInfo *doc1, DocInfo *doc2));
 
175
 
 
176
#ifndef DONT_TRACK_INTERNAL_LINKS
 
177
PRIVATE int are_phys_different PARAMS((DocInfo *doc1, DocInfo *doc2));
 
178
#endif
 
179
 
 
180
#define FASTTAB
 
181
 
 
182
PRIVATE int sametext ARGS2(
 
183
        char *,         een,
 
184
        char *,         twee)
 
185
{
 
186
    if (een && twee)
 
187
        return (strcmp(een, twee) == 0);
 
188
    return TRUE;
 
189
}
 
190
 
 
191
PUBLIC  HTList * Goto_URLs = NULL;  /* List of Goto URLs */
 
192
 
 
193
PUBLIC char * LYRequestTitle = NULL; /* newdoc.title in calls to getfile() */
 
194
PUBLIC char * LYRequestReferer = NULL; /* Referer, may be set in getfile() */
 
195
 
 
196
PRIVATE char prev_target[512];
 
197
 
 
198
#ifdef DISP_PARTIAL
 
199
PUBLIC BOOLEAN display_partial = FALSE; /* could be enabled in HText_new() */
 
200
PUBLIC int NumOfLines_partial = 0;  /* number of lines displayed in partial mode */
 
201
#endif
 
202
 
 
203
PRIVATE int Newline = 0;
 
204
PRIVATE DocInfo newdoc;
 
205
PRIVATE DocInfo curdoc;
 
206
PRIVATE char *traversal_host = NULL;
 
207
PRIVATE char *traversal_link_to_add = NULL;
 
208
PRIVATE char *owner_address = NULL;  /* Holds the responsible owner's address     */
 
209
PRIVATE char *ownerS_address = NULL; /* Holds owner's address during source fetch */
 
210
 
 
211
#ifdef TEXTFIELDS_MAY_NEED_ACTIVATION
 
212
PRIVATE BOOL textinput_activated = FALSE;
 
213
#else
 
214
#define textinput_activated TRUE /* a current text input is always active */
 
215
#endif
 
216
#ifdef INACTIVE_INPUT_STYLE_VH
 
217
PUBLIC BOOL textinput_redrawn = FALSE;
 
218
    /*must be public since used in LYhighlight(..)*/
 
219
#endif
 
220
 
 
221
#ifdef LY_FIND_LEAKS
 
222
/*
 
223
 *  Function for freeing allocated mainloop() variables. - FM
 
224
 */
 
225
PRIVATE void free_mainloop_variables NOARGS
 
226
{
 
227
    LYFreeDocInfo(&newdoc);
 
228
    LYFreeDocInfo(&curdoc);
 
229
 
 
230
#ifdef USE_COLOR_STYLE
 
231
    FREE(curdoc.style);
 
232
    FREE(newdoc.style);
 
233
#endif
 
234
    FREE(traversal_host);
 
235
    FREE(traversal_link_to_add);
 
236
    FREE(owner_address);
 
237
    FREE(ownerS_address);
 
238
#ifdef DIRED_SUPPORT
 
239
    clear_tags();
 
240
    reset_dired_menu();
 
241
#endif /* DIRED_SUPPORT */
 
242
    FREE(WWW_Download_File);    /* LYGetFile.c/HTFWriter.c */
 
243
    FREE(LYRequestReferer);
 
244
 
 
245
    return;
 
246
}
 
247
#endif /* LY_FIND_LEAKS */
 
248
 
 
249
#ifndef NO_LYNX_TRACE
 
250
PRIVATE void TracelogOpenFailed NOARGS
 
251
{
 
252
    WWW_TraceFlag = FALSE;
 
253
    if (LYCursesON) {
 
254
        HTUserMsg(TRACELOG_OPEN_FAILED);
 
255
    } else {
 
256
        fprintf(stderr, "%s\n", TRACELOG_OPEN_FAILED);
 
257
        exit(EXIT_FAILURE);
 
258
    }
 
259
}
 
260
 
 
261
PRIVATE BOOLEAN LYReopenTracelog ARGS1(BOOLEAN *, trace_flag_ptr)
 
262
{
 
263
    CTRACE((tfp, "\nTurning off TRACE for fetch of log.\n"));
 
264
    LYCloseTracelog();
 
265
    if ((LYTraceLogFP = LYAppendToTxtFile(LYTraceLogPath)) == NULL) {
 
266
        TracelogOpenFailed();
 
267
        return FALSE;
 
268
    }
 
269
    if (TRACE) {
 
270
        WWW_TraceFlag = FALSE;
 
271
        *trace_flag_ptr = TRUE;
 
272
    }
 
273
    return TRUE;
 
274
}
 
275
 
 
276
PRIVATE void turn_trace_back_on ARGS1(BOOLEAN *, trace_flag_ptr)
 
277
{
 
278
    if (*trace_flag_ptr == TRUE) {
 
279
        WWW_TraceFlag = TRUE;
 
280
        *trace_flag_ptr = FALSE;
 
281
        fprintf(tfp, "Turning TRACE back on.\n\n");
 
282
    }
 
283
}
 
284
#else
 
285
#define LYReopenTracelog(flag) TRUE
 
286
#define turn_trace_back_on(flag) /*nothing*/
 
287
#endif /* NO_LYNX_TRACE */
 
288
 
 
289
PUBLIC FILE *TraceFP NOARGS
 
290
{
 
291
#ifndef NO_LYNX_TRACE
 
292
    if (LYTraceLogFP != 0) {
 
293
        return LYTraceLogFP;
 
294
    }
 
295
#endif /* NO_LYNX_TRACE */
 
296
    return stderr;
 
297
}
 
298
 
 
299
PUBLIC BOOLEAN LYOpenTraceLog NOARGS
 
300
{
 
301
#ifndef NO_LYNX_TRACE
 
302
    if (TRACE && LYUseTraceLog && LYTraceLogFP == NULL) {
 
303
        /*
 
304
         * If we can't open it for writing, give up.  Otherwise, on VMS close
 
305
         * it, delete it and any versions from previous sessions so they don't
 
306
         * accumulate, and open it again.  - FM
 
307
         */
 
308
        if ((LYTraceLogFP = LYNewTxtFile(LYTraceLogPath)) == NULL) {
 
309
            TracelogOpenFailed();
 
310
            return FALSE;
 
311
        }
 
312
#ifdef VMS
 
313
        LYCloseTracelog();
 
314
        HTSYS_remove(LYTraceLogPath);
 
315
        if ((LYTraceLogFP = LYNewTxtFile(LYTraceLogPath)) == NULL) {
 
316
            TracelogOpenFailed();
 
317
            return FALSE;
 
318
        }
 
319
#endif /* VMS */
 
320
        fflush(stdout);
 
321
        fflush(stderr);
 
322
        fprintf(tfp, "\t\t%s (%s)\n\n", LYNX_TRACELOG_TITLE, LYNX_VERSION);
 
323
        /*
 
324
         *  If TRACE is on, indicate whether the
 
325
         *  anonymous restrictions are set. - FM, LP, kw
 
326
         *  This is only a summary for convenience - it doesn't
 
327
         *  take the case of individual -restrictions= options
 
328
         *  into account. - kw
 
329
         */
 
330
        if (LYValidate) {
 
331
            if (LYRestricted && had_restrictions_default) {
 
332
                CTRACE((tfp, "Validate and some anonymous restrictions are set.\n"));
 
333
            } else if (had_restrictions_default) {
 
334
                CTRACE((tfp, "Validate restrictions set, restriction \"default\" was given.\n"));
 
335
            } else if (LYRestricted) {
 
336
                CTRACE((tfp, "Validate restrictions set, additional anonymous restrictions ignored.\n"));
 
337
            } else {
 
338
                CTRACE((tfp, "Validate restrictions are set.\n"));
 
339
            }
 
340
            /* But none of the above can actually happen, since there should
 
341
             * never be a Trace Log with -validate.  If it appears in a log
 
342
             * file something went wrong! */
 
343
        } else if (LYRestricted) {
 
344
            if (had_restrictions_all) {
 
345
                CTRACE((tfp, "Anonymous restrictions set, restriction \"all\" was given.\n"));
 
346
            } else {
 
347
                CTRACE((tfp, "Anonymous restrictions are set.\n"));
 
348
            }
 
349
        } else if (had_restrictions_all && had_restrictions_default) {
 
350
            CTRACE((tfp, "Restrictions \"all\" and \"default\" were given.\n"));
 
351
        } else if (had_restrictions_default) {
 
352
            CTRACE((tfp, "Restriction \"default\" was given.\n"));
 
353
        } else if (had_restrictions_all) {
 
354
            CTRACE((tfp, "\"all\" restrictions are set.\n"));
 
355
        }
 
356
    }
 
357
#endif /* NO_LYNX_TRACE */
 
358
    return TRUE;
 
359
}
 
360
 
 
361
PUBLIC void LYCloseTracelog NOARGS
 
362
{
 
363
#ifndef NO_LYNX_TRACE
 
364
    if (LYTraceLogFP != 0) {
 
365
        fflush(stdout);
 
366
        fflush(stderr);
 
367
        fclose(LYTraceLogFP);
 
368
        LYTraceLogFP = 0;
 
369
    }
 
370
#endif /* NO_LYNX_TRACE */
 
371
}
 
372
 
 
373
PUBLIC void handle_LYK_TRACE_TOGGLE NOARGS
 
374
{
 
375
#ifndef NO_LYNX_TRACE
 
376
    WWW_TraceFlag = ! WWW_TraceFlag;
 
377
    if (LYOpenTraceLog())
 
378
        HTUserMsg(WWW_TraceFlag ? TRACE_ON : TRACE_OFF);
 
379
#else
 
380
    HTUserMsg(TRACE_DISABLED);
 
381
#endif /* NO_LYNX_TRACE */
 
382
}
 
383
 
 
384
PUBLIC void LYSetNewline ARGS1(
 
385
        int,            value)
 
386
{
 
387
    Newline = value;
 
388
}
 
389
 
 
390
PUBLIC int LYGetNewline NOARGS
 
391
{
 
392
    return Newline;
 
393
}
 
394
 
 
395
#ifdef USE_SOURCE_CACHE
 
396
PRIVATE BOOLEAN from_source_cache = FALSE;
 
397
 
 
398
/*
 
399
 * Like HTreparse_document(), but also set the flag.
 
400
 */
 
401
PRIVATE BOOLEAN reparse_document NOARGS
 
402
{
 
403
    BOOLEAN ok;
 
404
    from_source_cache = TRUE;   /* set for LYMainLoop_pageDisplay() */
 
405
    if ((ok = HTreparse_document()) != FALSE) {
 
406
        from_source_cache = TRUE;       /* set for mainloop refresh */
 
407
        return ok;
 
408
    }
 
409
    from_source_cache = FALSE;
 
410
    return ok;
 
411
}
 
412
#endif /* USE_SOURCE_CACHE */
 
413
 
 
414
/*
 
415
 * Prefer reparsing if we can, but reload if we must - to force regeneration
 
416
 * of the display.
 
417
 */
 
418
PRIVATE BOOLEAN reparse_or_reload ARGS1(
 
419
    int *,      cmd)
 
420
{
 
421
#ifdef USE_SOURCE_CACHE
 
422
    if (reparse_document()) {
 
423
        return FALSE;
 
424
    }
 
425
#endif
 
426
    *cmd = LYK_RELOAD;
 
427
    return TRUE;
 
428
}
 
429
 
 
430
/*
 
431
 * Functions for setting the current address
 
432
 */
 
433
PRIVATE void set_address ARGS2(
 
434
        DocInfo *,      doc,
 
435
        CONST char *,   address)
 
436
{
 
437
    StrAllocCopy(doc->address, address);
 
438
}
 
439
 
 
440
PRIVATE void copy_address ARGS2(
 
441
        DocInfo *,      dst,
 
442
        DocInfo *,      src)
 
443
{
 
444
    StrAllocCopy(dst->address, src->address);
 
445
}
 
446
 
 
447
PRIVATE void free_address ARGS1(
 
448
        DocInfo *,      doc)
 
449
{
 
450
    FREE(doc->address);
 
451
}
 
452
 
 
453
PRIVATE void move_address ARGS2(
 
454
        DocInfo *,      dst,
 
455
        DocInfo *,      src)
 
456
{
 
457
    copy_address(dst, src);
 
458
    free_address(src);
 
459
}
 
460
 
 
461
#ifdef DISP_PARTIAL
 
462
/*
 
463
 * This is for traversal call from within partial mode in LYUtils.c
 
464
 * and HTFormat.c  It simply calls HText_pageDisplay() but utilizes
 
465
 * LYMainLoop.c PRIVATE variables to manage proper newline position
 
466
 * in case of #fragment
 
467
 */
 
468
PUBLIC BOOL LYMainLoop_pageDisplay ARGS1(
 
469
        int,            line_num)
 
470
{
 
471
    CONST char * pound;
 
472
    int prev_newline = Newline;
 
473
 
 
474
    /*
 
475
     *  Override Newline with a new value if user
 
476
     *  scrolled the document while loading (in LYUtils.c).
 
477
     */
 
478
    Newline = line_num;
 
479
 
 
480
#ifdef USE_SOURCE_CACHE
 
481
    /*
 
482
     * reparse_document() acts on 'curdoc' which always on top of the
 
483
     * history stack: no need to resolve #fragment position since
 
484
     * we already know it (curdoc.line).
 
485
     * So bypass here. Sorry for possible confusion...
 
486
     */
 
487
    if (!from_source_cache)
 
488
#endif
 
489
        /*
 
490
         * If the requested URL has the #fragment, and we are not popped
 
491
         * from the history stack, and have not scrolled the document yet -
 
492
         * we should calculate correct newline position for the fragment.
 
493
         * (This is a bit suboptimal since HTFindPoundSelector() traverse
 
494
         * anchors list each time, so we have a quadratic complexity
 
495
         * and may load CPU in a worst case).
 
496
         */
 
497
        if (display_partial
 
498
            && newdoc.line == 1 && line_num == 1 && prev_newline == 1
 
499
            && (pound = findPoundSelector(newdoc.address))
 
500
            && *pound && *(pound+1)) {
 
501
            if (HTFindPoundSelector(pound+1)) {
 
502
                /* HTFindPoundSelector will initialize www_search_result */
 
503
                Newline = www_search_result;
 
504
            } else {
 
505
                Newline = prev_newline; /* restore ??? */
 
506
                return NO;      /* no repaint */
 
507
            }
 
508
        }
 
509
 
 
510
    HText_pageDisplay(Newline, prev_target);
 
511
    return YES;
 
512
}
 
513
#endif /* DISP_PARTIAL */
 
514
 
 
515
 
 
516
PRIVATE void set_curdoc_link ARGS1(
 
517
    int,        nextlink)
 
518
{
 
519
    if (curdoc.link != nextlink
 
520
     && nextlink >= 0
 
521
     && nextlink < nlinks) {
 
522
        if (curdoc.link >= 0 && curdoc.link < nlinks)
 
523
            LYhighlight(OFF, curdoc.link, prev_target);
 
524
        curdoc.link = nextlink;
 
525
    }
 
526
}
 
527
 
 
528
PRIVATE int do_change_link NOARGS
 
529
{
 
530
#ifdef USE_MOUSE
 
531
    /* Is there a mouse-clicked link waiting? */
 
532
    int mouse_tmp = get_mouse_link();
 
533
    /* If yes, use it as the link */
 
534
    if (mouse_tmp != -1) {
 
535
        if (mouse_tmp < 0 || mouse_tmp >= nlinks) {
 
536
            char *msgtmp = NULL;
 
537
            HTSprintf0(&msgtmp,
 
538
                       gettext("Internal error: Invalid mouse link %d!"),
 
539
                       mouse_tmp);
 
540
            HTAlert(msgtmp);
 
541
            FREE(msgtmp);
 
542
            return(-1);         /* indicates unexpected error */
 
543
        }
 
544
        set_curdoc_link(mouse_tmp);
 
545
    }
 
546
#endif /* USE_MOUSE */
 
547
    return(0);                  /* indicates OK */
 
548
}
 
549
 
 
550
#ifdef DIRED_SUPPORT
 
551
#define DIRED_UNCACHE_1 if (LYAutoUncacheDirLists < 1) /*nothing*/ ;\
 
552
                        else HTuncache_current_document()
 
553
#define DIRED_UNCACHE_2 if (LYAutoUncacheDirLists < 2) /*nothing*/ ;\
 
554
                        else HTuncache_current_document()
 
555
#endif /* DIRED_SUPPORT */
 
556
 
 
557
PRIVATE void do_check_goto_URL ARGS3(
 
558
    char *,     user_input_buffer,
 
559
    char **,    old_user_input,
 
560
    BOOLEAN *,  force_load)
 
561
{
 
562
    static BOOLEAN always = TRUE;
 
563
    static struct {
 
564
        CONST char *name;
 
565
        BOOLEAN *flag;
 
566
    } table[] = {
 
567
        { STR_FILE_URL,         &no_file_url },
 
568
        { STR_FILE_URL,         &no_goto_file },
 
569
        { STR_LYNXEXEC,         &no_goto_lynxexec },
 
570
        { STR_LYNXPROG,         &no_goto_lynxprog },
 
571
        { STR_LYNXCGI,          &no_goto_lynxcgi },
 
572
        { STR_CSO_URL,          &no_goto_cso },
 
573
        { STR_FINGER_URL,       &no_goto_finger },
 
574
        { STR_FTP_URL,          &no_goto_ftp },
 
575
        { STR_GOPHER_URL,       &no_goto_gopher },
 
576
        { STR_HTTP_URL,         &no_goto_http },
 
577
        { STR_HTTPS_URL,        &no_goto_https },
 
578
        { STR_MAILTO_URL,       &no_goto_mailto },
 
579
        { STR_RLOGIN_URL,       &no_goto_rlogin },
 
580
        { STR_TELNET_URL,       &no_goto_telnet },
 
581
        { STR_TN3270_URL,       &no_goto_tn3270 },
 
582
        { STR_WAIS_URL,         &no_goto_wais },
 
583
#ifndef DISABLE_BIBP
 
584
        { STR_BIBP_URL,         &no_goto_bibp },
 
585
#endif
 
586
#ifndef DISABLE_NEWS
 
587
        { STR_NEWS_URL,         &no_goto_news },
 
588
        { STR_NNTP_URL,         &no_goto_nntp },
 
589
        { STR_SNEWS_URL,        &no_goto_snews },
 
590
#endif
 
591
#ifdef EXEC_LINKS
 
592
        { STR_LYNXEXEC,         &local_exec_on_local_files },
 
593
        { STR_LYNXPROG,         &local_exec_on_local_files },
 
594
#endif /* EXEC_LINKS */
 
595
        { STR_LYNXCFG,          &no_goto_configinfo },
 
596
        { STR_LYNXCFLAGS,       &no_goto_configinfo },
 
597
        { STR_LYNXCOOKIE,       &always },
 
598
        { STR_LYNXDIRED,        &always },
 
599
        { STR_LYNXDOWNLOAD,     &always },
 
600
        { STR_LYNXOPTIONS,      &always },
 
601
        { STR_LYNXPRINT,        &always },
 
602
    };
 
603
    unsigned n;
 
604
    BOOLEAN found = FALSE;
 
605
 
 
606
    /* allow going to anchors*/
 
607
    if (*user_input_buffer == '#' ) {
 
608
        if ( user_input_buffer[1] &&
 
609
             HTFindPoundSelector(user_input_buffer+1) ) {
 
610
             /* HTFindPoundSelector will initialize www_search_result,
 
611
                so we do nothing else. */
 
612
            HTAddGotoURL(user_input_buffer);
 
613
            trimPoundSelector(curdoc.address);
 
614
            StrAllocCat(curdoc.address, user_input_buffer);
 
615
        }
 
616
    } else {
 
617
        /*
 
618
         * If it's not a URL then make it one.
 
619
         */
 
620
        StrAllocCopy(*old_user_input, user_input_buffer);
 
621
        LYEnsureAbsoluteURL(old_user_input, "", TRUE);
 
622
        sprintf(user_input_buffer, "%.*s",
 
623
                (int)(MAX_LINE - 1), *old_user_input);
 
624
        FREE(*old_user_input);
 
625
 
 
626
        for (n = 0; n < TABLESIZE(table); n++) {
 
627
            if (*(table[n].flag)
 
628
             && !strncmp(user_input_buffer, table[n].name, strlen(table[n].name))) {
 
629
                found = TRUE;
 
630
                HTUserMsg2(GOTO_XXXX_DISALLOWED, table[n].name);
 
631
                break;
 
632
            }
 
633
        }
 
634
        if (found) {
 
635
            ;
 
636
        } else if (LYValidate &&
 
637
                   !isHTTP_URL(user_input_buffer) &&
 
638
                   !isHTTPS_URL(user_input_buffer)) {
 
639
            HTUserMsg(GOTO_NON_HTTP_DISALLOWED);
 
640
 
 
641
        } else {
 
642
            set_address(&newdoc, user_input_buffer);
 
643
            newdoc.isHEAD = FALSE;
 
644
            /*
 
645
             *  Might be an anchor in the same doc from a POST
 
646
             *  form.  If so, dont't free the content. -- FM
 
647
             */
 
648
            if (are_different(&curdoc, &newdoc)) {
 
649
                /*
 
650
                 * Make a name for this new URL.
 
651
                 */
 
652
                StrAllocCopy(newdoc.title, gettext("A URL specified by the user"));
 
653
                LYFreePostData(&newdoc);
 
654
                FREE(newdoc.bookmark);
 
655
                newdoc.safe = FALSE;
 
656
                newdoc.internal_link = FALSE;
 
657
                *force_load = TRUE;
 
658
#ifdef DIRED_SUPPORT
 
659
                if (lynx_edit_mode) {
 
660
                    DIRED_UNCACHE_2;
 
661
                }
 
662
#endif /* DIRED_SUPPORT */
 
663
            }
 
664
            LYUserSpecifiedURL = TRUE;
 
665
            HTAddGotoURL(newdoc.address);
 
666
        }
 
667
    }
 
668
}
 
669
 
 
670
/* returns FALSE if user cancelled input or URL was invalid, TRUE otherwise */
 
671
PRIVATE BOOL do_check_recall ARGS7(
 
672
    int,        ch,
 
673
    char *,     user_input_buffer,
 
674
    char **,    old_user_input,
 
675
    int,        URLTotal,
 
676
    int *,      URLNum,
 
677
    int,        recall,
 
678
    BOOLEAN *,  FirstURLRecall)
 
679
{
 
680
    char *cp;
 
681
    BOOL ret = FALSE;
 
682
 
 
683
    if (*old_user_input == 0)
 
684
        StrAllocCopy(*old_user_input, "");
 
685
 
 
686
    for (;;) {
 
687
#ifdef WIN_EX   /* 1998/10/11 (Sun) 10:41:05 */
 
688
        int len = strlen(user_input_buffer);
 
689
 
 
690
        if (len >= 3) {
 
691
            if (len < MAX_LINE - 1
 
692
             && LYIsHtmlSep(user_input_buffer[len - 3])
 
693
             && LYIsDosDrive(user_input_buffer + len - 2))
 
694
                LYAddPathSep0(user_input_buffer);
 
695
 
 
696
        } else if (len == 2 && user_input_buffer[1] == ':') {
 
697
                if (LYIsDosDrive(user_input_buffer)) {
 
698
                        LYAddPathSep0(user_input_buffer);
 
699
                } else {
 
700
                        HTUserMsg2(WWW_ILLEGAL_URL_MESSAGE, user_input_buffer);
 
701
                        LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1);
 
702
                        FREE(*old_user_input);
 
703
                        ret = FALSE;
 
704
                        break;
 
705
                }
 
706
        }
 
707
#endif
 
708
        /*
 
709
         * Get rid of leading spaces (and any other spaces).
 
710
         */
 
711
        LYTrimAllStartfile(user_input_buffer);
 
712
        if (*user_input_buffer == '\0' &&
 
713
            !(recall && (ch == UPARROW || ch == DNARROW))) {
 
714
            LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1);
 
715
            FREE(*old_user_input);
 
716
            HTInfoMsg(CANCELLED);
 
717
            ret = FALSE;
 
718
            break;
 
719
        }
 
720
        if (recall && ch == UPARROW) {
 
721
            if (*FirstURLRecall) {
 
722
                /*
 
723
                 * Use last URL in the list.  - FM
 
724
                 */
 
725
                *FirstURLRecall = FALSE;
 
726
                *URLNum = 0;
 
727
            } else {
 
728
                /*
 
729
                 * Go back to the previous URL in the list.  - FM
 
730
                 */
 
731
                *URLNum += 1;
 
732
            }
 
733
            if (*URLNum >= URLTotal)
 
734
                /*
 
735
                 * Roll around to the last URL in the list.  - FM
 
736
                 */
 
737
                *URLNum = 0;
 
738
            if ((cp = (char *)HTList_objectAt(Goto_URLs,
 
739
                                              *URLNum)) != NULL) {
 
740
                LYstrncpy(user_input_buffer, cp, MAX_LINE - 1);
 
741
                if (goto_buffer
 
742
                 && **old_user_input
 
743
                 && !strcmp(*old_user_input, user_input_buffer)) {
 
744
                    _statusline(EDIT_CURRENT_GOTO);
 
745
                } else if ((goto_buffer && URLTotal == 2) ||
 
746
                           (!goto_buffer && URLTotal == 1)) {
 
747
                    _statusline(EDIT_THE_PREV_GOTO);
 
748
                } else {
 
749
                    _statusline(EDIT_A_PREV_GOTO);
 
750
                }
 
751
                if ((ch = LYgetstr(user_input_buffer, VISIBLE,
 
752
                                  MAX_LINE,
 
753
                                  recall)) < 0) {
 
754
                    /*
 
755
                     *  User cancelled the Goto via ^G.
 
756
                     *  Restore user_input_buffer and break. - FM
 
757
                     */
 
758
                    LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1);
 
759
                    FREE(*old_user_input);
 
760
                    HTInfoMsg(CANCELLED);
 
761
                    ret = FALSE;
 
762
                    break;
 
763
                }
 
764
                continue;
 
765
            }
 
766
        } else if (recall && ch == DNARROW) {
 
767
            if (*FirstURLRecall) {
 
768
                /*
 
769
                 * Use the first URL in the list.  - FM
 
770
                 */
 
771
                *FirstURLRecall = FALSE;
 
772
                *URLNum = URLTotal - 1;
 
773
            } else {
 
774
                /*
 
775
                 * Advance to the next URL in the list.  - FM
 
776
                 */
 
777
                *URLNum -= 1;
 
778
            }
 
779
            if (*URLNum < 0)
 
780
                /*
 
781
                 * Roll around to the first URL in the list.  - FM
 
782
                 */
 
783
                *URLNum = URLTotal - 1;
 
784
            if ((cp=(char *)HTList_objectAt(Goto_URLs, *URLNum)) != NULL) {
 
785
                LYstrncpy(user_input_buffer, cp, MAX_LINE - 1);
 
786
                if (goto_buffer && **old_user_input &&
 
787
                    !strcmp(*old_user_input, user_input_buffer)) {
 
788
                    _statusline(EDIT_CURRENT_GOTO);
 
789
                } else if ((goto_buffer && URLTotal == 2) ||
 
790
                           (!goto_buffer && URLTotal == 1)) {
 
791
                    _statusline(EDIT_THE_PREV_GOTO);
 
792
                } else {
 
793
                    _statusline(EDIT_A_PREV_GOTO);
 
794
                }
 
795
                if ((ch = LYgetstr(user_input_buffer, VISIBLE,
 
796
                                   MAX_LINE,
 
797
                                   recall)) < 0) {
 
798
                    /*
 
799
                     *  User cancelled the Goto via ^G.
 
800
                     *  Restore user_input_buffer and break. - FM
 
801
                     */
 
802
                    LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1);
 
803
                    FREE(*old_user_input);
 
804
                    HTInfoMsg(CANCELLED);
 
805
                    ret = FALSE;
 
806
                    break;
 
807
                }
 
808
                continue;
 
809
            }
 
810
        } else {
 
811
            ret = TRUE;
 
812
            break;
 
813
        }
 
814
    }
 
815
    return ret;
 
816
}
 
817
 
 
818
PRIVATE void do_cleanup_after_delete NOARGS
 
819
{
 
820
    HTuncache_current_document();
 
821
    move_address(&newdoc, &curdoc);
 
822
    newdoc.line = curdoc.line;
 
823
    if (curdoc.link == nlinks-1) {
 
824
        /*
 
825
         * We deleted the last link on the page.  - FM
 
826
         */
 
827
        newdoc.link = curdoc.link-1;
 
828
    } else {
 
829
        newdoc.link = curdoc.link;
 
830
    }
 
831
}
 
832
 
 
833
PRIVATE int find_link_near_col ARGS2(
 
834
        int,    col,
 
835
        int,    delta)
 
836
{
 
837
    int i;
 
838
 
 
839
    for (i = curdoc.link; delta > 0 ? (i < nlinks) : (i >= 0); i += delta) {
 
840
        if ( (links[i].ly - links[curdoc.link].ly) * delta > 0 ) {
 
841
            int cy = links[i].ly, best = -1, dist = 1000000;
 
842
 
 
843
            while ((delta > 0 ? (i < nlinks) : (i >= 0)) && cy == links[i].ly) {
 
844
                int cx = links[i].lx;
 
845
                char *text = LYGetHiliteStr(i, 0);
 
846
 
 
847
                if (text != NULL)
 
848
                    cx += strlen(text) / 2;
 
849
                cx -= col;
 
850
                if (cx < 0)
 
851
                    cx = -cx;
 
852
                if (cx < dist) {
 
853
                    dist = cx;
 
854
                    best = i;
 
855
                }
 
856
                i += delta;
 
857
            }
 
858
            return(best);
 
859
        }
 
860
    }
 
861
    return(-1);
 
862
}
 
863
 
 
864
/*
 
865
 * This is a special feature to traverse every http link derived from startfile
 
866
 * and check for errors or create crawl output files.  Only URL's that begin
 
867
 * with "traversal_host" are searched - this keeps the search from crossing to
 
868
 * other servers (a feature, not a bug!).
 
869
 */
 
870
PRIVATE int DoTraversal ARGS2(
 
871
    int,        c,
 
872
    BOOLEAN *,  crawl_ok)
 
873
{
 
874
    BOOLEAN rlink_rejected = FALSE;
 
875
    BOOLEAN rlink_exists;
 
876
    BOOLEAN rlink_allowed;
 
877
 
 
878
    rlink_exists = (BOOL) (nlinks > 0 &&
 
879
                    links[curdoc.link].type != WWW_FORM_LINK_TYPE &&
 
880
                    links[curdoc.link].lname != NULL);
 
881
 
 
882
    if (rlink_exists) {
 
883
        rlink_rejected = lookup_reject(links[curdoc.link].lname);
 
884
        if (!rlink_rejected &&
 
885
             traversal_host &&
 
886
             links[curdoc.link].lname) {
 
887
            if (!isLYNXIMGMAP(links[curdoc.link].lname)) {
 
888
                rlink_allowed = (BOOL) !strncmp(traversal_host,
 
889
                                         links[curdoc.link].lname,
 
890
                                         strlen(traversal_host));
 
891
            } else {
 
892
                rlink_allowed = (BOOL) !strncmp(traversal_host,
 
893
                                         links[curdoc.link].lname + LEN_LYNXIMGMAP,
 
894
                                         strlen(traversal_host));
 
895
            }
 
896
        } else {
 
897
            rlink_allowed = FALSE;
 
898
        }
 
899
    } else {
 
900
        rlink_allowed = FALSE;
 
901
    }
 
902
    if (rlink_exists && rlink_allowed) {
 
903
        if (lookup(links[curdoc.link].lname)) {
 
904
            if (more_links ||
 
905
                (curdoc.link > -1 && curdoc.link < nlinks -1))
 
906
                 c= DNARROW;
 
907
            else {
 
908
                if (STREQ(curdoc.title,"Entry into main screen") ||
 
909
                    (nhist <= 0 )) {
 
910
                    if (!dump_output_immediately) {
 
911
                        cleanup();
 
912
                        exit_immediately(EXIT_FAILURE);
 
913
                    }
 
914
                    return(-1);
 
915
                }
 
916
                c = LTARROW;
 
917
            }
 
918
        } else {
 
919
            StrAllocCopy(traversal_link_to_add,
 
920
                         links[curdoc.link].lname);
 
921
            if (!isLYNXIMGMAP(traversal_link_to_add))
 
922
                *crawl_ok = TRUE;
 
923
            c = RTARROW;
 
924
        }
 
925
    } else { /* no good right link, so only down and left arrow ok*/
 
926
        if (rlink_exists /* && !rlink_rejected */)
 
927
            /* uncomment in previous line to avoid duplicates - kw */
 
928
            add_to_reject_list(links[curdoc.link].lname);
 
929
        if (more_links ||
 
930
            (curdoc.link > -1 && curdoc.link < nlinks-1))
 
931
            c = DNARROW;
 
932
        else {
 
933
            /*
 
934
             *  curdoc.title doesn't always work, so
 
935
             *  bail out if the history list is empty.
 
936
             */
 
937
            if (STREQ(curdoc.title,"Entry into main screen") ||
 
938
                (nhist <= 0 )) {
 
939
                if (!dump_output_immediately) {
 
940
                    cleanup();
 
941
                    exit_immediately(EXIT_FAILURE);
 
942
                }
 
943
                return(-1);
 
944
            }
 
945
            c = LTARROW;
 
946
        }
 
947
    } /* right link not NULL or link to another site*/
 
948
    return c;
 
949
}
 
950
 
 
951
#ifndef DONT_TRACK_INTERNAL_LINKS
 
952
PRIVATE BOOLEAN check_history NOARGS
 
953
{
 
954
    CONST char *base;
 
955
 
 
956
    if (!curdoc.post_data)
 
957
        /*
 
958
         *  Normal case - List Page is not associated
 
959
         *  with post data. - kw
 
960
         */
 
961
        return TRUE;
 
962
 
 
963
    if (nhist > 0
 
964
     && !LYresubmit_posts
 
965
     && HDOC(nhist - 1).post_data
 
966
     && BINEQ(curdoc.post_data, HDOC(nhist - 1).post_data)
 
967
     && (base = HText_getContentBase()) != 0) {
 
968
         char *text = !isLYNXIMGMAP(HDOC(nhist - 1).address)
 
969
                     ? HDOC(nhist - 1).address
 
970
                     : HDOC(nhist - 1).address + LEN_LYNXIMGMAP;
 
971
        if (!strncmp(base, text, strlen(base))) {
 
972
            /*
 
973
             * Normal case - as best as we can check, the document at the top
 
974
             * of the history stack seems to be the document the List Page is
 
975
             * about (or a LYNXIMGMAP derived from it), and LYresubmit_posts is
 
976
             * not set, so don't prompt here.  If we actually have to repeat a
 
977
             * POST because, against expectations, the underlying document
 
978
             * isn't cached any more, HTAccess will prompt for confirmation,
 
979
             * unless we had LYK_NOCACHE -kw
 
980
             */
 
981
            return TRUE;
 
982
        }
 
983
    }
 
984
    return FALSE;
 
985
}
 
986
#endif
 
987
 
 
988
PRIVATE int handle_LYK_ACTIVATE ARGS6(
 
989
    int *,      c,
 
990
    int,        cmd GCC_UNUSED,
 
991
    BOOLEAN *,  try_internal GCC_UNUSED,
 
992
    BOOLEAN *,  refresh_screen,
 
993
    BOOLEAN *,  force_load,
 
994
    int,        real_cmd)
 
995
{
 
996
    if (do_change_link() == -1) {
 
997
        LYforce_no_cache = FALSE;
 
998
        reloading = FALSE;
 
999
        return 1;       /* mouse stuff was confused, ignore - kw */
 
1000
    }
 
1001
    if (nlinks > 0) {
 
1002
        if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
 
1003
#ifdef TEXTFIELDS_MAY_NEED_ACTIVATION
 
1004
            if (real_cmd == LYK_ACTIVATE && textfields_need_activation &&
 
1005
                F_TEXTLIKE(links[curdoc.link].l_form->type)) {
 
1006
 
 
1007
                textinput_activated = TRUE;
 
1008
                show_main_statusline(links[curdoc.link], FOR_INPUT);
 
1009
                textfields_need_activation = textfields_activation_option;
 
1010
 
 
1011
                return 0;
 
1012
            }
 
1013
#endif
 
1014
            /*
 
1015
             *  Don't try to submit forms with bad actions. - FM
 
1016
             */
 
1017
            if (links[curdoc.link].l_form->type == F_SUBMIT_TYPE ||
 
1018
                links[curdoc.link].l_form->type == F_IMAGE_SUBMIT_TYPE ||
 
1019
                links[curdoc.link].l_form->type ==
 
1020
                                            F_TEXT_SUBMIT_TYPE) {
 
1021
                /*
 
1022
                 *  Do nothing if it's disabled. - FM
 
1023
                 */
 
1024
                if (links[curdoc.link].l_form->disabled == YES) {
 
1025
                    HTOutputFormat = WWW_PRESENT;
 
1026
                    LYforce_no_cache = FALSE;
 
1027
                    reloading = FALSE;
 
1028
                    return 0;
 
1029
                }
 
1030
                /*
 
1031
                 *  Make sure we have an action. - FM
 
1032
                 */
 
1033
                if (!links[curdoc.link].l_form->submit_action ||
 
1034
                    *links[curdoc.link].l_form->submit_action
 
1035
                                                        == '\0') {
 
1036
                    HTUserMsg(NO_FORM_ACTION);
 
1037
                    HTOutputFormat = WWW_PRESENT;
 
1038
                    LYforce_no_cache = FALSE;
 
1039
                    reloading = FALSE;
 
1040
                    return 0;
 
1041
                }
 
1042
                /*
 
1043
                 *  Check for no_mail if the form action
 
1044
                 *  is a mailto URL. - FM
 
1045
                 */
 
1046
                if (links[curdoc.link].l_form->submit_method
 
1047
                             == URL_MAIL_METHOD && no_mail) {
 
1048
                    HTAlert(FORM_MAILTO_DISALLOWED);
 
1049
                    HTOutputFormat = WWW_PRESENT;
 
1050
                    LYforce_no_cache = FALSE;
 
1051
                    reloading = FALSE;
 
1052
                    return 0;
 
1053
                }
 
1054
                /*
 
1055
                 *  Make sure this isn't a spoof in an account
 
1056
                 *  with restrictions on file URLs. - FM
 
1057
                 */
 
1058
                if (no_file_url &&
 
1059
                    isFILE_URL(links[curdoc.link].l_form->submit_action)) {
 
1060
                    HTAlert(FILE_ACTIONS_DISALLOWED);
 
1061
                    HTOutputFormat = WWW_PRESENT;
 
1062
                    LYforce_no_cache = FALSE;
 
1063
                    reloading = FALSE;
 
1064
                    return 0;
 
1065
                }
 
1066
                /*
 
1067
                 *  Make sure this isn't a spoof attempt
 
1068
                 *  via an internal URL. - FM
 
1069
                 */
 
1070
                if (isLYNXCOOKIE(links[curdoc.link].l_form->submit_action) ||
 
1071
#ifdef DIRED_SUPPORT
 
1072
#ifdef OK_PERMIT
 
1073
                    (isLYNXDIRED(links[curdoc.link].l_form->submit_action) &&
 
1074
                     (no_dired_support ||
 
1075
                      strncasecomp(
 
1076
                        (links[curdoc.link].l_form->submit_action + 10),
 
1077
                                   "//PERMIT_LOCATION", 17) ||
 
1078
                      !LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS))) ||
 
1079
#else
 
1080
                    isLYNXDIRED(links[curdoc.link].l_form->submit_action) ||
 
1081
#endif /* OK_PERMIT */
 
1082
#endif /* DIRED_SUPPORT */
 
1083
                    isLYNXDOWNLOAD(links[curdoc.link].l_form->submit_action) ||
 
1084
                    isLYNXHIST(links[curdoc.link].l_form->submit_action) ||
 
1085
                    isLYNXKEYMAP(links[curdoc.link].l_form->submit_action) ||
 
1086
                    isLYNXIMGMAP(links[curdoc.link].l_form->submit_action) ||
 
1087
                    isLYNXPRINT(links[curdoc.link].l_form->submit_action) ||
 
1088
                    isLYNXEXEC(links[curdoc.link].l_form->submit_action) ||
 
1089
                    isLYNXPROG(links[curdoc.link].l_form->submit_action)) {
 
1090
 
 
1091
                    HTAlert(SPECIAL_ACTION_DISALLOWED);
 
1092
                    CTRACE((tfp, "LYMainLoop: Rejected '%s'\n",
 
1093
                                links[curdoc.link].l_form->submit_action));
 
1094
                    HTOutputFormat = WWW_PRESENT;
 
1095
                    LYforce_no_cache = FALSE;
 
1096
                    reloading = FALSE;
 
1097
                    return 0;
 
1098
                }
 
1099
#ifdef NOTDEFINED /* We're disabling form inputs instead of using this. - FM */
 
1100
                /*
 
1101
                 *  Check for enctype and let user know we
 
1102
                 *  don't yet support multipart/form-data - FM
 
1103
                 */
 
1104
                if (links[curdoc.link].l_form->submit_enctype) {
 
1105
                    if (!strcmp(
 
1106
                             links[curdoc.link].l_form->submit_enctype,
 
1107
                                "multipart/form-data")) {
 
1108
                        HTAlert(
 
1109
gettext("Enctype multipart/form-data not yet supported!  Cannot submit."));
 
1110
                        HTOutputFormat = WWW_PRESENT;
 
1111
                        LYforce_no_cache = FALSE;
 
1112
                        reloading = FALSE;
 
1113
                        return 0;
 
1114
                    }
 
1115
                }
 
1116
#endif /* NOTDEFINED */
 
1117
                if (check_realm) {
 
1118
                    LYPermitURL = TRUE;
 
1119
                }
 
1120
                if (no_filereferer == TRUE && isFILE_URL(curdoc.address)) {
 
1121
                    LYNoRefererForThis = TRUE;
 
1122
                }
 
1123
                if (links[curdoc.link].l_form->submit_method != URL_MAIL_METHOD) {
 
1124
                    StrAllocCopy(newdoc.title,
 
1125
                                 LYGetHiliteStr(curdoc.link, 0));
 
1126
                }
 
1127
            }
 
1128
 
 
1129
            /*
 
1130
             *  Normally we don't get here for text input fields,
 
1131
             *  but it can happen as a result of mouse positioning.
 
1132
             *  In that case the statusline will not have updated
 
1133
             *  info, so update it now. - kw
 
1134
             */
 
1135
            if (F_TEXTLIKE(links[curdoc.link].l_form->type)) {
 
1136
                show_formlink_statusline(links[curdoc.link].l_form,
 
1137
                                         (real_cmd == LYK_NOCACHE ||
 
1138
                                          real_cmd == LYK_DOWNLOAD ||
 
1139
                                          real_cmd == LYK_HEAD ||
 
1140
                                          (real_cmd == LYK_SUBMIT &&
 
1141
                                           !textinput_activated)) ?
 
1142
                                         FOR_PANEL : FOR_INPUT);
 
1143
                if (user_mode == NOVICE_MODE &&
 
1144
                    textinput_activated &&
 
1145
                    (real_cmd == LYK_ACTIVATE || real_cmd == LYK_SUBMIT)) {
 
1146
                        form_noviceline(links[curdoc.link].l_form->disabled);
 
1147
                }
 
1148
            }
 
1149
 
 
1150
            *c = change_form_link(curdoc.link,
 
1151
                                 &newdoc, refresh_screen,
 
1152
                                 FALSE,
 
1153
                                 (BOOLEAN)(real_cmd == LYK_SUBMIT ||
 
1154
                                  real_cmd == LYK_NOCACHE ||
 
1155
                                  real_cmd == LYK_DOWNLOAD ||
 
1156
                                  real_cmd == LYK_HEAD));
 
1157
            if (*c != LKC_DONE || *refresh_screen) {
 
1158
                /*
 
1159
                 *  Cannot have been a submit field for which
 
1160
                 *  newdoc was filled in. - kw
 
1161
                 */
 
1162
                if ((links[curdoc.link].l_form->type == F_SUBMIT_TYPE ||
 
1163
                     links[curdoc.link].l_form->type == F_IMAGE_SUBMIT_TYPE ||
 
1164
                     links[curdoc.link].l_form->type == F_TEXT_SUBMIT_TYPE) &&
 
1165
                    links[curdoc.link].l_form->submit_method
 
1166
                             != URL_MAIL_METHOD) {
 
1167
                    /*
 
1168
                     *  Try to undo change of newdoc.title done above.
 
1169
                     */
 
1170
                    if (HText_getTitle()) {
 
1171
                        StrAllocCopy(newdoc.title, HText_getTitle());
 
1172
                    } else if (curdoc.title) {
 
1173
                        StrAllocCopy(newdoc.title, curdoc.title);
 
1174
                    }
 
1175
                }
 
1176
            } else {
 
1177
                if (HTOutputFormat == HTAtom_for("www/download") &&
 
1178
                    newdoc.post_data != NULL &&
 
1179
                    newdoc.safe == FALSE) {
 
1180
 
 
1181
                    if ((HText_POSTReplyLoaded(&newdoc) == TRUE) &&
 
1182
                        HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
 
1183
                        HTInfoMsg(CANCELLED);
 
1184
                        HTOutputFormat = WWW_PRESENT;
 
1185
                        LYforce_no_cache = FALSE;
 
1186
                        copy_address(&newdoc, &curdoc);
 
1187
                        StrAllocCopy(newdoc.title, curdoc.title);
 
1188
                        BStrCopy(newdoc.post_data, curdoc.post_data);
 
1189
                        StrAllocCopy(newdoc.post_content_type,
 
1190
                                     curdoc.post_content_type);
 
1191
                        StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
 
1192
                        newdoc.isHEAD = curdoc.isHEAD;
 
1193
                        newdoc.safe = curdoc.safe;
 
1194
                        newdoc.internal_link = curdoc.internal_link;
 
1195
                        return 0;
 
1196
                    }
 
1197
                }
 
1198
                /*
 
1199
                 *  Moved here from earlier to only apply when it
 
1200
                 *  should.   Anyway, why should realm checking be
 
1201
                 *  overridden for form submissions, this seems to
 
1202
                 *  be an unnecessary loophole??  But that's the way
 
1203
                 *  it was, maybe there is some reason.
 
1204
                 *  However, at least make sure this doesn't weaken
 
1205
                 *  restrictions implied by -validate!
 
1206
                 *  - kw 1999-05-25
 
1207
                 */
 
1208
                if (check_realm && !LYValidate) {
 
1209
                    LYPermitURL = TRUE;
 
1210
                }
 
1211
            }
 
1212
            if (*c == LKC_DONE) {
 
1213
                *c = DO_NOTHING;
 
1214
            } else if (*c == 23) {
 
1215
                *c = DO_NOTHING;
 
1216
                *refresh_screen = TRUE;
 
1217
            } else {
 
1218
                /*  Avoid getting stuck with repeatedly calling
 
1219
                **  handle_LYK_ACTIVATE(), instead of calling
 
1220
                **  change_form_link() directly from mainloop(),
 
1221
                **  for text input fields. - kw
 
1222
                */
 
1223
                switch (LKC_TO_C(*c)) {
 
1224
                case '\n':
 
1225
                case '\r':
 
1226
                default:
 
1227
                    if ((real_cmd == LYK_ACTIVATE || real_cmd == LYK_SUBMIT) &&
 
1228
                        F_TEXTLIKE(links[curdoc.link].l_form->type) &&
 
1229
                        textinput_activated)
 
1230
                        return 3;
 
1231
                    break;
 
1232
                }
 
1233
            }
 
1234
            return 2;
 
1235
        } else {
 
1236
            /*
 
1237
             *  Not a forms link.
 
1238
             *
 
1239
             *  Make sure this isn't a spoof in an account
 
1240
             *  with restrictions on file URLs. - FM
 
1241
             */
 
1242
            if (no_file_url && isFILE_URL(links[curdoc.link].lname)) {
 
1243
                if (!isFILE_URL(curdoc.address) &&
 
1244
                    !((isLYNXKEYMAP(curdoc.address) ||
 
1245
                       isLYNXCOOKIE(curdoc.address)) &&
 
1246
                      !strncmp(links[curdoc.link].lname,
 
1247
                               helpfilepath,
 
1248
                               strlen(helpfilepath)))) {
 
1249
                    HTAlert(FILE_SERVED_LINKS_DISALLOWED);
 
1250
                    reloading = FALSE;
 
1251
                    return 0;
 
1252
                } else if (curdoc.bookmark != NULL) {
 
1253
                    HTAlert(FILE_BOOKMARKS_DISALLOWED);
 
1254
                    reloading = FALSE;
 
1255
                    return 0;
 
1256
                }
 
1257
            }
 
1258
            /*
 
1259
             *  Make sure this isn't a spoof attempt
 
1260
             *  via an internal URL in a non-internal
 
1261
             *  document. - FM
 
1262
             */
 
1263
            if ((isLYNXCOOKIE(links[curdoc.link].lname) &&
 
1264
                 (strcmp(NonNull(curdoc.title), COOKIE_JAR_TITLE) ||
 
1265
                  !isLYNXCOOKIE(curdoc.address))) ||
 
1266
#ifdef DIRED_SUPPORT
 
1267
                (isLYNXDIRED(links[curdoc.link].lname) &&
 
1268
                 !LYIsUIPage(curdoc.address, UIP_DIRED_MENU) &&
 
1269
                 !LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS) &&
 
1270
#ifdef OK_INSTALL
 
1271
                 !LYIsUIPage(curdoc.address, UIP_INSTALL) &&
 
1272
#endif /* OK_INSTALL */
 
1273
                 !LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS)) ||
 
1274
#endif /* DIRED_SUPPORT */
 
1275
                (isLYNXDOWNLOAD(links[curdoc.link].lname) &&
 
1276
                 !LYIsUIPage(curdoc.address, UIP_DOWNLOAD_OPTIONS)) ||
 
1277
                (isLYNXHIST(links[curdoc.link].lname) &&
 
1278
                 !LYIsUIPage(curdoc.address, UIP_HISTORY) &&
 
1279
                 !LYIsUIPage(curdoc.address, UIP_LIST_PAGE) &&
 
1280
                 !LYIsUIPage(curdoc.address, UIP_ADDRLIST_PAGE)) ||
 
1281
                (isLYNXPRINT(links[curdoc.link].lname) &&
 
1282
                 !LYIsUIPage(curdoc.address, UIP_PRINT_OPTIONS))) {
 
1283
                    HTAlert(SPECIAL_VIA_EXTERNAL_DISALLOWED);
 
1284
                    HTOutputFormat = WWW_PRESENT;
 
1285
                    LYforce_no_cache = FALSE;
 
1286
                    reloading = FALSE;
 
1287
                    return 0;
 
1288
                }
 
1289
 
 
1290
#ifdef USE_EXTERNALS
 
1291
            if (run_external(links[curdoc.link].lname, TRUE))
 
1292
            {
 
1293
                *refresh_screen = TRUE;
 
1294
                return 0;
 
1295
            }
 
1296
#endif /* USE_EXTERNALS */
 
1297
 
 
1298
            /*
 
1299
             *  Follow a normal link or anchor.
 
1300
             */
 
1301
            set_address(&newdoc, links[curdoc.link].lname);
 
1302
            StrAllocCopy(newdoc.title, LYGetHiliteStr(curdoc.link, 0));
 
1303
#ifndef DONT_TRACK_INTERNAL_LINKS
 
1304
        /*
 
1305
         *  For internal links, retain POST content if present.
 
1306
         *  If we are on the List Page, prevent pushing it on
 
1307
         *  the history stack.  Otherwise set try_internal to
 
1308
         *  signal that the top of the loop should attempt to
 
1309
         *  reposition directly, without calling getfile. - kw
 
1310
         */
 
1311
            /*
 
1312
             *  Might be an internal link anchor in the same doc.
 
1313
             *  If so, take the try_internal shortcut if we didn't
 
1314
             *  fall through from LYK_NOCACHE. - kw
 
1315
             */
 
1316
            newdoc.internal_link =
 
1317
                (links[curdoc.link].type == WWW_INTERN_LINK_TYPE);
 
1318
            if (newdoc.internal_link) {
 
1319
                /*
 
1320
                 *  Special case of List Page document with an
 
1321
                 *  internal link indication, which may really stand
 
1322
                 *  for an internal link within the document the
 
1323
                 *  List Page is about. - kw
 
1324
                 */
 
1325
                if (LYIsListpageTitle(NonNull(curdoc.title)) &&
 
1326
                    (LYIsUIPage(curdoc.address, UIP_LIST_PAGE) ||
 
1327
                     LYIsUIPage(curdoc.address, UIP_ADDRLIST_PAGE))) {
 
1328
                    if (check_history()) {
 
1329
                        LYinternal_flag = TRUE;
 
1330
                    } else {
 
1331
                        HTLastConfirmCancelled(); /* reset flag */
 
1332
                        if (!confirm_post_resub(newdoc.address,
 
1333
                                                newdoc.title,
 
1334
                                        (LYresubmit_posts &&
 
1335
                               HText_POSTReplyLoaded(&newdoc)) ? 1 : 2,
 
1336
                                                2)) {
 
1337
                            if (HTLastConfirmCancelled() ||
 
1338
                                (LYresubmit_posts &&
 
1339
                                 cmd != LYK_NOCACHE &&
 
1340
                                 !HText_POSTReplyLoaded(&newdoc))) {
 
1341
                                /* cancel the whole thing */
 
1342
                                LYforce_no_cache = FALSE;
 
1343
                                reloading = FALSE;
 
1344
                                copy_address(&newdoc, &curdoc);
 
1345
                                StrAllocCopy(newdoc.title, curdoc.title);
 
1346
                                newdoc.internal_link = curdoc.internal_link;
 
1347
                                HTInfoMsg(CANCELLED);
 
1348
                                return 1;
 
1349
                            } else if (LYresubmit_posts &&
 
1350
                                       cmd != LYK_NOCACHE) {
 
1351
                                /* If LYresubmit_posts is set, and the
 
1352
                                   answer was No, and the key wasn't
 
1353
                                   NOCACHE, and we have a cached copy,
 
1354
                                   then use it. - kw */
 
1355
                                LYforce_no_cache = FALSE;
 
1356
                            } else {
 
1357
                                /* if No, but not ^C or ^G, drop
 
1358
                                 * the post data.  Maybe the link
 
1359
                                 * wasn't meant to be internal after
 
1360
                                 * all, here we can recover from that
 
1361
                                 * assumption. - kw */
 
1362
                                LYFreePostData(&newdoc);
 
1363
                                newdoc.internal_link = FALSE;
 
1364
                                HTAlert(DISCARDING_POST_DATA);
 
1365
                            }
 
1366
                        }
 
1367
                    }
 
1368
                    /*
 
1369
                     *  Don't push the List Page if we follow an
 
1370
                     *  internal link given by it. - kw
 
1371
                     */
 
1372
                    free_address(&curdoc);
 
1373
                } else if (cmd != LYK_NOCACHE) {
 
1374
                    *try_internal = TRUE;
 
1375
                }
 
1376
                if (!(LYresubmit_posts && newdoc.post_data))
 
1377
                    LYinternal_flag = TRUE;
 
1378
                /* We still set force_load so that history pushing
 
1379
                ** etc. will be done.  - kw */
 
1380
                *force_load = TRUE;
 
1381
                return 1;
 
1382
            } else {
 
1383
                /*
 
1384
                 *  Free POST content if not an internal link. - kw
 
1385
                 */
 
1386
                LYFreePostData(&newdoc);
 
1387
            }
 
1388
#endif /* TRACK_INTERNAL_LINKS */
 
1389
            /*
 
1390
             *  Might be an anchor in the same doc from a POST
 
1391
             *  form.  If so, don't free the content. -- FM
 
1392
             */
 
1393
            if (are_different(&curdoc, &newdoc)) {
 
1394
                LYFreePostData(&newdoc);
 
1395
                FREE(newdoc.bookmark);
 
1396
                if (isLYNXMESSAGES(newdoc.address))
 
1397
                    LYforce_no_cache = TRUE;
 
1398
            }
 
1399
            if (!no_jump && lynxjumpfile && curdoc.address &&
 
1400
                !strcmp(lynxjumpfile, curdoc.address)) {
 
1401
                LYJumpFileURL = TRUE;
 
1402
                LYUserSpecifiedURL = TRUE;
 
1403
            } else if ((curdoc.title &&
 
1404
                        (LYIsUIPage(curdoc.address, UIP_HISTORY) ||
 
1405
                         !strcmp(curdoc.title, HISTORY_PAGE_TITLE))) ||
 
1406
                       curdoc.bookmark != NULL ||
 
1407
                       (lynxjumpfile &&
 
1408
                        !strcmp(lynxjumpfile, curdoc.address))) {
 
1409
                LYUserSpecifiedURL = TRUE;
 
1410
            } else if (no_filereferer == TRUE && isFILE_URL(curdoc.address)) {
 
1411
                LYNoRefererForThis = TRUE;
 
1412
            }
 
1413
            newdoc.link = 0;
 
1414
            *force_load = TRUE; /* force MainLoop to reload */
 
1415
#ifdef USE_PRETTYSRC
 
1416
            psrc_view = FALSE;  /* we get here if link is not internal */
 
1417
#endif
 
1418
 
 
1419
#if defined(DIRED_SUPPORT) && !defined(__DJGPP__)
 
1420
            if (lynx_edit_mode) {
 
1421
                  DIRED_UNCACHE_2;
 
1422
                  /*
 
1423
                   *  Unescaping any slash chars in the URL,
 
1424
                   *  but avoid double unescaping and too-early
 
1425
                   *  unescaping of other chars. - KW
 
1426
                   */
 
1427
                  HTUnEscapeSome(newdoc.address,"/");
 
1428
                  /* avoid stripping final slash for root dir - kw */
 
1429
                  if (strcasecomp(newdoc.address, "file://localhost/"))
 
1430
                      strip_trailing_slash(newdoc.address);
 
1431
            }
 
1432
#endif /* DIRED_SUPPORT  && !__DJGPP__ */
 
1433
            if (isLYNXCOOKIE(curdoc.address)) {
 
1434
                HTuncache_current_document();
 
1435
            }
 
1436
        }
 
1437
    }
 
1438
    return 0;
 
1439
}
 
1440
 
 
1441
#ifdef EXP_ADDRLIST_PAGE
 
1442
PRIVATE BOOLEAN handle_LYK_ADDRLIST ARGS1(
 
1443
    int *,     cmd)
 
1444
{
 
1445
    /*
 
1446
     *  Don't do if already viewing list addresses page.
 
1447
     */
 
1448
    if (LYIsUIPage(curdoc.address, UIP_ADDRLIST_PAGE)) {
 
1449
        /*
 
1450
         *  Already viewing list page, so get out.
 
1451
         */
 
1452
        *cmd = LYK_PREV_DOC;
 
1453
        return TRUE;
 
1454
    }
 
1455
 
 
1456
    /*
 
1457
     *  Print address list page to file.
 
1458
     */
 
1459
    if (showlist(&newdoc, FALSE) < 0)
 
1460
        return FALSE;
 
1461
    StrAllocCopy(newdoc.title, ADDRLIST_PAGE_TITLE);
 
1462
    /*
 
1463
     *  showlist will set newdoc's other fields.  It may leave
 
1464
     *  post_data intact so the list can be used to follow
 
1465
     *  internal links in the current document even if it is
 
1466
     *  a POST response. - kw
 
1467
     */
 
1468
 
 
1469
    if (LYValidate || check_realm) {
 
1470
        LYPermitURL = TRUE;
 
1471
        StrAllocCopy(lynxlistfile, newdoc.address);
 
1472
    }
 
1473
    return FALSE;
 
1474
}
 
1475
#endif /* EXP_ADDRLIST_PAGE */
 
1476
 
 
1477
PRIVATE void handle_LYK_ADD_BOOKMARK ARGS3(
 
1478
    BOOLEAN *,  refresh_screen,
 
1479
    int *,      old_c,
 
1480
    int,        real_c)
 
1481
{
 
1482
    int c;
 
1483
 
 
1484
    if (LYValidate) {
 
1485
        if (*old_c != real_c)   {
 
1486
            *old_c = real_c;
 
1487
            HTUserMsg(BOOKMARKS_DISABLED);
 
1488
        }
 
1489
        return;
 
1490
    }
 
1491
 
 
1492
    if (!LYIsUIPage(curdoc.address, UIP_HISTORY) &&
 
1493
        !LYIsUIPage(curdoc.address, UIP_SHOWINFO) &&
 
1494
        !LYIsUIPage(curdoc.address, UIP_PRINT_OPTIONS) &&
 
1495
#ifdef DIRED_SUPPORT
 
1496
        !LYIsUIPage(curdoc.address, UIP_DIRED_MENU) &&
 
1497
        !LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS) &&
 
1498
        !LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS) &&
 
1499
#endif /* DIRED_SUPPORT */
 
1500
        !LYIsUIPage(curdoc.address, UIP_DOWNLOAD_OPTIONS) &&
 
1501
        !isLYNXCOOKIE(curdoc.address) &&
 
1502
        !LYIsUIPage(curdoc.address, UIP_OPTIONS_MENU) &&
 
1503
        ((nlinks <= 0) ||
 
1504
         (links[curdoc.link].lname != NULL &&
 
1505
          !isLYNXHIST(links[curdoc.link].lname) &&
 
1506
          !isLYNXPRINT(links[curdoc.link].lname) &&
 
1507
          !isLYNXDIRED(links[curdoc.link].lname) &&
 
1508
          !isLYNXDOWNLOAD(links[curdoc.link].lname) &&
 
1509
          !isLYNXCOOKIE(links[curdoc.link].lname) &&
 
1510
          !isLYNXPRINT(links[curdoc.link].lname)))) {
 
1511
        if (nlinks > 0) {
 
1512
            if (curdoc.post_data == NULL &&
 
1513
                curdoc.bookmark == NULL &&
 
1514
                !LYIsUIPage(curdoc.address, UIP_LIST_PAGE) &&
 
1515
                !LYIsUIPage(curdoc.address, UIP_ADDRLIST_PAGE) &&
 
1516
                !LYIsUIPage(curdoc.address, UIP_VLINKS)) {
 
1517
                /*
 
1518
                 *  The document doesn't have POST content,
 
1519
                 *  and is not a bookmark file, nor is the
 
1520
                 *  list or visited links page, so we can
 
1521
                 *  save either that or the link. - FM
 
1522
                 */
 
1523
                _statusline(BOOK_D_L_OR_CANCEL);
 
1524
                if ((c = LYgetch_single()) == 'D') {
 
1525
                    save_bookmark_link(curdoc.address, curdoc.title);
 
1526
                    *refresh_screen = TRUE; /* MultiBookmark support */
 
1527
                    goto check_add_bookmark_to_self;
 
1528
                }
 
1529
            } else {
 
1530
                if (LYMultiBookmarks == MBM_OFF &&
 
1531
                    curdoc.bookmark != NULL &&
 
1532
                    strstr(curdoc.address,
 
1533
                           (*bookmark_page == '.'
 
1534
                                          ? (bookmark_page+1)
 
1535
                                          : bookmark_page)) != NULL) {
 
1536
                    /*
 
1537
                     *  If multiple bookmarks are disabled, offer
 
1538
                     *  the L)ink or C)ancel, but with wording
 
1539
                     *  which indicates that the link already
 
1540
                     *  exists in this bookmark file. - FM
 
1541
                     */
 
1542
                    _statusline(MULTIBOOKMARKS_SELF);
 
1543
                } else if (curdoc.post_data != NULL &&
 
1544
                           links[curdoc.link].type == WWW_INTERN_LINK_TYPE) {
 
1545
                    /*
 
1546
                     *  Internal link, and document has POST content.
 
1547
                     */
 
1548
                    HTUserMsg(NOBOOK_POST_FORM);
 
1549
                    return;
 
1550
                } else {
 
1551
                    /*
 
1552
                     *  Only offer the link in a document with
 
1553
                     *  POST content, or if the current document
 
1554
                     *  is a bookmark file and multiple bookmarks
 
1555
                     *  are enabled. - FM
 
1556
                     */
 
1557
                    _statusline(BOOK_L_OR_CANCEL);
 
1558
                }
 
1559
                c = LYgetch_single();
 
1560
            }
 
1561
            if (c == 'L') {
 
1562
                if (curdoc.post_data != NULL &&
 
1563
                    links[curdoc.link].type == WWW_INTERN_LINK_TYPE) {
 
1564
                    /*
 
1565
                     *  Internal link, and document has POST content.
 
1566
                     */
 
1567
                    HTUserMsg(NOBOOK_POST_FORM);
 
1568
                    return;
 
1569
                }
 
1570
                /*
 
1571
                 *  User does want to save the link. - FM
 
1572
                 */
 
1573
                if (links[curdoc.link].type != WWW_FORM_LINK_TYPE) {
 
1574
                    save_bookmark_link(links[curdoc.link].lname,
 
1575
                                       LYGetHiliteStr(curdoc.link, 0));
 
1576
                    *refresh_screen = TRUE; /* MultiBookmark support */
 
1577
                } else {
 
1578
                    HTUserMsg(NOBOOK_FORM_FIELD);
 
1579
                    return;
 
1580
                }
 
1581
            } else {
 
1582
                return;
 
1583
            }
 
1584
        } else if (curdoc.post_data != NULL) {
 
1585
            /*
 
1586
             *  No links, and document has POST content. - FM
 
1587
             */
 
1588
            HTUserMsg(NOBOOK_POST_FORM);
 
1589
            return;
 
1590
        } else if (curdoc.bookmark != NULL) {
 
1591
            /*
 
1592
             *  It's a bookmark file from which all
 
1593
             *  of the links were deleted. - FM
 
1594
             */
 
1595
            HTUserMsg(BOOKMARKS_NOLINKS);
 
1596
            return;
 
1597
        } else {
 
1598
            _statusline(BOOK_D_OR_CANCEL);
 
1599
            if (LYgetch_single() == 'D') {
 
1600
                save_bookmark_link(curdoc.address, curdoc.title);
 
1601
                *refresh_screen = TRUE; /* MultiBookmark support */
 
1602
            } else {
 
1603
                return;
 
1604
            }
 
1605
        }
 
1606
check_add_bookmark_to_self:
 
1607
        if (curdoc.bookmark && BookmarkPage &&
 
1608
            !strcmp(curdoc.bookmark, BookmarkPage)) {
 
1609
            HTuncache_current_document();
 
1610
            move_address(&newdoc, &curdoc);
 
1611
            StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
 
1612
            newdoc.line = curdoc.line;
 
1613
            newdoc.link = curdoc.link;
 
1614
            newdoc.internal_link = FALSE;
 
1615
        }
 
1616
    } else {
 
1617
        if (*old_c != real_c)   {
 
1618
            *old_c = real_c;
 
1619
            HTUserMsg(NOBOOK_HSML);
 
1620
        }
 
1621
    }
 
1622
}
 
1623
 
 
1624
PRIVATE void handle_LYK_CLEAR_AUTH ARGS2(
 
1625
    int *,      old_c,
 
1626
    int,        real_c)
 
1627
{
 
1628
    if (*old_c != real_c) {
 
1629
        *old_c = real_c;
 
1630
        if (HTConfirm(CLEAR_ALL_AUTH_INFO)) {
 
1631
            FREE(authentication_info[0]);
 
1632
            FREE(authentication_info[1]);
 
1633
            FREE(proxyauth_info[0]);
 
1634
            FREE(proxyauth_info[1]);
 
1635
            HTClearHTTPAuthInfo();
 
1636
#ifndef DISABLE_NEWS
 
1637
            HTClearNNTPAuthInfo();
 
1638
#endif
 
1639
#ifndef DISABLE_FTP
 
1640
            HTClearFTPPassword();
 
1641
#endif
 
1642
            HTUserMsg(AUTH_INFO_CLEARED);
 
1643
        } else {
 
1644
            HTUserMsg(CANCELLED);
 
1645
        }
 
1646
    }
 
1647
}
 
1648
 
 
1649
PRIVATE int handle_LYK_COMMAND ARGS1(
 
1650
    char *,     user_input_buffer)
 
1651
{
 
1652
    int ch;
 
1653
    Kcmd *mp;
 
1654
    char *src, *tmp;
 
1655
 
 
1656
    *user_input_buffer = 0;
 
1657
    _statusline(": ");
 
1658
    if (LYgetstr(user_input_buffer, VISIBLE, MAX_LINE, RECALL_CMD) >= 0) {
 
1659
        src = LYSkipBlanks(user_input_buffer);
 
1660
        tmp = LYSkipNonBlanks(src);
 
1661
        *tmp = 0;
 
1662
        ch = ((mp = LYStringToKcmd(src)) != 0) ? mp->code : 0;
 
1663
        CTRACE((tfp, "LYK_COMMAND(%s.%s) = %d\n", src, tmp, ch));
 
1664
        if (ch == 0) {
 
1665
            return *src ? -1 : 0;
 
1666
        }
 
1667
        /* FIXME: reuse the rest of the buffer for parameters */
 
1668
        return ch;
 
1669
    }
 
1670
    return 0;
 
1671
}
 
1672
 
 
1673
PRIVATE void handle_LYK_COMMENT ARGS4(
 
1674
    BOOLEAN *,  refresh_screen,
 
1675
    char **,    owner_address_p,
 
1676
    int *,      old_c,
 
1677
    int,        real_c)
 
1678
{
 
1679
    int c;
 
1680
 
 
1681
    if (!*owner_address_p &&
 
1682
        strncasecomp(curdoc.address, "http", 4)) {
 
1683
        if (*old_c != real_c)   {
 
1684
            *old_c = real_c;
 
1685
            HTUserMsg(NO_OWNER);
 
1686
        }
 
1687
    } else if (no_mail) {
 
1688
        if (*old_c != real_c) {
 
1689
            *old_c = real_c;
 
1690
            HTUserMsg(MAIL_DISALLOWED);
 
1691
        }
 
1692
    } else {
 
1693
        if (HTConfirmDefault(CONFIRM_COMMENT, NO)) {
 
1694
            if (!*owner_address_p) {
 
1695
                /*
 
1696
                 *  No owner defined, so make a guess and
 
1697
                 *  and offer it to the user. - FM
 
1698
                 */
 
1699
                char *address = NULL;
 
1700
                char *temp = HTParse(curdoc.address, "", PARSE_PATH);
 
1701
                char *cp;
 
1702
 
 
1703
                if (temp != NULL) {
 
1704
                    HTUnEscape(temp);
 
1705
                    if (*temp == '~' && strlen(temp) > 1) {
 
1706
                        /*
 
1707
                         *  It's a ~user URL so guess user@host. - FM
 
1708
                         */
 
1709
                        if ((cp = strchr((temp+1), '/')) != NULL)
 
1710
                            *cp = '\0';
 
1711
                        StrAllocCopy(address, STR_MAILTO_URL);
 
1712
                        StrAllocCat(address, (temp+1));
 
1713
                        StrAllocCat(address, "@");
 
1714
                    }
 
1715
                    FREE(temp);
 
1716
                }
 
1717
                if (address == NULL)
 
1718
                    /*
 
1719
                     *  Wasn't a ~user URL so guess WebMaster@host. - FM
 
1720
                     */
 
1721
                    StrAllocCopy(address, "mailto:WebMaster@");
 
1722
                temp = HTParse(curdoc.address, "", PARSE_HOST);
 
1723
                StrAllocCat(address, temp);
 
1724
                HTSprintf0(&temp, NO_OWNER_USE, address);
 
1725
                c = HTConfirmDefault(temp, NO);
 
1726
                FREE(temp);
 
1727
                if (c == YES) {
 
1728
                    StrAllocCopy(*owner_address_p, address);
 
1729
                    FREE(address);
 
1730
                } else {
 
1731
                    FREE(address);
 
1732
                    return;
 
1733
                }
 
1734
            }
 
1735
            if (is_url(*owner_address_p) != MAILTO_URL_TYPE) {
 
1736
                /*
 
1737
                 *  The address is a URL.  Just follow the link.
 
1738
                 */
 
1739
                set_address(&newdoc, *owner_address_p);
 
1740
                newdoc.internal_link = FALSE;
 
1741
            } else {
 
1742
                /*
 
1743
                 *  The owner_address is a mailto: URL.
 
1744
                 */
 
1745
                CONST char *kp = HText_getRevTitle();
 
1746
                CONST char *id = HText_getMessageID();
 
1747
                char *tmptitle = NULL;
 
1748
                if (!kp && HTMainAnchor) {
 
1749
                    kp = HTAnchor_subject(HTMainAnchor);
 
1750
                    if (kp && *kp) {
 
1751
                        if (strncasecomp(kp, "Re: ", 4)) {
 
1752
                            StrAllocCopy(tmptitle, "Re: ");
 
1753
                            StrAllocCat(tmptitle, kp);
 
1754
                            kp = tmptitle;
 
1755
                        }
 
1756
                    }
 
1757
                }
 
1758
 
 
1759
                if (strchr(*owner_address_p, ':') != NULL)
 
1760
                     /*
 
1761
                      *  Send a reply.  The address is after the colon.
 
1762
                      */
 
1763
                     reply_by_mail(strchr(*owner_address_p, ':') + 1,
 
1764
                                   curdoc.address,
 
1765
                                   NonNull(kp), id);
 
1766
                else
 
1767
                    reply_by_mail(*owner_address_p, curdoc.address,
 
1768
                                  NonNull(kp), id);
 
1769
 
 
1770
                FREE(tmptitle);
 
1771
                *refresh_screen = TRUE; /* to force a showpage */
 
1772
            }
 
1773
        }
 
1774
    }
 
1775
}
 
1776
 
 
1777
PRIVATE BOOLEAN handle_LYK_COOKIE_JAR ARGS1(
 
1778
    int *,      cmd)
 
1779
{
 
1780
    /*
 
1781
     *  Don't do if already viewing the cookie jar.
 
1782
     */
 
1783
    if (!isLYNXCOOKIE(curdoc.address)) {
 
1784
        set_address(&newdoc, "LYNXCOOKIE:/");
 
1785
        LYFreePostData(&newdoc);
 
1786
        FREE(newdoc.bookmark);
 
1787
        newdoc.isHEAD = FALSE;
 
1788
        newdoc.safe = FALSE;
 
1789
        newdoc.internal_link = FALSE;
 
1790
        LYforce_no_cache = TRUE;
 
1791
        if (LYValidate || check_realm) {
 
1792
            LYPermitURL = TRUE;
 
1793
        }
 
1794
    } else {
 
1795
        /*
 
1796
         *  If already in the cookie jar, get out.
 
1797
         */
 
1798
        *cmd = LYK_PREV_DOC;
 
1799
        return TRUE;
 
1800
    }
 
1801
    return FALSE;
 
1802
}
 
1803
 
 
1804
#if defined(DIRED_SUPPORT)
 
1805
PRIVATE void handle_LYK_CREATE NOARGS
 
1806
{
 
1807
    if (lynx_edit_mode && !no_dired_support) {
 
1808
        if (local_create(&curdoc) > 0) {
 
1809
            DIRED_UNCACHE_1;
 
1810
            move_address(&newdoc, &curdoc);
 
1811
            LYFreePostData(&newdoc);
 
1812
            FREE(newdoc.bookmark);
 
1813
            newdoc.isHEAD = FALSE;
 
1814
            newdoc.safe = FALSE;
 
1815
            newdoc.line = curdoc.line;
 
1816
            newdoc.link = curdoc.link > -1 ? curdoc.link : 0;
 
1817
            LYclear();
 
1818
        }
 
1819
    }
 
1820
}
 
1821
#endif /* DIRED_SUPPORT */
 
1822
 
 
1823
PRIVATE void handle_LYK_DEL_BOOKMARK ARGS3(
 
1824
    BOOLEAN *,  refresh_screen,
 
1825
    int *,      old_c,
 
1826
    int,        real_c)
 
1827
{
 
1828
    if (curdoc.bookmark != NULL) {
 
1829
        if (HTConfirmDefault(CONFIRM_BOOKMARK_DELETE,NO) != YES)
 
1830
            return;
 
1831
        remove_bookmark_link(links[curdoc.link].anchor_number-1,
 
1832
                             curdoc.bookmark);
 
1833
    } else {    /* behave like REFRESH for backward compatibility */
 
1834
        *refresh_screen = TRUE;
 
1835
        if (*old_c != real_c) {
 
1836
            *old_c = real_c;
 
1837
            lynx_force_repaint();
 
1838
        }
 
1839
        return;
 
1840
    }
 
1841
    do_cleanup_after_delete();
 
1842
}
 
1843
 
 
1844
#if defined(DIRED_SUPPORT) || defined(VMS)
 
1845
PRIVATE void handle_LYK_DIRED_MENU ARGS3(
 
1846
    BOOLEAN *,  refresh_screen,
 
1847
    int *,      old_c GCC_UNUSED,
 
1848
    int,        real_c GCC_UNUSED)
 
1849
{
 
1850
#ifdef VMS
 
1851
    char *cp, *temp = 0;
 
1852
    const char *test = HTGetProgramPath(ppCSWING);
 
1853
 
 
1854
    /*
 
1855
     *  Check if the CSwing Directory/File Manager is available.
 
1856
     *  Will be disabled if CSWING path is NULL, zero-length,
 
1857
     *  or "none" (case insensitive), if no_file_url was set via
 
1858
     *  the file_url restriction, if no_goto_file was set for
 
1859
     *  the anonymous account, or if HTDirAccess was set to
 
1860
     *  HT_DIR_FORBID or HT_DIR_SELECTIVE via the -nobrowse
 
1861
     *  or -selective switches. - FM
 
1862
     */
 
1863
    if (isEmpty(test) ||
 
1864
        !strcasecomp(test, "none") ||
 
1865
        no_file_url || no_goto_file ||
 
1866
        HTDirAccess == HT_DIR_FORBID ||
 
1867
        HTDirAccess == HT_DIR_SELECTIVE) {
 
1868
        if (*old_c != real_c)   {
 
1869
            *old_c = real_c;
 
1870
            HTUserMsg(DFM_NOT_AVAILABLE);
 
1871
        }
 
1872
        return;
 
1873
    }
 
1874
 
 
1875
    /*
 
1876
     *  If we are viewing a local directory listing or a
 
1877
     *  local file which is not temporary, invoke CSwing
 
1878
     *  with the URL's directory converted to VMS path specs
 
1879
     *  and passed as the argument, so we start up CSwing
 
1880
     *  positioned on that node of the directory tree.
 
1881
     *  Otherwise, pass the current default directory as
 
1882
     *  the argument. - FM
 
1883
     */
 
1884
    if (LYisLocalFile(curdoc.address) &&
 
1885
        strncasecomp(curdoc.address,
 
1886
                     lynx_temp_space, strlen(lynx_temp_space))) {
 
1887
        /*
 
1888
         *  We are viewing a local directory or a local file
 
1889
         *  which is not temporary. - FM
 
1890
         */
 
1891
        struct stat stat_info;
 
1892
 
 
1893
        cp = HTParse(curdoc.address, "", PARSE_PATH|PARSE_PUNCTUATION);
 
1894
        HTUnEscape(cp);
 
1895
        if (HTStat(cp, &stat_info) == -1) {
 
1896
            CTRACE((tfp, "mainloop: Can't stat %s\n", cp));
 
1897
            FREE(cp);
 
1898
            HTSprintf0(&temp, "%s []", HTGetProgramPath(ppCSWING));
 
1899
            *refresh_screen = TRUE;  /* redisplay */
 
1900
        } else {
 
1901
            char *VMSdir = NULL;
 
1902
 
 
1903
            if (S_ISDIR(stat_info.st_mode)) {
 
1904
                /*
 
1905
                 *  We're viewing a local directory.  Make
 
1906
                 *  that the CSwing argument. - FM
 
1907
                 */
 
1908
                LYAddPathSep(&cp);
 
1909
                StrAllocCopy(VMSdir, HTVMS_name("", cp));
 
1910
                FREE(cp);
 
1911
            } else {
 
1912
                /*
 
1913
                 *  We're viewing a local file.  Make its
 
1914
                 *  directory the CSwing argument. - FM
 
1915
                 */
 
1916
                StrAllocCopy(VMSdir, HTVMS_name("", cp));
 
1917
                FREE(cp);
 
1918
                if ((cp = strrchr(VMSdir, ']')) != NULL) {
 
1919
                    *(cp + 1) = '\0';
 
1920
                    cp == NULL;
 
1921
                } else if ((cp = strrchr(VMSdir, ':')) != NULL) {
 
1922
                    *(cp + 1) = '\0';
 
1923
                    cp == NULL;
 
1924
                }
 
1925
            }
 
1926
            HTSprintf0(&temp, "%s %s", HTGetProgramPath(ppCSWING), VMSdir);
 
1927
            FREE(VMSdir);
 
1928
            /*
 
1929
             *  Uncache the current document in case we
 
1930
             *  change, move, or delete it during the
 
1931
             *  CSwing session. - FM
 
1932
             */
 
1933
            /* could use DIRED_UNCACHE_1 but it's currently only defined
 
1934
               for dired - kw */
 
1935
            HTuncache_current_document();
 
1936
            move_address(&newdoc, &curdoc);
 
1937
            StrAllocCopy(newdoc.title, NonNull(curdoc.title));
 
1938
            StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
 
1939
            newdoc.line = curdoc.line;
 
1940
            newdoc.link = curdoc.link;
 
1941
        }
 
1942
    } else {
 
1943
        /*
 
1944
         *  We're not viewing a local directory or file.
 
1945
         *  Pass CSwing the current default directory as
 
1946
         *  an argument and don't uncache the current
 
1947
         *  document. - FM
 
1948
         */
 
1949
        HTSprintf0(&temp, "%s []", HTGetProgramPath(ppCSWING));
 
1950
        *refresh_screen = TRUE; /* redisplay */
 
1951
    }
 
1952
    stop_curses();
 
1953
    LYSystem(temp);
 
1954
    start_curses();
 
1955
    FREE(temp);
 
1956
#else
 
1957
    /*
 
1958
     *  Don't do if not allowed or already viewing the menu.
 
1959
     */
 
1960
    if (lynx_edit_mode && !no_dired_support &&
 
1961
        !LYIsUIPage(curdoc.address, UIP_DIRED_MENU) &&
 
1962
        strcmp(NonNull(curdoc.title), DIRED_MENU_TITLE)) {
 
1963
        dired_options(&curdoc,&newdoc.address);
 
1964
        *refresh_screen = TRUE; /* redisplay */
 
1965
    }
 
1966
#endif /* VMS */
 
1967
}
 
1968
#endif /* defined(DIRED_SUPPORT) || defined(VMS) */
 
1969
 
 
1970
PRIVATE int handle_LYK_DOWNLOAD ARGS3(
 
1971
    int *,      cmd,
 
1972
    int *,      old_c,
 
1973
    int,        real_c)
 
1974
{
 
1975
 
 
1976
    /*
 
1977
     *  Don't do if both download and disk_save are restricted.
 
1978
     */
 
1979
    if (LYValidate ||
 
1980
        (no_download && !override_no_download && no_disk_save)) {
 
1981
        if (*old_c != real_c)   {
 
1982
            *old_c = real_c;
 
1983
            HTUserMsg(DOWNLOAD_DISABLED);
 
1984
        }
 
1985
        return 0;
 
1986
    }
 
1987
 
 
1988
    /*
 
1989
     *  Don't do if already viewing download options page.
 
1990
     */
 
1991
    if (LYIsUIPage(curdoc.address, UIP_DOWNLOAD_OPTIONS))
 
1992
        return 0;
 
1993
 
 
1994
    if (do_change_link() == -1)
 
1995
        return 1;       /* mouse stuff was confused, ignore - kw */
 
1996
    if (nlinks > 0) {
 
1997
        if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
 
1998
            if (links[curdoc.link].l_form->type == F_SUBMIT_TYPE ||
 
1999
                links[curdoc.link].l_form->type == F_IMAGE_SUBMIT_TYPE ||
 
2000
                links[curdoc.link].l_form->type == F_TEXT_SUBMIT_TYPE) {
 
2001
                if (links[curdoc.link].l_form->submit_method ==
 
2002
                         URL_MAIL_METHOD) {
 
2003
                    if (*old_c != real_c) {
 
2004
                        *old_c = real_c;
 
2005
                        HTUserMsg(NO_DOWNLOAD_MAILTO_ACTION);
 
2006
                    }
 
2007
                    return 0;
 
2008
                }
 
2009
                if (isLYNXOPTIONS(links[curdoc.link].l_form->submit_action)) {
 
2010
                    if (*old_c != real_c) {
 
2011
                        *old_c = real_c;
 
2012
                        HTUserMsg(NO_DOWNLOAD_SPECIAL);
 
2013
                    }
 
2014
                    return 0;
 
2015
                }
 
2016
                HTOutputFormat = HTAtom_for("www/download");
 
2017
                LYforce_no_cache = TRUE;
 
2018
                *cmd = LYK_ACTIVATE;
 
2019
                return 2;
 
2020
            }
 
2021
            if (*old_c != real_c) {
 
2022
                *old_c = real_c;
 
2023
                HTUserMsg(NO_DOWNLOAD_INPUT);
 
2024
            }
 
2025
 
 
2026
        } else if (isLYNXCOOKIE(curdoc.address)) {
 
2027
            if (*old_c != real_c)       {
 
2028
                *old_c = real_c;
 
2029
                HTUserMsg(NO_DOWNLOAD_COOKIES);
 
2030
            }
 
2031
 
 
2032
        } else if (LYIsUIPage(curdoc.address, UIP_PRINT_OPTIONS)) {
 
2033
            if (*old_c != real_c)       {
 
2034
                *old_c = real_c;
 
2035
                HTUserMsg(NO_DOWNLOAD_PRINT_OP);
 
2036
            }
 
2037
 
 
2038
#ifdef DIRED_SUPPORT
 
2039
        } else if (LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS)) {
 
2040
            if (*old_c != real_c)       {
 
2041
                *old_c = real_c;
 
2042
                HTUserMsg(NO_DOWNLOAD_UPLOAD_OP);
 
2043
            }
 
2044
 
 
2045
        } else if (LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS)) {
 
2046
            if (*old_c != real_c)       {
 
2047
                *old_c = real_c;
 
2048
                HTUserMsg(NO_DOWNLOAD_PERMIT_OP);
 
2049
            }
 
2050
 
 
2051
        } else if (lynx_edit_mode && !no_dired_support &&
 
2052
                   !strstr(links[curdoc.link].lname, "/SugFile=")) {
 
2053
            /*
 
2054
             *  Don't bother making a /tmp copy of the local file.
 
2055
             */
 
2056
            static DocInfo temp;
 
2057
            copy_address(&temp, &newdoc);
 
2058
            set_address(&newdoc, links[curdoc.link].lname);
 
2059
            if (LYdownload_options(&newdoc.address,
 
2060
                                   links[curdoc.link].lname) < 0)
 
2061
                copy_address(&newdoc, &temp);
 
2062
            else
 
2063
                newdoc.internal_link = FALSE;
 
2064
            LYFreeDocInfo(&temp);
 
2065
#endif /* DIRED_SUPPORT */
 
2066
 
 
2067
        } else if (LYIsUIPage(curdoc.address, UIP_HISTORY) &&
 
2068
            isLYNXHIST(links[curdoc.link].lname)) {
 
2069
            int number = atoi(links[curdoc.link].lname + LEN_LYNXHIST);
 
2070
            if (number >= nhist || number < 0) {
 
2071
                HTUserMsg(NO_DOWNLOAD_SPECIAL);
 
2072
                return 0;
 
2073
            }
 
2074
            if ((HDOC(number).post_data != NULL &&
 
2075
                 HDOC(number).safe != TRUE) &&
 
2076
                HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
 
2077
                HTInfoMsg(CANCELLED);
 
2078
                return 0;
 
2079
            }
 
2080
            /*
 
2081
             *  OK, we download from history page, restore URL from stack.
 
2082
             */
 
2083
            copy_address(&newdoc, &HDOC(number));
 
2084
            StrAllocCopy(newdoc.title, LYGetHiliteStr(curdoc.link, 0));
 
2085
            StrAllocCopy(newdoc.bookmark, HDOC(number).bookmark);
 
2086
            LYFreePostData(&newdoc);
 
2087
            if (HDOC(number).post_data)
 
2088
                BStrCopy(newdoc.post_data,
 
2089
                         HDOC(number).post_data);
 
2090
            if (HDOC(number).post_content_type)
 
2091
                StrAllocCopy(newdoc.post_content_type,
 
2092
                             HDOC(number).post_content_type);
 
2093
            newdoc.isHEAD = HDOC(number).isHEAD;
 
2094
            newdoc.safe = HDOC(number).safe;
 
2095
            newdoc.internal_link = FALSE;
 
2096
            newdoc.link = 0;
 
2097
            HTOutputFormat = HTAtom_for("www/download");
 
2098
            LYUserSpecifiedURL = TRUE;
 
2099
            /*
 
2100
             *  Force the document to be reloaded.
 
2101
             */
 
2102
            LYforce_no_cache = TRUE;
 
2103
 
 
2104
        } else if (!strncmp(links[curdoc.link].lname, "data:", 5)) {
 
2105
            if (*old_c != real_c) {
 
2106
                *old_c = real_c;
 
2107
                HTAlert(UNSUPPORTED_DATA_URL);
 
2108
            }
 
2109
 
 
2110
        } else if (isLYNXCOOKIE(links[curdoc.link].lname) ||
 
2111
                   isLYNXDIRED(links[curdoc.link].lname) ||
 
2112
                   isLYNXDOWNLOAD(links[curdoc.link].lname) ||
 
2113
                   isLYNXPRINT(links[curdoc.link].lname) ||
 
2114
                   isLYNXOPTIONS(links[curdoc.link].lname) ||
 
2115
                   isLYNXHIST(links[curdoc.link].lname) ||
 
2116
                   /* handled above if valid - kw */
 
2117
/* @@@ should next two be downloadable? - kw */
 
2118
                   isLYNXHIST(links[curdoc.link].lname) ||
 
2119
                   isLYNXCFLAGS(links[curdoc.link].lname) ||
 
2120
                   isLYNXEXEC(links[curdoc.link].lname) ||
 
2121
                   isLYNXPROG(links[curdoc.link].lname)) {
 
2122
            HTUserMsg(NO_DOWNLOAD_SPECIAL);
 
2123
 
 
2124
        } else if (isMAILTO_URL(links[curdoc.link].lname)) {
 
2125
            HTUserMsg(NO_DOWNLOAD_MAILTO_LINK);
 
2126
 
 
2127
        /*
 
2128
         *  From here on we could have a remote host, so check if
 
2129
         *  that's allowed.
 
2130
         *
 
2131
         *  We copy all these checks from getfile() to LYK_DOWNLOAD
 
2132
         *  here because LYNXDOWNLOAD:// will NOT be pushing the
 
2133
         *  previous document into the history stack so preserve
 
2134
         *  getfile() from returning a wrong status (NULLFILE).
 
2135
         */
 
2136
        } else if (local_host_only &&
 
2137
                   !(LYisLocalHost(links[curdoc.link].lname) ||
 
2138
                     LYisLocalAlias(links[curdoc.link].lname))) {
 
2139
            HTUserMsg(ACCESS_ONLY_LOCALHOST);
 
2140
        } else {   /* Not a forms, options or history link */
 
2141
            /*
 
2142
             *  Follow a normal link or anchor.  Note that
 
2143
             *  if it's an anchor within the same document,
 
2144
             *  entire document will be downloaded.
 
2145
             */
 
2146
            set_address(&newdoc, links[curdoc.link].lname);
 
2147
            StrAllocCopy(newdoc.title, LYGetHiliteStr(curdoc.link, 0));
 
2148
#ifndef DONT_TRACK_INTERNAL_LINKS
 
2149
            /*
 
2150
             *  Might be an internal link in the same doc from a
 
2151
             *  POST form.  If so, don't free the content. - kw
 
2152
             */
 
2153
            if (links[curdoc.link].type != WWW_INTERN_LINK_TYPE)
 
2154
#else
 
2155
            /*
 
2156
             *  Might be an anchor in the same doc from a POST
 
2157
             *  form.  If so, don't free the content. -- FM
 
2158
             */
 
2159
            if (are_different(&curdoc, &newdoc))
 
2160
#endif /* TRACK_INTERNAL_LINKS */
 
2161
            {
 
2162
                LYFreePostData(&newdoc);
 
2163
                FREE(newdoc.bookmark);
 
2164
                newdoc.isHEAD = FALSE;
 
2165
                newdoc.safe = FALSE;
 
2166
            }
 
2167
            newdoc.internal_link = FALSE;
 
2168
            newdoc.link = 0;
 
2169
            HTOutputFormat = HTAtom_for("www/download");
 
2170
            /*
 
2171
             *  Force the document to be reloaded.
 
2172
             */
 
2173
            LYforce_no_cache = TRUE;
 
2174
        }
 
2175
    } else if (*old_c != real_c) {
 
2176
        *old_c = real_c;
 
2177
        HTUserMsg(NO_DOWNLOAD_CHOICE);
 
2178
    }
 
2179
    return 0;
 
2180
}
 
2181
 
 
2182
PRIVATE void handle_LYK_DOWN_HALF ARGS2(
 
2183
    int *,      old_c,
 
2184
    int,        real_c)
 
2185
{
 
2186
    int i;
 
2187
 
 
2188
    if (more) {
 
2189
        Newline += (display_lines/2);
 
2190
        if (nlinks > 0 && curdoc.link > -1 &&
 
2191
            links[curdoc.link].ly > display_lines/2) {
 
2192
            newdoc.link = curdoc.link;
 
2193
            for (i = 0; links[i].ly <= (display_lines/2); i++)
 
2194
                --newdoc.link;
 
2195
        }
 
2196
    } else if (*old_c != real_c) {
 
2197
        *old_c = real_c;
 
2198
        HTInfoMsg(ALREADY_AT_END);
 
2199
    }
 
2200
}
 
2201
 
 
2202
PRIVATE void handle_LYK_DOWN_LINK ARGS3(
 
2203
    int *,      follow_col,
 
2204
    int *,      old_c,
 
2205
    int,        real_c)
 
2206
{
 
2207
    if (curdoc.link < (nlinks-1)) {     /* more links? */
 
2208
        int newlink;
 
2209
 
 
2210
        if (*follow_col == -1) {
 
2211
            char *text = LYGetHiliteStr(curdoc.link, 0);
 
2212
            *follow_col = links[curdoc.link].lx;
 
2213
 
 
2214
            if (text != NULL)
 
2215
                *follow_col += strlen(text) / 2;
 
2216
        }
 
2217
 
 
2218
        newlink = find_link_near_col(*follow_col, 1);
 
2219
        if (newlink > -1) {
 
2220
            set_curdoc_link(newlink);
 
2221
        } else if (more) {  /* next page */
 
2222
            Newline += (display_lines);
 
2223
        } else if (*old_c != real_c) {
 
2224
            *old_c = real_c;
 
2225
            HTUserMsg(NO_LINKS_BELOW);
 
2226
            return;
 
2227
        }
 
2228
    } else if (more) {  /* next page */
 
2229
            Newline += (display_lines);
 
2230
 
 
2231
    } else if (*old_c != real_c) {
 
2232
        *old_c = real_c;
 
2233
        HTInfoMsg(ALREADY_AT_END);
 
2234
    }
 
2235
}
 
2236
 
 
2237
PRIVATE void handle_LYK_DOWN_TWO ARGS2(
 
2238
    int *,      old_c,
 
2239
    int,        real_c)
 
2240
{
 
2241
    int i;
 
2242
 
 
2243
    if (more) {
 
2244
        Newline += 2;
 
2245
        if (nlinks > 0 && curdoc.link > -1 &&
 
2246
            links[curdoc.link].ly > 2) {
 
2247
            newdoc.link = curdoc.link;
 
2248
            for (i = 0; links[i].ly <= 2; i++)
 
2249
                --newdoc.link;
 
2250
        }
 
2251
    } else if (*old_c != real_c) {
 
2252
        *old_c = real_c;
 
2253
        HTInfoMsg(ALREADY_AT_END);
 
2254
    }
 
2255
}
 
2256
 
 
2257
PRIVATE int handle_LYK_DWIMEDIT ARGS3(
 
2258
    int *,      cmd,
 
2259
    int *,      old_c,
 
2260
    int,        real_c)
 
2261
{
 
2262
#ifdef TEXTAREA_AUTOEXTEDIT
 
2263
    /*
 
2264
     *  If we're in a forms TEXTAREA, invoke the editor on *its*
 
2265
     *  contents, rather than attempting to edit the html source
 
2266
     *  document.  KED
 
2267
     */
 
2268
    if (nlinks > 0  &&
 
2269
        links[curdoc.link].type         == WWW_FORM_LINK_TYPE &&
 
2270
        links[curdoc.link].l_form->type == F_TEXTAREA_TYPE)   {
 
2271
        *cmd = LYK_EDIT_TEXTAREA;
 
2272
        return 2;
 
2273
    }
 
2274
 
 
2275
    /*
 
2276
     *  If we're in a forms TEXT type, tell user the request
 
2277
     *  is bogus (though in reality, without this trap, if the
 
2278
     *  document with the TEXT field is local, the editor *would*
 
2279
     *  be invoked on the source .html file; eg, the o(ptions)
 
2280
     *  form tempfile).
 
2281
     *
 
2282
     *  [This is done to avoid possible user confusion, due to
 
2283
     *   auto invocation of the editor on the TEXTAREA's contents
 
2284
     *   via the above if() statement.]
 
2285
     */
 
2286
    if (nlinks > 0 &&
 
2287
        links[curdoc.link].type         == WWW_FORM_LINK_TYPE &&
 
2288
        links[curdoc.link].l_form->type == F_TEXT_TYPE)       {
 
2289
        HTUserMsg (CANNOT_EDIT_FIELD);
 
2290
        return 1;
 
2291
    }
 
2292
 
 
2293
    if (no_editor) {
 
2294
        if (*old_c != real_c) {
 
2295
            *old_c = real_c;
 
2296
            HTUserMsg(ANYEDIT_DISABLED);
 
2297
        }
 
2298
        return 1;
 
2299
    }
 
2300
#endif /* TEXTAREA_AUTOEXTEDIT */
 
2301
    return 0;
 
2302
}
 
2303
 
 
2304
PRIVATE int handle_LYK_ECGOTO ARGS5(
 
2305
    int *,      ch,
 
2306
    char *,     user_input_buffer,
 
2307
    char **,    old_user_input,
 
2308
    int *,      old_c,
 
2309
    int,        real_c)
 
2310
{
 
2311
    if (no_goto && !LYValidate) {
 
2312
        /*
 
2313
         *  Go to not allowed. - FM
 
2314
         */
 
2315
        if (*old_c != real_c) {
 
2316
            *old_c = real_c;
 
2317
            HTUserMsg(GOTO_DISALLOWED);
 
2318
        }
 
2319
        return 0;
 
2320
    }
 
2321
#ifdef DIRED_SUPPORT
 
2322
    if (LYIsUIPage(curdoc.address, UIP_DIRED_MENU) ||
 
2323
        LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS) ||
 
2324
        LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS)) {
 
2325
        /*
 
2326
         *  Disallow editing of File Management URLs. - FM
 
2327
         */
 
2328
        if (*old_c != real_c) {
 
2329
            *old_c = real_c;
 
2330
            HTUserMsg(EDIT_FM_MENU_URLS_DISALLOWED);
 
2331
        }
 
2332
        return 0;
 
2333
    }
 
2334
#endif /* DIRED_SUPPORT */
 
2335
 
 
2336
    /*
 
2337
     *  Save the current user_input_buffer string,
 
2338
     *  and load the current document's address.
 
2339
     */
 
2340
    StrAllocCopy(*old_user_input, user_input_buffer);
 
2341
    LYstrncpy(user_input_buffer,
 
2342
              curdoc.address,
 
2343
              (MAX_LINE - 1));
 
2344
 
 
2345
    /*
 
2346
     *  Warn the user if the current document has POST
 
2347
     *  data associated with it. - FM
 
2348
     */
 
2349
    if (curdoc.post_data)
 
2350
        HTAlert(CURRENT_DOC_HAS_POST_DATA);
 
2351
 
 
2352
    /*
 
2353
     *  Offer the current document's URL for editing. - FM
 
2354
     */
 
2355
    _statusline(EDIT_CURDOC_URL);
 
2356
    if (((*ch = LYgetstr(user_input_buffer, VISIBLE,
 
2357
                        MAX_LINE, RECALL_URL)) >= 0) &&
 
2358
        user_input_buffer[0] != '\0' &&
 
2359
        strcmp(user_input_buffer, curdoc.address)) {
 
2360
        LYTrimAllStartfile(user_input_buffer);
 
2361
        if (user_input_buffer[0] != '\0') {
 
2362
            return 2;
 
2363
        }
 
2364
    }
 
2365
    /*
 
2366
     *  User cancelled via ^G, a full deletion,
 
2367
     *  or not modifying the URL. - FM
 
2368
     */
 
2369
    HTInfoMsg(CANCELLED);
 
2370
    LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1);
 
2371
    FREE(*old_user_input);
 
2372
    return 0;
 
2373
}
 
2374
 
 
2375
PRIVATE void handle_LYK_EDIT ARGS2(
 
2376
    int *,      old_c,
 
2377
    int,        real_c)
 
2378
{
 
2379
#ifdef DIRED_SUPPORT
 
2380
    char *cp;
 
2381
    char *tp = NULL;
 
2382
    struct stat dir_info;
 
2383
#endif /* DIRED_SUPPORT */
 
2384
 
 
2385
    if (no_editor) {
 
2386
        if (*old_c != real_c) {
 
2387
            *old_c = real_c;
 
2388
            HTUserMsg(EDIT_DISABLED);
 
2389
        }
 
2390
    } else
 
2391
 
 
2392
#ifdef DIRED_SUPPORT
 
2393
    /*
 
2394
     *  Allow the user to edit the link rather
 
2395
     *  than curdoc in edit mode.
 
2396
     */
 
2397
    if (lynx_edit_mode &&
 
2398
        editor && *editor != '\0' && !no_dired_support) {
 
2399
        if (nlinks > 0) {
 
2400
            cp = links[curdoc.link].lname;
 
2401
            if (is_url(cp) == FILE_URL_TYPE) {
 
2402
                cp = HTfullURL_toFile(cp);
 
2403
                StrAllocCopy(tp, cp);
 
2404
                FREE(cp);
 
2405
 
 
2406
                if (stat(tp, &dir_info) == -1) {
 
2407
                    HTAlert(NO_STATUS);
 
2408
                } else {
 
2409
                    if (S_ISREG(dir_info.st_mode)) {
 
2410
                        StrAllocCopy(tp, links[curdoc.link].lname);
 
2411
                        HTUnEscapeSome(tp, "/");
 
2412
                        if (edit_current_file(tp, curdoc.link, Newline)) {
 
2413
                            DIRED_UNCACHE_1;
 
2414
                            move_address(&newdoc, &curdoc);
 
2415
#ifdef NO_SEEK_OLD_POSITION
 
2416
                            /*
 
2417
                             *  Go to top of file.
 
2418
                             */
 
2419
                            newdoc.line = 1;
 
2420
                            newdoc.link = 0;
 
2421
#else
 
2422
                            /*
 
2423
                             *  Seek old position,
 
2424
                             *  which probably changed.
 
2425
                             */
 
2426
                            newdoc.line = curdoc.line;
 
2427
                            newdoc.link = curdoc.link;
 
2428
#endif /* NO_SEEK_OLD_POSITION */
 
2429
                            LYclear();  /* clear the screen */
 
2430
                        }
 
2431
                    }
 
2432
                }
 
2433
                FREE(tp);
 
2434
            }
 
2435
        }
 
2436
    } else
 
2437
#endif /* DIRED_SUPPORT */
 
2438
    if (editor && *editor != '\0') {
 
2439
        if (edit_current_file(newdoc.address, curdoc.link, Newline)) {
 
2440
            HTuncache_current_document();
 
2441
            LYforce_no_cache = TRUE;  /*force reload of document */
 
2442
            free_address(&curdoc); /* so it doesn't get pushed */
 
2443
#ifdef NO_SEEK_OLD_POSITION
 
2444
            /*
 
2445
             *  Go to top of file.
 
2446
             */
 
2447
            newdoc.line = 1;
 
2448
            newdoc.link = 0;
 
2449
#else
 
2450
            /*
 
2451
             *  Seek old position, which probably changed.
 
2452
             */
 
2453
            newdoc.line = curdoc.line;
 
2454
            newdoc.link = curdoc.link;
 
2455
#endif /* NO_SEEK_OLD_POSITION */
 
2456
            LYclear();  /* clear the screen */
 
2457
        }
 
2458
 
 
2459
    } else {
 
2460
        if (*old_c != real_c) {
 
2461
            *old_c = real_c;
 
2462
            HTUserMsg(NO_EDITOR);
 
2463
        }
 
2464
    }
 
2465
}
 
2466
 
 
2467
PRIVATE void handle_LYK_DWIMHELP ARGS1(
 
2468
    CONST char **,      cshelpfile)
 
2469
{
 
2470
    /*
 
2471
     *  Currently a help file different from the main
 
2472
     *  'helpfile' is shown only if current link is a
 
2473
     *  text input form field. - kw
 
2474
     */
 
2475
    if (curdoc.link >= 0 && curdoc.link < nlinks &&
 
2476
        links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
2477
        !links[curdoc.link].l_form->disabled &&
 
2478
        F_TEXTLIKE(links[curdoc.link].l_form->type)) {
 
2479
        *cshelpfile = LYLineeditHelpURL();
 
2480
    }
 
2481
}
 
2482
 
 
2483
PRIVATE void handle_LYK_EDIT_TEXTAREA ARGS3(
 
2484
    BOOLEAN *,  refresh_screen,
 
2485
    int *,      old_c,
 
2486
    int,        real_c)
 
2487
{
 
2488
    int n;
 
2489
 
 
2490
    if (no_editor) {
 
2491
        if (*old_c != real_c) {
 
2492
            *old_c = real_c;
 
2493
            HTUserMsg(ANYEDIT_DISABLED);
 
2494
        }
 
2495
    } else if (!editor || *editor == '\0') {
 
2496
        if (*old_c != real_c) {
 
2497
            *old_c = real_c;
 
2498
            HTUserMsg(NO_EDITOR);
 
2499
        }
 
2500
    }
 
2501
    /*
 
2502
     *  See if the current link is in a form TEXTAREA.
 
2503
     */
 
2504
    else if (links[curdoc.link].type         == WWW_FORM_LINK_TYPE &&
 
2505
             links[curdoc.link].l_form->type == F_TEXTAREA_TYPE)   {
 
2506
 
 
2507
        /* stop screen */
 
2508
        stop_curses();
 
2509
 
 
2510
        n = HText_ExtEditForm (&links[curdoc.link]);
 
2511
 
 
2512
        /*
 
2513
         *  TODO: Move cursor "n" lines from the current line to
 
2514
         *        position it on the 1st trailing blank line in
 
2515
         *        the now edited TEXTAREA.  If the target line/
 
2516
         *        anchor requires us to scroll up/down, position
 
2517
         *        the target in the approximate center of the
 
2518
         *        screen.
 
2519
         */
 
2520
 
 
2521
        /* curdoc.link += n;*/  /* works, except for page crossing, */
 
2522
                                /* damnit; why is nothing ever easy */
 
2523
 
 
2524
        /* start screen */
 
2525
        start_curses();
 
2526
        *refresh_screen = TRUE;
 
2527
 
 
2528
    } else {
 
2529
 
 
2530
        HTInfoMsg (NOT_IN_TEXTAREA_NOEDIT);
 
2531
    }
 
2532
}
 
2533
 
 
2534
PRIVATE int handle_LYK_ELGOTO ARGS5(
 
2535
    int *,      ch,
 
2536
    char *,     user_input_buffer,
 
2537
    char **,    old_user_input,
 
2538
    int *,      old_c,
 
2539
    int,        real_c)
 
2540
{
 
2541
    if (no_goto && !LYValidate) {
 
2542
        /*
 
2543
         *  Go to not allowed. - FM
 
2544
         */
 
2545
        if (*old_c != real_c) {
 
2546
            *old_c = real_c;
 
2547
            HTUserMsg(GOTO_DISALLOWED);
 
2548
        }
 
2549
        return 0;
 
2550
    }
 
2551
    if (!(nlinks > 0 && curdoc.link > -1) ||
 
2552
        (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
2553
         links[curdoc.link].l_form->type != F_SUBMIT_TYPE &&
 
2554
         links[curdoc.link].l_form->type != F_IMAGE_SUBMIT_TYPE &&
 
2555
         links[curdoc.link].l_form->type != F_TEXT_SUBMIT_TYPE)) {
 
2556
        /*
 
2557
         *  No links on page, or not a normal link
 
2558
         *  or form submit button. - FM
 
2559
         */
 
2560
        if (*old_c != real_c) {
 
2561
            *old_c = real_c;
 
2562
            HTUserMsg(NOT_ON_SUBMIT_OR_LINK);
 
2563
        }
 
2564
        return 0;
 
2565
    }
 
2566
    if ((links[curdoc.link].type == WWW_FORM_LINK_TYPE) &&
 
2567
        (!links[curdoc.link].l_form->submit_action ||
 
2568
         *links[curdoc.link].l_form->submit_action == '\0')) {
 
2569
        /*
 
2570
         *  Form submit button with no ACTION defined. - FM
 
2571
         */
 
2572
        if (*old_c != real_c) {
 
2573
            *old_c = real_c;
 
2574
            HTUserMsg(NO_FORM_ACTION);
 
2575
        }
 
2576
        return 0;
 
2577
    }
 
2578
#ifdef DIRED_SUPPORT
 
2579
    if (isLYNXDIRED(links[curdoc.link].lname) ||
 
2580
        LYIsUIPage(curdoc.address, UIP_DIRED_MENU) ||
 
2581
        LYIsUIPage(curdoc.address, UIP_PERMIT_OPTIONS) ||
 
2582
        LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS)) {
 
2583
        /*
 
2584
         *  Disallow editing of File Management URLs. - FM
 
2585
         */
 
2586
        if (*old_c != real_c) {
 
2587
            *old_c = real_c;
 
2588
            HTUserMsg(EDIT_FM_MENU_URLS_DISALLOWED);
 
2589
        }
 
2590
        return 0;
 
2591
    }
 
2592
#endif /* DIRED_SUPPORT */
 
2593
 
 
2594
    /*
 
2595
     *  Save the current user_input_buffer string,
 
2596
     *  and load the current link's address. - FM
 
2597
     */
 
2598
    StrAllocCopy(*old_user_input, user_input_buffer);
 
2599
    LYstrncpy(user_input_buffer,
 
2600
              ((links[curdoc.link].type == WWW_FORM_LINK_TYPE)
 
2601
                                        ?
 
2602
    links[curdoc.link].l_form->submit_action : links[curdoc.link].lname),
 
2603
              (MAX_LINE - 1));
 
2604
 
 
2605
    /*
 
2606
     *  Offer the current link's URL for editing. - FM
 
2607
     */
 
2608
    _statusline(EDIT_CURLINK_URL);
 
2609
    if (((*ch = LYgetstr(user_input_buffer, VISIBLE,
 
2610
                        MAX_LINE, RECALL_URL)) >= 0) &&
 
2611
        user_input_buffer[0] != '\0' &&
 
2612
        strcmp(user_input_buffer,
 
2613
               ((links[curdoc.link].type == WWW_FORM_LINK_TYPE)
 
2614
                        ? links[curdoc.link].l_form->submit_action
 
2615
                        : links[curdoc.link].lname))) {
 
2616
        LYTrimAllStartfile(user_input_buffer);
 
2617
        if (user_input_buffer[0] != '\0') {
 
2618
            return 2;
 
2619
        }
 
2620
    }
 
2621
    /*
 
2622
     *  User cancelled via ^G, a full deletion,
 
2623
     *  or not modifying the URL. - FM
 
2624
     */
 
2625
    HTInfoMsg(CANCELLED);
 
2626
    LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1);
 
2627
    FREE(*old_user_input);
 
2628
    return 0;
 
2629
}
 
2630
 
 
2631
#ifdef USE_EXTERNALS
 
2632
PRIVATE void handle_LYK_EXTERN_LINK ARGS1(
 
2633
    BOOLEAN *,  refresh_screen)
 
2634
{
 
2635
    if ((nlinks > 0) && (links[curdoc.link].lname != NULL))
 
2636
    {
 
2637
        run_external(links[curdoc.link].lname, FALSE);
 
2638
        *refresh_screen = TRUE;
 
2639
    }
 
2640
}
 
2641
 
 
2642
PRIVATE void handle_LYK_EXTERN_PAGE ARGS1(
 
2643
    BOOLEAN *,  refresh_screen)
 
2644
{
 
2645
    if (curdoc.address != NULL)
 
2646
    {
 
2647
        run_external(curdoc.address, FALSE);
 
2648
        *refresh_screen = TRUE;
 
2649
    }
 
2650
}
 
2651
#endif
 
2652
 
 
2653
PRIVATE BOOLEAN handle_LYK_FASTBACKW_LINK ARGS3(
 
2654
    int *,      cmd,
 
2655
    int *,      old_c,
 
2656
    int,        real_c)
 
2657
{
 
2658
    int samepage = 0, nextlink = curdoc.link;
 
2659
    int res;
 
2660
 
 
2661
    if (nlinks > 1) {
 
2662
 
 
2663
        /*
 
2664
         *  If in textarea, move to first link or textarea group
 
2665
         *  before it if there is one on this screen. - kw
 
2666
         */
 
2667
        if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
2668
            links[curdoc.link].l_form->type == F_TEXTAREA_TYPE) {
 
2669
            int thisgroup = links[curdoc.link].l_form->number;
 
2670
            char *thisname = links[curdoc.link].l_form->name;
 
2671
 
 
2672
            if (curdoc.link > 0 &&
 
2673
                !(links[0].type == WWW_FORM_LINK_TYPE &&
 
2674
                  links[0].l_form->type == F_TEXTAREA_TYPE &&
 
2675
                  links[0].l_form->number == thisgroup &&
 
2676
                  sametext(links[0].l_form->name, thisname))) {
 
2677
                do nextlink--;
 
2678
                while
 
2679
                    (links[nextlink].type == WWW_FORM_LINK_TYPE &&
 
2680
                     links[nextlink].l_form->type == F_TEXTAREA_TYPE &&
 
2681
                     links[nextlink].l_form->number == thisgroup &&
 
2682
                     sametext(links[nextlink].l_form->name, thisname));
 
2683
                samepage = 1;
 
2684
 
 
2685
            } else if (!more && Newline == 1 &&
 
2686
                       (links[0].type == WWW_FORM_LINK_TYPE &&
 
2687
                        links[0].l_form->type == F_TEXTAREA_TYPE &&
 
2688
                        links[0].l_form->number == thisgroup &&
 
2689
                        sametext(links[0].l_form->name, thisname)) &&
 
2690
                       !(links[nlinks-1].type == WWW_FORM_LINK_TYPE &&
 
2691
                         links[nlinks-1].l_form->type == F_TEXTAREA_TYPE &&
 
2692
                         links[nlinks-1].l_form->number == thisgroup &&
 
2693
                         sametext(links[nlinks-1].l_form->name, thisname))) {
 
2694
                nextlink = nlinks - 1;
 
2695
                samepage = 1;
 
2696
 
 
2697
            } else if (!more && Newline == 1 && curdoc.link > 0) {
 
2698
                nextlink = 0;
 
2699
                samepage = 1;
 
2700
            }
 
2701
        } else if (curdoc.link > 0) {
 
2702
            nextlink--;
 
2703
            samepage = 1;
 
2704
        } else if (!more && Newline == 1) {
 
2705
            nextlink = nlinks - 1;
 
2706
            samepage = 1;
 
2707
        }
 
2708
    }
 
2709
    if (samepage) {
 
2710
        /*
 
2711
         *  If the link as determined so far is part of a
 
2712
         *  group of textarea fields, try to use the first
 
2713
         *  of them that's on the screen instead. - kw
 
2714
         */
 
2715
        if (nextlink > 0 &&
 
2716
            links[nextlink].type == WWW_FORM_LINK_TYPE &&
 
2717
            links[nextlink].l_form->type == F_TEXTAREA_TYPE) {
 
2718
            int thisgroup = links[nextlink].l_form->number;
 
2719
            char *thisname = links[nextlink].l_form->name;
 
2720
            if (links[0].type == WWW_FORM_LINK_TYPE &&
 
2721
                links[0].l_form->type == F_TEXTAREA_TYPE &&
 
2722
                links[0].l_form->number == thisgroup &&
 
2723
                sametext(links[0].l_form->name, thisname)) {
 
2724
                nextlink = 0;
 
2725
            } else
 
2726
                while
 
2727
                    (nextlink > 1 &&
 
2728
                     links[nextlink-1].type == WWW_FORM_LINK_TYPE &&
 
2729
                     links[nextlink-1].l_form->type == F_TEXTAREA_TYPE &&
 
2730
                     links[nextlink-1].l_form->number == thisgroup &&
 
2731
                     sametext(links[nextlink-1].l_form->name, thisname)) {
 
2732
                    nextlink--;
 
2733
                }
 
2734
        }
 
2735
        set_curdoc_link(nextlink);
 
2736
        return FALSE;           /* and we are done. */
 
2737
 
 
2738
    } else if (Newline > 1 &&   /* need a previous page */
 
2739
               (res = HTGetLinkOrFieldStart(curdoc.link,
 
2740
                                            &Newline, &newdoc.link,
 
2741
                                            -1, TRUE)) != NO) {
 
2742
        if (res == LINK_DO_ARROWUP) {
 
2743
            /*
 
2744
             *  It says we should use the normal PREV_LINK
 
2745
             *  mechanism, so we'll do that. - kw
 
2746
             */
 
2747
            if (nlinks > 0)
 
2748
                curdoc.link = 0;
 
2749
            *cmd = LYK_PREV_LINK;
 
2750
            return TRUE;
 
2751
        }
 
2752
        Newline++;      /* our line counting starts with 1 not 0 */
 
2753
        /* nothing more to do here */
 
2754
 
 
2755
    } else if (*old_c != real_c) {
 
2756
        *old_c = real_c;
 
2757
        HTInfoMsg(NO_LINKS_ABOVE);
 
2758
    }
 
2759
    return FALSE;
 
2760
}
 
2761
 
 
2762
PRIVATE void handle_LYK_FASTFORW_LINK ARGS2(
 
2763
    int *,      old_c,
 
2764
    int,        real_c)
 
2765
{
 
2766
    int samepage = 0, nextlink = curdoc.link;
 
2767
 
 
2768
    if (nlinks > 1) {
 
2769
 
 
2770
        /*
 
2771
         *  If in textarea, move to first link or field
 
2772
         *  after it if there is one on this screen. - kw
 
2773
         */
 
2774
        if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
2775
            links[curdoc.link].l_form->type == F_TEXTAREA_TYPE) {
 
2776
            int thisgroup = links[curdoc.link].l_form->number;
 
2777
            char *thisname = links[curdoc.link].l_form->name;
 
2778
 
 
2779
            if (curdoc.link < nlinks-1 &&
 
2780
                !(links[nlinks-1].type == WWW_FORM_LINK_TYPE &&
 
2781
                  links[nlinks-1].l_form->type == F_TEXTAREA_TYPE &&
 
2782
                  links[nlinks-1].l_form->number == thisgroup &&
 
2783
                  sametext(links[nlinks-1].l_form->name, thisname))) {
 
2784
                do nextlink++;
 
2785
                while
 
2786
                    (links[nextlink].type == WWW_FORM_LINK_TYPE &&
 
2787
                     links[nextlink].l_form->type == F_TEXTAREA_TYPE &&
 
2788
                     links[nextlink].l_form->number == thisgroup &&
 
2789
                     sametext(links[nextlink].l_form->name, thisname));
 
2790
                samepage = 1;
 
2791
            } else if (!more && Newline == 1 && curdoc.link > 0) {
 
2792
                nextlink = 0;
 
2793
                samepage = 1;
 
2794
            }
 
2795
        } else if (curdoc.link < nlinks-1) {
 
2796
            nextlink++;
 
2797
            samepage = 1;
 
2798
        } else if (!more && Newline == 1 && curdoc.link > 0) {
 
2799
            nextlink = 0;
 
2800
            samepage = 1;
 
2801
        }
 
2802
    }
 
2803
    if (samepage) {
 
2804
        set_curdoc_link(nextlink);
 
2805
        return;         /* and we are done. */
 
2806
 
 
2807
    /*
 
2808
     *  At the bottom of list and there is only one page.
 
2809
     *  Move to the top link on the page.
 
2810
     */
 
2811
    } else if (!more && Newline == 1 && curdoc.link == nlinks-1) {
 
2812
        set_curdoc_link(0);
 
2813
 
 
2814
    } else if (more &&  /* need a later page */
 
2815
               HTGetLinkOrFieldStart(curdoc.link,
 
2816
                                     &Newline, &newdoc.link,
 
2817
                                     1, TRUE) != NO) {
 
2818
        Newline++;      /* our line counting starts with 1 not 0 */
 
2819
        /* nothing more to do here */
 
2820
 
 
2821
    } else if (*old_c != real_c) {
 
2822
        *old_c = real_c;
 
2823
        HTInfoMsg(NO_LINKS_BELOW);
 
2824
    }
 
2825
    return;
 
2826
}
 
2827
 
 
2828
PRIVATE void handle_LYK_FIRST_LINK NOARGS
 
2829
{
 
2830
    int i = curdoc.link;
 
2831
 
 
2832
    for (;;) {
 
2833
        if (--i < 0
 
2834
         || links[i].ly != links[curdoc.link].ly) {
 
2835
            set_curdoc_link(i + 1);
 
2836
            break;
 
2837
        }
 
2838
    }
 
2839
}
 
2840
 
 
2841
PRIVATE BOOLEAN handle_LYK_GOTO ARGS9(
 
2842
    int *,      ch,
 
2843
    char *,     user_input_buffer,
 
2844
    char **,    old_user_input,
 
2845
    int *,      recall,
 
2846
    int *,      URLTotal,
 
2847
    int *,      URLNum,
 
2848
    BOOLEAN *,  FirstURLRecall,
 
2849
    int *,      old_c,
 
2850
    int,        real_c)
 
2851
{
 
2852
 
 
2853
    if (no_goto && !LYValidate) {
 
2854
        if (*old_c != real_c) {
 
2855
            *old_c = real_c;
 
2856
            HTUserMsg(GOTO_DISALLOWED);
 
2857
        }
 
2858
        return FALSE;
 
2859
    }
 
2860
 
 
2861
    StrAllocCopy(*old_user_input, user_input_buffer);
 
2862
    if (!goto_buffer)
 
2863
        *user_input_buffer = '\0';
 
2864
 
 
2865
    *URLTotal = (Goto_URLs ? HTList_count(Goto_URLs) : 0);
 
2866
    if (goto_buffer && *user_input_buffer) {
 
2867
        *recall = ((*URLTotal > 1) ? RECALL_URL : NORECALL);
 
2868
        *URLNum = 0;
 
2869
        *FirstURLRecall = FALSE;
 
2870
    } else {
 
2871
        *recall = ((*URLTotal >= 1) ? RECALL_URL : NORECALL);
 
2872
        *URLNum = *URLTotal;
 
2873
        *FirstURLRecall = TRUE;
 
2874
    }
 
2875
 
 
2876
    /*
 
2877
     *  Ask the user.
 
2878
     */
 
2879
    _statusline(URL_TO_OPEN);
 
2880
    if ((*ch = LYgetstr(user_input_buffer, VISIBLE,
 
2881
                       MAX_LINE, *recall)) < 0 ) {
 
2882
        /*
 
2883
         *  User cancelled the Goto via ^G.
 
2884
         *  Restore user_input_buffer and break. - FM
 
2885
         */
 
2886
        LYstrncpy(user_input_buffer, *old_user_input, MAX_LINE - 1);
 
2887
        FREE(*old_user_input);
 
2888
        HTInfoMsg(CANCELLED);
 
2889
        return FALSE;
 
2890
    }
 
2891
    return TRUE;
 
2892
}
 
2893
 
 
2894
PRIVATE void handle_LYK_GROW_TEXTAREA ARGS1(
 
2895
    BOOLEAN *,  refresh_screen)
 
2896
{
 
2897
    /*
 
2898
     *  See if the current link is in a form TEXTAREA.
 
2899
     */
 
2900
    if (links[curdoc.link].type         == WWW_FORM_LINK_TYPE &&
 
2901
        links[curdoc.link].l_form->type == F_TEXTAREA_TYPE)   {
 
2902
 
 
2903
        HText_ExpandTextarea (&links[curdoc.link], TEXTAREA_EXPAND_SIZE);
 
2904
 
 
2905
        *refresh_screen = TRUE;
 
2906
 
 
2907
    } else {
 
2908
 
 
2909
        HTInfoMsg (NOT_IN_TEXTAREA);
 
2910
    }
 
2911
}
 
2912
 
 
2913
PRIVATE BOOLEAN handle_LYK_HEAD ARGS1(
 
2914
    int *,      cmd)
 
2915
{
 
2916
    int c;
 
2917
 
 
2918
    if (nlinks > 0 &&
 
2919
        (links[curdoc.link].type         != WWW_FORM_LINK_TYPE ||
 
2920
         links[curdoc.link].l_form->type == F_SUBMIT_TYPE ||
 
2921
         links[curdoc.link].l_form->type == F_IMAGE_SUBMIT_TYPE ||
 
2922
         links[curdoc.link].l_form->type == F_TEXT_SUBMIT_TYPE)) {
 
2923
        /*
 
2924
         * We have links, and the current link is a normal link or a form's
 
2925
         * submit button.  - FM
 
2926
         */
 
2927
        _statusline(HEAD_D_L_OR_CANCEL);
 
2928
        c = LYgetch_single();
 
2929
        if (c == 'D') {
 
2930
            char *scheme = !isLYNXIMGMAP(curdoc.address)
 
2931
                         ? curdoc.address
 
2932
                         : curdoc.address + LEN_LYNXIMGMAP;
 
2933
            if (LYCanDoHEAD(scheme) != TRUE) {
 
2934
                HTUserMsg(DOC_NOT_HTTP_URL);
 
2935
            } else {
 
2936
                /*
 
2937
                 * Check if this is a reply from a POST, and if so, seek
 
2938
                 * confirmation if the safe element is not set.  - FM
 
2939
                 */
 
2940
                if ((curdoc.post_data != NULL &&
 
2941
                     curdoc.safe != TRUE) &&
 
2942
                    HTConfirm(CONFIRM_POST_DOC_HEAD) == FALSE) {
 
2943
                    HTInfoMsg(CANCELLED);
 
2944
                } else {
 
2945
                    HEAD_request = TRUE;
 
2946
                    LYforce_no_cache = TRUE;
 
2947
                    StrAllocCopy(newdoc.title, curdoc.title);
 
2948
                    if (HTLoadedDocumentIsHEAD()) {
 
2949
                        HText_setNoCache(HTMainText);
 
2950
                        free_address(&curdoc);
 
2951
                    } else {
 
2952
                        StrAllocCat(newdoc.title, " - HEAD");
 
2953
                    }
 
2954
                }
 
2955
            }
 
2956
        } else if (c == 'L') {
 
2957
            if (links[curdoc.link].type != WWW_FORM_LINK_TYPE &&
 
2958
                strncmp(links[curdoc.link].lname, "http", 4) &&
 
2959
                strncmp(links[curdoc.link].lname,
 
2960
                        "LYNXIMGMAP:http", 15) &&
 
2961
                LYCanDoHEAD(links[curdoc.link].lname) != TRUE &&
 
2962
                (links[curdoc.link].type != WWW_INTERN_LINK_TYPE ||
 
2963
                 !curdoc.address ||
 
2964
                 strncmp(curdoc.address, "http", 4))) {
 
2965
                HTUserMsg(LINK_NOT_HTTP_URL);
 
2966
            } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
2967
                       links[curdoc.link].l_form->disabled) {
 
2968
                HTUserMsg(FORM_ACTION_DISABLED);
 
2969
            } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
2970
                       !isLYNXCGI(links[curdoc.link].l_form->submit_action) &&
 
2971
                       strncmp(links[curdoc.link].l_form->submit_action,
 
2972
                                                         "http", 4)) {
 
2973
                HTUserMsg(FORM_ACTION_NOT_HTTP_URL);
 
2974
            } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
2975
                       links[curdoc.link].l_form->submit_method ==
 
2976
                                                  URL_POST_METHOD &&
 
2977
                       HTConfirm(CONFIRM_POST_LINK_HEAD) == FALSE) {
 
2978
                HTInfoMsg(CANCELLED);
 
2979
            } else {
 
2980
                HEAD_request = TRUE;
 
2981
                LYforce_no_cache = TRUE;
 
2982
                *cmd = LYK_ACTIVATE;
 
2983
                return TRUE;
 
2984
            }
 
2985
        }
 
2986
    } else {
 
2987
        /*
 
2988
         * We can offer only this document for a HEAD request.  Check if this
 
2989
         * is a reply from a POST, and if so, seek confirmation if the safe
 
2990
         * element is not set.  - FM
 
2991
         */
 
2992
        if ((curdoc.post_data != NULL &&
 
2993
             curdoc.safe != TRUE) &&
 
2994
            HTConfirm(CONFIRM_POST_DOC_HEAD) == FALSE) {
 
2995
            HTInfoMsg(CANCELLED);
 
2996
        } else {
 
2997
            if (nlinks > 0) {
 
2998
                /*
 
2999
                 * The current link is a non-submittable form link, so prompt
 
3000
                 * the user to make it clear that the HEAD request would be for
 
3001
                 * the current document, not the form link.  - FM
 
3002
                 */
 
3003
                _statusline(HEAD_D_OR_CANCEL);
 
3004
                c = LYgetch_single();
 
3005
            } else {
 
3006
                /*
 
3007
                 * No links, so we can just assume that the user wants a HEAD
 
3008
                 * request for the current document.  - FM
 
3009
                 */
 
3010
                c = 'D';
 
3011
            }
 
3012
            if (c == 'D') {
 
3013
                char *scheme = !isLYNXIMGMAP(curdoc.address)
 
3014
                             ? curdoc.address
 
3015
                             : curdoc.address + LEN_LYNXIMGMAP;
 
3016
                /*
 
3017
                 * The user didn't cancel, so check if a HEAD request is
 
3018
                 * appropriate for the current document.  - FM
 
3019
                 */
 
3020
                if (LYCanDoHEAD(scheme) != TRUE) {
 
3021
                    HTUserMsg(DOC_NOT_HTTP_URL);
 
3022
                } else {
 
3023
                    HEAD_request = TRUE;
 
3024
                    LYforce_no_cache = TRUE;
 
3025
                    StrAllocCopy(newdoc.title, curdoc.title);
 
3026
                    if (HTLoadedDocumentIsHEAD()) {
 
3027
                        HText_setNoCache(HTMainText);
 
3028
                        free_address(&curdoc);
 
3029
                    } else {
 
3030
                        StrAllocCat(newdoc.title, " - HEAD");
 
3031
                    }
 
3032
                }
 
3033
            }
 
3034
        }
 
3035
    }
 
3036
    return FALSE;
 
3037
}
 
3038
 
 
3039
PRIVATE void handle_LYK_HELP ARGS1(
 
3040
    CONST char **,      cshelpfile)
 
3041
{
 
3042
    if (*cshelpfile == NULL)
 
3043
        *cshelpfile = helpfile;
 
3044
    if (!STREQ(curdoc.address, *cshelpfile)) {
 
3045
        /*
 
3046
         *  Set the filename.
 
3047
         */
 
3048
        set_address(&newdoc, *cshelpfile);
 
3049
        /*
 
3050
         *  Make a name for this help file.
 
3051
         */
 
3052
        StrAllocCopy(newdoc.title, gettext("Help Screen"));
 
3053
        LYFreePostData(&newdoc);
 
3054
        FREE(newdoc.bookmark);
 
3055
        newdoc.isHEAD = FALSE;
 
3056
        newdoc.safe = FALSE;
 
3057
        newdoc.internal_link = FALSE;
 
3058
    }
 
3059
    *cshelpfile = NULL;         /* reset pointer - kw */
 
3060
}
 
3061
 
 
3062
PRIVATE void handle_LYK_HISTORICAL NOARGS
 
3063
{
 
3064
#ifdef USE_SOURCE_CACHE
 
3065
    if (!HTcan_reparse_document()) {
 
3066
#endif
 
3067
    /*
 
3068
     *  Check if this is a reply from a POST, and if so,
 
3069
     *  seek confirmation of reload if the safe element
 
3070
     *  is not set. - FM
 
3071
     */
 
3072
    if ((curdoc.post_data != NULL &&
 
3073
         curdoc.safe != TRUE) &&
 
3074
        confirm_post_resub(curdoc.address, NULL, 0, 0) == FALSE) {
 
3075
        HTInfoMsg(WILL_NOT_RELOAD_DOC);
 
3076
    } else {
 
3077
        HText_setNoCache(HTMainText);
 
3078
        move_address(&newdoc, &curdoc);
 
3079
        newdoc.line = curdoc.line;
 
3080
        newdoc.link = curdoc.link;
 
3081
    }
 
3082
#ifdef USE_SOURCE_CACHE
 
3083
    } /* end if no bypass */
 
3084
#endif
 
3085
    historical_comments = !historical_comments;
 
3086
    if (minimal_comments) {
 
3087
        HTAlert(historical_comments ?
 
3088
                HISTORICAL_ON_MINIMAL_OFF : HISTORICAL_OFF_MINIMAL_ON);
 
3089
    } else {
 
3090
        HTAlert(historical_comments ?
 
3091
                HISTORICAL_ON_VALID_OFF : HISTORICAL_OFF_VALID_ON);
 
3092
    }
 
3093
#ifdef USE_SOURCE_CACHE
 
3094
    (void) reparse_document();
 
3095
#endif
 
3096
    return;
 
3097
}
 
3098
 
 
3099
PRIVATE BOOLEAN handle_LYK_HISTORY ARGS1(
 
3100
    BOOLEAN,    ForcePush)
 
3101
{
 
3102
    if (curdoc.title && !LYIsUIPage(curdoc.address, UIP_HISTORY)) {
 
3103
        /*
 
3104
         *  Don't do this if already viewing history page.
 
3105
         *
 
3106
         *  Push the current file so that the history list
 
3107
         *  contains the current file for printing purposes.
 
3108
         *  Pop the file afterwards to prevent multiple copies.
 
3109
         */
 
3110
        if (TRACE && !LYUseTraceLog && LYCursesON) {
 
3111
            LYHideCursor();     /* make sure cursor is down */
 
3112
#ifdef USE_SLANG
 
3113
            LYaddstr("\n");
 
3114
#endif /* USE_SLANG */
 
3115
            LYrefresh();
 
3116
        }
 
3117
        LYpush(&curdoc, ForcePush);
 
3118
 
 
3119
        /*
 
3120
         *  Print history options to file.
 
3121
         */
 
3122
        if (showhistory(&newdoc.address) < 0) {
 
3123
            LYpop(&curdoc);
 
3124
            return TRUE;
 
3125
        }
 
3126
        LYRegisterUIPage(newdoc.address, UIP_HISTORY);
 
3127
        StrAllocCopy(newdoc.title, HISTORY_PAGE_TITLE);
 
3128
        LYFreePostData(&newdoc);
 
3129
        FREE(newdoc.bookmark);
 
3130
        newdoc.isHEAD = FALSE;
 
3131
        newdoc.safe = FALSE;
 
3132
        newdoc.internal_link = FALSE;
 
3133
        newdoc.link = 1; /*@@@ bypass "recent statusline messages" link */
 
3134
        free_address(&curdoc);  /* so it doesn't get pushed */
 
3135
 
 
3136
        if (LYValidate || check_realm) {
 
3137
            LYPermitURL = TRUE;
 
3138
        }
 
3139
        return TRUE;
 
3140
    } /* end if strncmp */
 
3141
    return FALSE;
 
3142
}
 
3143
 
 
3144
PRIVATE BOOLEAN handle_LYK_IMAGE_TOGGLE ARGS1(
 
3145
    int *,      cmd)
 
3146
{
 
3147
    clickable_images = !clickable_images;
 
3148
 
 
3149
    HTUserMsg(clickable_images ?
 
3150
             CLICKABLE_IMAGES_ON : CLICKABLE_IMAGES_OFF);
 
3151
    return reparse_or_reload(cmd);
 
3152
}
 
3153
 
 
3154
PRIVATE void handle_LYK_INDEX ARGS2(
 
3155
    int *,      old_c,
 
3156
    int,        real_c)
 
3157
{
 
3158
    /*
 
3159
     *  Make sure we are not in the index already.
 
3160
     */
 
3161
    if (!STREQ(curdoc.address, indexfile)) {
 
3162
 
 
3163
        if (indexfile[0]=='\0') { /* no defined index */
 
3164
                if (*old_c != real_c)   {
 
3165
                    *old_c = real_c;
 
3166
                    HTUserMsg(NO_INDEX_FILE);
 
3167
                }
 
3168
 
 
3169
        } else {
 
3170
#ifdef KANJI_CODE_OVERRIDE
 
3171
            if (HTCJK == JAPANESE) {
 
3172
                last_kcode = NOKANJI;   /* AUTO */
 
3173
            }
 
3174
#endif
 
3175
            set_address(&newdoc, indexfile);
 
3176
            StrAllocCopy(newdoc.title, gettext("System Index")); /* name it */
 
3177
            LYFreePostData(&newdoc);
 
3178
            FREE(newdoc.bookmark);
 
3179
            newdoc.isHEAD = FALSE;
 
3180
            newdoc.safe = FALSE;
 
3181
            newdoc.internal_link = FALSE;
 
3182
        } /* end else */
 
3183
    }  /* end if */
 
3184
}
 
3185
 
 
3186
PRIVATE void handle_LYK_INDEX_SEARCH ARGS4(
 
3187
    BOOLEAN *,  force_load,
 
3188
    BOOLEAN,    ForcePush,
 
3189
    int *,      old_c,
 
3190
    int,        real_c)
 
3191
{
 
3192
    if (is_www_index) {
 
3193
        /*
 
3194
         *  Perform a database search.
 
3195
         *
 
3196
         *  do_www_search will try to go out and get the document.
 
3197
         *  If it returns TRUE, a new document was returned and is
 
3198
         *  named in the newdoc.address.
 
3199
         */
 
3200
        newdoc.isHEAD = FALSE;
 
3201
        newdoc.safe = FALSE;
 
3202
        if (do_www_search(&newdoc) == NORMAL) {
 
3203
            /*
 
3204
             *  Yah, the search succeeded.
 
3205
             */
 
3206
            if (TRACE && !LYUseTraceLog && LYCursesON) {
 
3207
                /*
 
3208
                 *  Make sure cursor is down.
 
3209
                 */
 
3210
                LYHideCursor();
 
3211
#ifdef USE_SLANG
 
3212
                LYaddstr("\n");
 
3213
#endif /* USE_SLANG */
 
3214
                LYrefresh();
 
3215
            }
 
3216
            LYpush(&curdoc, ForcePush);
 
3217
            /*
 
3218
             *  Make the curdoc.address the newdoc.address so that
 
3219
             *  getfile doesn't try to get the newdoc.address.
 
3220
             *  Since we have already gotten it.
 
3221
             */
 
3222
            copy_address(&curdoc, &newdoc);
 
3223
            BStrCopy(newdoc.post_data, curdoc.post_data);
 
3224
            StrAllocCopy(newdoc.post_content_type, curdoc.post_content_type);
 
3225
            newdoc.internal_link = FALSE;
 
3226
            curdoc.line = -1;
 
3227
            Newline = 0;
 
3228
        } else if (use_this_url_instead != NULL) {
 
3229
            /*
 
3230
             *  Got back a redirecting URL.  Check it out.
 
3231
             */
 
3232
            HTUserMsg2 (WWW_USING_MESSAGE, use_this_url_instead);
 
3233
 
 
3234
            /*
 
3235
             *  Make a name for this URL.
 
3236
             */
 
3237
            StrAllocCopy(newdoc.title,
 
3238
                         "A URL specified by redirection");
 
3239
            set_address(&newdoc, use_this_url_instead);
 
3240
            LYFreePostData(&newdoc);
 
3241
            FREE(newdoc.bookmark);
 
3242
            newdoc.isHEAD = FALSE;
 
3243
            newdoc.safe = FALSE;
 
3244
            newdoc.internal_link = FALSE;
 
3245
            FREE(use_this_url_instead);
 
3246
            *force_load = TRUE;
 
3247
        } else {
 
3248
            /*
 
3249
             *  Yuk, the search failed.  Restore the old file.
 
3250
             */
 
3251
            copy_address(&newdoc, &curdoc);
 
3252
            BStrCopy(newdoc.post_data, curdoc.post_data);
 
3253
            StrAllocCopy(newdoc.post_content_type,
 
3254
                         curdoc.post_content_type);
 
3255
            StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
 
3256
            newdoc.isHEAD = curdoc.isHEAD;
 
3257
            newdoc.safe = curdoc.safe;
 
3258
            newdoc.internal_link = curdoc.internal_link;
 
3259
        }
 
3260
    } else if (*old_c != real_c) {
 
3261
        *old_c = real_c;
 
3262
        HTUserMsg(NOT_ISINDEX);
 
3263
    }
 
3264
}
 
3265
 
 
3266
PRIVATE BOOLEAN handle_LYK_INFO ARGS1(
 
3267
    int *,      cmd)
 
3268
{
 
3269
    /*
 
3270
     *  Don't do if already viewing info page.
 
3271
     */
 
3272
    if (!LYIsUIPage(curdoc.address, UIP_SHOWINFO)) {
 
3273
        if (do_change_link() != -1
 
3274
         && LYShowInfo(&curdoc, HText_getNumOfLines(),
 
3275
                       &newdoc, owner_address) >= 0) {
 
3276
            LYRegisterUIPage(newdoc.address, UIP_SHOWINFO);
 
3277
            StrAllocCopy(newdoc.title, SHOWINFO_TITLE);
 
3278
            LYFreePostData(&newdoc);
 
3279
            FREE(newdoc.bookmark);
 
3280
            newdoc.isHEAD = FALSE;
 
3281
            newdoc.safe = FALSE;
 
3282
            newdoc.internal_link = FALSE;
 
3283
            LYforce_no_cache = TRUE;
 
3284
            if (LYValidate || check_realm)
 
3285
                LYPermitURL = TRUE;
 
3286
        }
 
3287
    } else {
 
3288
        /*
 
3289
         *  If already in info page, get out.
 
3290
         */
 
3291
        *cmd = LYK_PREV_DOC;
 
3292
        return TRUE;
 
3293
    }
 
3294
    return FALSE;
 
3295
}
 
3296
 
 
3297
PRIVATE BOOLEAN handle_LYK_INLINE_TOGGLE ARGS1(
 
3298
    int *,      cmd)
 
3299
{
 
3300
    pseudo_inline_alts = !pseudo_inline_alts;
 
3301
 
 
3302
    HTUserMsg(pseudo_inline_alts ?
 
3303
              PSEUDO_INLINE_ALTS_ON : PSEUDO_INLINE_ALTS_OFF);
 
3304
    return reparse_or_reload(cmd);
 
3305
}
 
3306
 
 
3307
PRIVATE void handle_LYK_INSERT_FILE ARGS3(
 
3308
    BOOLEAN *,  refresh_screen,
 
3309
    int *,      old_c,
 
3310
    int,        real_c)
 
3311
{
 
3312
    int n;
 
3313
 
 
3314
    /*
 
3315
     *  See if the current link is in a form TEXTAREA.
 
3316
     */
 
3317
    if (links[curdoc.link].type         == WWW_FORM_LINK_TYPE &&
 
3318
        links[curdoc.link].l_form->type == F_TEXTAREA_TYPE)   {
 
3319
 
 
3320
        /*
 
3321
         *  Reject attempts to use this for gaining access to
 
3322
         *  local files when such access is restricted:
 
3323
         *  if no_file_url was set via the file_url restriction,
 
3324
         *  if no_goto_file was set for the anonymous account,
 
3325
         *  or if HTDirAccess was set to HT_DIR_FORBID or
 
3326
         *  HT_DIR_SELECTIVE via the -nobrowse or -selective
 
3327
         *  switches, it is assumed that inserting files or
 
3328
         *  checking for existence of files needs to be denied. - kw
 
3329
         */
 
3330
        if (no_file_url || no_goto_file ||
 
3331
            HTDirAccess == HT_DIR_FORBID ||
 
3332
            HTDirAccess == HT_DIR_SELECTIVE) {
 
3333
            if (*old_c != real_c) {
 
3334
                *old_c = real_c;
 
3335
                if (no_goto_file)
 
3336
                    HTUserMsg2(GOTO_XXXX_DISALLOWED, STR_FILE_URL);
 
3337
                else
 
3338
                    HTUserMsg(NOAUTH_TO_ACCESS_FILES);
 
3339
                HTInfoMsg(FILE_INSERT_CANCELLED);
 
3340
            }
 
3341
            return;
 
3342
        }
 
3343
 
 
3344
        n = HText_InsertFile (&links[curdoc.link]);
 
3345
 
 
3346
        /*
 
3347
         *  TODO: Move cursor "n" lines from the current line to
 
3348
         *        position it on the 1st line following the text
 
3349
         *        that was inserted.  If the target line/anchor
 
3350
         *        requires us to scroll up/down, position the
 
3351
         *        target in the approximate center of the screen.
 
3352
         *
 
3353
         *  [Current behavior leaves cursor on the same line relative
 
3354
         *   to the start of the TEXTAREA that it was on before the
 
3355
         *   insertion.  This is the same behavior that occurs with
 
3356
         *   (my) editor, so this TODO will stay unimplemented.]
 
3357
         */
 
3358
 
 
3359
        *refresh_screen = TRUE;
 
3360
 
 
3361
    } else {
 
3362
 
 
3363
        HTInfoMsg (NOT_IN_TEXTAREA);
 
3364
    }
 
3365
}
 
3366
 
 
3367
#if defined(DIRED_SUPPORT) && defined(OK_INSTALL)
 
3368
PRIVATE void handle_LYK_INSTALL NOARGS
 
3369
{
 
3370
    if (lynx_edit_mode && nlinks > 0 && !no_dired_support)
 
3371
        local_install(NULL, links[curdoc.link].lname, &newdoc.address);
 
3372
}
 
3373
#endif
 
3374
 
 
3375
PRIVATE BOOLEAN handle_LYK_JUMP ARGS10(
 
3376
    int,        c,
 
3377
    char *,     user_input_buffer,
 
3378
    char **,    old_user_input GCC_UNUSED,
 
3379
    int *,      recall GCC_UNUSED,
 
3380
    BOOLEAN *,  FirstURLRecall GCC_UNUSED,
 
3381
    int *,      URLNum GCC_UNUSED,
 
3382
    int *,      URLTotal GCC_UNUSED,
 
3383
    int *,      ch GCC_UNUSED,
 
3384
    int *,      old_c,
 
3385
    int,        real_c)
 
3386
{
 
3387
    char *ret;
 
3388
 
 
3389
    if (no_jump || JThead == NULL) {
 
3390
        if (*old_c != real_c) {
 
3391
            *old_c = real_c;
 
3392
            if (no_jump)
 
3393
                HTUserMsg(JUMP_DISALLOWED);
 
3394
            else
 
3395
                HTUserMsg(NO_JUMPFILE);
 
3396
        }
 
3397
    } else {
 
3398
        LYJumpFileURL = TRUE;
 
3399
        if ((ret = LYJump(c)) != NULL) {
 
3400
#ifdef PERMIT_GOTO_FROM_JUMP
 
3401
            if (!strncasecomp(ret, "Go ", 3)) {
 
3402
                LYJumpFileURL = FALSE;
 
3403
                StrAllocCopy(*old_user_input, user_input_buffer);
 
3404
                *URLTotal = (Goto_URLs ? HTList_count(Goto_URLs) : 0);
 
3405
                *recall = ((*URLTotal >= 1) ? RECALL_URL : NORECALL);
 
3406
                *URLNum = *URLTotal;
 
3407
                *FirstURLRecall = TRUE;
 
3408
                if (!strcasecomp(ret, "Go :")) {
 
3409
                    if (recall) {
 
3410
                        *ch = UPARROW;
 
3411
                        return TRUE;
 
3412
                    }
 
3413
                    FREE(*old_user_input);
 
3414
                    HTUserMsg(NO_RANDOM_URLS_YET);
 
3415
                    return FALSE;
 
3416
                }
 
3417
                ret = HTParse((ret+3), startfile, PARSE_ALL);
 
3418
                LYstrncpy(user_input_buffer, ret, MAX_LINE - 1);
 
3419
                FREE(ret);
 
3420
                return TRUE;
 
3421
            }
 
3422
#endif /* PERMIT_GOTO_FROM_JUMP */
 
3423
            ret = HTParse(ret, startfile, PARSE_ALL);
 
3424
            if (!LYTrimStartfile(ret)) {
 
3425
                LYRemoveBlanks(user_input_buffer);
 
3426
            }
 
3427
            set_address(&newdoc, ret);
 
3428
            StrAllocCopy(lynxjumpfile, ret);
 
3429
            LYFreePostData(&newdoc);
 
3430
            FREE(newdoc.bookmark);
 
3431
            newdoc.isHEAD = FALSE;
 
3432
            newdoc.safe = FALSE;
 
3433
            newdoc.internal_link = FALSE;
 
3434
            FREE(ret);
 
3435
            LYUserSpecifiedURL = TRUE;
 
3436
        } else {
 
3437
            LYJumpFileURL = FALSE;
 
3438
        }
 
3439
    }
 
3440
    return FALSE;
 
3441
}
 
3442
 
 
3443
PRIVATE void handle_LYK_KEYMAP ARGS4(
 
3444
    BOOLEAN *,  vi_keys_flag,
 
3445
    BOOLEAN *,  emacs_keys_flag,
 
3446
    int *,      old_c,
 
3447
    int,        real_c)
 
3448
{
 
3449
    if (*old_c != real_c) {
 
3450
        *old_c = real_c;
 
3451
        set_address(&newdoc, STR_LYNXKEYMAP);
 
3452
        StrAllocCopy(newdoc.title, CURRENT_KEYMAP_TITLE);
 
3453
        LYFreePostData(&newdoc);
 
3454
        FREE(newdoc.bookmark);
 
3455
        newdoc.isHEAD = FALSE;
 
3456
        newdoc.safe = FALSE;
 
3457
        newdoc.internal_link = FALSE;
 
3458
        /*
 
3459
         *  If vi_keys changed, the keymap did too,
 
3460
         *  so force no cache, and reset the flag. - FM
 
3461
         */
 
3462
        if (*vi_keys_flag != vi_keys ||
 
3463
            *emacs_keys_flag != emacs_keys) {
 
3464
            LYforce_no_cache = TRUE;
 
3465
            *vi_keys_flag = vi_keys;
 
3466
            *emacs_keys_flag = emacs_keys;
 
3467
        }
 
3468
#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
 
3469
        /*
 
3470
         *  Remember whether we are in dired menu
 
3471
         *  so we can display the right keymap.
 
3472
         */
 
3473
        if (!no_dired_support) {
 
3474
            prev_lynx_edit_mode = lynx_edit_mode;
 
3475
        }
 
3476
#endif /* DIRED_SUPPORT && OK_OVERRIDE */
 
3477
        LYforce_no_cache = TRUE;
 
3478
    }
 
3479
}
 
3480
 
 
3481
PRIVATE void handle_LYK_LAST_LINK NOARGS
 
3482
{
 
3483
    int i = curdoc.link;
 
3484
 
 
3485
    for (;;) {
 
3486
        if (++i >= nlinks
 
3487
         || links[i].ly != links[curdoc.link].ly) {
 
3488
            set_curdoc_link(i - 1);
 
3489
            break;
 
3490
        }
 
3491
    }
 
3492
}
 
3493
 
 
3494
PRIVATE void handle_LYK_LEFT_LINK NOARGS
 
3495
{
 
3496
    if (curdoc.link>0 &&
 
3497
                links[curdoc.link].ly == links[curdoc.link-1].ly) {
 
3498
        set_curdoc_link(curdoc.link-1);
 
3499
    }
 
3500
}
 
3501
 
 
3502
PRIVATE BOOLEAN handle_LYK_LIST ARGS1(
 
3503
    int *,     cmd)
 
3504
{
 
3505
    /*
 
3506
     *  Don't do if already viewing list page.
 
3507
     */
 
3508
    if (!strcmp(NonNull(curdoc.title), LIST_PAGE_TITLE) &&
 
3509
        LYIsUIPage(curdoc.address, UIP_LIST_PAGE)) {
 
3510
        /*
 
3511
         *  Already viewing list page, so get out.
 
3512
         */
 
3513
        *cmd = LYK_PREV_DOC;
 
3514
        return TRUE;
 
3515
    }
 
3516
 
 
3517
    /*
 
3518
     *  Print list page to file.
 
3519
     */
 
3520
    if (showlist(&newdoc, TRUE) < 0)
 
3521
        return FALSE;
 
3522
    StrAllocCopy(newdoc.title, LIST_PAGE_TITLE);
 
3523
    /*
 
3524
     *  showlist will set newdoc's other fields.  It may leave
 
3525
     *  post_data intact so the list can be used to follow
 
3526
     *  internal links in the current document even if it is
 
3527
     *  a POST response. - kw
 
3528
     */
 
3529
 
 
3530
    if (LYValidate || check_realm) {
 
3531
        LYPermitURL = TRUE;
 
3532
        StrAllocCopy(lynxlistfile, newdoc.address);
 
3533
    }
 
3534
    return FALSE;
 
3535
}
 
3536
 
 
3537
PRIVATE void handle_LYK_MAIN_MENU ARGS2(
 
3538
    int *,      old_c,
 
3539
    int,        real_c)
 
3540
{
 
3541
    /*
 
3542
     *  If its already the homepage then don't reload it.
 
3543
     */
 
3544
    if (!STREQ(curdoc.address,homepage)) {
 
3545
 
 
3546
        if (HTConfirmDefault(CONFIRM_MAIN_SCREEN, NO) == YES) {
 
3547
            set_address(&newdoc, homepage);
 
3548
            StrAllocCopy(newdoc.title, gettext("Entry into main screen"));
 
3549
            LYFreePostData(&newdoc);
 
3550
            FREE(newdoc.bookmark);
 
3551
            newdoc.isHEAD = FALSE;
 
3552
            newdoc.safe = FALSE;
 
3553
            newdoc.internal_link = FALSE;
 
3554
            LYhighlight(OFF, curdoc.link, prev_target);
 
3555
#ifdef DIRED_SUPPORT
 
3556
            if (lynx_edit_mode) {
 
3557
                DIRED_UNCACHE_2;
 
3558
            }
 
3559
#endif /* DIRED_SUPPORT */
 
3560
        }
 
3561
    } else {
 
3562
        if (*old_c != real_c) {
 
3563
            *old_c = real_c;
 
3564
            HTUserMsg(IN_MAIN_SCREEN);
 
3565
        }
 
3566
    }
 
3567
}
 
3568
 
 
3569
PRIVATE void handle_LYK_MINIMAL NOARGS
 
3570
{
 
3571
    if (!historical_comments) {
 
3572
#ifdef USE_SOURCE_CACHE
 
3573
    if (!HTcan_reparse_document()) {
 
3574
#endif
 
3575
        /*
 
3576
         *  Check if this is a reply from a POST, and if so,
 
3577
         *  seek confirmation of reload if the safe element
 
3578
         *  is not set. - FM
 
3579
         */
 
3580
        if ((curdoc.post_data != NULL &&
 
3581
             curdoc.safe != TRUE) &&
 
3582
            confirm_post_resub(curdoc.address, NULL, 0, 0) == FALSE) {
 
3583
            HTInfoMsg(WILL_NOT_RELOAD_DOC);
 
3584
        } else {
 
3585
            HText_setNoCache(HTMainText);
 
3586
            move_address(&newdoc, &curdoc);
 
3587
            newdoc.line = curdoc.line;
 
3588
            newdoc.link = curdoc.link;
 
3589
        }
 
3590
#ifdef USE_SOURCE_CACHE
 
3591
    } /* end if no bypass */
 
3592
#endif
 
3593
    }
 
3594
    minimal_comments = !minimal_comments;
 
3595
    if (!historical_comments) {
 
3596
        HTAlert(minimal_comments ?
 
3597
                MINIMAL_ON_IN_EFFECT : MINIMAL_OFF_VALID_ON);
 
3598
    } else {
 
3599
        HTAlert(minimal_comments ?
 
3600
                MINIMAL_ON_BUT_HISTORICAL : MINIMAL_OFF_HISTORICAL_ON);
 
3601
    }
 
3602
#ifdef USE_SOURCE_CACHE
 
3603
    (void)reparse_document();
 
3604
#endif
 
3605
    return;
 
3606
}
 
3607
 
 
3608
#if defined(DIRED_SUPPORT)
 
3609
PRIVATE void handle_LYK_MODIFY ARGS1(
 
3610
    BOOLEAN *,  refresh_screen)
 
3611
{
 
3612
    if (lynx_edit_mode && nlinks > 0 && !no_dired_support) {
 
3613
        int ret;
 
3614
 
 
3615
        ret = local_modify(&curdoc, &newdoc.address);
 
3616
        if (ret == PERMIT_FORM_RESULT) { /* Permit form thrown up */
 
3617
            *refresh_screen = TRUE;
 
3618
        } else if (ret) {
 
3619
            DIRED_UNCACHE_1;
 
3620
            move_address(&newdoc, &curdoc);
 
3621
            LYFreePostData(&newdoc);
 
3622
            FREE(newdoc.bookmark);
 
3623
            newdoc.isHEAD = FALSE;
 
3624
            newdoc.safe = FALSE;
 
3625
            newdoc.internal_link = FALSE;
 
3626
            newdoc.line = curdoc.line;
 
3627
            newdoc.link = curdoc.link;
 
3628
            LYclear();
 
3629
        }
 
3630
    }
 
3631
}
 
3632
#endif /* DIRED_SUPPORT */
 
3633
 
 
3634
#ifdef EXP_NESTED_TABLES
 
3635
PRIVATE BOOLEAN handle_LYK_NESTED_TABLES ARGS1(
 
3636
    int *,      cmd)
 
3637
{
 
3638
    nested_tables = !nested_tables;
 
3639
    HTUserMsg(nested_tables ? NESTED_TABLES_ON : NESTED_TABLES_OFF);
 
3640
    return reparse_or_reload(cmd);
 
3641
}
 
3642
#endif
 
3643
 
 
3644
PRIVATE BOOLEAN handle_LYK_OPTIONS ARGS2(
 
3645
    int *,      cmd,
 
3646
    BOOLEAN *,  refresh_screen)
 
3647
{
 
3648
#ifndef NO_OPTION_MENU
 
3649
    if (!LYUseFormsOptions) {
 
3650
        BOOLEAN LYUseDefaultRawMode_flag = LYUseDefaultRawMode;
 
3651
        BOOLEAN LYSelectPopups_flag = LYSelectPopups;
 
3652
        BOOLEAN verbose_img_flag = verbose_img;
 
3653
        BOOLEAN keypad_mode_flag = (BOOL) keypad_mode;
 
3654
        BOOLEAN show_dotfiles_flag = show_dotfiles;
 
3655
        BOOLEAN user_mode_flag = (BOOL) user_mode;
 
3656
        int CurrentAssumeCharSet_flag = UCLYhndl_for_unspec;
 
3657
        int CurrentCharSet_flag = current_char_set;
 
3658
        int HTfileSortMethod_flag = HTfileSortMethod;
 
3659
        char *CurrentUserAgent = NULL;
 
3660
        char *CurrentNegoLanguage = NULL;
 
3661
        char *CurrentNegoCharset = NULL;
 
3662
        StrAllocCopy(CurrentUserAgent, (LYUserAgent ?
 
3663
                                        LYUserAgent : ""));
 
3664
        StrAllocCopy(CurrentNegoLanguage, (language ?
 
3665
                                           language : ""));
 
3666
        StrAllocCopy(CurrentNegoCharset, (pref_charset ?
 
3667
                                          pref_charset : ""));
 
3668
 
 
3669
        LYoptions(); /** do the old-style options stuff **/
 
3670
 
 
3671
        if (keypad_mode_flag != keypad_mode ||
 
3672
            (user_mode_flag != user_mode &&
 
3673
             (user_mode_flag == NOVICE_MODE ||
 
3674
              user_mode == NOVICE_MODE)) ||
 
3675
            (((HTfileSortMethod_flag != HTfileSortMethod) ||
 
3676
              (show_dotfiles_flag != show_dotfiles)) &&
 
3677
             (isFILE_URL(curdoc.address) ||
 
3678
              isFTP_URL(curdoc.address))) ||
 
3679
            CurrentCharSet_flag != current_char_set ||
 
3680
            CurrentAssumeCharSet_flag != UCLYhndl_for_unspec ||
 
3681
            verbose_img_flag != verbose_img ||
 
3682
            LYUseDefaultRawMode_flag != LYUseDefaultRawMode ||
 
3683
            LYSelectPopups_flag != LYSelectPopups ||
 
3684
            ((strcmp(CurrentUserAgent, (LYUserAgent ?
 
3685
                                        LYUserAgent : "")) ||
 
3686
              strcmp(CurrentNegoLanguage, (language ?
 
3687
                                           language : "")) ||
 
3688
              strcmp(CurrentNegoCharset, (pref_charset ?
 
3689
                                          pref_charset : ""))) &&
 
3690
             (!strncmp(curdoc.address, "http", 4) ||
 
3691
              isLYNXCGI(curdoc.address)))) {
 
3692
 
 
3693
            BOOLEAN canreparse_post = FALSE;
 
3694
 
 
3695
            /*
 
3696
             *  Check if this is a reply from a POST, and if so,
 
3697
             *  seek confirmation of reload if the safe element
 
3698
             *  is not set. - FM
 
3699
             */
 
3700
            if ((curdoc.post_data != NULL &&
 
3701
                 curdoc.safe != TRUE) &&
 
3702
#ifdef USE_SOURCE_CACHE
 
3703
                (!(canreparse_post = HTcan_reparse_document())) &&
 
3704
#endif
 
3705
                confirm_post_resub(curdoc.address, curdoc.title,
 
3706
                                   2, 1) == FALSE) {
 
3707
                HTInfoMsg(WILL_NOT_RELOAD_DOC);
 
3708
            } else {
 
3709
                copy_address(&newdoc, &curdoc);
 
3710
                if (((strcmp(CurrentUserAgent, (LYUserAgent ?
 
3711
                                        LYUserAgent : "")) ||
 
3712
                      strcmp(CurrentNegoLanguage, NonNull(language)) ||
 
3713
                      strcmp(CurrentNegoCharset, NonNull(pref_charset))) &&
 
3714
                     (strncmp(curdoc.address, "http", 4) == 0 ||
 
3715
                      !isLYNXCGI(curdoc.address) == 0))) {
 
3716
                    /*
 
3717
                     *  An option has changed which may influence
 
3718
                     *  content negotiation, and the resource is from
 
3719
                     *  a http or https or lynxcgi URL (the only protocols
 
3720
                     *  which currently do anything with this information).
 
3721
                     *  Set reloading = TRUE so that proxy caches will be
 
3722
                     *  flushed, which is necessary until the time when
 
3723
                     *  all proxies understand HTTP 1.1 Vary: and all
 
3724
                     *  Servers properly use it...      Treat like
 
3725
                     *  case LYK_RELOAD (see comments there). - KW
 
3726
                     */
 
3727
                    reloading = TRUE;
 
3728
                }
 
3729
                if (HTisDocumentSource()) {
 
3730
                    srcmode_for_next_retrieval(1);
 
3731
                }
 
3732
#ifdef USE_SOURCE_CACHE
 
3733
                if (reloading == FALSE) {
 
3734
                    /* one more attempt to be smart enough: */
 
3735
                    if (reparse_document()) {
 
3736
                        FREE(CurrentUserAgent);
 
3737
                        FREE(CurrentNegoLanguage);
 
3738
                        FREE(CurrentNegoCharset);
 
3739
                        return FALSE;
 
3740
                    }
 
3741
                }
 
3742
#endif
 
3743
                if (canreparse_post &&
 
3744
                    confirm_post_resub(curdoc.address, curdoc.title,
 
3745
                                       2, 1) == FALSE) {
 
3746
                    if (HTisDocumentSource()) {
 
3747
                        srcmode_for_next_retrieval(0);
 
3748
                    }
 
3749
                    FREE(CurrentUserAgent);
 
3750
                    FREE(CurrentNegoLanguage);
 
3751
                    FREE(CurrentNegoCharset);
 
3752
                    return FALSE;
 
3753
                }
 
3754
 
 
3755
                HEAD_request = HTLoadedDocumentIsHEAD();
 
3756
                HText_setNoCache(HTMainText);
 
3757
#ifdef NO_ASSUME_SAME_DOC
 
3758
                newdoc.line = 1;
 
3759
                newdoc.link = 0;
 
3760
#else
 
3761
                newdoc.line = curdoc.line;
 
3762
                newdoc.link = curdoc.link;
 
3763
#endif /* NO_ASSUME_SAME_DOC */
 
3764
                LYforce_no_cache = TRUE;
 
3765
                free_address(&curdoc); /* So it doesn't get pushed. */
 
3766
            }
 
3767
        }
 
3768
        FREE(CurrentUserAgent);
 
3769
        FREE(CurrentNegoLanguage);
 
3770
        FREE(CurrentNegoCharset);
 
3771
        *refresh_screen = TRUE; /* to repaint screen */
 
3772
        return FALSE;
 
3773
    } /* end if !LYUseFormsOptions */
 
3774
#endif /* !NO_OPTION_MENU */
 
3775
#ifndef NO_OPTION_FORMS
 
3776
    /*
 
3777
     * Generally stolen from LYK_COOKIE_JAR.  Options menu handling is
 
3778
     * done in postoptions(), called from getfile() currently.
 
3779
     *
 
3780
     * postoptions() is also responsible for reloading the document
 
3781
     * before the 'options menu' but only when (a few) important
 
3782
     * options were changed.
 
3783
     *
 
3784
     * It is critical that post_data is freed here since the
 
3785
     * submission of changed options is done via the same protocol as
 
3786
     * LYNXOPTIONS:
 
3787
     */
 
3788
    /*
 
3789
     *  Don't do if already viewing options page.
 
3790
     */
 
3791
    if (!LYIsUIPage(curdoc.address, UIP_OPTIONS_MENU)) {
 
3792
 
 
3793
        set_address(&newdoc, "LYNXOPTIONS:/");
 
3794
        LYFreePostData(&newdoc);
 
3795
        FREE(newdoc.bookmark);
 
3796
        newdoc.isHEAD = FALSE;
 
3797
        newdoc.safe = FALSE;
 
3798
        newdoc.internal_link = FALSE;
 
3799
        LYforce_no_cache = TRUE;
 
3800
        /* change to 'if (check_realm && !LYValidate)' and
 
3801
           make change near top of getfile to forbid
 
3802
           using forms options menu with -validate:  - kw */
 
3803
        if (LYValidate || check_realm) {
 
3804
            LYPermitURL = TRUE;
 
3805
        }
 
3806
   } else {
 
3807
        /*
 
3808
         *  If already in the options menu, get out.
 
3809
         */
 
3810
        *cmd = LYK_PREV_DOC;
 
3811
        return TRUE;
 
3812
    }
 
3813
#endif /* !NO_OPTION_FORMS */
 
3814
    return FALSE;
 
3815
}
 
3816
 
 
3817
PRIVATE void handle_NEXT_DOC NOARGS
 
3818
{
 
3819
    if (LYhist_next(&curdoc, &newdoc)) {
 
3820
        free_address(&curdoc);  /* avoid push */
 
3821
        return;
 
3822
    }
 
3823
    HTUserMsg(gettext("No next document present"));
 
3824
}
 
3825
 
 
3826
PRIVATE void handle_LYK_NEXT_LINK ARGS3(
 
3827
    int,        c,
 
3828
    int *,      old_c,
 
3829
    int,        real_c)
 
3830
{
 
3831
    if (curdoc.link < nlinks-1) {       /* next link */
 
3832
        LYhighlight(OFF, curdoc.link, prev_target);
 
3833
#ifdef FASTTAB
 
3834
        /*
 
3835
         *  Move to different textarea if TAB in textarea.
 
3836
         */
 
3837
        if (links[curdoc.link].type         == WWW_FORM_LINK_TYPE &&
 
3838
            links[curdoc.link].l_form->type == F_TEXTAREA_TYPE &&
 
3839
            c=='\t') {
 
3840
            int thisgroup = links[curdoc.link].l_form->number;
 
3841
            char *thisname = links[curdoc.link].l_form->name;
 
3842
 
 
3843
            do curdoc.link++;
 
3844
            while ((curdoc.link < nlinks-1) &&
 
3845
                   links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
3846
                   links[curdoc.link].l_form->type == F_TEXTAREA_TYPE &&
 
3847
                   links[curdoc.link].l_form->number == thisgroup &&
 
3848
                   sametext(links[curdoc.link].l_form->name, thisname));
 
3849
        } else {
 
3850
            curdoc.link++;
 
3851
        }
 
3852
#else
 
3853
        curdoc.link++;
 
3854
#endif /* FASTTAB */
 
3855
    /*
 
3856
     *  At the bottom of list and there is only one page.
 
3857
     *  Move to the top link on the page.
 
3858
     */
 
3859
    } else if (!more && Newline == 1 && curdoc.link == nlinks-1) {
 
3860
        set_curdoc_link(0);
 
3861
 
 
3862
    } else if (more) {  /* next page */
 
3863
        Newline += (display_lines);
 
3864
 
 
3865
    } else if (*old_c != real_c) {
 
3866
        *old_c = real_c;
 
3867
        HTInfoMsg(ALREADY_AT_END);
 
3868
    }
 
3869
}
 
3870
 
 
3871
PRIVATE void handle_LYK_NEXT_PAGE ARGS2(
 
3872
    int *,      old_c,
 
3873
    int,        real_c)
 
3874
{
 
3875
    if (more) {
 
3876
        Newline += display_lines;
 
3877
    } else if (curdoc.link < nlinks-1) {
 
3878
        set_curdoc_link(nlinks - 1);
 
3879
    } else if (*old_c != real_c) {
 
3880
        *old_c = real_c;
 
3881
        HTInfoMsg(ALREADY_AT_END);
 
3882
    }
 
3883
}
 
3884
 
 
3885
PRIVATE BOOLEAN handle_LYK_NOCACHE ARGS2(
 
3886
    int *,      old_c,
 
3887
    int,        real_c)
 
3888
{
 
3889
    if (nlinks > 0) {
 
3890
        if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
3891
            links[curdoc.link].l_form->type != F_SUBMIT_TYPE &&
 
3892
            links[curdoc.link].l_form->type != F_IMAGE_SUBMIT_TYPE &&
 
3893
            links[curdoc.link].l_form->type != F_TEXT_SUBMIT_TYPE) {
 
3894
            if (*old_c != real_c) {
 
3895
                *old_c = real_c;
 
3896
                HTUserMsg(NOT_ON_SUBMIT_OR_LINK);
 
3897
            }
 
3898
            return FALSE;
 
3899
        } else {
 
3900
            LYforce_no_cache = TRUE;
 
3901
            reloading = TRUE;
 
3902
        }
 
3903
    }
 
3904
    return TRUE;
 
3905
}
 
3906
 
 
3907
PRIVATE void handle_LYK_PREV_LINK ARGS3(
 
3908
    int *,      arrowup,
 
3909
    int *,      old_c,
 
3910
    int,        real_c)
 
3911
{
 
3912
    if (curdoc.link > 0) {           /* previous link */
 
3913
        set_curdoc_link(curdoc.link - 1);
 
3914
 
 
3915
    } else if (!more &&
 
3916
               curdoc.link==0 && Newline==1) { /* at the top of list */
 
3917
        /*
 
3918
         *  If there is only one page of data and the user
 
3919
         *  goes off the top, just move the cursor to last link on
 
3920
         *  the page.
 
3921
         */
 
3922
        set_curdoc_link(nlinks - 1);
 
3923
 
 
3924
    } else if (curdoc.line > 1) {       /* previous page */
 
3925
        /*
 
3926
         *  Go back to the previous page.
 
3927
         */
 
3928
        int scrollamount = (Newline > display_lines ?
 
3929
                                      display_lines : Newline - 1);
 
3930
        Newline -= scrollamount;
 
3931
        if (scrollamount < display_lines &&
 
3932
            nlinks > 0 && curdoc.link == 0 &&
 
3933
            links[0].ly - 1 + scrollamount <= display_lines) {
 
3934
                newdoc.link = HText_LinksInLines(HTMainText,
 
3935
                                                 1,
 
3936
                                                 scrollamount) - 1;
 
3937
        } else {
 
3938
            *arrowup = TRUE;
 
3939
        }
 
3940
 
 
3941
    } else if (*old_c != real_c) {
 
3942
        *old_c = real_c;
 
3943
        HTInfoMsg(ALREADY_AT_BEGIN);
 
3944
    }
 
3945
}
 
3946
 
 
3947
PRIVATE int handle_PREV_DOC ARGS3(
 
3948
    int *,      cmd,
 
3949
    int *,      old_c,
 
3950
    int,        real_c)
 
3951
{
 
3952
    if (nhist > 0) {  /* if there is anything to go back to */
 
3953
        /*
 
3954
         *  Check if the previous document is a reply from a POST,
 
3955
         *  and if so, seek confirmation of resubmission if the safe
 
3956
         *  element is not set and the document is not still in the
 
3957
         *  cache or LYresubmit_posts is set.  If not confirmed and
 
3958
         *  it is not the startfile, pop it so we go to the yet
 
3959
         *  previous document, until we're OK or reach the startfile.
 
3960
         *  If we reach the startfile and its not OK or we don't get
 
3961
         *  confirmation, cancel. - FM
 
3962
         */
 
3963
        DocAddress WWWDoc;
 
3964
        HTParentAnchor *tmpanchor;
 
3965
        HText *text;
 
3966
        BOOLEAN conf = FALSE, first = TRUE;
 
3967
 
 
3968
        HTLastConfirmCancelled(); /* reset flag */
 
3969
        while (nhist > 0) {
 
3970
            conf = FALSE;
 
3971
            if (HDOC(nhist - 1).post_data == NULL) {
 
3972
                break;
 
3973
            }
 
3974
            WWWDoc.address = HDOC(nhist - 1).address;
 
3975
            WWWDoc.post_data = HDOC(nhist - 1).post_data;
 
3976
            WWWDoc.post_content_type =
 
3977
                               HDOC(nhist - 1).post_content_type;
 
3978
            WWWDoc.bookmark = HDOC(nhist - 1).bookmark;
 
3979
            WWWDoc.isHEAD = HDOC(nhist - 1).isHEAD;
 
3980
            WWWDoc.safe = HDOC(nhist - 1).safe;
 
3981
            tmpanchor = HTAnchor_findAddress(&WWWDoc);
 
3982
            if (HTAnchor_safe(tmpanchor)) {
 
3983
                break;
 
3984
            }
 
3985
            if (((text = (HText *)HTAnchor_document(tmpanchor)) == NULL &&
 
3986
                 (isLYNXIMGMAP(WWWDoc.address) ||
 
3987
                 (conf = confirm_post_resub(WWWDoc.address,
 
3988
                                            HDOC(nhist - 1).title,
 
3989
                                            0, 0))
 
3990
                  == FALSE)) ||
 
3991
                ((LYresubmit_posts && !conf &&
 
3992
                  (NONINTERNAL_OR_PHYS_DIFFERENT(
 
3993
                      (DocInfo *)&history[(nhist - 1)],
 
3994
                      &curdoc) ||
 
3995
                   NONINTERNAL_OR_PHYS_DIFFERENT(
 
3996
                       (DocInfo *)&history[(nhist - 1)],
 
3997
                       &newdoc))) &&
 
3998
                 !confirm_post_resub(WWWDoc.address,
 
3999
                                     HDOC(nhist - 1).title,
 
4000
                                     2, 2))) {
 
4001
                if (HTLastConfirmCancelled()) {
 
4002
                    if (!first && curdoc.internal_link)
 
4003
                        free_address(&curdoc);
 
4004
                    *cmd = LYK_DO_NOTHING;
 
4005
                    return 2;
 
4006
                }
 
4007
                if (nhist == 1) {
 
4008
                    HTInfoMsg(CANCELLED);
 
4009
                    *old_c = 0;
 
4010
                    *cmd = LYK_DO_NOTHING;
 
4011
                    return 2;
 
4012
                } else {
 
4013
                    HTUserMsg2(WWW_SKIP_MESSAGE, WWWDoc.address);
 
4014
                    do {        /* Should be LYhist_prev when _next supports */
 
4015
                        LYpop(&curdoc);         /* skipping of forms */
 
4016
                    } while (nhist > 1 && !are_different(
 
4017
                        (DocInfo *)&history[(nhist - 1)],
 
4018
                        &curdoc));
 
4019
                    first = FALSE; /* have popped at least one */
 
4020
                    continue;
 
4021
                }
 
4022
            } else {
 
4023
                /*
 
4024
                 *  Break from loop; if user just confirmed to
 
4025
                 *  load again because document wasn't in cache,
 
4026
                 *  set LYforce_no_cache to avoid unnecessary
 
4027
                 *  repeat question down the road. - kw
 
4028
                 */
 
4029
                if (conf)
 
4030
                    LYforce_no_cache = TRUE;
 
4031
                break;
 
4032
            }
 
4033
        }
 
4034
 
 
4035
        if (!first)
 
4036
            curdoc.internal_link = FALSE;
 
4037
 
 
4038
        /*
 
4039
         *  Set newdoc.address to empty to pop a file.
 
4040
         */
 
4041
        LYhist_prev_register(&curdoc);  /* Why not call _prev instead of zeroing address?  */
 
4042
        free_address(&newdoc);
 
4043
#ifdef DIRED_SUPPORT
 
4044
        if (lynx_edit_mode) {
 
4045
            DIRED_UNCACHE_2;
 
4046
        }
 
4047
#endif /* DIRED_SUPPORT */
 
4048
    } else if (child_lynx == TRUE) {
 
4049
        return(1); /* exit on left arrow in main screen */
 
4050
 
 
4051
    } else if (*old_c != real_c) {
 
4052
        *old_c = real_c;
 
4053
        HTUserMsg(ALREADY_AT_FIRST);
 
4054
    }
 
4055
    return 0;
 
4056
}
 
4057
 
 
4058
PRIVATE void handle_LYK_PREV_PAGE ARGS2(
 
4059
    int *,      old_c,
 
4060
    int,        real_c)
 
4061
{
 
4062
    if (Newline > 1) {
 
4063
        Newline -= display_lines;
 
4064
    } else if (curdoc.link > 0) {
 
4065
        set_curdoc_link(0);
 
4066
    } else if (*old_c != real_c) {
 
4067
        *old_c = real_c;
 
4068
        HTInfoMsg(ALREADY_AT_BEGIN);
 
4069
    }
 
4070
}
 
4071
 
 
4072
PRIVATE void handle_LYK_PRINT ARGS3(
 
4073
    BOOLEAN *,  ForcePush,
 
4074
    int *,      old_c,
 
4075
    int,        real_c)
 
4076
{
 
4077
    if (LYValidate) {
 
4078
        if (*old_c != real_c)   {
 
4079
            *old_c = real_c;
 
4080
            HTUserMsg(PRINT_DISABLED);
 
4081
        }
 
4082
        return;
 
4083
    }
 
4084
 
 
4085
    /*
 
4086
     *  Don't do if already viewing print options page.
 
4087
     */
 
4088
    if (!LYIsUIPage(curdoc.address, UIP_PRINT_OPTIONS)
 
4089
     && print_options(&newdoc.address,
 
4090
                      curdoc.address, HText_getNumOfLines()) >= 0) {
 
4091
        LYRegisterUIPage(newdoc.address, UIP_PRINT_OPTIONS);
 
4092
        StrAllocCopy(newdoc.title, PRINT_OPTIONS_TITLE);
 
4093
        LYFreePostData(&newdoc);
 
4094
        FREE(newdoc.bookmark);
 
4095
        newdoc.isHEAD = FALSE;
 
4096
        newdoc.safe = FALSE;
 
4097
        *ForcePush = TRUE;  /* see LYpush() and print_options() */
 
4098
        if (check_realm)
 
4099
            LYPermitURL = TRUE;
 
4100
    }
 
4101
}
 
4102
 
 
4103
PRIVATE BOOLEAN handle_LYK_QUIT NOARGS
 
4104
{
 
4105
    int c;
 
4106
 
 
4107
    if (LYQuitDefaultYes == TRUE) {
 
4108
        c = HTConfirmDefault(REALLY_QUIT, YES);
 
4109
    } else {
 
4110
        c = HTConfirmDefault(REALLY_QUIT, NO);
 
4111
    }
 
4112
    if (LYQuitDefaultYes == TRUE) {
 
4113
        if (c != NO) {
 
4114
            return(TRUE);
 
4115
        } else {
 
4116
            HTInfoMsg(NO_CANCEL);
 
4117
        }
 
4118
    } else if (c == YES) {
 
4119
        return(TRUE);
 
4120
    } else {
 
4121
        HTInfoMsg(NO_CANCEL);
 
4122
    }
 
4123
    return FALSE;
 
4124
}
 
4125
 
 
4126
PRIVATE BOOLEAN handle_LYK_RAW_TOGGLE ARGS1(
 
4127
    int *,      cmd)
 
4128
{
 
4129
    if (HTLoadedDocumentCharset()) {
 
4130
        HTUserMsg(gettext("charset for this document specified explicitly, sorry..."));
 
4131
        return FALSE;
 
4132
    } else {
 
4133
        LYUseDefaultRawMode = (BOOL) !LYUseDefaultRawMode;
 
4134
        HTUserMsg(LYRawMode ? RAWMODE_OFF : RAWMODE_ON);
 
4135
        HTMLSetCharacterHandling(current_char_set);
 
4136
        return reparse_or_reload(cmd);
 
4137
    }
 
4138
}
 
4139
 
 
4140
PRIVATE void handle_LYK_RELOAD ARGS1(
 
4141
    int,        real_cmd)
 
4142
{
 
4143
    /*
 
4144
     * Check if this is a reply from a POST, and if so,
 
4145
     * seek confirmation if the safe element is not set.  - FM
 
4146
     */
 
4147
    if ((curdoc.post_data != NULL &&
 
4148
         curdoc.safe != TRUE) &&
 
4149
        HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
 
4150
        HTInfoMsg(CANCELLED);
 
4151
        return;
 
4152
    }
 
4153
 
 
4154
    /*
 
4155
     *  Check to see if should reload source, or load html
 
4156
     */
 
4157
 
 
4158
    if (HTisDocumentSource()) {
 
4159
        if ((forced_UCLYhdnl = HTMainText_Get_UCLYhndl()) >= 0)
 
4160
            force_old_UCLYhndl_on_reload = TRUE;
 
4161
        srcmode_for_next_retrieval(1);
 
4162
    }
 
4163
 
 
4164
    HEAD_request = HTLoadedDocumentIsHEAD();
 
4165
    HText_setNoCache(HTMainText);
 
4166
#ifdef NO_ASSUME_SAME_DOC
 
4167
    /*
 
4168
     *  Don't assume the reloaded document will be the same. - FM
 
4169
     */
 
4170
    newdoc.line = 1;
 
4171
    newdoc.link = 0;
 
4172
#else
 
4173
    /*
 
4174
     *  Do assume the reloaded document will be the same. - FM
 
4175
     *  (I don't remember all the reasons why we couldn't assume
 
4176
     *   this.  As the problems show up, we'll try to fix them,
 
4177
     *   or add warnings.  - FM)
 
4178
     */
 
4179
    newdoc.line = curdoc.line;
 
4180
    newdoc.link = curdoc.link;
 
4181
#endif /* NO_ASSUME_SAME_DOC */
 
4182
    free_address(&curdoc); /* so it doesn't get pushed */
 
4183
#ifdef VMS
 
4184
    lynx_force_repaint();
 
4185
#endif /* VMS */
 
4186
    /*
 
4187
     *  Reload should force a cache refresh on a proxy.
 
4188
     *        -- Ari L. <luotonen@dxcern.cern.ch>
 
4189
     *
 
4190
     *  -- but only if this was really a reload requested by
 
4191
     *  the user, not if we jumped here to handle reloading for
 
4192
     *  INLINE_TOGGLE, IMAGE_TOGGLE, RAW_TOGGLE, etc. - KW
 
4193
     */
 
4194
    if (real_cmd == LYK_RELOAD)
 
4195
        reloading = TRUE;
 
4196
 
 
4197
    return;
 
4198
}
 
4199
 
 
4200
#ifdef DIRED_SUPPORT
 
4201
PRIVATE void handle_LYK_REMOVE ARGS1(
 
4202
    BOOLEAN *,  refresh_screen)
 
4203
{
 
4204
    if (lynx_edit_mode && nlinks > 0 && !no_dired_support) {
 
4205
        int linkno = curdoc.link; /* may be changed in local_remove - kw */
 
4206
        local_remove(&curdoc);
 
4207
        if (LYAutoUncacheDirLists >= 1)
 
4208
            do_cleanup_after_delete();
 
4209
        else if (curdoc.link != linkno)
 
4210
            *refresh_screen = TRUE;
 
4211
    }
 
4212
}
 
4213
#endif /* DIRED_SUPPORT */
 
4214
 
 
4215
PRIVATE void handle_LYK_RIGHT_LINK NOARGS
 
4216
{
 
4217
    if (curdoc.link<nlinks-1 &&
 
4218
                links[curdoc.link].ly == links[curdoc.link+1].ly) {
 
4219
        set_curdoc_link(curdoc.link + 1);
 
4220
    }
 
4221
}
 
4222
 
 
4223
PRIVATE void handle_LYK_SHELL ARGS3(
 
4224
    BOOLEAN *,  refresh_screen,
 
4225
    int *,      old_c,
 
4226
    int,        real_c)
 
4227
{
 
4228
    if (!no_shell) {
 
4229
        stop_curses();
 
4230
        printf("%s\r\n", SPAWNING_MSG);
 
4231
#if defined(__CYGWIN__)
 
4232
        /* handling "exec $SHELL" does not work if $SHELL is null */
 
4233
        if (LYGetEnv("SHELL") == NULL) {
 
4234
            Cygwin_Shell();
 
4235
        } else
 
4236
#endif
 
4237
        LYSystem(LYSysShell());
 
4238
        start_curses();
 
4239
        *refresh_screen = TRUE; /* for an HText_pageDisplay() */
 
4240
    } else {
 
4241
        if (*old_c != real_c)   {
 
4242
            *old_c = real_c;
 
4243
            HTUserMsg(SPAWNING_DISABLED);
 
4244
        }
 
4245
    }
 
4246
}
 
4247
 
 
4248
PRIVATE void handle_LYK_SOFT_DQUOTES NOARGS
 
4249
{
 
4250
#ifdef USE_SOURCE_CACHE
 
4251
    if (!HTcan_reparse_document()) {
 
4252
#endif
 
4253
    /*
 
4254
     *  Check if this is a reply from a POST, and if so,
 
4255
     *  seek confirmation of reload if the safe element
 
4256
     *  is not set. - FM
 
4257
     */
 
4258
    if ((curdoc.post_data != NULL &&
 
4259
         curdoc.safe != TRUE) &&
 
4260
        confirm_post_resub(curdoc.address, NULL, 1, 1) == FALSE) {
 
4261
        HTInfoMsg(WILL_NOT_RELOAD_DOC);
 
4262
    } else {
 
4263
        HText_setNoCache(HTMainText);
 
4264
        move_address(&newdoc, &curdoc);
 
4265
        newdoc.line = curdoc.line;
 
4266
        newdoc.link = curdoc.link;
 
4267
    }
 
4268
#ifdef USE_SOURCE_CACHE
 
4269
    } /* end if no bypass */
 
4270
#endif
 
4271
    soft_dquotes = !soft_dquotes;
 
4272
    HTUserMsg(soft_dquotes ?
 
4273
              SOFT_DOUBLE_QUOTE_ON : SOFT_DOUBLE_QUOTE_OFF);
 
4274
#ifdef USE_SOURCE_CACHE
 
4275
    (void)reparse_document();
 
4276
#endif
 
4277
    return;
 
4278
}
 
4279
 
 
4280
PRIVATE void handle_LYK_SOURCE ARGS1(
 
4281
    char **,    ownerS_address_p)
 
4282
{
 
4283
    /*
 
4284
     * Check if this is a reply from a POST, and if so,
 
4285
     * seek confirmation if the safe element is not set.  - FM
 
4286
     */
 
4287
#ifdef USE_SOURCE_CACHE
 
4288
    BOOLEAN canreparse_post = FALSE;
 
4289
#endif
 
4290
    if ((curdoc.post_data != NULL &&
 
4291
         curdoc.safe != TRUE) &&
 
4292
#ifdef USE_SOURCE_CACHE
 
4293
        (!(canreparse_post = HTcan_reparse_document())) &&
 
4294
#endif
 
4295
        (curdoc.isHEAD ? HTConfirm(CONFIRM_POST_RESUBMISSION) :
 
4296
         confirm_post_resub(curdoc.address, curdoc.title, 1, 1)) == FALSE) {
 
4297
        HTInfoMsg(CANCELLED);
 
4298
        return;
 
4299
    }
 
4300
 
 
4301
    if (HTisDocumentSource()) {
 
4302
        srcmode_for_next_retrieval(-1);
 
4303
    } else {
 
4304
        if (HText_getOwner())
 
4305
            StrAllocCopy(*ownerS_address_p, HText_getOwner());
 
4306
        LYUCPushAssumed(HTMainAnchor);
 
4307
        srcmode_for_next_retrieval(1);
 
4308
    }
 
4309
 
 
4310
#ifdef USE_SOURCE_CACHE
 
4311
    if (reparse_document()) {
 
4312
        /*
 
4313
         * These normally get cleaned up after getfile() returns;
 
4314
         * since we're not calling getfile(), we have to clean them
 
4315
         * up ourselves.  -dsb
 
4316
         */
 
4317
        HTOutputFormat = WWW_PRESENT;
 
4318
#ifdef USE_PRETTYSRC
 
4319
        if (psrc_view)
 
4320
            HTMark_asSource();
 
4321
        psrc_view = FALSE;
 
4322
#endif
 
4323
        FREE(*ownerS_address_p);  /* not used with source_cache */
 
4324
        LYUCPopAssumed();       /* probably a right place here */
 
4325
        HTMLSetCharacterHandling(current_char_set);  /* restore now */
 
4326
 
 
4327
        return;
 
4328
    } else if (canreparse_post) {
 
4329
        srcmode_for_next_retrieval(0);
 
4330
        LYUCPopAssumed();       /* probably a right place here */
 
4331
        return;
 
4332
    }
 
4333
#endif
 
4334
 
 
4335
    if (curdoc.title)
 
4336
        StrAllocCopy(newdoc.title, curdoc.title);
 
4337
    free_address(&curdoc); /* so it doesn't get pushed */
 
4338
    LYforce_no_cache = TRUE;
 
4339
}
 
4340
 
 
4341
PRIVATE void handle_LYK_SWITCH_DTD NOARGS
 
4342
{
 
4343
#ifdef USE_SOURCE_CACHE
 
4344
    BOOLEAN canreparse = FALSE;
 
4345
    if (!(canreparse = HTcan_reparse_document())) {
 
4346
#endif
 
4347
        /*
 
4348
         * Check if this is a reply from a POST, and if so,
 
4349
         * seek confirmation of reload if the safe element
 
4350
         * is not set.  - FM, kw
 
4351
         */
 
4352
        if ((curdoc.post_data != NULL &&
 
4353
             curdoc.safe != TRUE) &&
 
4354
            confirm_post_resub(curdoc.address, NULL, 1, 1) == FALSE) {
 
4355
            HTInfoMsg(WILL_NOT_RELOAD_DOC);
 
4356
        } else {
 
4357
            /*
 
4358
             *  If currently viewing preparsed source, switching
 
4359
             *  to the other DTD parsing may show source differences,
 
4360
             *  so stay in source view - kw
 
4361
             */
 
4362
 
 
4363
            /* NOTE: this conditional can be considered incorrect -
 
4364
               current behaviour - when viewing source and
 
4365
               LYPreparsedSource==TRUE, pressing ^V will toggle parser mode
 
4366
               AND switch back from the source view to presentation view.-HV
 
4367
            */
 
4368
            if (HTisDocumentSource() && LYPreparsedSource) {
 
4369
                srcmode_for_next_retrieval(1);
 
4370
            }
 
4371
            HText_setNoCache(HTMainText);
 
4372
            move_address(&newdoc, &curdoc);
 
4373
#ifdef NO_ASSUME_SAME_DOC
 
4374
            newdoc.line = 1;
 
4375
            newdoc.link = 0;
 
4376
#else
 
4377
            newdoc.line = curdoc.line;
 
4378
            newdoc.link = curdoc.link;
 
4379
#endif /* NO_ASSUME_SAME_DOC */
 
4380
        }
 
4381
#ifdef USE_SOURCE_CACHE
 
4382
    } /* end if no bypass */
 
4383
#endif
 
4384
    Old_DTD = !Old_DTD;
 
4385
    HTSwitchDTD(!Old_DTD);
 
4386
    HTUserMsg(Old_DTD ? USING_DTD_0 : USING_DTD_1);
 
4387
#ifdef USE_SOURCE_CACHE
 
4388
    if (canreparse) {
 
4389
        if (HTisDocumentSource() && LYPreparsedSource) {
 
4390
            srcmode_for_next_retrieval(1);
 
4391
        }
 
4392
        if (!reparse_document()) {
 
4393
            srcmode_for_next_retrieval(0);
 
4394
        }
 
4395
    }
 
4396
#endif
 
4397
    return;
 
4398
}
 
4399
 
 
4400
#ifdef DIRED_SUPPORT
 
4401
PRIVATE void handle_LYK_TAG_LINK NOARGS
 
4402
{
 
4403
    if (lynx_edit_mode && nlinks > 0 && !no_dired_support) {
 
4404
        if (!strcmp(LYGetHiliteStr(curdoc.link, 0), ".."))
 
4405
            return;     /* Never tag the parent directory */
 
4406
        if (dir_list_style == MIXED_STYLE) {
 
4407
            if (!strcmp(LYGetHiliteStr(curdoc.link, 0), "../"))
 
4408
                return;
 
4409
        } else if (!strncmp(LYGetHiliteStr(curdoc.link, 0), "Up to ", 6))
 
4410
            return;
 
4411
        {
 
4412
            /*
 
4413
             *  HTList-based management of tag list, see LYLocal.c - KW
 
4414
             */
 
4415
            HTList * t1 = tagged;
 
4416
            char * tagname = NULL;
 
4417
            BOOLEAN found = FALSE;
 
4418
 
 
4419
            while ((tagname = (char *)HTList_nextObject(t1)) != NULL) {
 
4420
                if (!strcmp(links[curdoc.link].lname, tagname)) {
 
4421
                    found = TRUE;
 
4422
                    HTList_removeObject(tagged, tagname);
 
4423
                    FREE(tagname);
 
4424
                    tagflag(OFF,curdoc.link);
 
4425
                    break;
 
4426
                }
 
4427
            }
 
4428
            if (!found) {
 
4429
                if (tagged == NULL)
 
4430
                    tagged = HTList_new();
 
4431
                tagname = NULL;
 
4432
                StrAllocCopy(tagname,links[curdoc.link].lname);
 
4433
                HTList_addObject(tagged,tagname);
 
4434
                tagflag(ON,curdoc.link);
 
4435
            }
 
4436
        }
 
4437
        if (curdoc.link < nlinks-1) {
 
4438
            set_curdoc_link(curdoc.link + 1);
 
4439
        } else if (!more && Newline == 1 && curdoc.link == nlinks-1) {
 
4440
            set_curdoc_link(0);
 
4441
        } else if (more) {  /* next page */
 
4442
            Newline += (display_lines);
 
4443
        }
 
4444
    }
 
4445
}
 
4446
#endif /* DIRED_SUPPORT */
 
4447
 
 
4448
PRIVATE void handle_LYK_TOGGLE_HELP NOARGS
 
4449
{
 
4450
    if (user_mode == NOVICE_MODE) {
 
4451
        toggle_novice_line();
 
4452
        noviceline(more);
 
4453
    }
 
4454
}
 
4455
 
 
4456
PRIVATE void handle_LYK_TOOLBAR ARGS4(
 
4457
    BOOLEAN *,  try_internal,
 
4458
    BOOLEAN *,  force_load,
 
4459
    int *,      old_c,
 
4460
    int,        real_c)
 
4461
{
 
4462
    char *cp;
 
4463
    char *toolbar = NULL;
 
4464
 
 
4465
    if (!HText_hasToolbar(HTMainText)) {
 
4466
        if (*old_c != real_c) {
 
4467
            *old_c = real_c;
 
4468
            HTUserMsg(NO_TOOLBAR);
 
4469
        }
 
4470
    } else if (*old_c != real_c) {
 
4471
        *old_c = real_c;
 
4472
        cp = trimPoundSelector(curdoc.address);
 
4473
        HTSprintf0(&toolbar, "%s#%s", curdoc.address, LYToolbarName);
 
4474
        restorePoundSelector(cp);
 
4475
        set_address(&newdoc, toolbar);
 
4476
        FREE(toolbar);
 
4477
        *try_internal = TRUE;
 
4478
        *force_load = TRUE;  /* force MainLoop to reload */
 
4479
    }
 
4480
}
 
4481
 
 
4482
PRIVATE void handle_LYK_TRACE_LOG ARGS1(
 
4483
    BOOLEAN *,  trace_flag_ptr)
 
4484
{
 
4485
#ifndef NO_LYNX_TRACE
 
4486
    /*
 
4487
     *  Check whether we've started a TRACE log
 
4488
     *  in this session. - FM
 
4489
     */
 
4490
    if (LYTraceLogFP == NULL) {
 
4491
        HTUserMsg(NO_TRACELOG_STARTED);
 
4492
        return;
 
4493
    }
 
4494
 
 
4495
    /*
 
4496
     *  Don't do if already viewing the TRACE log. - FM
 
4497
     */
 
4498
    if (LYIsUIPage(curdoc.address, UIP_TRACELOG))
 
4499
        return;
 
4500
 
 
4501
    /*
 
4502
     *  If TRACE mode is on, turn it off during this fetch of the
 
4503
     *  TRACE log, so we don't enter stuff about this fetch, and
 
4504
     *  set a flag for turning it back on when we return to this
 
4505
     *  loop.  Note that we'll miss any messages about memory
 
4506
     *  exhaustion if it should occur.  It seems unlikely that
 
4507
     *  anything else bad might happen, but if it does, we'll
 
4508
     *  miss messages about that too.  We also fflush(), close,
 
4509
     *  and open it again, to make sure all stderr messages thus
 
4510
     *  far will be in the log. - FM
 
4511
     */
 
4512
    if (!LYReopenTracelog(trace_flag_ptr))
 
4513
        return;
 
4514
 
 
4515
    LYLocalFileToURL (&(newdoc.address), LYTraceLogPath);
 
4516
    LYRegisterUIPage(newdoc.address, UIP_TRACELOG);
 
4517
    StrAllocCopy(newdoc.title, LYNX_TRACELOG_TITLE);
 
4518
    LYFreePostData(&newdoc);
 
4519
    FREE(newdoc.bookmark);
 
4520
    newdoc.isHEAD = FALSE;
 
4521
    newdoc.safe = FALSE;
 
4522
    newdoc.internal_link = FALSE;
 
4523
    if (LYValidate || check_realm) {
 
4524
        LYPermitURL = TRUE;
 
4525
    }
 
4526
    LYforce_no_cache = TRUE;
 
4527
#else
 
4528
    HTUserMsg(TRACE_DISABLED);
 
4529
#endif /* NO_LYNX_TRACE */
 
4530
}
 
4531
 
 
4532
#ifdef DIRED_SUPPORT
 
4533
PRIVATE void handle_LYK_UPLOAD NOARGS
 
4534
{
 
4535
    /*
 
4536
     *  Don't do if already viewing upload options page.
 
4537
     */
 
4538
    if (LYIsUIPage(curdoc.address, UIP_UPLOAD_OPTIONS))
 
4539
        return;
 
4540
 
 
4541
    if (lynx_edit_mode && !no_dired_support) {
 
4542
        LYUpload_options(&(newdoc.address), curdoc.address);
 
4543
        StrAllocCopy(newdoc.title, UPLOAD_OPTIONS_TITLE);
 
4544
        LYFreePostData(&newdoc);
 
4545
        FREE(newdoc.bookmark);
 
4546
        newdoc.isHEAD = FALSE;
 
4547
        newdoc.safe = FALSE;
 
4548
        newdoc.internal_link = FALSE;
 
4549
        /*
 
4550
         *  Uncache the current listing so that it will
 
4551
         *  be updated to included the uploaded file if
 
4552
         *  placed in the current directory. - FM
 
4553
         */
 
4554
        DIRED_UNCACHE_1;
 
4555
     }
 
4556
}
 
4557
#endif /* DIRED_SUPPORT */
 
4558
 
 
4559
PRIVATE void handle_LYK_UP_HALF ARGS3(
 
4560
    int *,      arrowup,
 
4561
    int *,      old_c,
 
4562
    int,        real_c)
 
4563
{
 
4564
    if (Newline > 1) {
 
4565
        int scrollamount = display_lines/2;
 
4566
        if (Newline - scrollamount < 1)
 
4567
            scrollamount = Newline - 1;
 
4568
        Newline -= scrollamount;
 
4569
        if (nlinks > 0 && curdoc.link > -1) {
 
4570
            if (links[curdoc.link].ly + scrollamount <= display_lines) {
 
4571
                newdoc.link = curdoc.link +
 
4572
                              HText_LinksInLines(HTMainText,
 
4573
                                                 Newline,
 
4574
                                                 scrollamount);
 
4575
            } else {
 
4576
                *arrowup = TRUE;
 
4577
            }
 
4578
        }
 
4579
    } else if (*old_c != real_c) {
 
4580
        *old_c = real_c;
 
4581
        HTInfoMsg(ALREADY_AT_BEGIN);
 
4582
    }
 
4583
}
 
4584
 
 
4585
PRIVATE void handle_LYK_UP_LINK ARGS4(
 
4586
    int *,      follow_col,
 
4587
    int *,      arrowup,
 
4588
    int *,      old_c,
 
4589
    int,        real_c)
 
4590
{
 
4591
    if (curdoc.link > 0 &&
 
4592
        (links[0].ly != links[curdoc.link].ly ||
 
4593
         !HText_LinksInLines(HTMainText, 1, Newline - 1))) {
 
4594
        /* more links before this on screen, and first of them on
 
4595
           a different line or no previous links before this screen? */
 
4596
        int newlink;
 
4597
 
 
4598
        if (*follow_col == -1) {
 
4599
            char *text = LYGetHiliteStr(curdoc.link, 0);
 
4600
            *follow_col = links[curdoc.link].lx;
 
4601
 
 
4602
            if (text != NULL)
 
4603
                *follow_col += strlen(text) / 2;
 
4604
        }
 
4605
 
 
4606
        newlink = find_link_near_col(*follow_col, -1);
 
4607
        if (newlink > -1) {
 
4608
            set_curdoc_link(newlink);
 
4609
        } else if (*old_c != real_c) {
 
4610
            *old_c = real_c;
 
4611
            HTUserMsg(NO_LINKS_ABOVE);
 
4612
        }
 
4613
 
 
4614
    } else if (curdoc.line > 1 && Newline > 1) {  /* previous page */
 
4615
        int scrollamount = (Newline > display_lines ?
 
4616
                                      display_lines : Newline - 1);
 
4617
        Newline -= scrollamount;
 
4618
        if (scrollamount < display_lines &&
 
4619
            nlinks > 0 && curdoc.link > -1 &&
 
4620
            links[0].ly -1 + scrollamount <= display_lines) {
 
4621
                newdoc.link = HText_LinksInLines(HTMainText,
 
4622
                                                 1,
 
4623
                                                 scrollamount) - 1;
 
4624
        } else {
 
4625
            *arrowup = TRUE;
 
4626
        }
 
4627
 
 
4628
    } else if (*old_c != real_c) {
 
4629
        *old_c = real_c;
 
4630
        HTInfoMsg(ALREADY_AT_BEGIN);
 
4631
    }
 
4632
}
 
4633
 
 
4634
PRIVATE void handle_LYK_UP_TWO ARGS3(
 
4635
    int *,      arrowup,
 
4636
    int *,      old_c,
 
4637
    int,        real_c)
 
4638
{
 
4639
    if (Newline > 1) {
 
4640
        int scrollamount = (Newline > 2 ? 2 : 1);
 
4641
        Newline -= scrollamount;
 
4642
        if (nlinks > 0 && curdoc.link > -1) {
 
4643
            if (links[curdoc.link].ly + scrollamount <= display_lines) {
 
4644
                newdoc.link = curdoc.link +
 
4645
                              HText_LinksInLines(HTMainText,
 
4646
                                                 Newline, scrollamount);
 
4647
            } else {
 
4648
                *arrowup = TRUE;
 
4649
            }
 
4650
        }
 
4651
    } else if (*old_c != real_c) {
 
4652
        *old_c = real_c;
 
4653
        HTInfoMsg(ALREADY_AT_BEGIN);
 
4654
    }
 
4655
}
 
4656
 
 
4657
PRIVATE void handle_LYK_VIEW_BOOKMARK ARGS3(
 
4658
    BOOLEAN *,  refresh_screen,
 
4659
    int *,      old_c,
 
4660
    int,        real_c)
 
4661
{
 
4662
    char *cp;
 
4663
 
 
4664
    if (LYValidate) {
 
4665
        if (*old_c != real_c)   {
 
4666
            *old_c = real_c;
 
4667
            HTUserMsg(BOOKMARKS_DISABLED);
 
4668
        }
 
4669
        return;
 
4670
    }
 
4671
 
 
4672
    /*
 
4673
     *  See if a bookmark exists.
 
4674
     *  If it does replace newdoc.address with its name.
 
4675
     */
 
4676
    if ((cp = get_bookmark_filename(&newdoc.address)) != NULL) {
 
4677
        if (*cp == '\0' || !strcmp(cp, " ") ||
 
4678
            !strcmp(curdoc.address, newdoc.address)) {
 
4679
            if (LYMultiBookmarks != MBM_OFF)
 
4680
                *refresh_screen = TRUE;
 
4681
            return;
 
4682
        }
 
4683
#ifdef KANJI_CODE_OVERRIDE
 
4684
        if (HTCJK == JAPANESE) {
 
4685
            last_kcode = NOKANJI;       /* AUTO */
 
4686
        }
 
4687
#endif
 
4688
        LYforce_no_cache = TRUE;  /*force the document to be reloaded*/
 
4689
        StrAllocCopy(newdoc.title, BOOKMARK_TITLE);
 
4690
        StrAllocCopy(newdoc.bookmark, BookmarkPage);
 
4691
        LYFreePostData(&newdoc);
 
4692
        newdoc.isHEAD = FALSE;
 
4693
        newdoc.safe = FALSE;
 
4694
        newdoc.internal_link = FALSE;
 
4695
    } else {
 
4696
        if (*old_c != real_c) {
 
4697
            *old_c = real_c;
 
4698
            LYMBM_statusline(BOOKMARKS_NOT_OPEN);
 
4699
            LYSleepAlert();
 
4700
            if (LYMultiBookmarks != MBM_OFF) {
 
4701
                *refresh_screen = TRUE;
 
4702
            }
 
4703
        }
 
4704
    }
 
4705
}
 
4706
 
 
4707
PRIVATE BOOLEAN handle_LYK_VLINKS ARGS2(
 
4708
    int *,      cmd,
 
4709
    BOOLEAN *,  newdoc_link_is_absolute)
 
4710
{
 
4711
    int c;
 
4712
 
 
4713
    if (LYIsUIPage(curdoc.address, UIP_VLINKS)) {
 
4714
        /*
 
4715
         *  Already viewing visited links page, so get out.
 
4716
         */
 
4717
        *cmd = LYK_PREV_DOC;
 
4718
        return TRUE;
 
4719
    }
 
4720
 
 
4721
    /*
 
4722
     *  Print visited links page to file.
 
4723
     */
 
4724
    c = LYShowVisitedLinks(&newdoc.address);
 
4725
    if (c < 0) {
 
4726
        HTUserMsg(VISITED_LINKS_EMPTY);
 
4727
        return FALSE;
 
4728
    }
 
4729
    StrAllocCopy(newdoc.title, VISITED_LINKS_TITLE);
 
4730
    LYFreePostData(&newdoc);
 
4731
    FREE(newdoc.bookmark);
 
4732
    newdoc.isHEAD = FALSE;
 
4733
    newdoc.safe = FALSE;
 
4734
    newdoc.internal_link = FALSE;
 
4735
    if (c > 0) {
 
4736
        /* Select a correct link. */
 
4737
        *newdoc_link_is_absolute = TRUE;
 
4738
        newdoc.link = c - 1;
 
4739
    }
 
4740
    if (LYValidate || check_realm) {
 
4741
        LYPermitURL = TRUE;
 
4742
        StrAllocCopy(lynxlinksfile, newdoc.address);
 
4743
    }
 
4744
    return FALSE;
 
4745
}
 
4746
 
 
4747
PUBLIC void handle_LYK_WHEREIS ARGS2(
 
4748
    int,        cmd,
 
4749
    BOOLEAN *,  refresh_screen)
 
4750
{
 
4751
    BOOLEAN have_target_onscreen = (BOOLEAN) (*prev_target != '\0' &&
 
4752
                                    HText_pageHasPrevTarget());
 
4753
    BOOL found;
 
4754
    int oldcur = curdoc.link; /* temporarily remember */
 
4755
    char *remember_old_target = NULL;
 
4756
    if (have_target_onscreen)
 
4757
        StrAllocCopy(remember_old_target, prev_target);
 
4758
    else
 
4759
        StrAllocCopy(remember_old_target, "");
 
4760
 
 
4761
    if (cmd == LYK_WHEREIS) {
 
4762
        /*
 
4763
         *  Reset prev_target to force prompting
 
4764
         *  for a new search string and to turn
 
4765
         *  off highlighting if no search string
 
4766
         *  is entered by the user.
 
4767
         */
 
4768
        *prev_target = '\0';
 
4769
    }
 
4770
    found = textsearch(&curdoc, prev_target, sizeof(prev_target)-1,
 
4771
                       (cmd == LYK_WHEREIS)
 
4772
                       ? 0
 
4773
                       : ((cmd == LYK_NEXT)
 
4774
                         ? 1
 
4775
                         : -1));
 
4776
 
 
4777
    /*
 
4778
     *  Force a redraw to ensure highlighting of hits
 
4779
     *  even when found on the same page, or clearing
 
4780
     *  of highlighting if the default search string
 
4781
     *  was erased without replacement. - FM
 
4782
     */
 
4783
    /*
 
4784
    ** Well let's try to avoid it at least in a few cases
 
4785
    ** where it is not needed. - kw
 
4786
    */
 
4787
    if (www_search_result >= 0 && www_search_result != curdoc.line) {
 
4788
        *refresh_screen = TRUE; /* doesn't really matter */
 
4789
    } else if (!found) {
 
4790
        *refresh_screen = have_target_onscreen;
 
4791
    } else if (!have_target_onscreen && found) {
 
4792
        *refresh_screen = TRUE;
 
4793
    } else if (www_search_result == curdoc.line &&
 
4794
               curdoc.link == oldcur &&
 
4795
               curdoc.link >= 0 && nlinks > 0 &&
 
4796
               links[curdoc.link].ly >= (display_lines/3)) {
 
4797
        *refresh_screen = TRUE;
 
4798
    } else if ((case_sensitive && 0!=strcmp(prev_target,
 
4799
                                            remember_old_target)) ||
 
4800
             (!case_sensitive && 0!=strcasecomp8(prev_target,
 
4801
                                            remember_old_target))) {
 
4802
        *refresh_screen = TRUE;
 
4803
    }
 
4804
    FREE(remember_old_target);
 
4805
}
 
4806
 
 
4807
/*
 
4808
 * Get a number from the user and follow that link number.
 
4809
 */
 
4810
PRIVATE void handle_LYK_digit ARGS6(
 
4811
    int,        c,
 
4812
    BOOLEAN *,  force_load,
 
4813
    char *,     user_input_buffer,
 
4814
    int *,      old_c,
 
4815
    int,        real_c,
 
4816
    BOOLEAN *,  try_internal GCC_UNUSED)
 
4817
{
 
4818
    int lindx = ((nlinks > 0) ? curdoc.link : 0);
 
4819
    int number;
 
4820
    char *temp = NULL;
 
4821
 
 
4822
    /* pass cur line num for use in follow_link_number()
 
4823
     * Note: Current line may not equal links[cur].line
 
4824
     */
 
4825
    number = curdoc.line;
 
4826
    switch (follow_link_number(c, lindx, &newdoc, &number)) {
 
4827
    case DO_LINK_STUFF:
 
4828
        /*
 
4829
         *  Follow a normal link.
 
4830
         */
 
4831
        set_address(&newdoc, links[lindx].lname);
 
4832
        StrAllocCopy(newdoc.title, LYGetHiliteStr(lindx, 0));
 
4833
#ifndef DONT_TRACK_INTERNAL_LINKS
 
4834
        /*
 
4835
         *  For internal links, retain POST content if present.
 
4836
         *  If we are on the List Page, prevent pushing it on
 
4837
         *  the history stack.  Otherwise set try_internal to
 
4838
         *  signal that the top of the loop should attempt to
 
4839
         *  reposition directly, without calling getfile. - kw
 
4840
         */
 
4841
        if (links[lindx].type == WWW_INTERN_LINK_TYPE) {
 
4842
            LYinternal_flag = TRUE;
 
4843
            newdoc.internal_link = TRUE;
 
4844
            if (LYIsListpageTitle(NonNull(curdoc.title)) &&
 
4845
                (LYIsUIPage(curdoc.address, UIP_LIST_PAGE) ||
 
4846
                 LYIsUIPage(curdoc.address, UIP_ADDRLIST_PAGE))) {
 
4847
                if (check_history()) {
 
4848
                    LYinternal_flag = TRUE;
 
4849
                } else {
 
4850
                    HTLastConfirmCancelled(); /* reset flag */
 
4851
                    if (!confirm_post_resub(newdoc.address,
 
4852
                                            newdoc.title,
 
4853
                                            (LYresubmit_posts &&
 
4854
                                             HText_POSTReplyLoaded(&newdoc)) ? 1 : 2,
 
4855
                                            2)) {
 
4856
                        if (HTLastConfirmCancelled() ||
 
4857
                            (LYresubmit_posts &&
 
4858
                             !HText_POSTReplyLoaded(&newdoc))) {
 
4859
                            /* cancel the whole thing */
 
4860
                            LYforce_no_cache = FALSE;
 
4861
                            reloading = FALSE;
 
4862
                            copy_address(&newdoc, &curdoc);
 
4863
                            StrAllocCopy(newdoc.title, curdoc.title);
 
4864
                            newdoc.internal_link = curdoc.internal_link;
 
4865
                            HTInfoMsg(CANCELLED);
 
4866
                            if (nlinks > 0)
 
4867
                                HText_pageDisplay(curdoc.line, prev_target);
 
4868
                            break;
 
4869
                        } else if (LYresubmit_posts) {
 
4870
                            /* If LYresubmit_posts is set, and the
 
4871
                               answer was No, and we have a cached
 
4872
                               copy, then use it. - kw */
 
4873
                            LYforce_no_cache = FALSE;
 
4874
                        } else {
 
4875
                            /* if No, but not ^C or ^G, drop
 
4876
                             * the post data.  Maybe the link
 
4877
                             * wasn't meant to be internal after
 
4878
                             * all, here we can recover from that
 
4879
                             * assumption. - kw */
 
4880
                            LYFreePostData(&newdoc);
 
4881
                            newdoc.internal_link = FALSE;
 
4882
                            HTAlert(DISCARDING_POST_DATA);
 
4883
                        }
 
4884
                    }
 
4885
                }
 
4886
                /*
 
4887
                 *  Don't push the List Page if we follow an
 
4888
                 *  internal link given by it. - kw
 
4889
                 */
 
4890
                free_address(&curdoc);
 
4891
            } else
 
4892
                *try_internal = TRUE;
 
4893
            if (!(LYresubmit_posts && newdoc.post_data))
 
4894
                LYinternal_flag = TRUE;
 
4895
            *force_load = TRUE;
 
4896
            break;
 
4897
        } else {
 
4898
            /*
 
4899
             *  Free POST content if not an internal link. - kw
 
4900
             */
 
4901
            LYFreePostData(&newdoc);
 
4902
        }
 
4903
#endif /* DONT_TRACK_INTERNAL_LINKS */
 
4904
        /*
 
4905
         *  Might be an anchor in the same doc from a POST
 
4906
         *  form.  If so, don't free the content. -- FM
 
4907
         */
 
4908
        if (are_different(&curdoc, &newdoc)) {
 
4909
            LYFreePostData(&newdoc);
 
4910
            FREE(newdoc.bookmark);
 
4911
            newdoc.isHEAD = FALSE;
 
4912
            newdoc.safe = FALSE;
 
4913
            if (isLYNXMESSAGES(newdoc.address))
 
4914
                LYforce_no_cache = TRUE;
 
4915
        }
 
4916
        newdoc.internal_link = FALSE;
 
4917
        *force_load = TRUE;  /* force MainLoop to reload */
 
4918
        break;
 
4919
 
 
4920
    case DO_GOTOLINK_STUFF:
 
4921
        /*
 
4922
         *  Position on a normal link, don't follow it. - KW
 
4923
         */
 
4924
        Newline = newdoc.line;
 
4925
        newdoc.line = 1;
 
4926
        if (Newline == curdoc.line) {
 
4927
            /*
 
4928
             *  It's a link in the current page. - FM
 
4929
             */
 
4930
            if (nlinks > 0 && curdoc.link > -1) {
 
4931
                if (curdoc.link == newdoc.link) {
 
4932
                    /*
 
4933
                     *  It's the current link, and presumably
 
4934
                     *  reflects a typo in the statusline entry,
 
4935
                     *  so issue a statusline message for the
 
4936
                     *  typo-prone users (like me 8-). - FM
 
4937
                     */
 
4938
                    StrAllocCopy(temp, user_input_buffer);
 
4939
                    sprintf(user_input_buffer,
 
4940
                            LINK_ALREADY_CURRENT, number);
 
4941
                    HTUserMsg(user_input_buffer);
 
4942
                    LYstrncpy(user_input_buffer, temp, MAX_LINE - 1);
 
4943
                    FREE(temp);
 
4944
                } else {
 
4945
                    /*
 
4946
                     *  It's a different link on this page,
 
4947
                     */
 
4948
                    set_curdoc_link(newdoc.link);
 
4949
                    newdoc.link = 0;
 
4950
                }
 
4951
            }
 
4952
        }
 
4953
        break;          /* nothing more to do */
 
4954
 
 
4955
    case DO_GOTOPAGE_STUFF:
 
4956
        /*
 
4957
         *  Position on a page in this document. - FM
 
4958
         */
 
4959
        Newline = newdoc.line;
 
4960
        newdoc.line = 1;
 
4961
        if (Newline == curdoc.line) {
 
4962
            /*
 
4963
             *  It's the current page, so issue a
 
4964
             *  statusline message for the typo-prone
 
4965
             *  users (like me 8-). - FM
 
4966
             */
 
4967
            if (Newline <= 1) {
 
4968
                HTInfoMsg(ALREADY_AT_BEGIN);
 
4969
            } else if (!more) {
 
4970
                HTInfoMsg(ALREADY_AT_END);
 
4971
            } else {
 
4972
                StrAllocCopy(temp, user_input_buffer);
 
4973
                sprintf(user_input_buffer,
 
4974
                        ALREADY_AT_PAGE, number);
 
4975
                HTUserMsg(user_input_buffer);
 
4976
                LYstrncpy(user_input_buffer, temp, MAX_LINE - 1);
 
4977
                FREE(temp);
 
4978
            }
 
4979
        }
 
4980
        break;
 
4981
 
 
4982
    case PRINT_ERROR:
 
4983
        *old_c = real_c;
 
4984
        HTUserMsg(BAD_LINK_NUM_ENTERED);
 
4985
        break;
 
4986
    }
 
4987
    return;
 
4988
}
 
4989
 
 
4990
#ifdef SUPPORT_CHDIR
 
4991
 
 
4992
/* original implementation by VH */
 
4993
PUBLIC void handle_LYK_CHDIR NOARGS
 
4994
{
 
4995
    static char buf[LY_MAXPATH];
 
4996
    char *p = NULL;
 
4997
 
 
4998
    if (no_chdir) {
 
4999
        HTUserMsg(CHDIR_DISABLED);
 
5000
        return;
 
5001
    }
 
5002
 
 
5003
    _statusline(gettext("cd to:"));
 
5004
    /* some people may prefer automatic clearing of the previous user input,
 
5005
       here, to do this, just uncomment next line - VH */
 
5006
    /* buf[0]='\0'; */
 
5007
    if (LYgetstr(buf, VISIBLE, sizeof(buf)-1, 0) < 0 || !*buf) {
 
5008
        HTInfoMsg(CANCELLED);
 
5009
        return;
 
5010
    }
 
5011
 
 
5012
    if (*buf == '~' && !buf[1]) {
 
5013
        StrAllocCopy(p, Home_Dir());
 
5014
    } else if (*buf == '~') {
 
5015
        HTSprintf0(&p, "%s%s", Home_Dir(), buf+1);
 
5016
    } else {
 
5017
        StrAllocCopy(p, buf);
 
5018
    }
 
5019
 
 
5020
    CTRACE((tfp, "changing directory to '%s'\n", p));
 
5021
    if (chdir(p)) {
 
5022
        switch (errno) {
 
5023
        case EACCES:
 
5024
            HTInfoMsg(COULD_NOT_ACCESS_DIR);
 
5025
            break;
 
5026
        case ENOENT:
 
5027
            HTInfoMsg(gettext("No such directory"));
 
5028
            break;
 
5029
        case ENOTDIR:
 
5030
            HTInfoMsg(gettext("A component of path is not a directory"));
 
5031
            break;
 
5032
        default:
 
5033
            HTInfoMsg(gettext("failed to change directory"));
 
5034
            break;
 
5035
        }
 
5036
    } else {
 
5037
#ifdef DIRED_SUPPORT
 
5038
        /*if in dired, load content of other directory*/
 
5039
        if (!no_dired_support
 
5040
         && (lynx_edit_mode || (LYIsUIPage(curdoc.address, UIP_DIRED_MENU)))) {
 
5041
            char buf2[LY_MAXPATH];
 
5042
            char* addr = NULL;
 
5043
 
 
5044
            Current_Dir(buf2);
 
5045
            LYLocalFileToURL(&addr, buf2);
 
5046
 
 
5047
            newdoc.address = addr;
 
5048
            newdoc.isHEAD = FALSE;
 
5049
            StrAllocCopy(newdoc.title, gettext("A URL specified by the user"));
 
5050
            LYFreePostData(&newdoc);
 
5051
            FREE(newdoc.bookmark);
 
5052
            newdoc.safe = FALSE;
 
5053
            newdoc.internal_link = FALSE;
 
5054
            /**force_load = TRUE;*/
 
5055
            if (lynx_edit_mode) {
 
5056
                DIRED_UNCACHE_2;
 
5057
            }
 
5058
        } else
 
5059
#endif
 
5060
            HTInfoMsg(OPERATION_DONE);
 
5061
    }
 
5062
    FREE(p);
 
5063
}
 
5064
#endif
 
5065
 
 
5066
#ifdef USE_CURSES_PADS
 
5067
/*
 
5068
 * Having jumps larger than this is counter-productive.  Indeed, it is natural
 
5069
 * to expect that when the relevant text appears, one would "overshoot" and
 
5070
 * would scroll 3-4 extra full screens.  When going back, the "accumulation"
 
5071
 * logic would again start moving in full screens, so one would overshoot
 
5072
 * again, etc.
 
5073
 *
 
5074
 * Going back, one can fix it in 28 keypresses. The relevant text will appear
 
5075
 * on the screen soon enough for the key-repeat to become not that important,
 
5076
 * and we are still moving in smaller steps than when we overshot.  Since key
 
5077
 * repeat is not important, even if we overshoot again, it is going to be by 30
 
5078
 * steps, which is easy to fix by reversing the direction again.
 
5079
 */
 
5080
PRIVATE int repeat_to_delta ARGS1(int, n)
 
5081
{
 
5082
    int threshold = LYcols / 3;
 
5083
 
 
5084
    while (threshold > 0) {
 
5085
        if (n >= threshold) {
 
5086
            n = threshold;
 
5087
            break;
 
5088
        }
 
5089
        threshold = (threshold * 2) / 3;
 
5090
    }
 
5091
    return n;
 
5092
}
 
5093
 
 
5094
PRIVATE void handle_LYK_SHIFT_LEFT ARGS2(BOOLEAN *, flag, int, count)
 
5095
{
 
5096
    if (!LYwideLines) {
 
5097
        HTAlert(SHIFT_VS_LINEWRAP);
 
5098
        return;
 
5099
    }
 
5100
    if (LYshiftWin > 0) {
 
5101
        LYshiftWin -= repeat_to_delta(count);
 
5102
        *flag = TRUE;
 
5103
    }
 
5104
    if (LYshiftWin < 0)
 
5105
        LYshiftWin = 0;
 
5106
}
 
5107
 
 
5108
PRIVATE void handle_LYK_SHIFT_RIGHT ARGS2(BOOLEAN *, flag, int, count)
 
5109
{
 
5110
    if (!LYwideLines) {
 
5111
        HTAlert(SHIFT_VS_LINEWRAP);
 
5112
        return;
 
5113
    }
 
5114
    LYshiftWin += repeat_to_delta(count);
 
5115
    *flag = TRUE;
 
5116
}
 
5117
 
 
5118
PRIVATE BOOLEAN handle_LYK_LINEWRAP_TOGGLE ARGS2(
 
5119
    int *,      cmd,
 
5120
    BOOLEAN *,  flag)
 
5121
{
 
5122
    static char *choices[] = {
 
5123
        "Try to fit screen width",
 
5124
        "No line wrap in columns",
 
5125
        "Wrap columns at screen width",
 
5126
        "Wrap columns at 3/4 screen width",
 
5127
        "Wrap columns at 2/3 screen width",
 
5128
        "Wrap columns at 1/2 screen width",
 
5129
        "Wrap columns at 1/3 screen width",
 
5130
        "Wrap columns at 1/4 screen width",
 
5131
        NULL
 
5132
    };
 
5133
    static int wrap[] = {
 
5134
        0,
 
5135
        0,
 
5136
        12,                             /* In units of 1/12 */
 
5137
        9,
 
5138
        8,
 
5139
        6,
 
5140
        4,
 
5141
        3
 
5142
    };
 
5143
    int c;
 
5144
 
 
5145
    if (LYwin == stdscr)
 
5146
        return FALSE;
 
5147
 
 
5148
    /* Somehow the mouse is over the number instead of being over the
 
5149
       name, so we decrease x. */
 
5150
    c = LYChoosePopup(!LYwideLines, LYlines /2 - 2, LYcols/2-6,
 
5151
                      choices, TABLESIZE(choices) - 1, FALSE, TRUE);
 
5152
    /*
 
5153
     *  LYhandlePopupList() wasn't really meant to be used
 
5154
     *  outside of old-style Options menu processing.  One result of
 
5155
     *  mis-using it here is that we have to deal with side-effects
 
5156
     *  regarding SIGINT signal handler and the term_options global
 
5157
     *  variable. - kw
 
5158
     */
 
5159
    if (term_options)
 
5160
        return FALSE;
 
5161
    LYwideLines = c;
 
5162
    LYtableCols = wrap[c];
 
5163
 
 
5164
    if (LYwideLines == 0)
 
5165
        LYshiftWin = 0;
 
5166
    *flag = TRUE;
 
5167
    HTUserMsg(LYwideLines ? LINEWRAP_OFF : LINEWRAP_ON);
 
5168
    return reparse_or_reload(cmd);
 
5169
}
 
5170
#endif
 
5171
 
 
5172
/*
 
5173
 *  Here's where we do all the work.
 
5174
 *  mainloop is basically just a big switch dependent on the users input.
 
5175
 *  I have tried to offload most of the work done here to procedures to
 
5176
 *  make it more modular, but this procedure still does a lot of variable
 
5177
 *  manipulation.  This needs some work to make it neater. - Lou Moutilli
 
5178
 *                                      (memoir from the original Lynx - FM)
 
5179
 */
 
5180
 
 
5181
int mainloop NOARGS
 
5182
{
 
5183
#if defined(WIN_EX)     /* 1997/10/08 (Wed) 14:52:06 */
 
5184
#undef  STRING_MAX
 
5185
#define STRING_MAX      4096
 
5186
    char temp_buff[STRING_MAX];
 
5187
 
 
5188
#define BUFF_MAX        1024
 
5189
    char sjis_buff[BUFF_MAX];
 
5190
#endif
 
5191
    int c = 0, real_c = 0, old_c = 0, pending_form_c = -1;
 
5192
    int cmd = LYK_DO_NOTHING, real_cmd = LYK_DO_NOTHING;
 
5193
    int getresult;
 
5194
    int arrowup = FALSE, show_help = FALSE;
 
5195
    char user_input_buffer[MAX_LINE];
 
5196
    CONST char *cshelpfile = NULL;
 
5197
    BOOLEAN first_file = TRUE;
 
5198
    BOOLEAN popped_doc = FALSE;
 
5199
    BOOLEAN refresh_screen = FALSE;
 
5200
    BOOLEAN force_load = FALSE;
 
5201
    BOOLEAN try_internal = FALSE;
 
5202
    BOOLEAN crawl_ok = FALSE;
 
5203
    BOOLEAN vi_keys_flag = vi_keys;
 
5204
    BOOLEAN emacs_keys_flag = emacs_keys;
 
5205
    BOOLEAN trace_mode_flag = FALSE;
 
5206
    BOOLEAN forced_HTML_mode = LYforce_HTML_mode;
 
5207
    char cfile[128];
 
5208
    FILE *cfp;
 
5209
    char *cp;
 
5210
    int ch, recall;
 
5211
    int URLTotal;
 
5212
    int URLNum;
 
5213
    BOOLEAN FirstURLRecall = TRUE;
 
5214
    char *temp = NULL;
 
5215
    BOOLEAN ForcePush = FALSE;
 
5216
    BOOLEAN override_LYresubmit_posts = FALSE;
 
5217
    BOOLEAN newdoc_link_is_absolute = FALSE;
 
5218
    BOOLEAN curlink_is_editable;
 
5219
    BOOLEAN use_last_tfpos;
 
5220
    unsigned int len;
 
5221
    int i;
 
5222
    int follow_col = -1, key_count = 0, last_key = 0;
 
5223
 
 
5224
/*  "internal" means "within the same document, with certainty".
 
5225
 *  It includes a space so it cannot conflict with any (valid) "TYPE"
 
5226
 *  attributes on A elements. [According to which DTD, anyway??] - kw
 
5227
 */
 
5228
    HTInternalLink = HTAtom_for("internal link");  /* init, used as const */
 
5229
 
 
5230
#ifndef WWW_SOURCE
 
5231
    WWW_SOURCE = HTAtom_for("www/source");  /* init, used as const */
 
5232
#endif
 
5233
 
 
5234
/*
 
5235
 *  curdoc.address contains the name of the file that is currently open.
 
5236
 *  newdoc.address contains the name of the file that will soon be
 
5237
 *                   opened if it exits.
 
5238
 *  prev_target    contains the last search string the user searched for.
 
5239
 *  newdoc.title   contains the link name that the user last chose to get
 
5240
 *                   into the current link (file).
 
5241
 */
 
5242
    /* initialize some variables*/
 
5243
    newdoc.address = NULL;
 
5244
    newdoc.title = NULL;
 
5245
    newdoc.post_data = NULL;
 
5246
    newdoc.post_content_type = NULL;
 
5247
    newdoc.bookmark = NULL;
 
5248
    newdoc.internal_link = FALSE;
 
5249
    curdoc.address = NULL;
 
5250
    curdoc.title = NULL;
 
5251
    curdoc.post_data = NULL;
 
5252
    curdoc.post_content_type = NULL;
 
5253
    curdoc.bookmark = NULL;
 
5254
    curdoc.internal_link = FALSE;
 
5255
#ifdef USE_COLOR_STYLE
 
5256
    curdoc.style = NULL;
 
5257
    newdoc.style = NULL;
 
5258
#endif
 
5259
    nhist = 0;
 
5260
    user_input_buffer[(sizeof(user_input_buffer) - 1)] = '\0';
 
5261
    *prev_target = '\0';
 
5262
    *user_input_buffer = '\0';
 
5263
#ifdef LY_FIND_LEAKS
 
5264
    atexit(free_mainloop_variables);
 
5265
#endif
 
5266
initialize:
 
5267
    set_address(&newdoc, startfile);
 
5268
    StrAllocCopy(startrealm, startfile);
 
5269
    StrAllocCopy(newdoc.title, gettext("Entry into main screen"));
 
5270
    newdoc.isHEAD = FALSE;
 
5271
    newdoc.safe = FALSE;
 
5272
    newdoc.line = 1;
 
5273
    newdoc.link = 0;
 
5274
 
 
5275
#ifdef USE_SLANG
 
5276
    if (TRACE && LYCursesON) {
 
5277
        LYaddstr("\n");
 
5278
        LYrefresh();
 
5279
    }
 
5280
#endif /* USE_SLANG */
 
5281
    CTRACE((tfp, "Entering mainloop, startfile=%s\n", startfile));
 
5282
 
 
5283
    if (form_post_data) {
 
5284
        BStrCopy0(newdoc.post_data, form_post_data);
 
5285
        StrAllocCopy(newdoc.post_content_type,
 
5286
                     "application/x-www-form-urlencoded");
 
5287
    } else if (form_get_data) {
 
5288
        StrAllocCat(newdoc.address, form_get_data);
 
5289
    }
 
5290
 
 
5291
    if (bookmark_start) {
 
5292
        if (LYValidate) {
 
5293
            HTAlert(BOOKMARKS_DISABLED);
 
5294
            bookmark_start = FALSE;
 
5295
            goto initialize;
 
5296
        } else if (traversal) {
 
5297
            HTAlert(BOOKMARKS_NOT_TRAVERSED);
 
5298
            traversal = FALSE;
 
5299
            crawl = FALSE;
 
5300
            bookmark_start = FALSE;
 
5301
            goto initialize;
 
5302
        } else {
 
5303
            /*
 
5304
             *  See if a bookmark page exists.  If it does,
 
5305
             *  replace newdoc.address with its name
 
5306
             */
 
5307
            if ((cp = get_bookmark_filename(&newdoc.address)) != NULL &&
 
5308
                 *cp != '\0' && strcmp(cp, " ")) {
 
5309
                StrAllocCopy(newdoc.title, BOOKMARK_TITLE);
 
5310
                StrAllocCopy(newdoc.bookmark, BookmarkPage);
 
5311
                StrAllocCopy(startrealm, newdoc.address);
 
5312
                LYFreePostData(&newdoc);
 
5313
                newdoc.isHEAD = FALSE;
 
5314
                newdoc.safe = FALSE;
 
5315
                CTRACE((tfp, "Using bookmarks=%s\n", newdoc.address));
 
5316
            } else {
 
5317
                HTUserMsg(BOOKMARKS_NOT_OPEN);
 
5318
                bookmark_start = FALSE;
 
5319
                goto initialize;
 
5320
            }
 
5321
        }
 
5322
    }
 
5323
 
 
5324
    FREE(form_post_data);
 
5325
    FREE(form_get_data);
 
5326
 
 
5327
    if (user_mode == NOVICE_MODE)
 
5328
        display_lines = LYlines-4;
 
5329
    else
 
5330
        display_lines = LYlines-2;
 
5331
 
 
5332
    while (TRUE) {
 
5333
#ifdef USE_COLOR_STYLE
 
5334
        if (curdoc.style != NULL) force_load = TRUE;
 
5335
#endif
 
5336
        /*
 
5337
         *  If newdoc.address is different then curdoc.address then
 
5338
         *  we need to go out and find and load newdoc.address.
 
5339
         */
 
5340
        if (LYforce_no_cache || force_load ||
 
5341
            are_different(&curdoc, &newdoc)) {
 
5342
 
 
5343
                force_load = FALSE;  /* done */
 
5344
                if (TRACE && LYCursesON) {
 
5345
                    LYHideCursor();     /* make sure cursor is down */
 
5346
#ifdef USE_SLANG
 
5347
                    LYaddstr("\n");
 
5348
#endif /* USE_SLANG */
 
5349
                    LYrefresh();
 
5350
                }
 
5351
try_again:
 
5352
                /*
 
5353
                 *  Push the old file onto the history stack if we
 
5354
                 *  have a current doc and a new address. - FM
 
5355
                 */
 
5356
                if (curdoc.address && newdoc.address) {
 
5357
                    /*
 
5358
                     *  Don't actually push if this is a LYNXDOWNLOAD
 
5359
                     *  URL, because that returns NORMAL even if it
 
5360
                     *  fails due to a spoof attempt or file access
 
5361
                     *  problem, and we set the newdoc structure
 
5362
                     *  elements to the curdoc structure elements
 
5363
                     *  under case NORMAL.  - FM
 
5364
                     */
 
5365
                    if (!isLYNXDOWNLOAD(newdoc.address))
 
5366
                    {
 
5367
                        LYpush(&curdoc, ForcePush);
 
5368
                    }
 
5369
                } else if (!newdoc.address) {
 
5370
                    /*
 
5371
                     *  If newdoc.address is empty then pop a file
 
5372
                     *  and load it.  - FM
 
5373
                     */
 
5374
                    LYhist_prev(&newdoc);
 
5375
                    popped_doc = TRUE;
 
5376
 
 
5377
 
 
5378
 
 
5379
#ifndef DONT_TRACK_INTERNAL_LINKS
 
5380
                    /*
 
5381
                    ** If curdoc had been reached via an internal
 
5382
                    ** (fragment) link from what we now have just
 
5383
                    ** popped into newdoc, then override non-caching in
 
5384
                    ** all cases. - kw
 
5385
                    */
 
5386
                    if (curdoc.internal_link &&
 
5387
                        !are_phys_different(&curdoc, &newdoc)) {
 
5388
                        LYinternal_flag = TRUE;
 
5389
                        LYoverride_no_cache = TRUE;
 
5390
                        LYforce_no_cache = FALSE;
 
5391
                        try_internal = TRUE;
 
5392
                    } else
 
5393
#endif /* TRACK_INTERNAL_LINKS */
 
5394
                    {
 
5395
                        /*
 
5396
                         * Force a no_cache override unless
 
5397
                         *  it's a bookmark file, or it has POST content
 
5398
                         *  and LYresubmit_posts is set without safe also
 
5399
                         *  set, and we are not going to another position
 
5400
                         *  in the current document or restoring the previous
 
5401
                         *  document due to a NOT_FOUND or NULLFILE return
 
5402
                         *  value from getfile(). - FM
 
5403
                         */
 
5404
                        if ((newdoc.bookmark != NULL) ||
 
5405
                            (newdoc.post_data != NULL &&
 
5406
                             !newdoc.safe &&
 
5407
                             LYresubmit_posts &&
 
5408
                             !override_LYresubmit_posts &&
 
5409
                                NO_INTERNAL_OR_DIFFERENT(&curdoc, &newdoc))) {
 
5410
                            LYoverride_no_cache = FALSE;
 
5411
                        } else {
 
5412
                            LYoverride_no_cache = TRUE;
 
5413
                        }
 
5414
                    }
 
5415
                }
 
5416
                override_LYresubmit_posts = FALSE;
 
5417
 
 
5418
                if (HEAD_request) {
 
5419
                    /*
 
5420
                     *  Make SURE this is an appropriate request. - FM
 
5421
                     */
 
5422
                    if (newdoc.address) {
 
5423
                        if (LYCanDoHEAD(newdoc.address) == TRUE) {
 
5424
                            newdoc.isHEAD = TRUE;
 
5425
                        } else if (isLYNXIMGMAP(newdoc.address)) {
 
5426
                            if (LYCanDoHEAD(newdoc.address + LEN_LYNXIMGMAP) == TRUE) {
 
5427
                                StrAllocCopy(temp, newdoc.address + LEN_LYNXIMGMAP);
 
5428
                                free_address(&newdoc);
 
5429
                                newdoc.address = temp;
 
5430
                                newdoc.isHEAD = TRUE;
 
5431
                                temp = NULL;
 
5432
                            }
 
5433
                        }
 
5434
                    }
 
5435
                    try_internal = FALSE;
 
5436
                    HEAD_request = FALSE;
 
5437
                }
 
5438
 
 
5439
                /*
 
5440
                 *  If we're getting the TRACE log and it's not new,
 
5441
                 *  check whether its HText structure has been dumped,
 
5442
                 *  and if so, fflush() and fclose() it to ensure it's
 
5443
                 *  fully updated, and then fopen() it again. - FM
 
5444
                 */
 
5445
                if (LYUseTraceLog == TRUE &&
 
5446
                    trace_mode_flag == FALSE &&
 
5447
                    LYTraceLogFP != NULL &&
 
5448
                    LYIsUIPage(newdoc.address, UIP_TRACELOG)) {
 
5449
                    DocAddress WWWDoc;
 
5450
                    HTParentAnchor *tmpanchor;
 
5451
 
 
5452
                    WWWDoc.address = newdoc.address;
 
5453
                    WWWDoc.post_data = newdoc.post_data;
 
5454
                    WWWDoc.post_content_type = newdoc.post_content_type;
 
5455
                    WWWDoc.bookmark = newdoc.bookmark;
 
5456
                    WWWDoc.isHEAD = newdoc.isHEAD;
 
5457
                    WWWDoc.safe = newdoc.safe;
 
5458
                    tmpanchor = HTAnchor_findAddress(&WWWDoc);
 
5459
                    if ((HText *)HTAnchor_document(tmpanchor) == NULL) {
 
5460
                        if (!LYReopenTracelog(&trace_mode_flag)) {
 
5461
                            old_c = 0;
 
5462
                            cmd = LYK_PREV_DOC;
 
5463
                            goto new_cmd;
 
5464
                        }
 
5465
                    }
 
5466
                }
 
5467
 
 
5468
                LYRequestTitle = newdoc.title;
 
5469
                if (newdoc.bookmark)
 
5470
                    LYforce_HTML_mode = TRUE;
 
5471
                if (LYValidate &&
 
5472
                    startfile_ok &&
 
5473
                    newdoc.address && startfile && homepage &&
 
5474
                    (!strcmp(newdoc.address, startfile) ||
 
5475
                     !strcmp(newdoc.address, homepage))) {
 
5476
                    LYPermitURL = TRUE;
 
5477
                }
 
5478
 
 
5479
                /* reset these two variables here before getfile()
 
5480
                 * so they will be available in partial mode
 
5481
                 * (was previously implemented in case NORMAL).
 
5482
                 */
 
5483
                *prev_target = '\0';    /* Reset for new coming document */
 
5484
                Newline = newdoc.line;  /* set for LYGetNewline() */
 
5485
 
 
5486
#ifdef USE_PRETTYSRC
 
5487
                psrc_first_tag = TRUE;
 
5488
#endif
 
5489
#ifdef TEXTFIELDS_MAY_NEED_ACTIVATION
 
5490
                textfields_need_activation = textfields_activation_option;
 
5491
#endif
 
5492
                FREE(LYRequestReferer);
 
5493
                /*
 
5494
                 *  Don't send Referer if we have to load a document again
 
5495
                 *  that we got from the history stack.  We don't know
 
5496
                 *  any more how we originally got to that page.  Using
 
5497
                 *  a Referer based on the current HTMainText could only
 
5498
                 *  be right by coincidence. - kw 1999-11-01
 
5499
                 */
 
5500
                if (popped_doc)
 
5501
                    LYNoRefererForThis = TRUE;
 
5502
 
 
5503
#ifndef DONT_TRACK_INTERNAL_LINKS
 
5504
                if (try_internal) {
 
5505
                    if (newdoc.address &&
 
5506
                        isLYNXIMGMAP(newdoc.address)) {
 
5507
                        try_internal = FALSE;
 
5508
                    } else if (curdoc.address &&
 
5509
                        isLYNXIMGMAP(curdoc.address)) {
 
5510
                        try_internal = FALSE;
 
5511
                    }
 
5512
                }
 
5513
                if (try_internal) {
 
5514
                    char *hashp = findPoundSelector(newdoc.address);
 
5515
                    if (hashp) {
 
5516
                        HTFindPoundSelector(hashp+1);
 
5517
                    }
 
5518
                    getresult = (HTMainText != NULL) ? NORMAL : NOT_FOUND;
 
5519
                    try_internal = FALSE; /* done */
 
5520
                    /* fix up newdoc.address which may have been fragment-only */
 
5521
                    if (getresult == NORMAL && (!hashp || hashp == newdoc.address)) {
 
5522
                        if (!hashp) {
 
5523
                            set_address(&newdoc, HTLoadedDocumentURL());
 
5524
                        } else {
 
5525
                            StrAllocCopy(temp, HTLoadedDocumentURL());
 
5526
                            StrAllocCat(temp, hashp); /* append fragment */
 
5527
                            set_address(&newdoc, temp);
 
5528
                            FREE(temp);
 
5529
                        }
 
5530
                    }
 
5531
                } else {
 
5532
                    if (newdoc.internal_link && newdoc.address &&
 
5533
                        *newdoc.address == '#' && nhist > 0) {
 
5534
                        char *cp0;
 
5535
                        if (isLYNXIMGMAP(HDOC(nhist-1).address))
 
5536
                            cp0 = HDOC(nhist-1).address + LEN_LYNXIMGMAP;
 
5537
                        else
 
5538
                            cp0 = HDOC(nhist-1).address;
 
5539
                        StrAllocCopy(temp, cp0);
 
5540
                        (void) trimPoundSelector(temp);
 
5541
                        StrAllocCat(temp, newdoc.address);
 
5542
                        free_address(&newdoc);
 
5543
                        newdoc.address = temp;
 
5544
                        temp = NULL;
 
5545
                    }
 
5546
                    getresult = getfile(&newdoc);
 
5547
                }
 
5548
#else  /* TRACK_INTERNAL_LINKS */
 
5549
                getresult = getfile(&newdoc);
 
5550
#endif /* TRACK_INTERNAL_LINKS */
 
5551
 
 
5552
#ifdef INACTIVE_INPUT_STYLE_VH
 
5553
                textinput_redrawn = FALSE; /* for sure */
 
5554
#endif
 
5555
 
 
5556
                switch(getresult) {
 
5557
 
 
5558
                case NOT_FOUND:
 
5559
                    /*
 
5560
                     *  OK! can't find the file, so it must not be around now.
 
5561
                     *  Do any error logging, if appropriate.
 
5562
                     */
 
5563
                    LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */
 
5564
                    LYinternal_flag = FALSE;     /* Reset to default. - kw */
 
5565
                    turn_trace_back_on(&trace_mode_flag);
 
5566
                    if (!first_file && !LYCancelledFetch) {
 
5567
                        /*
 
5568
                         *  Do error mail sending and/or traversal
 
5569
                         *  stuff.  Note that the links[] elements may
 
5570
                         *  not be valid at this point, if we did call
 
5571
                         *  HTuncache_current_document!   This should
 
5572
                         *  not have happened for traversal, but for
 
5573
                         *  sending error mail check that HTMainText
 
5574
                         *  exists for this reason. - kw
 
5575
                         */
 
5576
                        if (error_logging && nhist > 0 && !popped_doc &&
 
5577
                            !LYUserSpecifiedURL &&
 
5578
                            HTMainText &&
 
5579
                            nlinks > 0 && curdoc.link < nlinks &&
 
5580
                            !isLYNXHIST(NonNull(newdoc.address)) &&
 
5581
                            !isLYNXCOOKIE(NonNull(newdoc.address))) {
 
5582
                            char *mail_owner = NULL;
 
5583
                            if (owner_address && isMAILTO_URL(owner_address)) {
 
5584
                                mail_owner = owner_address + LEN_MAILTO_URL;
 
5585
                            }
 
5586
                            /*
 
5587
                             *  Email a bad link message to the owner of
 
5588
                             *  the document, or to ALERTMAIL if defined,
 
5589
                             *  but NOT to lynx-dev (it is rejected in
 
5590
                             *  mailmsg). - FM, kw
 
5591
                             */
 
5592
#ifndef ALERTMAIL
 
5593
                            if (mail_owner)
 
5594
#endif
 
5595
                                mailmsg(curdoc.link,
 
5596
                                        mail_owner,
 
5597
                                        HDOC(nhist-1).address,
 
5598
                                        HDOC(nhist-1).title);
 
5599
                        }
 
5600
                        if (traversal) {
 
5601
                            FILE *ofp;
 
5602
 
 
5603
                            if ((ofp = LYAppendToTxtFile(TRAVERSE_ERRORS)) == NULL) {
 
5604
                                if ((ofp = LYNewTxtFile(TRAVERSE_ERRORS)) == NULL) {
 
5605
                                    perror(NOOPEN_TRAV_ERR_FILE);
 
5606
                                    exit_immediately(EXIT_FAILURE);
 
5607
                                }
 
5608
                            }
 
5609
                            if (nhist > 0) {
 
5610
                                fprintf(ofp,
 
5611
                                        "%s %s\tin %s\n",
 
5612
                                        popped_doc ?
 
5613
                                        newdoc.address : links[curdoc.link].lname,
 
5614
                                        links[curdoc.link].target,
 
5615
                                        HDOC(nhist-1).address);
 
5616
                            } else {
 
5617
                                fprintf(ofp,
 
5618
                                        "%s %s\t\n",
 
5619
                                        popped_doc ?
 
5620
                                        newdoc.address : links[curdoc.link].lname,
 
5621
                                        links[curdoc.link].target);
 
5622
                            }
 
5623
                            LYCloseOutput(ofp);
 
5624
                        }
 
5625
                    }
 
5626
 
 
5627
                    /*
 
5628
                     *  Fall through to do the NULL stuff and reload the
 
5629
                     *  old file, unless the first file wasn't found or
 
5630
                     *  has gone missing.
 
5631
                     */
 
5632
                    if (!nhist) {
 
5633
                        /*
 
5634
                         *  If nhist = 0 then it must be the first file.
 
5635
                         */
 
5636
                        exit_immediately_with_error_message(NOT_FOUND, first_file);
 
5637
                        return(EXIT_FAILURE);
 
5638
                    }
 
5639
                    /* FALLTHRU */
 
5640
 
 
5641
                case NULLFILE:
 
5642
                    /*
 
5643
                     *  Not supposed to return any file.
 
5644
                     */
 
5645
                    LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */
 
5646
                    popped_doc = FALSE;          /* Was TRUE if popped. - FM */
 
5647
                    LYinternal_flag = FALSE;     /* Reset to default. - kw */
 
5648
                    turn_trace_back_on(&trace_mode_flag);
 
5649
                    free_address(&newdoc); /* to pop last doc */
 
5650
                    FREE(newdoc.bookmark);
 
5651
                    LYJumpFileURL = FALSE;
 
5652
                    reloading = FALSE;
 
5653
                    LYPermitURL = FALSE;
 
5654
                    LYCancelledFetch = FALSE;
 
5655
                    ForcePush = FALSE;
 
5656
                    LYforce_HTML_mode = FALSE;
 
5657
                    force_old_UCLYhndl_on_reload = FALSE;
 
5658
                    if (traversal) {
 
5659
                        crawl_ok = FALSE;
 
5660
                        if (traversal_link_to_add) {
 
5661
                            /*
 
5662
                             *  It's a binary file, or the fetch attempt
 
5663
                             *  failed.  Add it to TRAVERSE_REJECT_FILE
 
5664
                             *  so we don't try again in this run.
 
5665
                             */
 
5666
                            if (!lookup_reject(traversal_link_to_add)) {
 
5667
                                add_to_reject_list(traversal_link_to_add);
 
5668
                            }
 
5669
                            FREE(traversal_link_to_add);
 
5670
                        }
 
5671
                    }
 
5672
                    /*
 
5673
                     *  Make sure the first file was found and
 
5674
                     *  has not gone missing.
 
5675
                     */
 
5676
                    if (!nhist) {
 
5677
                        /*
 
5678
                         *  If nhist = 0 then it must be the first file.
 
5679
                         */
 
5680
                        if (first_file && homepage &&
 
5681
                           !LYSameFilename(homepage, startfile)) {
 
5682
                           /*
 
5683
                            *  Couldn't return to the first file but there is a
 
5684
                            *  homepage we can use instead. Useful for when the
 
5685
                            *  first URL causes a program to be invoked. - GL
 
5686
                            *
 
5687
                            *  But first make sure homepage is different from
 
5688
                            *  startfile (above), then make it the same (below)
 
5689
                            *  so we don't enter an infinite getfile() loop on
 
5690
                            *  on failures to find the files. - FM
 
5691
                            */
 
5692
                           set_address(&newdoc, homepage);
 
5693
                           LYFreePostData(&newdoc);
 
5694
                           FREE(newdoc.bookmark);
 
5695
                           StrAllocCopy(startfile, homepage);
 
5696
                           newdoc.isHEAD = FALSE;
 
5697
                           newdoc.safe = FALSE;
 
5698
                           newdoc.internal_link = FALSE;
 
5699
                           goto try_again;
 
5700
                        } else {
 
5701
                           exit_immediately_with_error_message(NULLFILE, first_file);
 
5702
                           return(EXIT_FAILURE);
 
5703
                        }
 
5704
                    }
 
5705
 
 
5706
                   /*
 
5707
                    *  If we're going to pop from history because
 
5708
                    *  getfile didn't succeed, reset LYforce_no_cache
 
5709
                    *  first.  This would have been done in HTAccess.c
 
5710
                    *  if the request got that far, but the URL may
 
5711
                    *  have been handled or rejected in getfile without
 
5712
                    *  taking care of that. - kw
 
5713
                    */
 
5714
                    LYforce_no_cache = FALSE;
 
5715
                   /*
 
5716
                    *  Retrieval of a newdoc just failed, and just
 
5717
                    *  going to try_again would pop the next doc
 
5718
                    *  from history and try to get it without further
 
5719
                    *  questions.  This may not be the right thing to do if
 
5720
                    *  we have POST data, so fake a PREV_DOC key if it seems
 
5721
                    *  that some prompting should be done.  This doesn't
 
5722
                    *  affect the traversal logic, since with traversal
 
5723
                    *  POST data can never occur. - kw
 
5724
                    */
 
5725
                   if (HDOC(nhist - 1).post_data &&
 
5726
                       !HDOC(nhist - 1).safe) {
 
5727
                       if (HText_POSTReplyLoaded((DocInfo *)&history[(nhist - 1)])) {
 
5728
                           override_LYresubmit_posts = TRUE;
 
5729
                           goto try_again;
 
5730
                       }
 
5731
                       /*  Set newdoc fields, just in case the PREV_DOC
 
5732
                        *  gets cancelled. - kw */
 
5733
                       if (!curdoc.address) {
 
5734
                           set_address(&newdoc, HTLoadedDocumentURL());
 
5735
                           StrAllocCopy(newdoc.title, HTLoadedDocumentTitle());
 
5736
                           if (HTMainAnchor
 
5737
                            && HTMainAnchor->post_data) {
 
5738
                               BStrCopy(newdoc.post_data,
 
5739
                                        HTMainAnchor->post_data);
 
5740
                               StrAllocCopy(newdoc.post_content_type,
 
5741
                                            HTMainAnchor->post_content_type);
 
5742
                           } else {
 
5743
                               BStrFree(newdoc.post_data);
 
5744
                           }
 
5745
                           newdoc.isHEAD = HTLoadedDocumentIsHEAD();
 
5746
                           newdoc.safe = HTLoadedDocumentIsSafe();
 
5747
                           newdoc.internal_link = FALSE;
 
5748
                       } else {
 
5749
                           copy_address(&newdoc, &curdoc);
 
5750
                           StrAllocCopy(newdoc.title, curdoc.title);
 
5751
                           BStrCopy(newdoc.post_data, curdoc.post_data);
 
5752
                           StrAllocCopy(newdoc.post_content_type,
 
5753
                                        curdoc.post_content_type);
 
5754
                           newdoc.isHEAD = curdoc.isHEAD;
 
5755
                           newdoc.safe = curdoc.safe;
 
5756
                           newdoc.internal_link = curdoc.internal_link;
 
5757
                           newdoc.line = curdoc.line;
 
5758
                           newdoc.link = curdoc.link;
 
5759
                       }
 
5760
                       cmd = LYK_PREV_DOC;
 
5761
                       goto new_cmd;
 
5762
                    }
 
5763
                    override_LYresubmit_posts = TRUE;
 
5764
                    goto try_again;
 
5765
 
 
5766
                case NORMAL:
 
5767
                    /*
 
5768
                     *  Marvelously, we got the document!
 
5769
                     */
 
5770
                    LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */
 
5771
                    LYinternal_flag = FALSE;     /* Reset to default. - kw */
 
5772
                    turn_trace_back_on(&trace_mode_flag);
 
5773
 
 
5774
                    /*
 
5775
                     *  If it's the first file and we're interactive,
 
5776
                     *  check whether it's a bookmark file which was
 
5777
                     *  not accessed via the -book switch. - FM
 
5778
                     */
 
5779
                    if (((first_file == TRUE) &&
 
5780
                         (dump_output_immediately == FALSE) &&
 
5781
                         !(newdoc.bookmark && *newdoc.bookmark)) &&
 
5782
                        ((LYisLocalFile(newdoc.address) == TRUE) &&
 
5783
                         !(strcmp(NonNull(HText_getTitle()),
 
5784
                                  BOOKMARK_TITLE))) &&
 
5785
                        (temp = HTParse(newdoc.address, "",
 
5786
                                     PARSE_PATH+PARSE_PUNCTUATION)) != NULL) {
 
5787
                        CONST char *name = wwwName(Home_Dir());
 
5788
                        len = strlen(name);
 
5789
#ifdef VMS
 
5790
                        if (!strncasecomp(temp, name, len) &&
 
5791
                            strlen(temp) > len)
 
5792
#else
 
5793
                        if (!strncmp(temp, name, len) &&
 
5794
                            strlen(temp) > len)
 
5795
#endif /* VMS */
 
5796
                        {
 
5797
                            /*
 
5798
                             *  We're interactive and this might be a
 
5799
                             *  bookmark file entered as a startfile
 
5800
                             *  rather than invoked via -book.  Check
 
5801
                             *  if it's in our bookmark file list, and
 
5802
                             *  if so, reload if with the relevant
 
5803
                             *  bookmark elements set. - FM
 
5804
                             */
 
5805
                            cp = NULL;
 
5806
                            if (temp[len] == '/') {
 
5807
                                if (strchr(&temp[(len + 1)], '/')) {
 
5808
                                    HTSprintf0(&cp, ".%s", &temp[len]);
 
5809
                                } else {
 
5810
                                    StrAllocCopy(cp, &temp[(len + 1)]);
 
5811
                                }
 
5812
                            } else {
 
5813
                                StrAllocCopy(cp, &temp[len]);
 
5814
                            }
 
5815
                            for (i = 0; i <= MBM_V_MAXFILES; i++) {
 
5816
                                if (MBM_A_subbookmark[i] &&
 
5817
                                    LYSameFilename(cp, MBM_A_subbookmark[i])) {
 
5818
                                    StrAllocCopy(BookmarkPage,
 
5819
                                                 MBM_A_subbookmark[i]);
 
5820
                                    break;
 
5821
                                }
 
5822
                            }
 
5823
                            FREE(cp);
 
5824
                            if (i <= MBM_V_MAXFILES) {
 
5825
                                FREE(temp);
 
5826
                                if (LYValidate) {
 
5827
                                    HTAlert(BOOKMARKS_DISABLED);
 
5828
                                    return(EXIT_FAILURE);
 
5829
                                }
 
5830
                                if ((temp = HTParse(newdoc.address, "",
 
5831
                                 PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION))) {
 
5832
                                    set_address(&newdoc, temp);
 
5833
                                    HTuncache_current_document();
 
5834
                                    free_address(&curdoc);
 
5835
                                    StrAllocCat(newdoc.address,
 
5836
                                            wwwName(Home_Dir()));
 
5837
                                    StrAllocCat(newdoc.address, "/");
 
5838
                                    StrAllocCat(newdoc.address,
 
5839
                                        (strncmp(BookmarkPage, "./", 2) ?
 
5840
                                                           BookmarkPage :
 
5841
                                                        (BookmarkPage + 2)));
 
5842
                                    StrAllocCopy(newdoc.title, BOOKMARK_TITLE);
 
5843
                                    StrAllocCopy(newdoc.bookmark, BookmarkPage);
 
5844
#ifdef USE_COLOR_STYLE
 
5845
                                    if (curdoc.style)
 
5846
                                        StrAllocCopy(newdoc.style, curdoc.style);
 
5847
#endif
 
5848
                                    StrAllocCopy(startrealm, newdoc.address);
 
5849
                                    LYFreePostData(&newdoc);
 
5850
                                    newdoc.isHEAD = FALSE;
 
5851
                                    newdoc.safe = FALSE;
 
5852
                                    FREE(temp);
 
5853
                                    if (!strcmp(homepage, startfile))
 
5854
                                        StrAllocCopy(homepage, newdoc.address);
 
5855
                                    StrAllocCopy(startfile, newdoc.address);
 
5856
                                    CTRACE((tfp, "Reloading as bookmarks=%s\n",
 
5857
                                                newdoc.address));
 
5858
                                    goto try_again;
 
5859
                                }
 
5860
                            }
 
5861
                        }
 
5862
                        cp = NULL;
 
5863
                    }
 
5864
                    FREE(temp);
 
5865
 
 
5866
                    if (traversal) {
 
5867
                        /*
 
5868
                         *  During traversal build up lists of all links
 
5869
                         *  traversed.  Traversal mode is a special
 
5870
                         *  feature for traversing http links in the web.
 
5871
                         */
 
5872
                        if (traversal_link_to_add) {
 
5873
                            /*
 
5874
                             *  Add the address we sought to TRAVERSE_FILE.
 
5875
                             */
 
5876
                            if (!lookup(traversal_link_to_add))
 
5877
                                add_to_table(traversal_link_to_add);
 
5878
                            FREE(traversal_link_to_add);
 
5879
                        }
 
5880
                        if (curdoc.address && curdoc.title &&
 
5881
                            !isLYNXIMGMAP(curdoc.address))
 
5882
                            /*
 
5883
                             *  Add the address we got to TRAVERSE_FOUND_FILE.
 
5884
                             */
 
5885
                            add_to_traverse_list(curdoc.address, curdoc.title);
 
5886
                    }
 
5887
 
 
5888
                    /*
 
5889
                     *  If this was a LYNXDOWNLOAD, we still have curdoc,
 
5890
                     *  not a newdoc, so reset the address, title and
 
5891
                     *  positioning elements. - FM
 
5892
                     */
 
5893
                    if (newdoc.address && curdoc.address &&
 
5894
                        isLYNXDOWNLOAD(newdoc.address)) {
 
5895
                        copy_address(&newdoc, &curdoc);
 
5896
                        StrAllocCopy(newdoc.title, (curdoc.title ?
 
5897
                                                    curdoc.title : ""));
 
5898
                        StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
 
5899
                        newdoc.line = curdoc.line;
 
5900
                        newdoc.link = curdoc.link;
 
5901
                        newdoc.internal_link = FALSE; /* can't be true. - kw */
 
5902
                    }
 
5903
 
 
5904
                    /*
 
5905
                     *  Set Newline to the saved line.  It contains the
 
5906
                     *  line the user was on if s/he has been in the file
 
5907
                     *  before, or it is 1 if this is a new file.
 
5908
                     *
 
5909
                     * We already set Newline before getfile() and probably
 
5910
                     * update it explicitly if popping from the history stack
 
5911
                     * via LYpop() or LYpop_num() within getfile() cycle.
 
5912
                     *
 
5913
                     * In partial mode, Newline was probably updated in
 
5914
                     * LYMainLoop_pageDisplay() if user scrolled
 
5915
                     * the document while loading.
 
5916
                     * Incremental loading stage already closed in HT*Copy().
 
5917
                     */
 
5918
#ifdef DISP_PARTIAL
 
5919
                    /* Newline = newdoc.line; */
 
5920
                    display_partial = FALSE; /* for sure, LYNXfoo:/ may be a problem */
 
5921
#else
 
5922
                    /* Should not be needed either if we remove
 
5923
                     * "DISP_PARTIAL" from LYHistory.c, but lets leave it
 
5924
                     * as an important comment for now.
 
5925
                     */
 
5926
                    Newline = newdoc.line;
 
5927
#endif
 
5928
 
 
5929
                    /*
 
5930
                     *  If we are going to a target line or
 
5931
                     *  the first page of a popped document,
 
5932
                     *  override any www_search line result.
 
5933
                     */
 
5934
                    if (Newline > 1 || popped_doc == TRUE)
 
5935
                         www_search_result = -1;
 
5936
 
 
5937
                    /*
 
5938
                     *  Make sure curdoc.line will not be equal
 
5939
                     *  to Newline, so we get a redraw.
 
5940
                     */
 
5941
                    curdoc.line = -1;
 
5942
                    break;
 
5943
                }  /* end switch */
 
5944
 
 
5945
            if (TRACE) {
 
5946
                if (!LYTraceLogFP || trace_mode_flag) {
 
5947
                    LYSleepAlert(); /* allow me to look at the results */
 
5948
                }
 
5949
            }
 
5950
 
 
5951
            /*
 
5952
             *  Set the files the same.
 
5953
             */
 
5954
            copy_address(&curdoc, &newdoc);
 
5955
            BStrCopy(curdoc.post_data, newdoc.post_data);
 
5956
            StrAllocCopy(curdoc.post_content_type, newdoc.post_content_type);
 
5957
            StrAllocCopy(curdoc.bookmark, newdoc.bookmark);
 
5958
#ifdef USE_COLOR_STYLE
 
5959
            StrAllocCopy(curdoc.style, HText_getStyle());
 
5960
            if (curdoc.style != NULL)
 
5961
                style_readFromFile (curdoc.style);
 
5962
#endif
 
5963
            curdoc.isHEAD = newdoc.isHEAD;
 
5964
            curdoc.internal_link = newdoc.internal_link;
 
5965
 
 
5966
            /*
 
5967
             *  Set the remaining document elements and add to
 
5968
             *  the visited links list. - FM
 
5969
             */
 
5970
            if (ownerS_address != NULL) {
 
5971
#ifndef USE_PRETTYSRC
 
5972
                if (HTOutputFormat == WWW_SOURCE && !HText_getOwner())
 
5973
#else
 
5974
                if ( (LYpsrc ? psrc_view : HTOutputFormat == WWW_SOURCE)
 
5975
                        && !HText_getOwner() )
 
5976
#endif
 
5977
                    HText_setMainTextOwner(ownerS_address);
 
5978
                FREE(ownerS_address);
 
5979
            }
 
5980
            if (HText_getTitle()) {
 
5981
                StrAllocCopy(curdoc.title, HText_getTitle());
 
5982
            } else if (!dump_output_immediately) {
 
5983
                StrAllocCopy(curdoc.title, newdoc.title);
 
5984
            }
 
5985
            StrAllocCopy(owner_address, HText_getOwner());
 
5986
            curdoc.safe = HTLoadedDocumentIsSafe();
 
5987
            if (!dump_output_immediately) {
 
5988
                LYAddVisitedLink(&curdoc);
 
5989
            }
 
5990
 
 
5991
 
 
5992
           /*
 
5993
            *  Reset WWW present mode so that if we were getting
 
5994
            *  the source, we get rendered HTML from now on.
 
5995
            */
 
5996
           HTOutputFormat = WWW_PRESENT;
 
5997
#ifdef USE_PRETTYSRC
 
5998
           psrc_view = FALSE;
 
5999
#endif
 
6000
 
 
6001
           HTMLSetCharacterHandling(current_char_set);  /* restore, for sure? */
 
6002
 
 
6003
           /*
 
6004
            *  Reset all of the other relevant flags. - FM
 
6005
            */
 
6006
           LYUserSpecifiedURL = FALSE;  /* only set for goto's and jumps's */
 
6007
           LYJumpFileURL = FALSE;       /* only set for jump's */
 
6008
           LYNoRefererForThis = FALSE;  /* always reset on return here */
 
6009
           reloading = FALSE;           /* set for RELOAD and NOCACHE keys */
 
6010
           HEAD_request = FALSE;        /* only set for HEAD requests */
 
6011
           LYPermitURL = FALSE;         /* only for LYValidate or check_realm */
 
6012
           ForcePush = FALSE;           /* only set for some PRINT requests. */
 
6013
           LYforce_HTML_mode = FALSE;
 
6014
           force_old_UCLYhndl_on_reload = FALSE;
 
6015
           popped_doc = FALSE;
 
6016
           pending_form_c = -1;
 
6017
 
 
6018
        } /* end if (LYforce_no_cache || force_load || are_different(...)) */
 
6019
 
 
6020
        if (dump_output_immediately) {
 
6021
            if (crawl) {
 
6022
                print_crawl_to_fd(stdout, curdoc.address, curdoc.title);
 
6023
            } else {
 
6024
                print_wwwfile_to_fd(stdout, FALSE);
 
6025
            }
 
6026
            return(EXIT_SUCCESS);
 
6027
        }
 
6028
 
 
6029
        /*
 
6030
         *  If the recent_sizechange variable is set to TRUE
 
6031
         *  then the window size changed recently.
 
6032
         */
 
6033
        if (recent_sizechange) {
 
6034
            /*
 
6035
             *  First we need to make sure the display library - curses, slang,
 
6036
             *  whatever - gets notified about the change, and gets a chance
 
6037
             *  to update external structures appropriately.  Hopefully the
 
6038
             *  stop_curses()/start_curses() sequence achieves this, at least
 
6039
             *  if the display library has a way to get the new screen size
 
6040
             *  from the OS.
 
6041
             *  However, at least for ncurses, the update of the internal
 
6042
             *  structures will come still too late - the changed screen
 
6043
             *  size is detected in doupdate(), which would only be called
 
6044
             *  (indirectly through the HText_pageDisplay below) after the
 
6045
             *  WINDOW structures are already filled based on the old size.
 
6046
             *  So we notify the ncurses library directly here. - kw
 
6047
             */
 
6048
#if defined(NCURSES) && defined(HAVE_RESIZETERM) && defined(HAVE_WRESIZE)
 
6049
            resizeterm(LYlines, LYcols);
 
6050
            wresize(LYwin, LYlines, LYcols);
 
6051
#else
 
6052
#if 0 /* defined(PDCURSES) && defined(HAVE_XCURSES) */
 
6053
            resize_term(LYlines, LYcols);
 
6054
            if (LYwin != 0)
 
6055
                LYwin = resize_window(LYwin, LYlines, LYcols);
 
6056
            refresh();
 
6057
#else
 
6058
            stop_curses();
 
6059
            start_curses();
 
6060
            LYclear();
 
6061
#endif
 
6062
#endif
 
6063
            refresh_screen = TRUE; /* to force a redraw */
 
6064
            if (HTMainText)     /* to REALLY force it... - kw */
 
6065
                HText_setStale(HTMainText);
 
6066
            recent_sizechange = FALSE;
 
6067
            if (user_mode == NOVICE_MODE) {
 
6068
                display_lines = LYlines-4;
 
6069
            } else {
 
6070
                display_lines = LYlines-2;
 
6071
            }
 
6072
        }
 
6073
 
 
6074
        if (www_search_result != -1) {
 
6075
             /*
 
6076
              *  This was a WWW search, set the line
 
6077
              *  to the result of the search.
 
6078
              */
 
6079
             Newline = www_search_result;
 
6080
             www_search_result = -1;  /* reset */
 
6081
        }
 
6082
 
 
6083
        if (first_file == TRUE) {
 
6084
            /*
 
6085
             *  We can never again have the first file.
 
6086
             */
 
6087
            first_file = FALSE;
 
6088
 
 
6089
            /*
 
6090
             *  Set the startrealm, and deal as best we can
 
6091
             *  with preserving forced HTML mode for a local
 
6092
             *  startfile. - FM
 
6093
             */
 
6094
            temp = HTParse(curdoc.address, "",
 
6095
                           PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION);
 
6096
            if (!temp || *temp == '\0') {
 
6097
                StrAllocCopy(startrealm, NO_NOTHING);
 
6098
            } else {
 
6099
                StrAllocCopy(startrealm, temp);
 
6100
                FREE(temp);
 
6101
                if (!(temp = HTParse(curdoc.address, "",
 
6102
                                     PARSE_PATH+PARSE_PUNCTUATION))) {
 
6103
                    LYAddHtmlSep(&startrealm);
 
6104
                } else {
 
6105
                    if (forced_HTML_mode &&
 
6106
                        !dump_output_immediately &&
 
6107
                        !curdoc.bookmark &&
 
6108
                        isFILE_URL(curdoc.address) &&
 
6109
                        strlen(temp) > 1) {
 
6110
                        /*
 
6111
                         *  We forced HTML for a local startfile which
 
6112
                         *  is not a bookmark file and has a path of at
 
6113
                         *  least two letters.  If it doesn't have a
 
6114
                         *  suffix mapped to text/html, we'll set the
 
6115
                         *  entire path (including the lead slash) as a
 
6116
                         *  "suffix" mapped to text/html to ensure it is
 
6117
                         *  always treated as an HTML source file.  We
 
6118
                         *  are counting on a tail match to this full path
 
6119
                         *  for some other URL fetched during the session
 
6120
                         *  having too low a probability to worry about,
 
6121
                         *  but it could happen. - FM
 
6122
                         */
 
6123
                        HTAtom *encoding;
 
6124
 
 
6125
                        if (HTFileFormat(temp, &encoding, NULL) != WWW_HTML) {
 
6126
                            HTSetSuffix(temp, "text/html", "8bit", 1.0);
 
6127
                        }
 
6128
                    }
 
6129
                    if ((cp = strrchr(temp, '/')) != NULL) {
 
6130
                        *(cp+1) = '\0';
 
6131
                        StrAllocCat(startrealm, temp);
 
6132
                    }
 
6133
                }
 
6134
            }
 
6135
            FREE(temp);
 
6136
            CTRACE((tfp, "Starting realm is '%s'\n\n", startrealm));
 
6137
            if (traversal) {
 
6138
                /*
 
6139
                 *  Set up the crawl output stuff.
 
6140
                 */
 
6141
                if (curdoc.address && !lookup(curdoc.address)) {
 
6142
                    if (!isLYNXIMGMAP(curdoc.address))
 
6143
                        crawl_ok = TRUE;
 
6144
                    add_to_table(curdoc.address);
 
6145
                }
 
6146
                /*
 
6147
                 *  Set up the traversal_host comparison string.
 
6148
                 */
 
6149
                if (strncmp((curdoc.address ? curdoc.address : "NULL"),
 
6150
                            "http", 4)) {
 
6151
                    StrAllocCopy(traversal_host, NO_NOTHING);
 
6152
                } else if (check_realm) {
 
6153
                    StrAllocCopy(traversal_host, startrealm);
 
6154
                } else {
 
6155
                    temp = HTParse(curdoc.address, "",
 
6156
                                   PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION);
 
6157
                    if (!temp || *temp == '\0') {
 
6158
                        StrAllocCopy(traversal_host, NO_NOTHING);
 
6159
                    } else {
 
6160
                        StrAllocCopy(traversal_host, temp);
 
6161
                        LYAddHtmlSep(&traversal_host);
 
6162
                    }
 
6163
                    FREE(temp);
 
6164
                }
 
6165
                CTRACE((tfp, "Traversal host is '%s'\n\n", traversal_host));
 
6166
            }
 
6167
            if (startfile) {
 
6168
                /*
 
6169
                 *  If homepage was not equated to startfile,
 
6170
                 *  make the homepage URL the first goto
 
6171
                 *  entry. - FM
 
6172
                 */
 
6173
                if (homepage && strcmp(startfile, homepage))
 
6174
                    HTAddGotoURL(homepage);
 
6175
                /*
 
6176
                 *  If we are not starting up with startfile
 
6177
                 *  (e.g., had -book), or if we are using the
 
6178
                 *  startfile and it has no POST content, make
 
6179
                 *  the startfile URL a goto entry. - FM
 
6180
                 */
 
6181
                if (strcmp(startfile, newdoc.address) ||
 
6182
                    newdoc.post_data == NULL)
 
6183
                    HTAddGotoURL(startfile);
 
6184
            }
 
6185
            if (TRACE) {
 
6186
                refresh_screen = TRUE;
 
6187
                if (!LYTraceLogFP || trace_mode_flag) {
 
6188
                    LYSleepAlert();
 
6189
                }
 
6190
            }
 
6191
        }
 
6192
 
 
6193
#ifdef USE_SOURCE_CACHE
 
6194
        /*
 
6195
         * If the parse settings have changed since this HText was
 
6196
         * generated, we need to reparse and redraw it.  -dsb
 
6197
         *
 
6198
         * Should be configured to avoid shock for experienced lynx users.
 
6199
         * Currently enabled for cached sources only.
 
6200
         */
 
6201
        if (HTdocument_settings_changed()) {
 
6202
           if (HTcan_reparse_document()) {
 
6203
                HTInfoMsg(gettext("Reparsing document under current settings..."));
 
6204
                reparse_document();
 
6205
           } else {
 
6206
                /*
 
6207
                 * Urk.  I have no idea how to recover from a failure here.
 
6208
                 * At a guess, I'll try reloading.  -dsb
 
6209
                 */
 
6210
                        /*  currently disabled ***
 
6211
                HTUserMsg(gettext("Reparsing document under current settings..."));
 
6212
                cmd = LYK_RELOAD;
 
6213
                goto new_cmd;
 
6214
                        */
 
6215
            }
 
6216
        }
 
6217
 
 
6218
        if (from_source_cache) {
 
6219
            from_source_cache = FALSE; /* reset */
 
6220
            curdoc.line = -1 ;  /* so curdoc.line != Newline, see below */
 
6221
        }
 
6222
#endif
 
6223
 
 
6224
        /*
 
6225
         *  If the curdoc.line is different than Newline then there must
 
6226
         *  have been a change since last update.  Run HText_pageDisplay()
 
6227
         *  create a fresh screen of text out.
 
6228
         *
 
6229
         *  If we got new HTMainText go this way.
 
6230
         *  All display_partial calls ends here for final redraw.
 
6231
         */
 
6232
        if (curdoc.line != Newline) {
 
6233
#ifdef INACTIVE_INPUT_STYLE_VH
 
6234
            textinput_redrawn = FALSE;
 
6235
#endif
 
6236
 
 
6237
            refresh_screen = FALSE;
 
6238
 
 
6239
            HText_pageDisplay(Newline, prev_target);
 
6240
 
 
6241
#ifdef DIRED_SUPPORT
 
6242
            if (lynx_edit_mode && nlinks > 0 && !HTList_isEmpty(tagged))
 
6243
              showtags(tagged);
 
6244
#endif /* DIRED_SUPPORT */
 
6245
 
 
6246
            /*
 
6247
             *  If more equals TRUE, then there is more info below this page.
 
6248
             */
 
6249
            more = HText_canScrollDown();
 
6250
            curdoc.line = Newline = HText_getTopOfScreen()+1;
 
6251
 
 
6252
            if (curdoc.title == NULL) {
 
6253
                /*
 
6254
                 *  If we don't yet have a title, try to get it,
 
6255
                 *  or set to that for newdoc.title. - FM
 
6256
                 */
 
6257
                if (HText_getTitle()) {
 
6258
                    StrAllocCopy(curdoc.title, HText_getTitle());
 
6259
                } else {
 
6260
                    StrAllocCopy(curdoc.title, newdoc.title);
 
6261
                }
 
6262
            }
 
6263
 
 
6264
            /*
 
6265
             *  If the request is to highlight a link which is counted
 
6266
             *  from the start of document, correct the link number:
 
6267
             */
 
6268
            if (newdoc_link_is_absolute) {
 
6269
                newdoc_link_is_absolute = FALSE;
 
6270
                if (curdoc.line > 1)
 
6271
                    newdoc.link -= HText_LinksInLines(HTMainText, 1,
 
6272
                                                      curdoc.line - 1);
 
6273
            }
 
6274
 
 
6275
            if (arrowup) {
 
6276
                /*
 
6277
                 *  arrowup is set if we just came up from
 
6278
                 *  a page below.
 
6279
                 */
 
6280
                curdoc.link = nlinks - 1;
 
6281
                arrowup = FALSE;
 
6282
            } else {
 
6283
                curdoc.link = newdoc.link;
 
6284
                if (curdoc.link >= nlinks) {
 
6285
                    curdoc.link = nlinks - 1;
 
6286
                } else if (curdoc.link < 0 && nlinks > 0) {
 
6287
                    /*
 
6288
                     *  We may have popped a doc (possibly in local_dired)
 
6289
                     *  which didn't have any links when it was pushed, but
 
6290
                     *  does have links now (e.g., a file was created).
 
6291
                     *  Code below assumes that curdoc.link is valid and
 
6292
                     *  that (curdoc.link==-1) only occurs if (nlinks==0)
 
6293
                     *  is true. - KW
 
6294
                     */
 
6295
                    curdoc.link = 0;
 
6296
                }
 
6297
            }
 
6298
 
 
6299
            show_help = FALSE; /* reset */
 
6300
            newdoc.line = 1;
 
6301
            newdoc.link = 0;
 
6302
            curdoc.line = Newline; /* set */
 
6303
        }
 
6304
 
 
6305
        /*
 
6306
         *  Refresh the screen if necessary.
 
6307
         */
 
6308
        if (refresh_screen) {
 
6309
#if defined(FANCY_CURSES) || defined (USE_SLANG)
 
6310
            if (enable_scrollback) {
 
6311
                LYclear();
 
6312
            } else {
 
6313
                LYerase();
 
6314
            }
 
6315
#else
 
6316
            LYclear();
 
6317
#endif /* FANCY_CURSES || USE_SLANG */
 
6318
           HText_pageDisplay(Newline, prev_target);
 
6319
 
 
6320
#ifdef DIRED_SUPPORT
 
6321
            if (lynx_edit_mode && nlinks > 0 && !HTList_isEmpty(tagged))
 
6322
                showtags(tagged);
 
6323
#endif /* DIRED_SUPPORT */
 
6324
 
 
6325
            /*
 
6326
             *  If more equals TRUE, then there is more info below this page.
 
6327
             */
 
6328
            more = HText_canScrollDown();
 
6329
 
 
6330
            /*
 
6331
             *  Adjust curdoc.link as above; nlinks may have changed,
 
6332
             *  if the refresh_screen flag was set as a result of
 
6333
             *  a size change.
 
6334
             *  Code below assumes that curdoc.link is valid and
 
6335
             *  that (curdoc.link==-1) only occurs if (nlinks==0)
 
6336
             *  is true. - kw
 
6337
             */
 
6338
            if (curdoc.link >= nlinks) {
 
6339
                curdoc.link = nlinks - 1;
 
6340
            } else if (curdoc.link < 0 && nlinks > 0) {
 
6341
                curdoc.link = 0;
 
6342
            }
 
6343
 
 
6344
            if (user_mode == NOVICE_MODE)
 
6345
                noviceline(more);  /* print help message */
 
6346
            refresh_screen = FALSE;
 
6347
 
 
6348
        }
 
6349
 
 
6350
        curlink_is_editable =
 
6351
            (nlinks > 0 &&
 
6352
             links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
6353
             F_TEXTLIKE(links[curdoc.link].l_form->type));
 
6354
 
 
6355
        use_last_tfpos = (curlink_is_editable &&
 
6356
                          (real_cmd == LYK_LPOS_PREV_LINK ||
 
6357
                           real_cmd == LYK_LPOS_NEXT_LINK));
 
6358
 
 
6359
#ifdef TEXTFIELDS_MAY_NEED_ACTIVATION
 
6360
        if (!textfields_need_activation)
 
6361
            textinput_activated = TRUE;
 
6362
#endif
 
6363
 
 
6364
#if defined(WIN_EX)                     /* 1997/10/08 (Wed) 14:52:06 */
 
6365
        if (nlinks > 0) {
 
6366
            char *p = "LYNX (unknown link type)";
 
6367
 
 
6368
            /* Show the URL & kanji code . */
 
6369
            if (strlen(links[curdoc.link].lname) == 0) {
 
6370
 
 
6371
               if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
 
6372
 
 
6373
                    switch(links[curdoc.link].l_form->type) {
 
6374
                    case F_TEXT_SUBMIT_TYPE:
 
6375
                    case F_SUBMIT_TYPE:
 
6376
                    case F_IMAGE_SUBMIT_TYPE:
 
6377
                        p = "[SUBMIT]";
 
6378
                        break;
 
6379
                    case F_PASSWORD_TYPE:
 
6380
                        p = "Password";
 
6381
                        break;
 
6382
                    case F_OPTION_LIST_TYPE:
 
6383
                        p = "Option list";
 
6384
                        break;
 
6385
                    case F_CHECKBOX_TYPE:
 
6386
                        p = "Check box";
 
6387
                        break;
 
6388
                    case F_RADIO_TYPE:
 
6389
                        p = "[Radio]";
 
6390
                        break;
 
6391
                    case F_RESET_TYPE:
 
6392
                        p = "[Reset]";
 
6393
                        break;
 
6394
                    case F_TEXT_TYPE:
 
6395
                        p = "Text input";
 
6396
                        break;
 
6397
                    case F_TEXTAREA_TYPE:
 
6398
                        p = "Text input lines";
 
6399
                        break;
 
6400
                    default:
 
6401
                        break;
 
6402
                    }
 
6403
                    set_ws_title(p);
 
6404
               }
 
6405
            } else {
 
6406
                if (user_mode == ADVANCED_MODE) {
 
6407
                    p = curdoc.title;
 
6408
                } else {
 
6409
                    p = links[curdoc.link].lname;
 
6410
                }
 
6411
 
 
6412
                if (strlen(p) < 500) {
 
6413
                    strcpy(temp_buff, p);
 
6414
                    if (strchr(temp_buff, '%')) {
 
6415
                        HTUnEscape(temp_buff);
 
6416
                    }
 
6417
                    str_sjis(sjis_buff, temp_buff);
 
6418
                    set_ws_title(LYElideString(sjis_buff, 10));
 
6419
                }
 
6420
            }
 
6421
        } else {
 
6422
            if (strlen(curdoc.address) < sizeof(temp_buff)-1) {
 
6423
                if (user_mode == ADVANCED_MODE) {
 
6424
                    str_sjis(temp_buff, curdoc.title);
 
6425
                } else {
 
6426
                    strcpy(temp_buff, curdoc.address);
 
6427
                }
 
6428
                set_ws_title(HTUnEscape(temp_buff));
 
6429
            }
 
6430
        }
 
6431
#endif /* WIN_EX */
 
6432
 
 
6433
        /*
 
6434
         *  Report unread or new mail, if appropriate.
 
6435
         */
 
6436
        if (check_mail && !no_mail)
 
6437
            LYCheckMail();
 
6438
 
 
6439
        /*
 
6440
         *  If help is not on the screen,
 
6441
         *  then put a message on the screen
 
6442
         *  to tell the user other misc info.
 
6443
         */
 
6444
        if (!show_help) {
 
6445
           show_main_statusline(links[curdoc.link],
 
6446
                                (curlink_is_editable && textinput_activated) ?
 
6447
                                FOR_INPUT : FOR_PANEL);
 
6448
        } else {
 
6449
           show_help = FALSE;
 
6450
        }
 
6451
 
 
6452
        if (nlinks > 0) {
 
6453
             /*
 
6454
              *  Highlight current link, unless it is an active
 
6455
              *  text input field.
 
6456
              */
 
6457
            if (!curlink_is_editable) {
 
6458
                LYhighlight(ON, curdoc.link, prev_target);
 
6459
#ifndef INACTIVE_INPUT_STYLE_VH
 
6460
            } else if (!textinput_activated) {
 
6461
                LYhighlight(ON, curdoc.link, prev_target);
 
6462
#endif
 
6463
            }
 
6464
        }
 
6465
 
 
6466
        if (traversal) {
 
6467
            /*
 
6468
             *  Don't go interactively into forms,
 
6469
             *  or accept keystrokes from the user
 
6470
             */
 
6471
            if (crawl && crawl_ok) {
 
6472
                crawl_ok = FALSE;
 
6473
#ifdef FNAMES_8_3
 
6474
                sprintf(cfile,"lnk%05d.dat",ccount);
 
6475
#else
 
6476
                sprintf(cfile,"lnk%08d.dat",ccount);
 
6477
#endif /* FNAMES_8_3 */
 
6478
                ccount = ccount + 1;
 
6479
                if ((cfp = LYNewTxtFile(cfile))  != NULL) {
 
6480
                    print_crawl_to_fd(cfp,curdoc.address,curdoc.title);
 
6481
                    LYCloseOutput(cfp);
 
6482
                } else {
 
6483
                    if (!dump_output_immediately)
 
6484
                        cleanup();
 
6485
#ifdef UNIX
 
6486
                    if (dump_output_immediately)
 
6487
                        fprintf(stderr,
 
6488
                        gettext("Fatal error - could not open output file %s\n"),cfile);
 
6489
                    else
 
6490
#endif
 
6491
                        printf(
 
6492
                        gettext("Fatal error - could not open output file %s\n"),cfile);
 
6493
                    if (!dump_output_immediately) {
 
6494
                        exit_immediately(EXIT_FAILURE);
 
6495
                    }
 
6496
                    return(EXIT_FAILURE);
 
6497
                }
 
6498
            }
 
6499
        } else {
 
6500
            /*
 
6501
             *  Normal, non-traversal handling.
 
6502
             */
 
6503
 
 
6504
            if (curlink_is_editable &&
 
6505
                (textinput_activated || pending_form_c != -1)) {
 
6506
                if (pending_form_c != -1) {
 
6507
                    real_c = pending_form_c;
 
6508
                    pending_form_c = -1;
 
6509
                } else {
 
6510
                    /*
 
6511
                     *  Replace novice lines if in NOVICE_MODE.
 
6512
                     */
 
6513
                    if (user_mode==NOVICE_MODE) {
 
6514
                        form_noviceline(links[curdoc.link].l_form->disabled);
 
6515
                    }
 
6516
                    real_c = change_form_link(curdoc.link,
 
6517
                                     &newdoc, &refresh_screen,
 
6518
                                     use_last_tfpos, FALSE);
 
6519
                }
 
6520
#ifdef TEXTFIELDS_MAY_NEED_ACTIVATION
 
6521
                if (textfields_need_activation)
 
6522
                    textinput_activated = FALSE;
 
6523
#ifdef INACTIVE_INPUT_STYLE_VH
 
6524
                textinput_redrawn = FALSE;
 
6525
#endif
 
6526
#endif
 
6527
 
 
6528
                c = (real_c==LKC_DONE) ? DO_NOTHING : LKC_TO_C(real_c);
 
6529
                if (c != DO_NOTHING &&
 
6530
                    peek_mouse_link() != -1 && peek_mouse_link() != -2)
 
6531
                    old_c = 0;
 
6532
                if (peek_mouse_link() >= 0 &&
 
6533
                    LKC_TO_LAC(keymap,real_c) != LYK_CHANGE_LINK) {
 
6534
                    do_change_link();
 
6535
                    if ((c == '\n' || c == '\r') &&
 
6536
                        links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
6537
                        F_TEXTLIKE(links[curdoc.link].l_form->type) &&
 
6538
                        !textfields_need_activation) {
 
6539
                        c = DO_NOTHING;
 
6540
                    }
 
6541
#ifdef TEXTFIELDS_MAY_NEED_ACTIVATION
 
6542
                } else if ((links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
6543
                            links[curdoc.link].l_form->type == F_TEXTAREA_TYPE)
 
6544
                           && textfields_need_activation
 
6545
                           && !links[curdoc.link].l_form->disabled
 
6546
                           && peek_mouse_link() < 0 &&
 
6547
                           (((LKC_TO_LAC(keymap,real_c) == LYK_NEXT_LINK ||
 
6548
#ifdef TEXTAREA_AUTOGROW
 
6549
                              LKC_TO_LAC(keymap,real_c) == LYK_ACTIVATE ||
 
6550
#endif
 
6551
                              LKC_TO_LAC(keymap,real_c) == LYK_LPOS_NEXT_LINK ||
 
6552
                              LKC_TO_LAC(keymap,real_c) == LYK_DOWN_LINK) &&
 
6553
                             ((curdoc.link < nlinks-1 &&
 
6554
                               links[curdoc.link+1].type == WWW_FORM_LINK_TYPE  &&
 
6555
                               links[curdoc.link+1].l_form->type == F_TEXTAREA_TYPE
 
6556
                               && (links[curdoc.link].l_form->number ==
 
6557
                                   links[curdoc.link+1].l_form->number) &&
 
6558
                               strcmp(links[curdoc.link].l_form->name,
 
6559
                                      links[curdoc.link+1].l_form->name) == 0) ||
 
6560
                              (curdoc.link == nlinks-1 && more &&
 
6561
                               HText_TAHasMoreLines(curdoc.link, 1)))) ||
 
6562
                            ((LKC_TO_LAC(keymap,real_c) == LYK_PREV_LINK ||
 
6563
                              LKC_TO_LAC(keymap,real_c) == LYK_LPOS_PREV_LINK ||
 
6564
                              LKC_TO_LAC(keymap,real_c) == LYK_UP_LINK) &&
 
6565
                             ((curdoc.link > 0 &&
 
6566
                               links[curdoc.link-1].type == WWW_FORM_LINK_TYPE  &&
 
6567
                               links[curdoc.link-1].l_form->type == F_TEXTAREA_TYPE
 
6568
                               && (links[curdoc.link].l_form->number ==
 
6569
                                   links[curdoc.link-1].l_form->number) &&
 
6570
                               strcmp(links[curdoc.link].l_form->name,
 
6571
                                      links[curdoc.link-1].l_form->name) == 0) ||
 
6572
                              (curdoc.link == 0 && curdoc.line > 1 &&
 
6573
                               HText_TAHasMoreLines(curdoc.link, -1)))))) {
 
6574
                    textinput_activated = TRUE;
 
6575
#ifdef TEXTAREA_AUTOGROW
 
6576
                    if ((c == '\n' || c == '\r') &&
 
6577
                        LKC_TO_LAC(keymap,real_c) == LYK_ACTIVATE)
 
6578
                        c = LAC_TO_LKC0(LYK_NEXT_LINK);
 
6579
#endif /* TEXTAREA_AUTOGROW */
 
6580
#endif /* TEXTFIELDS_MAY_NEED_ACTIVATION */
 
6581
                } else
 
6582
                    switch (c) {
 
6583
                    case '\n':
 
6584
                    case '\r':
 
6585
#ifdef TEXTAREA_AUTOGROW
 
6586
                    /*
 
6587
                     *  If on the bottom line of a TEXTAREA, and the user hit
 
6588
                     *  the ENTER key, we add a new line/anchor automatically,
 
6589
                     *  positioning the cursor on it.
 
6590
                     *
 
6591
                     *  If at the bottom of the screen, we effectively perform
 
6592
                     *  an LYK_DOWN_HALF-like operation, then move down to the
 
6593
                     *  new line we just added.  --KED  02/14/99
 
6594
                     *
 
6595
                     *  [There is some redundancy and non-standard indentation
 
6596
                     *   in the monster-if() below.  This is intentional ... to
 
6597
                     *   try and improve the "readability" (such as it is).
 
6598
                     *   Caveat emptor to anyone trying to change it.]
 
6599
                     */
 
6600
                    if ((links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
6601
                         links[curdoc.link].l_form->type == F_TEXTAREA_TYPE) &&
 
6602
                        ((curdoc.link == nlinks-1 &&
 
6603
                          !(more && HText_TAHasMoreLines(curdoc.link, 1)))
 
6604
                         ||
 
6605
                         ((curdoc.link <  nlinks-1) &&
 
6606
                          !(links[curdoc.link+1].type == WWW_FORM_LINK_TYPE  &&
 
6607
                            links[curdoc.link+1].l_form->type == F_TEXTAREA_TYPE))
 
6608
                         ||
 
6609
                         ((curdoc.link <  nlinks-1) &&
 
6610
                          ((links[curdoc.link+1].type == WWW_FORM_LINK_TYPE  &&
 
6611
                            links[curdoc.link+1].l_form->type == F_TEXTAREA_TYPE)
 
6612
                            &&
 
6613
                            ((links[curdoc.link].l_form->number        !=
 
6614
                                      links[curdoc.link+1].l_form->number) ||
 
6615
                             (strcmp (links[curdoc.link].l_form->name,
 
6616
                                      links[curdoc.link+1].l_form->name) != 0)))))) {
 
6617
 
 
6618
                        HText_ExpandTextarea (&links[curdoc.link], 1);
 
6619
 
 
6620
                        if (links[curdoc.link].ly < display_lines) {
 
6621
                            refresh_screen = TRUE;
 
6622
 
 
6623
                        } else {
 
6624
 
 
6625
                            Newline += (display_lines/2);
 
6626
                            if (nlinks > 0 && curdoc.link > -1 &&
 
6627
                                links[curdoc.link].ly > display_lines/2) {
 
6628
                                    newdoc.link = curdoc.link;
 
6629
                                    for (i = 0; links[i].ly <= (display_lines/2); i++)
 
6630
                                        --newdoc.link;
 
6631
                                    newdoc.link++;
 
6632
                            }
 
6633
                        }
 
6634
#ifdef TEXTFIELDS_MAY_NEED_ACTIVATION
 
6635
                        if (textfields_need_activation) {
 
6636
                            textinput_activated = TRUE;
 
6637
                            textfields_need_activation = textfields_activation_option;
 
6638
#ifdef INACTIVE_INPUT_STYLE_VH
 
6639
                            textinput_redrawn = TRUE;
 
6640
#endif
 
6641
                        };
 
6642
#endif
 
6643
 
 
6644
                   }
 
6645
#endif /* TEXTAREA_AUTOGROW */
 
6646
 
 
6647
                    /*
 
6648
                     *  Make return in input field (if it was returned
 
6649
                     *  by change_form_link) act as LYK_NEXT_LINK,
 
6650
                     *  independent of what key (if any) is mapped to
 
6651
                     *  LYK_NEXT_LINK. - kw
 
6652
                     */
 
6653
                    c = LAC_TO_LKC0(LYK_NEXT_LINK);
 
6654
                    break;
 
6655
                default:
 
6656
 
 
6657
                    if (old_c != c && old_c != real_c && c != real_c)
 
6658
                        real_c = c;
 
6659
                }
 
6660
            } else {
 
6661
#if defined(TEXTFIELDS_MAY_NEED_ACTIVATION) && defined(INACTIVE_INPUT_STYLE_VH)
 
6662
                if (curlink_is_editable && !textinput_redrawn) {
 
6663
                /*draw the text entry, but don't activate it*/
 
6664
                    textinput_redrawn = TRUE;
 
6665
                    change_form_link_ex(curdoc.link,
 
6666
                                    &newdoc, &refresh_screen,
 
6667
                                    use_last_tfpos, FALSE, TRUE);
 
6668
                    if (LYShowCursor) {
 
6669
                        LYmove(links[curdoc.link].ly,
 
6670
                             ((links[curdoc.link].lx > 0) ?
 
6671
                              (links[curdoc.link].lx - 1) : 0));
 
6672
                    } else {
 
6673
                        LYHideCursor();
 
6674
                    }
 
6675
                }
 
6676
#endif /* TEXTFIELDS_MAY_NEED_ACTIVATION && INACTIVE_INPUT_STYLE_VH */
 
6677
                /*
 
6678
                 *  Get a keystroke from the user.
 
6679
                 *  Save the last keystroke to avoid
 
6680
                 *  redundant error reporting.
 
6681
                 */
 
6682
                real_c = c = LYgetch(); /* get user input */
 
6683
 
 
6684
                if (c != last_key)
 
6685
                    key_count = 0;
 
6686
                key_count++;
 
6687
                last_key = c;
 
6688
#ifndef VMS
 
6689
                if (c == 3) {           /* ^C */
 
6690
                    /*
 
6691
                     *  This shouldn't happen.  We'll try to
 
6692
                     *  deal with whatever bug caused it. - FM
 
6693
                     */
 
6694
                    signal(SIGINT, cleanup_sig);
 
6695
                    old_c = 0;
 
6696
                    cmd = LYK_QUIT;
 
6697
                    goto new_cmd;
 
6698
                }
 
6699
#endif /* !VMS */
 
6700
                if (LKC_HAS_ESC_MOD(c) && EditBinding(c) != LYE_FORM_PASS) {
 
6701
                    /*
 
6702
                     *  If ESC + <key> was read (and not recognized as a
 
6703
                     *  terminal escape sequence for another key), ignore
 
6704
                     *  the ESC modifier and act on <key> only if the line
 
6705
                     *  editor binding would have passed the same ESC-modified
 
6706
                     *  lynxkeycode back to us if it had been pressed in a
 
6707
                     *  text input field.  Otherwise set interesting part
 
6708
                     *  so that it will map to 0, to prevent that ESC + <key>
 
6709
                     *  acts like <key>, which might be unexpected. - kw
 
6710
                     */
 
6711
                    c = (c & ~LKC_MASK) | LAC_TO_LKC(0);
 
6712
                }
 
6713
                if (old_c != real_c) {
 
6714
                    old_c = 0;
 
6715
                }
 
6716
            }
 
6717
        }
 
6718
 
 
6719
#ifdef VMS
 
6720
        if (HadVMSInterrupt) {
 
6721
            HadVMSInterrupt = FALSE;
 
6722
            c = DO_NOTHING;
 
6723
        }
 
6724
#else
 
6725
        if (recent_sizechange) {
 
6726
            if (c <= 0)
 
6727
                c = DO_NOTHING;
 
6728
        }
 
6729
#endif /* VMS */
 
6730
 
 
6731
new_keyboard_input:
 
6732
        /*
 
6733
         *  A goto point for new input without going
 
6734
         *  back through the getch() loop.
 
6735
         */
 
6736
        if (traversal) {
 
6737
            if ((c = DoTraversal(c, &crawl_ok)) < 0)
 
6738
                return (EXIT_FAILURE);
 
6739
        } /* traversal */
 
6740
 
 
6741
#ifdef WIN_EX
 
6742
        if (c == DO_NOTHING)
 
6743
            cmd = LYK_DO_NOTHING;
 
6744
        else
 
6745
#endif
 
6746
        cmd = LKC_TO_LAC(keymap,c);  /* adds 1 to map EOF to 0 */
 
6747
 
 
6748
#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
 
6749
        if (lynx_edit_mode && !no_dired_support && LKC_TO_LAC(key_override,c))
 
6750
          cmd = LKC_TO_LAC(key_override,c);
 
6751
#endif /* DIRED_SUPPORT && OK_OVERRIDE */
 
6752
 
 
6753
        real_cmd = cmd;
 
6754
 
 
6755
new_cmd:  /*
 
6756
           *  A goto point for new input without going
 
6757
           *  back through the getch() loop.
 
6758
           */
 
6759
 
 
6760
        force_old_UCLYhndl_on_reload = FALSE;
 
6761
        CTRACE_FLUSH(tfp);
 
6762
 
 
6763
        if (cmd != LYK_UP_LINK && cmd != LYK_DOWN_LINK)
 
6764
            follow_col = -1;
 
6765
 
 
6766
        switch(cmd) {
 
6767
        case -1:
 
6768
            HTUserMsg(COMMAND_UNKNOWN);
 
6769
            break;
 
6770
        case 0: /* unmapped character */
 
6771
        default:
 
6772
            if (curdoc.link >= 0 && curdoc.link < nlinks &&
 
6773
                links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
 
6774
                F_TEXTLIKE(links[curdoc.link].l_form->type)) {
 
6775
 
 
6776
#ifdef TEXTFIELDS_MAY_NEED_ACTIVATION
 
6777
                if (textfields_need_activation) {
 
6778
                    show_main_statusline(links[curdoc.link], FOR_PANEL);
 
6779
#ifdef INACTIVE_INPUT_STYLE_VH
 
6780
                    textinput_redrawn = FALSE;
 
6781
#endif
 
6782
                } else
 
6783
#endif
 
6784
                    show_main_statusline(links[curdoc.link], FOR_INPUT);
 
6785
            } else if (more) {
 
6786
                HTInfoMsg(MOREHELP);
 
6787
            } else {
 
6788
                HTInfoMsg(HELP);
 
6789
            }
 
6790
            show_help = TRUE;
 
6791
 
 
6792
            if (TRACE) {
 
6793
                sprintf(cfile, "%d", c);
 
6794
                LYaddstr(cfile);        /* show the user input */
 
6795
                cfile[0] = '\0';
 
6796
            }
 
6797
            break;
 
6798
 
 
6799
        case LYK_COMMAND:
 
6800
            cmd = handle_LYK_COMMAND(user_input_buffer);
 
6801
            goto new_cmd;
 
6802
 
 
6803
        case LYK_INTERRUPT:
 
6804
            /*
 
6805
             *  No network transmission to interrupt - 'til we multithread.
 
6806
             */
 
6807
            break;
 
6808
 
 
6809
        case LYK_F_LINK_NUM:
 
6810
             c = '\0';
 
6811
             /* FALLTHRU */
 
6812
        case LYK_1: /* FALLTHRU */
 
6813
        case LYK_2: /* FALLTHRU */
 
6814
        case LYK_3: /* FALLTHRU */
 
6815
        case LYK_4: /* FALLTHRU */
 
6816
        case LYK_5: /* FALLTHRU */
 
6817
        case LYK_6: /* FALLTHRU */
 
6818
        case LYK_7: /* FALLTHRU */
 
6819
        case LYK_8: /* FALLTHRU */
 
6820
        case LYK_9:
 
6821
            handle_LYK_digit(c, &force_load, user_input_buffer,
 
6822
                             &old_c, real_c, &try_internal);
 
6823
            break;
 
6824
 
 
6825
        case LYK_SOURCE:  /* toggle view source mode */
 
6826
            handle_LYK_SOURCE(&ownerS_address);
 
6827
            break;
 
6828
 
 
6829
        case LYK_CHG_CENTER:    /* ^Q */
 
6830
 
 
6831
            if (no_table_center) {
 
6832
                no_table_center = FALSE;
 
6833
                HTInfoMsg(gettext("TABLE center enable."));
 
6834
            } else {
 
6835
                no_table_center = TRUE;
 
6836
                HTInfoMsg(gettext("TABLE center disable."));
 
6837
            }
 
6838
            /* FALLTHRU */
 
6839
 
 
6840
        case LYK_RELOAD:  /* control-R to reload and refresh */
 
6841
            handle_LYK_RELOAD(real_cmd);
 
6842
            break;
 
6843
 
 
6844
        case LYK_HISTORICAL:    /* toggle 'historical' comments parsing */
 
6845
            handle_LYK_HISTORICAL();
 
6846
            break;
 
6847
 
 
6848
        case LYK_MINIMAL:       /* toggle 'minimal' comments parsing */
 
6849
            handle_LYK_MINIMAL();
 
6850
            break;
 
6851
 
 
6852
        case LYK_SOFT_DQUOTES:
 
6853
            handle_LYK_SOFT_DQUOTES();
 
6854
            break;
 
6855
 
 
6856
        case LYK_SWITCH_DTD:
 
6857
            handle_LYK_SWITCH_DTD();
 
6858
            break;
 
6859
 
 
6860
        case LYK_QUIT:          /* quit */
 
6861
            if (handle_LYK_QUIT())
 
6862
                return(EXIT_SUCCESS);
 
6863
            break;
 
6864
 
 
6865
        case LYK_ABORT:         /* don't ask the user about quitting */
 
6866
            return(EXIT_SUCCESS);
 
6867
 
 
6868
        case LYK_NEXT_PAGE:     /* next page */
 
6869
            handle_LYK_NEXT_PAGE(&old_c, real_c);
 
6870
            break;
 
6871
 
 
6872
        case LYK_PREV_PAGE:     /* page up */
 
6873
            handle_LYK_PREV_PAGE(&old_c, real_c);
 
6874
            break;
 
6875
 
 
6876
        case  LYK_UP_TWO:
 
6877
            handle_LYK_UP_TWO(&arrowup, &old_c, real_c);
 
6878
            break;
 
6879
 
 
6880
        case  LYK_DOWN_TWO:
 
6881
            handle_LYK_DOWN_TWO(&old_c, real_c);
 
6882
            break;
 
6883
 
 
6884
        case  LYK_UP_HALF:
 
6885
            handle_LYK_UP_HALF(&arrowup, &old_c, real_c);
 
6886
            break;
 
6887
 
 
6888
        case  LYK_DOWN_HALF:
 
6889
            handle_LYK_DOWN_HALF(&old_c, real_c);
 
6890
            break;
 
6891
 
 
6892
#ifdef CAN_CUT_AND_PASTE
 
6893
        case LYK_TO_CLIPBOARD:  /* ^S */
 
6894
            {
 
6895
                char *s;
 
6896
                int ch2;
 
6897
 
 
6898
                /* The logic resembles one of ADD_BOOKMARK */
 
6899
                if (nlinks > 0 && links[curdoc.link].lname
 
6900
                    && links[curdoc.link].type != WWW_FORM_LINK_TYPE) {
 
6901
                    /* Makes sense to copy a link */
 
6902
                    _statusline("Copy D)ocument's or L)ink's URL to clipboard or C)ancel?");
 
6903
                    ch2 = LYgetch_single();
 
6904
                    if (ch2 == 'D')
 
6905
                        s = curdoc.address;
 
6906
                    else if (ch2 == 'C')
 
6907
                        break;
 
6908
                    else
 
6909
                        s = links[curdoc.link].lname;
 
6910
                } else
 
6911
                    s = curdoc.address;
 
6912
                if (isEmpty(s))
 
6913
                    HTInfoMsg(gettext("Current URL is empty."));
 
6914
                if (put_clip(s))
 
6915
                    HTInfoMsg(gettext("Copy to clipboard failed."));
 
6916
                else if (s == curdoc.address)
 
6917
                    HTInfoMsg(gettext("Document URL put to clipboard."));
 
6918
                else
 
6919
                    HTInfoMsg(gettext("Link URL put to clipboard."));
 
6920
            }
 
6921
            break;
 
6922
 
 
6923
        case LYK_PASTE_URL:
 
6924
            if (no_goto && !LYValidate) { /*  Go to not allowed. - FM */
 
6925
                HTUserMsg(GOTO_DISALLOWED);
 
6926
            } else {
 
6927
                unsigned char *s = (unsigned char *) get_clip_grab(), *e, *t;
 
6928
                char *buf;
 
6929
                int len2;
 
6930
 
 
6931
                if (!s)
 
6932
                    break;
 
6933
                len2 = strlen((const char *) s);
 
6934
                e = s + len2;
 
6935
                while (s < e && strchr(" \t\n\r", *s))
 
6936
                    s++;
 
6937
                while (s < e && strchr(" \t\n\r", e[-1]))
 
6938
                    e--;
 
6939
                if (s[0] == '<' && e > s && e[-1] == '>') {
 
6940
                    s++; e--;
 
6941
                    if (!strncasecomp((const char *) s,"URL:", 4))
 
6942
                        s += 4;
 
6943
                }
 
6944
                if (s >= e) {
 
6945
                    HTInfoMsg(gettext("No URL in the clipboard."));
 
6946
                    break;
 
6947
                }
 
6948
                len = e - s + 1;
 
6949
                if (len < MAX_LINE)
 
6950
                    len = MAX_LINE;     /* Required for do_check_goto_URL() */
 
6951
                buf = (char*)malloc(len);
 
6952
                strncpy(buf, (const char *) s, e - s);
 
6953
                buf[e - s] = '\0';
 
6954
                t = (unsigned char *) buf;
 
6955
 
 
6956
                while (s < e) {
 
6957
                    if (strchr(" \t\n\r", *s)) {
 
6958
                        int nl2 = 0;    /* Keep whitespace without NL - file names! */
 
6959
                        unsigned char *s1 = s;
 
6960
 
 
6961
                        while (strchr(" \t\n\r", *s)) {
 
6962
                            if (!nl2 && *s == '\n')
 
6963
                                nl2 = 1;
 
6964
                            s++;
 
6965
                        }
 
6966
                        if (!nl2) {
 
6967
                            while (s1 < s) {
 
6968
                                if (*s1 != '\r' && *s1 != '\r')
 
6969
                                    *t = *s1;
 
6970
                                t++, s1++;
 
6971
                            }
 
6972
                        }
 
6973
                    } else
 
6974
                        *t++ = *s++;
 
6975
                }
 
6976
                *t = '\0';
 
6977
                get_clip_release();
 
6978
                do_check_goto_URL(buf, &temp, &force_load);
 
6979
                free(buf);
 
6980
            }
 
6981
            break;
 
6982
#endif
 
6983
 
 
6984
#ifdef KANJI_CODE_OVERRIDE
 
6985
        case LYK_CHG_KCODE:     /* ^L */
 
6986
            if (LYRawMode && (HTCJK == JAPANESE)) {
 
6987
                switch(last_kcode) {
 
6988
                case NOKANJI:
 
6989
                    last_kcode = SJIS;
 
6990
                    break;
 
6991
                case SJIS:
 
6992
                    last_kcode = EUC;
 
6993
                    break;
 
6994
                case EUC:
 
6995
                    last_kcode = NOKANJI;
 
6996
                    break;
 
6997
                default:
 
6998
                    break;
 
6999
                }
 
7000
            }
 
7001
            LYmove(0, 0);
 
7002
            lynx_start_title_color ();
 
7003
            LYaddstr(str_kcode(last_kcode));
 
7004
            lynx_stop_title_color ();
 
7005
 
 
7006
            break;
 
7007
#endif
 
7008
 
 
7009
        case LYK_REFRESH:
 
7010
            refresh_screen = TRUE;
 
7011
            lynx_force_repaint();
 
7012
            break;
 
7013
 
 
7014
        case LYK_HOME:
 
7015
            if (curdoc.line > 1)
 
7016
                Newline = 1;
 
7017
            else {
 
7018
                cmd = LYK_PREV_PAGE;
 
7019
                goto new_cmd;
 
7020
            }
 
7021
            break;
 
7022
 
 
7023
        case LYK_END:
 
7024
            i = HText_getNumOfLines() - display_lines + 2;
 
7025
            if (i >= 1 && Newline != i) {
 
7026
                Newline = i;            /* go to end of file */
 
7027
                arrowup = TRUE;         /* position on last link */
 
7028
            } else {
 
7029
                cmd = LYK_NEXT_PAGE;
 
7030
                goto new_cmd;
 
7031
            }
 
7032
            break;
 
7033
 
 
7034
        case LYK_FIRST_LINK:
 
7035
            handle_LYK_FIRST_LINK();
 
7036
            break;
 
7037
 
 
7038
        case LYK_LAST_LINK:
 
7039
            handle_LYK_LAST_LINK();
 
7040
            break;
 
7041
 
 
7042
        case LYK_PREV_LINK:
 
7043
        case LYK_LPOS_PREV_LINK:
 
7044
            handle_LYK_PREV_LINK(&arrowup, &old_c, real_c);
 
7045
            break;
 
7046
 
 
7047
        case LYK_NEXT_LINK:
 
7048
        case LYK_LPOS_NEXT_LINK:
 
7049
            handle_LYK_NEXT_LINK(c, &old_c, real_c);
 
7050
            break;
 
7051
 
 
7052
        case LYK_FASTFORW_LINK:
 
7053
            handle_LYK_FASTFORW_LINK(&old_c, real_c);
 
7054
            break;
 
7055
 
 
7056
        case LYK_FASTBACKW_LINK:
 
7057
            if (handle_LYK_FASTBACKW_LINK(&cmd, &old_c, real_c))
 
7058
                goto new_cmd;
 
7059
            break;
 
7060
 
 
7061
        case LYK_UP_LINK:
 
7062
            handle_LYK_UP_LINK(&follow_col, &arrowup, &old_c, real_c);
 
7063
            break;
 
7064
 
 
7065
        case LYK_DOWN_LINK:
 
7066
            handle_LYK_DOWN_LINK(&follow_col, &old_c, real_c);
 
7067
            break;
 
7068
 
 
7069
        case LYK_CHANGE_LINK:
 
7070
            do_change_link();
 
7071
#if defined(TEXTFIELDS_MAY_NEED_ACTIVATION) && defined(INACTIVE_INPUT_STYLE_VH)
 
7072
            if (textfields_need_activation)
 
7073
                textinput_redrawn = FALSE;
 
7074
#endif /* TEXTFIELDS_MAY_NEED_ACTIVATION && INACTIVE_INPUT_STYLE_VH */
 
7075
            break;
 
7076
 
 
7077
        case LYK_RIGHT_LINK:
 
7078
            handle_LYK_RIGHT_LINK();
 
7079
            break;
 
7080
 
 
7081
        case LYK_LEFT_LINK:
 
7082
            handle_LYK_LEFT_LINK();
 
7083
            break;
 
7084
 
 
7085
        case LYK_COOKIE_JAR:    /* show the cookie jar */
 
7086
            if (handle_LYK_COOKIE_JAR(&cmd))
 
7087
                goto new_cmd;
 
7088
            break;
 
7089
 
 
7090
        case LYK_HISTORY:       /* show the history page */
 
7091
            if (handle_LYK_HISTORY(ForcePush))
 
7092
                break;
 
7093
 
 
7094
            /* FALLTHRU */
 
7095
        case LYK_PREV_DOC:      /* back up a level */
 
7096
            switch (handle_PREV_DOC(&cmd, &old_c, real_c)) {
 
7097
            case 1:
 
7098
                return(EXIT_SUCCESS);
 
7099
            case 2:
 
7100
                goto new_cmd;
 
7101
            }
 
7102
            break;
 
7103
 
 
7104
        case LYK_NEXT_DOC:      /* undo back up a level */
 
7105
            handle_NEXT_DOC();
 
7106
            break;
 
7107
 
 
7108
        case LYK_NOCACHE: /* Force submission of form or link with no-cache */
 
7109
            if (!handle_LYK_NOCACHE(&old_c, real_c))
 
7110
                break;
 
7111
 
 
7112
            /* FALLTHRU */
 
7113
        case LYK_ACTIVATE:      /* follow a link */
 
7114
        case LYK_SUBMIT:        /* follow a link, submit TEXT_SUBMIT input */
 
7115
            switch (handle_LYK_ACTIVATE(&c, cmd, &try_internal, &refresh_screen, &force_load, real_cmd)) {
 
7116
            case 1:
 
7117
                continue;
 
7118
            case 2:
 
7119
                goto new_keyboard_input;
 
7120
            case 3:
 
7121
                pending_form_c = c;
 
7122
            }
 
7123
            break;
 
7124
 
 
7125
        case LYK_ELGOTO:        /* edit URL of current link and go to it  */
 
7126
            if (handle_LYK_ELGOTO(&ch, user_input_buffer, &temp, &old_c, real_c))
 
7127
                do_check_goto_URL(user_input_buffer, &temp, &force_load);
 
7128
            break;
 
7129
 
 
7130
        case LYK_ECGOTO:        /* edit current URL and go to to it     */
 
7131
            if (handle_LYK_ECGOTO(&ch, user_input_buffer, &temp, &old_c, real_c))
 
7132
                do_check_goto_URL(user_input_buffer, &temp, &force_load);
 
7133
            break;
 
7134
 
 
7135
        case LYK_GOTO:          /* 'g' to goto a random URL  */
 
7136
            if (handle_LYK_GOTO(&ch, user_input_buffer, &temp, &recall,
 
7137
                                &URLTotal, &URLNum, &FirstURLRecall, &old_c,
 
7138
                                real_c)) {
 
7139
                if (do_check_recall (ch, user_input_buffer, &temp, URLTotal,
 
7140
                                 &URLNum, recall, &FirstURLRecall))
 
7141
                    do_check_goto_URL(user_input_buffer, &temp, &force_load);
 
7142
            }
 
7143
            break;
 
7144
 
 
7145
        case LYK_DWIMHELP:      /* show context-dependent help file */
 
7146
            handle_LYK_DWIMHELP(&cshelpfile);
 
7147
            /* FALLTHRU */
 
7148
 
 
7149
        case LYK_HELP:          /* show help file */
 
7150
            handle_LYK_HELP(&cshelpfile);
 
7151
            break;
 
7152
 
 
7153
        case LYK_INDEX:         /* index file */
 
7154
            handle_LYK_INDEX(&old_c, real_c);
 
7155
            break;
 
7156
 
 
7157
        case LYK_MAIN_MENU:     /* return to main screen */
 
7158
            handle_LYK_MAIN_MENU(&old_c, real_c);
 
7159
            break;
 
7160
 
 
7161
#ifdef EXP_NESTED_TABLES
 
7162
        case LYK_NESTED_TABLES:
 
7163
            if (handle_LYK_NESTED_TABLES(&cmd))
 
7164
                goto new_cmd;
 
7165
            break;
 
7166
#endif
 
7167
        case LYK_OPTIONS:       /* options screen */
 
7168
            if (handle_LYK_OPTIONS(&cmd, &refresh_screen))
 
7169
                goto new_cmd;
 
7170
            break;
 
7171
 
 
7172
        case LYK_INDEX_SEARCH:  /* search for a user string */
 
7173
            handle_LYK_INDEX_SEARCH(&force_load, ForcePush, &old_c, real_c);
 
7174
            break;
 
7175
 
 
7176
        case LYK_WHEREIS:       /* search within the document */
 
7177
        case LYK_NEXT:          /* find the next occurrence in the document */
 
7178
        case LYK_PREV:          /* find the previous occurrence in the document */
 
7179
            handle_LYK_WHEREIS(cmd, &refresh_screen);
 
7180
            break;
 
7181
 
 
7182
        case LYK_COMMENT:       /* reply by mail */
 
7183
            handle_LYK_COMMENT(&refresh_screen, &owner_address, &old_c, real_c);
 
7184
            break;
 
7185
 
 
7186
#ifdef DIRED_SUPPORT
 
7187
        case LYK_TAG_LINK:      /* tag or untag the current link */
 
7188
            handle_LYK_TAG_LINK();
 
7189
            break;
 
7190
 
 
7191
        case LYK_MODIFY:        /* rename a file or directory */
 
7192
            handle_LYK_MODIFY(&refresh_screen);
 
7193
            break;
 
7194
 
 
7195
        case LYK_CREATE:        /* create a new file or directory */
 
7196
            handle_LYK_CREATE();
 
7197
            break;
 
7198
#endif /* DIRED_SUPPORT */
 
7199
 
 
7200
        case LYK_DWIMEDIT:      /* context-dependent edit */
 
7201
            switch (handle_LYK_DWIMEDIT(&cmd, &old_c, real_c)) {
 
7202
            case 1:
 
7203
                continue;
 
7204
            case 2:
 
7205
                goto new_cmd;
 
7206
            }
 
7207
            /* FALLTHRU */
 
7208
 
 
7209
        case LYK_EDIT:          /* edit */
 
7210
            handle_LYK_EDIT(&old_c, real_c);
 
7211
            break;
 
7212
 
 
7213
        case LYK_DEL_BOOKMARK:  /* remove a bookmark file link */
 
7214
            handle_LYK_DEL_BOOKMARK(&refresh_screen, &old_c, real_c);
 
7215
            break;
 
7216
 
 
7217
#ifdef DIRED_SUPPORT
 
7218
        case LYK_REMOVE:        /* remove files and directories */
 
7219
            handle_LYK_REMOVE(&refresh_screen);
 
7220
            break;
 
7221
#endif /* DIRED_SUPPORT */
 
7222
 
 
7223
#if defined(DIRED_SUPPORT) && defined(OK_INSTALL)
 
7224
        case LYK_INSTALL:       /* install a file into system area */
 
7225
            handle_LYK_INSTALL();
 
7226
            break;
 
7227
#endif /* DIRED_SUPPORT && OK_INSTALL */
 
7228
 
 
7229
        case LYK_INFO:          /* show document info */
 
7230
            if (handle_LYK_INFO(&cmd))
 
7231
                goto new_cmd;
 
7232
            break;
 
7233
 
 
7234
        case LYK_EDIT_TEXTAREA: /* use external editor on a TEXTAREA - KED */
 
7235
            handle_LYK_EDIT_TEXTAREA(&refresh_screen, &old_c, real_c);
 
7236
            break;
 
7237
 
 
7238
        case LYK_GROW_TEXTAREA: /* add new lines to bottom of TEXTAREA - KED */
 
7239
            handle_LYK_GROW_TEXTAREA(&refresh_screen);
 
7240
            break;
 
7241
 
 
7242
        case LYK_INSERT_FILE:   /* insert file in TEXTAREA, above cursor - KED */
 
7243
            handle_LYK_INSERT_FILE(&refresh_screen, &old_c, real_c);
 
7244
            break;
 
7245
 
 
7246
        case LYK_PRINT:         /* print the file */
 
7247
            handle_LYK_PRINT(&ForcePush, &old_c, real_c);
 
7248
            break;
 
7249
 
 
7250
        case LYK_LIST:          /* list links in the current document */
 
7251
            if (handle_LYK_LIST(&cmd))
 
7252
                goto new_cmd;
 
7253
            break;
 
7254
 
 
7255
#ifdef EXP_ADDRLIST_PAGE
 
7256
        case LYK_ADDRLIST:      /* always list URL's (only) */
 
7257
            if (handle_LYK_ADDRLIST(&cmd))
 
7258
                goto new_cmd;
 
7259
            break;
 
7260
#endif /* EXP_ADDRLIST_PAGE */
 
7261
 
 
7262
        case LYK_VLINKS:  /* list links visited during the current session */
 
7263
            if (handle_LYK_VLINKS(&cmd, &newdoc_link_is_absolute))
 
7264
                goto new_cmd;
 
7265
            break;
 
7266
 
 
7267
        case LYK_TOOLBAR:  /* go to Toolbar or Banner in current document */
 
7268
            handle_LYK_TOOLBAR(&try_internal, &force_load, &old_c, real_c);
 
7269
            break;
 
7270
 
 
7271
#if defined(DIRED_SUPPORT) || defined(VMS)
 
7272
        case LYK_DIRED_MENU:  /* provide full file management menu */
 
7273
            handle_LYK_DIRED_MENU(&refresh_screen, &old_c, real_c);
 
7274
            break;
 
7275
#endif /* DIRED_SUPPORT || VMS*/
 
7276
 
 
7277
#ifdef USE_EXTERNALS
 
7278
        case LYK_EXTERN_LINK:   /* use external program on url */
 
7279
            handle_LYK_EXTERN_LINK(&refresh_screen);
 
7280
            break;
 
7281
        case LYK_EXTERN_PAGE:   /* use external program on current page */
 
7282
            handle_LYK_EXTERN_PAGE(&refresh_screen);
 
7283
            break;
 
7284
#endif /* USE_EXTERNALS */
 
7285
 
 
7286
        case LYK_ADD_BOOKMARK:  /* add link to bookmark file */
 
7287
            handle_LYK_ADD_BOOKMARK(&refresh_screen, &old_c, real_c);
 
7288
            break;
 
7289
 
 
7290
        case LYK_VIEW_BOOKMARK: /* v to view home page */
 
7291
            handle_LYK_VIEW_BOOKMARK(&refresh_screen, &old_c, real_c);
 
7292
            break;
 
7293
 
 
7294
        case LYK_SHELL:         /* (!) shell escape */
 
7295
            handle_LYK_SHELL(&refresh_screen, &old_c, real_c);
 
7296
            break;
 
7297
 
 
7298
        case LYK_DOWNLOAD:
 
7299
            switch (handle_LYK_DOWNLOAD(&cmd, &old_c, real_c)) {
 
7300
            case 1:
 
7301
                continue;
 
7302
            case 2:
 
7303
                goto new_cmd;
 
7304
            }
 
7305
            break;
 
7306
 
 
7307
#ifdef DIRED_SUPPORT
 
7308
          case LYK_UPLOAD:
 
7309
            handle_LYK_UPLOAD();
 
7310
            break;
 
7311
#endif /* DIRED_SUPPORT */
 
7312
 
 
7313
        case LYK_TRACE_TOGGLE:  /*  Toggle TRACE mode. */
 
7314
            handle_LYK_TRACE_TOGGLE();
 
7315
            break;
 
7316
 
 
7317
        case LYK_TRACE_LOG:     /*  View TRACE log. */
 
7318
            handle_LYK_TRACE_LOG(&trace_mode_flag);
 
7319
            break;
 
7320
 
 
7321
        case LYK_IMAGE_TOGGLE:
 
7322
            if (handle_LYK_IMAGE_TOGGLE(&cmd))
 
7323
                goto new_cmd;
 
7324
            break;
 
7325
 
 
7326
        case LYK_INLINE_TOGGLE:
 
7327
            if (handle_LYK_INLINE_TOGGLE(&cmd))
 
7328
                goto new_cmd;
 
7329
            break;
 
7330
 
 
7331
        case LYK_RAW_TOGGLE:
 
7332
            if (handle_LYK_RAW_TOGGLE(&cmd))
 
7333
                goto new_cmd;
 
7334
            break;
 
7335
 
 
7336
        case LYK_HEAD:
 
7337
            if (handle_LYK_HEAD(&cmd))
 
7338
                goto new_cmd;
 
7339
            break;
 
7340
 
 
7341
        case LYK_TOGGLE_HELP:
 
7342
            handle_LYK_TOGGLE_HELP();
 
7343
            break;
 
7344
 
 
7345
        case LYK_KEYMAP:
 
7346
            handle_LYK_KEYMAP(&vi_keys_flag, &emacs_keys_flag, &old_c, real_c);
 
7347
            break;
 
7348
 
 
7349
        case LYK_JUMP:
 
7350
            if (handle_LYK_JUMP(c, user_input_buffer, &temp, &recall,
 
7351
                                    &FirstURLRecall, &URLNum, &URLTotal, &ch,
 
7352
                                    &old_c, real_c)) {
 
7353
                if (do_check_recall (ch, user_input_buffer, &temp, URLTotal,
 
7354
                                 &URLNum, recall, &FirstURLRecall))
 
7355
                    do_check_goto_URL(user_input_buffer, &temp, &force_load);
 
7356
            }
 
7357
            break;
 
7358
 
 
7359
        case LYK_CLEAR_AUTH:
 
7360
            handle_LYK_CLEAR_AUTH(&old_c, real_c);
 
7361
            break;
 
7362
 
 
7363
        case LYK_DO_NOTHING:    /* pretty self explanatory */
 
7364
            break;
 
7365
#ifdef SUPPORT_CHDIR
 
7366
        case LYK_CHDIR:
 
7367
            handle_LYK_CHDIR();
 
7368
            break;
 
7369
#endif
 
7370
#ifdef USE_CURSES_PADS
 
7371
        case LYK_SHIFT_LEFT:
 
7372
            handle_LYK_SHIFT_LEFT(&refresh_screen, key_count);
 
7373
            break;
 
7374
        case LYK_SHIFT_RIGHT:
 
7375
            handle_LYK_SHIFT_RIGHT(&refresh_screen, key_count);
 
7376
            break;
 
7377
        case LYK_LINEWRAP_TOGGLE:
 
7378
            if (handle_LYK_LINEWRAP_TOGGLE(&cmd, &refresh_screen))
 
7379
                goto new_cmd;
 
7380
            break;
 
7381
#endif
 
7382
        } /* end of BIG switch */
 
7383
    }
 
7384
}
 
7385
 
 
7386
PRIVATE int are_different ARGS2(
 
7387
        DocInfo *,      doc1,
 
7388
        DocInfo *,      doc2)
 
7389
{
 
7390
    char *cp1, *cp2;
 
7391
 
 
7392
    /*
 
7393
     *  Do we have two addresses?
 
7394
     */
 
7395
    if (!doc1->address || !doc2->address)
 
7396
        return (TRUE);
 
7397
 
 
7398
    /*
 
7399
     *  Do they differ in the type of request?
 
7400
     */
 
7401
    if (doc1->isHEAD != doc2->isHEAD)
 
7402
        return (TRUE);
 
7403
 
 
7404
    /*
 
7405
     *  See if the addresses are different, making sure
 
7406
     *  we're not tripped up by multiple anchors in the
 
7407
     *  the same document from a POST form. -- FM
 
7408
     */
 
7409
    cp1 = trimPoundSelector(doc1->address);
 
7410
    cp2 = trimPoundSelector(doc2->address);
 
7411
    /*
 
7412
     *  Are the base addresses different?
 
7413
     */
 
7414
    if (strcmp(doc1->address, doc2->address)) {
 
7415
        restorePoundSelector(cp1);
 
7416
        restorePoundSelector(cp2);
 
7417
        return(TRUE);
 
7418
    }
 
7419
    restorePoundSelector(cp1);
 
7420
    restorePoundSelector(cp2);
 
7421
 
 
7422
    /*
 
7423
     *  Do the docs have different contents?
 
7424
     */
 
7425
    if (doc1->post_data) {
 
7426
        if (doc2->post_data) {
 
7427
            if (!BINEQ(doc1->post_data, doc2->post_data))
 
7428
                return(TRUE);
 
7429
        } else
 
7430
            return(TRUE);
 
7431
    } else if (doc2->post_data)
 
7432
        return(TRUE);
 
7433
 
 
7434
    /*
 
7435
     *  We'll assume the two documents in fact are the same.
 
7436
     */
 
7437
    return(FALSE);
 
7438
}
 
7439
 
 
7440
/* This determines whether two docs are _physically_ different,
 
7441
 * meaning they are "from different files". - kw
 
7442
 */
 
7443
#ifndef DONT_TRACK_INTERNAL_LINKS
 
7444
PRIVATE int are_phys_different ARGS2(
 
7445
        DocInfo *,      doc1,
 
7446
        DocInfo *,      doc2)
 
7447
{
 
7448
    char *cp1, *cp2, *ap1 = doc1->address, *ap2 = doc2->address;
 
7449
 
 
7450
    /*
 
7451
     *  Do we have two addresses?
 
7452
     */
 
7453
    if (!doc1->address || !doc2->address)
 
7454
        return (TRUE);
 
7455
 
 
7456
    /*
 
7457
     *  Do they differ in the type of request?
 
7458
     */
 
7459
    if (doc1->isHEAD != doc2->isHEAD)
 
7460
        return (TRUE);
 
7461
 
 
7462
    /*
 
7463
     * Skip over possible LYNXIMGMAP parts. - kw
 
7464
     */
 
7465
    if (isLYNXIMGMAP(doc1->address))
 
7466
        ap1 += LEN_LYNXIMGMAP;
 
7467
    if (isLYNXIMGMAP(doc2->address))
 
7468
        ap2 += LEN_LYNXIMGMAP;
 
7469
    /*
 
7470
     * If there isn't any real URL in doc2->address, but maybe just
 
7471
     * a fragment, doc2 is assumed to be an internal reference in
 
7472
     * the same physical document, so return FALSE. - kw
 
7473
     */
 
7474
    if (*ap2 == '\0' || *ap2 == '#')
 
7475
        return(FALSE);
 
7476
 
 
7477
    /*
 
7478
     *  See if the addresses are different, making sure
 
7479
     *  we're not tripped up by multiple anchors in the
 
7480
     *  the same document from a POST form. -- FM
 
7481
     */
 
7482
    cp1 = trimPoundSelector(doc1->address);
 
7483
    cp2 = trimPoundSelector(doc2->address);
 
7484
    /*
 
7485
     *  Are the base addresses different?
 
7486
     */
 
7487
    if (strcmp(ap1, ap2)) {
 
7488
        restorePoundSelector(cp1);
 
7489
        restorePoundSelector(cp2);
 
7490
        return(TRUE);
 
7491
    }
 
7492
    restorePoundSelector(cp1);
 
7493
    restorePoundSelector(cp2);
 
7494
 
 
7495
    /*
 
7496
     *  Do the docs have different contents?
 
7497
     */
 
7498
    if (doc1->post_data) {
 
7499
        if (doc2->post_data) {
 
7500
            if (!BINEQ(doc1->post_data, doc2->post_data))
 
7501
                return(TRUE);
 
7502
        } else
 
7503
            return(TRUE);
 
7504
    } else if (doc2->post_data)
 
7505
        return(TRUE);
 
7506
 
 
7507
    /*
 
7508
     *  We'll assume the two documents in fact are the same.
 
7509
     */
 
7510
    return(FALSE);
 
7511
}
 
7512
#endif
 
7513
 
 
7514
/*
 
7515
 *  Utility for freeing the list of goto URLs. - FM
 
7516
 */
 
7517
#ifdef LY_FIND_LEAKS
 
7518
PRIVATE void HTGotoURLs_free NOARGS
 
7519
{
 
7520
    char *url;
 
7521
    HTList *cur = Goto_URLs;
 
7522
 
 
7523
    if (cur != 0) {
 
7524
        while (NULL != (url = (char *)HTList_nextObject(cur))) {
 
7525
            FREE(url);
 
7526
        }
 
7527
        HTList_delete(Goto_URLs);
 
7528
        Goto_URLs = NULL;
 
7529
    }
 
7530
}
 
7531
#endif
 
7532
 
 
7533
/*
 
7534
 *  Utility for listing Goto URLs, making any
 
7535
 *  repeated URLs the most current in the list. - FM
 
7536
 */
 
7537
PUBLIC void HTAddGotoURL ARGS1(
 
7538
        char *,         url)
 
7539
{
 
7540
    char *new = NULL;
 
7541
    char *old;
 
7542
    HTList *cur;
 
7543
 
 
7544
    if (!(url && *url))
 
7545
        return;
 
7546
 
 
7547
    CTRACE((tfp, "HTAddGotoURL %s\n", url));
 
7548
    StrAllocCopy(new, url);
 
7549
 
 
7550
    if (!Goto_URLs) {
 
7551
        Goto_URLs = HTList_new();
 
7552
#ifdef LY_FIND_LEAKS
 
7553
        atexit(HTGotoURLs_free);
 
7554
#endif
 
7555
        HTList_addObject(Goto_URLs, new);
 
7556
        return;
 
7557
    }
 
7558
 
 
7559
    cur = Goto_URLs;
 
7560
    while (NULL != (old = (char *)HTList_nextObject(cur))) {
 
7561
        if (!strcmp(old, new)) {
 
7562
            HTList_removeObject(Goto_URLs, old);
 
7563
            FREE(old);
 
7564
            break;
 
7565
        }
 
7566
    }
 
7567
    HTList_addObject(Goto_URLs, new);
 
7568
 
 
7569
    return;
 
7570
}
 
7571
 
 
7572
/*
 
7573
 *  When help is not on the screen,
 
7574
 *  put a message on the screen
 
7575
 *  to tell the user other misc info.
 
7576
 */
 
7577
PRIVATE void show_main_statusline ARGS2(
 
7578
    CONST LinkInfo,     curlink,
 
7579
    int,                for_what)
 
7580
{
 
7581
    /*
 
7582
     *  Make sure form novice lines are replaced.
 
7583
     */
 
7584
    if (user_mode == NOVICE_MODE && for_what != FOR_INPUT) {
 
7585
        noviceline(more);
 
7586
    }
 
7587
 
 
7588
    if (HTisDocumentSource()) {
 
7589
        /*
 
7590
         *  Currently displaying HTML source.
 
7591
         */
 
7592
        _statusline(SOURCE_HELP);
 
7593
 
 
7594
    /*
 
7595
     *  If we are in forms mode then explicitly
 
7596
     *  tell the user what each kind of link is.
 
7597
     */
 
7598
#ifdef INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE
 
7599
    } else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0) {
 
7600
#else
 
7601
#ifdef NORMAL_NON_FORM_LINK_STATUSLINES_FOR_ALL_USER_MODES
 
7602
    } else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0 &&
 
7603
               !(curlink.type & WWW_LINK_TYPE)) {
 
7604
#else
 
7605
    } else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0 &&
 
7606
               !(user_mode == ADVANCED_MODE &&
 
7607
                 (curlink.type & WWW_LINK_TYPE))) {
 
7608
#endif /* NORMAL_NON_FORM_LINK_STATUSLINES_FOR_ALL_USER_MODES */
 
7609
#endif /* INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE */
 
7610
        if (curlink.type == WWW_FORM_LINK_TYPE) {
 
7611
            show_formlink_statusline(curlink.l_form, for_what);
 
7612
        } else {
 
7613
            statusline(NORMAL_LINK_MESSAGE);
 
7614
        }
 
7615
 
 
7616
        /*
 
7617
         *  Let them know if it's an index -- very rare.
 
7618
         */
 
7619
        if (is_www_index) {
 
7620
            char *indx = gettext("-index-");
 
7621
            LYmove(LYlines-1, LYcols - strlen(indx) - 1);
 
7622
            lynx_start_reverse();
 
7623
            LYaddstr(indx);
 
7624
            lynx_stop_reverse();
 
7625
        }
 
7626
 
 
7627
    } else if (user_mode == ADVANCED_MODE && nlinks > 0) {
 
7628
        /*
 
7629
         *  Show the URL or, for some internal links, the fragment
 
7630
         */
 
7631
        char *cp = NULL;
 
7632
 
 
7633
        if (curlink.type == WWW_INTERN_LINK_TYPE &&
 
7634
            !isLYNXIMGMAP(curlink.lname)) {
 
7635
            cp = findPoundSelector(curlink.lname);
 
7636
        }
 
7637
        if (!cp)
 
7638
            cp = curlink.lname;
 
7639
        status_link(cp, more, is_www_index);
 
7640
    } else if (is_www_index && more) {
 
7641
        char buf[128];
 
7642
 
 
7643
        sprintf(buf, WWW_INDEX_MORE_MESSAGE, key_for_func(LYK_INDEX_SEARCH));
 
7644
        _statusline(buf);
 
7645
    } else if (is_www_index) {
 
7646
        char buf[128];
 
7647
 
 
7648
        sprintf(buf, WWW_INDEX_MESSAGE, key_for_func(LYK_INDEX_SEARCH));
 
7649
        _statusline(buf);
 
7650
    } else if (more) {
 
7651
        if (user_mode == NOVICE_MODE)
 
7652
            _statusline(MORE);
 
7653
        else
 
7654
            _statusline(MOREHELP);
 
7655
    } else {
 
7656
        _statusline(HELP);
 
7657
    }
 
7658
 
 
7659
    /* turn off cursor since now it's probably on statusline -HV */
 
7660
    /* But not if LYShowCursor is on.  -show_cursor may be used as a
 
7661
     * workaround to avoid putting the cursor in the last position, for
 
7662
     * curses implementations or terminals that cannot deal with that
 
7663
     * correctly. - kw */
 
7664
    if (!LYShowCursor) {
 
7665
        LYHideCursor();
 
7666
    }
 
7667
}
 
7668
 
 
7669
/*
 
7670
 *  Public function for redrawing the statusline appropriate for the
 
7671
 *  selected link.  It should only be called at times when curdoc.link,
 
7672
 *  nlinks, and the links[] array are valid. - kw
 
7673
 */
 
7674
PUBLIC void repaint_main_statusline ARGS1(
 
7675
    int,        for_what)
 
7676
{
 
7677
    if (curdoc.link >= 0 && curdoc.link < nlinks)
 
7678
        show_main_statusline(links[curdoc.link], for_what);
 
7679
}
 
7680
 
 
7681
PRIVATE void form_noviceline ARGS1(
 
7682
    int,        disabled)
 
7683
{
 
7684
    LYmove(LYlines-2,0); LYclrtoeol();
 
7685
    if (!disabled) {
 
7686
        LYaddstr(FORM_NOVICELINE_ONE);
 
7687
    }
 
7688
    LYmove(LYlines-1,0); LYclrtoeol();
 
7689
    if (disabled)
 
7690
        return;
 
7691
    if (EditBinding(FROMASCII('\025')) == LYE_ERASE) {
 
7692
        LYaddstr(FORM_NOVICELINE_TWO);
 
7693
    } else if (EditBinding(FROMASCII('\025')) == LYE_DELBL) {
 
7694
        LYaddstr(FORM_NOVICELINE_TWO_DELBL);
 
7695
    } else {
 
7696
        char *temp = NULL;
 
7697
        char *erasekey = fmt_keys(LYKeyForEditAction(LYE_ERASE), -1);
 
7698
        if (erasekey) {
 
7699
            HTSprintf0(&temp, FORM_NOVICELINE_TWO_VAR, erasekey);
 
7700
        } else {
 
7701
            erasekey = fmt_keys(LYKeyForEditAction(LYE_DELBL), -1);
 
7702
            if (erasekey)
 
7703
                HTSprintf0(&temp,
 
7704
                           FORM_NOVICELINE_TWO_DELBL_VAR, erasekey);
 
7705
        }
 
7706
        if (temp) {
 
7707
            LYaddstr(temp);
 
7708
            FREE(temp);
 
7709
        }
 
7710
        FREE(erasekey);
 
7711
    }
 
7712
}
 
7713
 
 
7714
PRIVATE void exit_immediately_with_error_message ARGS2(
 
7715
        int,            state,
 
7716
        BOOLEAN,        first_file)
 
7717
{
 
7718
    char *buf = 0;
 
7719
    char *buf2 = 0;
 
7720
 
 
7721
    if (first_file) {
 
7722
        /* print statusline messages as a hint, if any */
 
7723
        LYstatusline_messages_on_exit(&buf2);
 
7724
    }
 
7725
 
 
7726
    if (state == NOT_FOUND)
 
7727
    {
 
7728
        HTSprintf0(&buf, "%s\n%s %s\n",
 
7729
                   NonNull(buf2),
 
7730
                   gettext("lynx: Can't access startfile"),
 
7731
                   /*
 
7732
                    * hack: if we fail in HTAccess.c
 
7733
                    * avoid duplicating URL, oh.
 
7734
                    */
 
7735
                   (buf2 && strstr(buf2, gettext("Can't Access"))) ?
 
7736
                                                               "" : startfile);
 
7737
    }
 
7738
 
 
7739
    if (state == NULLFILE)
 
7740
    {
 
7741
        HTSprintf0(&buf, "%s\n%s\n%s\n",
 
7742
                   NonNull(buf2),
 
7743
                   gettext("lynx: Start file could not be found or is not text/html or text/plain"),
 
7744
                   gettext("      Exiting..."));
 
7745
    }
 
7746
 
 
7747
    FREE(buf2);
 
7748
 
 
7749
    if (!dump_output_immediately)
 
7750
        cleanup();
 
7751
 
 
7752
#ifdef UNIX
 
7753
    if (dump_output_immediately) {
 
7754
        fputs(buf, stderr);
 
7755
    } else
 
7756
#endif /* UNIX */
 
7757
    {
 
7758
        SetOutputMode( O_TEXT );
 
7759
        fputs(buf, stdout);
 
7760
        SetOutputMode( O_BINARY );
 
7761
    }
 
7762
 
 
7763
    FREE(buf);
 
7764
 
 
7765
    if (!dump_output_immediately) {
 
7766
        exit_immediately(EXIT_FAILURE);
 
7767
    }
 
7768
    /* else: return(EXIT_FAILURE) in mainloop */
 
7769
}
 
7770
 
 
7771
 
 
7772
PRIVATE void status_link ARGS3(
 
7773
        char *,         curlink_name,
 
7774
        BOOLEAN,        show_more,
 
7775
        BOOLEAN,        show_indx)
 
7776
{
 
7777
#define MAX_STATUS (LYcols - 2)
 
7778
#define MIN_STATUS 0
 
7779
    char format[MAX_LINE];
 
7780
    int prefix = 0;
 
7781
    int length;
 
7782
 
 
7783
    *format = 0;
 
7784
    if (show_more) {
 
7785
        sprintf(format, "%.*s ",
 
7786
                (int)(sizeof(format) - 2),
 
7787
                gettext("-more-"));
 
7788
        prefix = strlen(format);
 
7789
    }
 
7790
    if (show_indx) {
 
7791
        sprintf(format + prefix, "%.*s ",
 
7792
                (int)(sizeof(format) - prefix - 2),
 
7793
                gettext("-index-"));
 
7794
    }
 
7795
    prefix = strlen(format);
 
7796
    length = strlen(curlink_name);
 
7797
 
 
7798
    if (prefix > MAX_STATUS || prefix >= MAX_LINE - 1) {
 
7799
        _user_message("%s", format);    /* no room for url */
 
7800
    } else {
 
7801
        sprintf(format + prefix, "%%.%ds", MAX_STATUS - prefix);
 
7802
 
 
7803
        if ((length + prefix > MAX_STATUS) && long_url_ok) {
 
7804
            char *buf = NULL;
 
7805
            int cut_from_pos;
 
7806
            int cut_to_pos;
 
7807
            int n;
 
7808
 
 
7809
            StrAllocCopy(buf, curlink_name);
 
7810
            /*
 
7811
             *  Scan to find the final leaf of the URL.
 
7812
             *  Ignore trailing '/'.
 
7813
             */
 
7814
            for (cut_to_pos = length - 2;
 
7815
                 (cut_to_pos > 0) && (buf[cut_to_pos] != '/');
 
7816
                 cut_to_pos--)
 
7817
                 ;
 
7818
            /*
 
7819
             *  Jump back to the next leaf to remove.
 
7820
             */
 
7821
            for (cut_from_pos = cut_to_pos - 4;
 
7822
                 (cut_from_pos > 0) && ((buf[cut_from_pos] != '/')
 
7823
                 || (prefix + cut_from_pos + 4 + (length - cut_to_pos) >= MAX_STATUS));
 
7824
                 cut_from_pos--)
 
7825
                 ;
 
7826
            /*
 
7827
             *  Replace some leaves to '...', if possible, and put the
 
7828
             *  final leaf at the end. We assume that one can recognize
 
7829
             *  the link from at least MIN_STATUS characters.
 
7830
             */
 
7831
            if (cut_from_pos > MIN_STATUS) {
 
7832
                for (n = 1; n <= 3; n++)
 
7833
                    buf[cut_from_pos + n] = '.';
 
7834
                for (n = 0; cut_to_pos + n <= length; n++)
 
7835
                    buf[cut_from_pos + 4 + n] = buf[cut_to_pos + n];
 
7836
            }
 
7837
            _user_message(format, buf);
 
7838
            CTRACE((tfp,"lastline = %s\n",buf)); /* don't forget to erase me */
 
7839
            FREE(buf);
 
7840
        } else {        /* show (possibly truncated) url */
 
7841
            _user_message(format, curlink_name);
 
7842
        }
 
7843
    }
 
7844
}
 
7845
 
 
7846
PUBLIC char*
 
7847
LYDownLoadAddress NOARGS
 
7848
{
 
7849
    char *s = newdoc.address ? newdoc.address : "";
 
7850
    return s;
 
7851
}