#include <HTUtils.h>
#include <HTAccess.h>
#include <HTParse.h>
#include <HTList.h>
#include <HTML.h>
#include <HTFTP.h>
#include <HTFile.h>
#include <HTTP.h>
#include <HTAABrow.h>
#include <HTNews.h>
#include <LYCurses.h>
#include <LYStyle.h>
#include <LYGlobalDefs.h>
#include <HTAlert.h>
#include <LYUtils.h>
#include <GridText.h>
#include <LYStrings.h>
#include <LYOptions.h>
#include <LYSignal.h>
#include <LYGetFile.h>
#include <HTForms.h>
#include <LYSearch.h>
#include <LYClean.h>
#include <LYHistory.h>
#include <LYPrint.h>
#include <LYMail.h>
#include <LYEdit.h>
#include <LYShowInfo.h>
#include <LYBookmark.h>
#include <LYKeymap.h>
#include <LYJump.h>
#include <LYDownload.h>
#include <LYList.h>
#include <LYMap.h>
#include <LYTraversal.h>
#include <LYCharSets.h>
#include <LYCharUtils.h>
#include <LYCookie.h>
#include <LYMainLoop.h>
#include <LYPrettySrc.h>
#ifdef USE_EXTERNALS
#include <LYExtern.h>
#endif
#ifdef __EMX__
#include <io.h>
#endif
#ifdef DIRED_SUPPORT
#include <LYLocal.h>
#include <LYUpload.h>
#endif /* DIRED_SUPPORT */
#include <LYexit.h>
#include <LYLeaks.h>
PRIVATE void exit_immediately_with_error_message PARAMS((int state, BOOLEAN first_file));
PRIVATE void show_main_statusline PARAMS((CONST linkstruct curlink));
PRIVATE BOOL confirm_post_resub PARAMS((
CONST char* address,
CONST char* title,
int if_imgmap,
int if_file));
PRIVATE int are_different PARAMS((document *doc1, document *doc2));
#ifndef DONT_TRACK_INTERNAL_LINKS
PRIVATE int are_phys_different PARAMS((document *doc1, document *doc2));
#endif
#define FASTTAB
PRIVATE int sametext ARGS2(
char *, een,
char *, twee)
{
if (een && twee)
return (strcmp(een, twee) == 0);
return TRUE;
}
PUBLIC HTList * Goto_URLs = NULL; /* List of Goto URLs */
PUBLIC char * LYRequestTitle = NULL; /* newdoc.title in calls to getfile() */
#ifdef DISP_PARTIAL
PUBLIC int Newline_partial = 0; /* required for display_partial mode */
PUBLIC int NumOfLines_partial = -1; /* initialize to -1 the very first time */
PUBLIC BOOLEAN display_partial = FALSE;
PUBLIC int Newline = 0;
#else
PRIVATE int Newline = 0;
#endif
PRIVATE document newdoc;
PRIVATE document curdoc;
PRIVATE char *traversal_host = NULL;
PRIVATE char *traversal_link_to_add = NULL;
#ifdef LY_FIND_LEAKS
/*
* Function for freeing allocated mainloop() variables. - FM
*/
PRIVATE void free_mainloop_variables NOARGS
{
FREE(newdoc.title);
FREE(newdoc.address);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
FREE(curdoc.title);
FREE(curdoc.address);
FREE(curdoc.post_data);
FREE(curdoc.post_content_type);
FREE(curdoc.bookmark);
#ifdef USE_HASH
FREE(curdoc.style);
FREE(newdoc.style);
#endif
FREE(traversal_host);
FREE(traversal_link_to_add);
#ifdef DIRED_SUPPORT
clear_tags();
#endif /* DIRED_SUPPORT */
return;
}
#endif /* LY_FIND_LEAKS */
PUBLIC FILE *TraceFP NOARGS
{
if (LYTraceLogFP != 0) {
return LYTraceLogFP;
}
return stderr;
}
PRIVATE void TracelogOpenFailed NOARGS
{
WWW_TraceFlag = FALSE;
if (LYCursesON) {
HTUserMsg(TRACELOG_OPEN_FAILED);
} else {
fprintf(stderr, "%s\n", TRACELOG_OPEN_FAILED);
exit(-1);
}
}
PUBLIC BOOLEAN LYOpenTraceLog NOARGS
{
if (TRACE && LYUseTraceLog && LYTraceLogFP == NULL) {
/*
* If we can't open it for writing, give up. Otherwise, on VMS close
* it, delete it and any versions from previous sessions so they don't
* accumulate, and open it again. - FM
*/
if ((LYTraceLogFP = LYNewTxtFile(LYTraceLogPath)) == NULL) {
TracelogOpenFailed();
return FALSE;
}
#ifdef VMS
LYCloseTracelog();
HTSYS_remove(LYTraceLogPath);
if ((LYTraceLogFP = LYNewTxtFile(LYTraceLogPath)) == NULL) {
TracelogOpenFailed();
return FALSE;
}
#endif /* VMS */
fflush(stdout);
fflush(stderr);
fprintf(tfp, "\t\t%s (%s)\n\n", LYNX_TRACELOG_TITLE, LYNX_VERSION);
/*
* If TRACE is on, indicate whether the
* anonymous restrictions are set. - FM, LP, kw
* This is only a summary for convenience - it doesn't
* take the case of individual -restrictions= options
* into account. - kw
*/
if (LYValidate) {
if (LYRestricted && had_restrictions_default) {
CTRACE(tfp, "Validate and some anonymous restrictions are set.\n");
} else if (had_restrictions_default) {
CTRACE(tfp, "Validate restrictions set, restriction \"default\" was given.\n");
} else if (LYRestricted) {
CTRACE(tfp, "Validate restrictions set, additional anonymous restrictions ignored.\n");
} else {
CTRACE(tfp, "Validate restrictions are set.\n");
}
/* But none of the above can actually happen, since there should
* never be a Trace Log with -validate. If it appears in a log
* file something went wrong! */
} else if (LYRestricted) {
if (had_restrictions_all) {
CTRACE(tfp, "Anonymous restrictions set, restriction \"all\" was given.\n");
} else {
CTRACE(tfp, "Anonymous restrictions are set.\n");
}
} else if (had_restrictions_all && had_restrictions_default) {
CTRACE(tfp, "Restrictions \"all\" and \"default\" were given.\n");
} else if (had_restrictions_default) {
CTRACE(tfp, "Restriction \"default\" was given.\n");
} else if (had_restrictions_all) {
CTRACE(tfp, "\"all\" restrictions are set.\n");
}
}
return TRUE;
}
PUBLIC void LYCloseTracelog NOARGS
{
if (LYTraceLogFP != 0) {
fflush(stdout);
fflush(stderr);
fclose(LYTraceLogFP);
LYTraceLogFP = 0;
}
}
PRIVATE BOOLEAN LYReopenTracelog ARGS1(BOOLEAN *, trace_flag_ptr)
{
CTRACE(tfp, "\nTurning off TRACE for fetch of log.\n");
LYCloseTracelog();
if ((LYTraceLogFP = LYAppendToTxtFile(LYTraceLogPath)) == NULL) {
TracelogOpenFailed();
return FALSE;
}
if (TRACE) {
WWW_TraceFlag = FALSE;
*trace_flag_ptr = TRUE;
}
return TRUE;
}
PRIVATE int do_change_link ARGS1(
char *, prev_target)
{
/* Is there a mouse-clicked link waiting? */
int mouse_tmp = get_mouse_link();
/* If yes, use it as the link */
if (mouse_tmp != -1) {
if (curdoc.link >= 0 && curdoc.link < nlinks &&
curdoc.link != mouse_tmp) {
highlight(OFF, curdoc.link, prev_target);
}
if (mouse_tmp < 0 || mouse_tmp >= nlinks) {
char *msgtmp = NULL;
HTSprintf0(&msgtmp,
gettext("Internal error: Invalid mouse link %d!"),
mouse_tmp);
HTAlert(msgtmp);
FREE(msgtmp);
return(-1); /* indicates unexpected error */
}
curdoc.link = mouse_tmp;
}
return(0); /* indicates OK */
}
/*
* Here's where we do all the work.
* mainloop is basically just a big switch dependent on the users input.
* I have tried to offload most of the work done here to procedures to
* make it more modular, but this procedure still does a lot of variable
* manipulation. This needs some work to make it neater. - Lou Moutilli
* (memoir from the original Lynx - FM)
*/
int mainloop NOARGS
{
int c = 0, real_c = 0, old_c = 0;
int cmd = LYK_DO_NOTHING, real_cmd = LYK_DO_NOTHING;
int getresult;
int arrowup = FALSE, show_help = FALSE;
char prev_target[512];
char user_input_buffer[1024];
char *owner_address = NULL; /* Holds the responsible owner's address */
char *ownerS_address = NULL; /* Holds owner's address during source fetch */
CONST char *cshelpfile = NULL;
BOOLEAN first_file = TRUE;
BOOLEAN popped_doc = FALSE;
BOOLEAN refresh_screen = FALSE;
BOOLEAN force_load = FALSE;
BOOLEAN try_internal = FALSE;
BOOLEAN crawl_ok = FALSE;
BOOLEAN rlink_exists;
BOOLEAN rlink_allowed;
BOOLEAN vi_keys_flag = vi_keys;
BOOLEAN emacs_keys_flag = emacs_keys;
BOOLEAN trace_mode_flag = FALSE;
BOOLEAN forced_HTML_mode = LYforce_HTML_mode;
char cfile[128];
FILE *cfp;
char *cp, *toolbar;
int ch, recall;
int URLTotal;
int URLNum;
BOOLEAN FirstURLRecall = TRUE;
char *temp = NULL;
BOOLEAN ForcePush = FALSE;
BOOLEAN override_LYresubmit_posts = FALSE;
unsigned int len;
int i;
int n;
#ifdef DIRED_SUPPORT
char *tp = NULL;
struct stat dir_info;
#endif /* DIRED_SUPPORT */
/*
* curdoc.address contains the name of the file that is currently open.
* newdoc.address contains the name of the file that will soon be
* opened if it exits.
* prev_target contains the last search string the user searched for.
* newdoc.title contains the link name that the user last chose to get
* into the current link (file).
*/
/* initialize some variables*/
newdoc.address = NULL;
newdoc.title = NULL;
newdoc.post_data = NULL;
newdoc.post_content_type = NULL;
newdoc.bookmark = NULL;
newdoc.internal_link = FALSE;
curdoc.address = NULL;
curdoc.title = NULL;
curdoc.post_data = NULL;
curdoc.post_content_type = NULL;
curdoc.bookmark = NULL;
curdoc.internal_link = FALSE;
#ifdef USE_HASH
curdoc.style = NULL;
newdoc.style = NULL;
#endif
nhist = 0;
user_input_buffer[(sizeof(user_input_buffer) - 1)] = '\0';
*prev_target = '\0';
*user_input_buffer = '\0';
#ifdef LY_FIND_LEAKS
atexit(free_mainloop_variables);
#endif
initialize:
StrAllocCopy(newdoc.address, startfile);
StrAllocCopy(startrealm, startfile);
StrAllocCopy(newdoc.title, gettext("Entry into main screen"));
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.line = 1;
newdoc.link = 0;
#ifdef USE_SLANG
if (TRACE && LYCursesON) {
addstr("\n");
refresh();
}
#endif /* USE_SLANG */
CTRACE(tfp,"Entering mainloop, startfile=%s\n",startfile);
if (form_post_data) {
StrAllocCopy(newdoc.post_data, form_post_data);
StrAllocCopy(newdoc.post_content_type,
"application/x-www-form-urlencoded");
} else if (form_get_data) {
StrAllocCat(newdoc.address, form_get_data);
}
if (bookmark_start) {
if (LYValidate) {
HTAlert(BOOKMARKS_DISABLED);
bookmark_start = FALSE;
goto initialize;
} else if (traversal) {
HTAlert(BOOKMARKS_NOT_TRAVERSED);
traversal = FALSE;
crawl = FALSE;
bookmark_start = FALSE;
goto initialize;
} else {
/*
* See if a bookmark page exists. If it does,
* replace newdoc.address with it's name
*/
if ((cp = get_bookmark_filename(&newdoc.address)) != NULL &&
*cp != '\0' && strcmp(cp, " ")) {
StrAllocCopy(newdoc.title, BOOKMARK_TITLE);
StrAllocCopy(newdoc.bookmark, BookmarkPage);
StrAllocCopy(startrealm, newdoc.address);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
CTRACE(tfp, "Using bookmarks=%s\n", newdoc.address);
} else {
HTUserMsg(BOOKMARKS_NOT_OPEN);
bookmark_start = FALSE;
goto initialize;
}
}
}
FREE(form_post_data);
FREE(form_get_data);
if (user_mode == NOVICE_MODE)
display_lines = LYlines-4;
else
display_lines = LYlines-2;
while (TRUE) {
#ifdef USE_HASH
if (curdoc.style != NULL) force_load = TRUE;
#endif
/*
* If newdoc.address is different then curdoc.address then
* we need to go out and find and load newdoc.address.
*/
if (LYforce_no_cache || force_load ||
are_different(&curdoc, &newdoc)) {
force_load = FALSE; /* done */
if (TRACE && LYCursesON) {
move(LYlines-1, LYcols-1); /* make sure cursor is down */
#ifdef USE_SLANG
addstr("\n");
#endif /* USE_SLANG */
refresh();
}
try_again:
/*
* Push the old file onto the history stack if we
* have a current doc and a new address. - FM
*/
if (curdoc.address && newdoc.address) {
/*
* Don't actually push if this is a LYNXDOWNLOAD
* URL, because that returns NORMAL even if it
* fails due to a spoof attempt or file access
* problem, and we set the newdoc structure
* elements to the curdoc structure elements
* under case NORMAL. - FM
*/
if (strncmp(newdoc.address, "LYNXDOWNLOAD:", 13))
{
LYpush(&curdoc, ForcePush);
}
} else if (!newdoc.address) {
/*
* If newdoc.address is empty then pop a file
* and load it. - FM
*/
LYpop(&newdoc);
popped_doc = TRUE;
#ifndef DONT_TRACK_INTERNAL_LINKS
#define NO_INTERNAL_OR_DIFFERENT(c,n) TRUE
#define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) (!curdoc.internal_link || \
are_phys_different(p,n))
#else /* TRACK_INTERNAL_LINKS */
#define NO_INTERNAL_OR_DIFFERENT(c,n) are_different(c,n)
#define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) are_different(p,n)
#endif /* TRACK_INTERNAL_LINKS */
#ifndef DONT_TRACK_INTERNAL_LINKS
/*
** If curdoc had been reached via an internal
** (fragment) link from what we now have just
** popped into newdoc, then override non-caching in
** all cases. - kw
*/
if (curdoc.internal_link &&
!are_phys_different(&curdoc, &newdoc)) {
LYinternal_flag = TRUE;
LYoverride_no_cache = TRUE;
LYforce_no_cache = FALSE;
try_internal = TRUE;
} else
#endif /* TRACK_INTERNAL_LINKS */
/*
* Force a no_cache override unless
* it's a bookmark file, or it has POST content
* and LYresubmit_posts is set without safe also
* set, and we are not going to another position
* in the current document or restoring the previous
* document due to a NOT_FOUND or NULLFILE return
* value from getfile(). - FM
*/
if ((newdoc.bookmark != NULL) ||
(newdoc.post_data != NULL &&
!newdoc.safe &&
LYresubmit_posts &&
!override_LYresubmit_posts &&
NO_INTERNAL_OR_DIFFERENT(&curdoc, &newdoc))) {
LYoverride_no_cache = FALSE;
} else {
LYoverride_no_cache = TRUE;
}
}
override_LYresubmit_posts = FALSE;
if (HEAD_request) {
/*
* Make SURE this is an appropriate request. - FM
*/
if (newdoc.address) {
if (LYCanDoHEAD(newdoc.address) == TRUE) {
newdoc.isHEAD = TRUE;
} else if (!strncmp(newdoc.address, "LYNXIMGMAP:", 11)) {
if (LYCanDoHEAD(newdoc.address + 11) == TRUE) {
StrAllocCopy(temp, newdoc.address + 11);
FREE(newdoc.address);
newdoc.address = temp;
newdoc.isHEAD = TRUE;
temp = NULL;
}
}
}
try_internal = FALSE;
HEAD_request = FALSE;
}
/*
* If we're getting the TRACE log and it's not new,
* check whether its HText structure has been dumped,
* and if so, fflush() and fclose() it to ensure it's
* fully updated, and then fopen() it again. - FM
*/
if (LYUseTraceLog == TRUE &&
trace_mode_flag == FALSE &&
LYTraceLogFP != NULL &&
!strcmp((newdoc.title ? newdoc.title : ""),
LYNX_TRACELOG_TITLE)) {
DocAddress WWWDoc;
HTParentAnchor *tmpanchor;
WWWDoc.address = newdoc.address;
WWWDoc.post_data = newdoc.post_data;
WWWDoc.post_content_type = newdoc.post_content_type;
WWWDoc.bookmark = newdoc.bookmark;
WWWDoc.isHEAD = newdoc.isHEAD;
WWWDoc.safe = newdoc.safe;
tmpanchor = HTAnchor_parent(HTAnchor_findAddress(&WWWDoc));
if ((HText *)HTAnchor_document(tmpanchor) == NULL) {
if (!LYReopenTracelog(&trace_mode_flag)) {
old_c = 0;
cmd = LYK_PREV_DOC;
goto new_cmd;
}
}
}
LYRequestTitle = newdoc.title;
if (newdoc.bookmark)
LYforce_HTML_mode = TRUE;
if (LYValidate &&
startfile_ok &&
newdoc.address && startfile && homepage &&
(!strcmp(newdoc.address, startfile) ||
!strcmp(newdoc.address, homepage))) {
LYPermitURL = TRUE;
}
Newline = newdoc.line; /* bypass for partial mode */
#ifdef DISP_PARTIAL
display_partial = display_partial_flag; /* restore */
Newline_partial = Newline; /* initialize */
/*
* Disable display_partial if requested URL has #fragment
* and we are not popped from the history stack
* so can't calculate correct newline position for fragment.
* Otherwise user got the new document from the first page
* and be moved to #fragment later after download
* completed, but only if s/he did not mess screen up by
* scrolling before... So fall down to old behavior here.
*/
if (Newline_partial == 1 && strchr(newdoc.address, '#'))
display_partial = FALSE;
#endif /* DISP_PARTIAL */
#ifdef USE_PSRC
psrc_first_tag = TRUE;
#endif
#ifndef DONT_TRACK_INTERNAL_LINKS
if (try_internal) {
if (newdoc.address &&
0==strncmp(newdoc.address, "LYNXIMGMAP:", 11)) {
try_internal = FALSE;
} else if (curdoc.address &&
0==strncmp(curdoc.address, "LYNXIMGMAP:", 11)) {
try_internal = FALSE;
}
}
if (try_internal) {
char *hashp = strchr(newdoc.address,'#');
if (hashp) {
HTFindPoundSelector(hashp+1);
}
getresult = (HTMainText != NULL) ? NORMAL : NOT_FOUND;
try_internal = FALSE; /* done */
/* fix up newdoc.address which may have been fragment-only */
if (getresult == NORMAL && (!hashp || hashp == newdoc.address)) {
if (!hashp) {
StrAllocCopy(newdoc.address, HTLoadedDocumentURL());
} else {
StrAllocCopy(temp, HTLoadedDocumentURL());
StrAllocCat(temp, hashp); /* append fragment */
StrAllocCopy(newdoc.address, temp);
FREE(temp);
}
}
} else {
if (newdoc.internal_link && newdoc.address &&
*newdoc.address == '#' && nhist > 0) {
char *cp0;
if (0==strncmp(history[nhist-1].address, "LYNXIMGMAP:", 11))
cp0 = history[nhist-1].address + 11;
else
cp0 = history[nhist-1].address;
StrAllocCopy(temp, cp0);
cp0 = strchr(temp, '#');
if (cp0)
*cp0 = '\0';
StrAllocCat(temp, newdoc.address);
FREE(newdoc.address);
newdoc.address = temp;
temp = NULL;
}
getresult = getfile(&newdoc);
}
#else /* TRACK_INTERNAL_LINKS */
getresult = getfile(&newdoc);
#endif /* TRACK_INTERNAL_LINKS */
switch(getresult) {
case NOT_FOUND:
/*
* OK! can't find the file, so it must not be around now.
* Do any error logging, if appropriate.
*/
LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */
LYinternal_flag = FALSE; /* Reset to default. - kw */
if (trace_mode_flag == TRUE) {
WWW_TraceFlag = TRUE;
trace_mode_flag = FALSE;
fprintf(tfp, "Turning TRACE back on.\n\n");
}
if (!first_file && !LYCancelledFetch) {
/*
* Do error mail sending and/or traversal
* stuff. Note that the links[] elements may
* not be valid at this point, if we did call
* HTuncache_current_document! This should
* not have happened for traversal, but for
* sending error mail check that HTMainText
* exists for this reason. - kw
*/
if (error_logging && nhist > 0 && !popped_doc &&
!LYUserSpecifiedURL &&
HTMainText &&
nlinks > 0 && curdoc.link < nlinks &&
strncmp(newdoc.address ? newdoc.address : "",
"LYNXHIST:", 9) &&
strncmp(newdoc.address ? newdoc.address : "",
"LYNXCOOKIE:", 11)) {
char *mail_owner = NULL;
if (owner_address &&
strncasecomp(owner_address, "mailto:", 7)) {
mail_owner = owner_address + 7;
}
/*
* Email a bad link message to the owner of
* the document, or to ALERTMAIL if defined,
* but NOT to lynx-dev (it is rejected in
* mailmsg). - FM, kw
*/
#ifndef ALERTMAIL
if (mail_owner)
#endif
mailmsg(curdoc.link,
mail_owner,
history[nhist-1].address,
history[nhist-1].title);
}
if (traversal) {
FILE *ofp;
if ((ofp = LYAppendToTxtFile(TRAVERSE_ERRORS)) == NULL) {
if ((ofp = LYNewTxtFile(TRAVERSE_ERRORS)) == NULL) {
perror(NOOPEN_TRAV_ERR_FILE);
exit_immediately(-1);
}
}
if (nhist > 0) {
fprintf(ofp,
"%s %s\tin %s\n",
popped_doc ?
newdoc.address : links[curdoc.link].lname,
links[curdoc.link].target,
history[nhist-1].address);
} else {
fprintf(ofp,
"%s %s\t\n",
popped_doc ?
newdoc.address : links[curdoc.link].lname,
links[curdoc.link].target);
}
fclose(ofp);
}
}
/*
* Fall through to do the NULL stuff and reload the
* old file, unless the first file wasn't found or
* has gone missing.
*/
if (!nhist) {
/*
* If nhist = 0 then it must be the first file.
*/
exit_immediately_with_error_message(NOT_FOUND, first_file);
return(-1);
}
case NULLFILE:
/*
* Not supposed to return any file.
*/
LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */
popped_doc = FALSE; /* Was TRUE if popped. - FM */
LYinternal_flag = FALSE; /* Reset to default. - kw */
if (trace_mode_flag == TRUE) {
WWW_TraceFlag = TRUE;
trace_mode_flag = FALSE;
fprintf(tfp, "Turning TRACE back on.\n\n");
}
FREE(newdoc.address); /* to pop last doc */
FREE(newdoc.bookmark);
LYJumpFileURL = FALSE;
reloading = FALSE;
LYPermitURL = FALSE;
LYCancelledFetch = FALSE;
ForcePush = FALSE;
LYforce_HTML_mode = FALSE;
if (traversal) {
crawl_ok = FALSE;
if (traversal_link_to_add) {
/*
* It's a binary file, or the fetch attempt
* failed. Add it to TRAVERSE_REJECT_FILE
* so we don't try again in this run.
*/
if (!lookup_reject(traversal_link_to_add)) {
add_to_reject_list(traversal_link_to_add);
}
FREE(traversal_link_to_add);
}
}
/*
* Make sure the first file was found and
* has not gone missing.
*/
if (!nhist) {
/*
* If nhist = 0 then it must be the first file.
*/
if (first_file && homepage &&
#ifdef VMS
strcasecomp(homepage, startfile) != 0
#else
strcmp(homepage, startfile) != 0
#endif /* VMS */
) {
/*
* Couldn't return to the first file but there is a
* homepage we can use instead. Useful for when the
* first URL causes a program to be invoked. - GL
*
* But first make sure homepage is different from
* startfile (above), then make it the same (below)
* so we don't enter an infinite getfile() loop on
* on failures to find the files. - FM
*/
StrAllocCopy(newdoc.address, homepage);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
StrAllocCopy(startfile, homepage);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
goto try_again;
} else {
exit_immediately_with_error_message(NULLFILE, first_file);
return(-1);
}
}
/*
* If we're going to pop from history because
* getfile didn't succeed, reset LYforce_no_cache
* first. This would have been done in HTAccess.c
* if the request got that far, but the URL may
* have been handled or rejected in getfile without
* taking care of that. - kw
*/
LYforce_no_cache = FALSE;
/*
* Retrieval of a newdoc just failed, and just
* going to try_again would pop the next doc
* from history and try to get it without further
* questions. This may not be the right thing to do if
* we have POST data, so fake a PREV_DOC key if it seems
* that some prompting should be done. This doesn't
* affect the traversal logic, since with traversal
* POST data can never occur. - kw
*/
if (history[nhist - 1].post_data &&
!history[nhist - 1].safe) {
if (HText_POSTReplyLoaded((document *)&history[(nhist - 1)])) {
override_LYresubmit_posts = TRUE;
goto try_again;
}
/* Set newdoc fields, just in case the PREV_DOC
* gets cancelled. - kw */
if (!curdoc.address) {
StrAllocCopy(newdoc.address, HTLoadedDocumentURL());
StrAllocCopy(newdoc.title, HTLoadedDocumentTitle());
if (HTMainAnchor && HTMainAnchor->post_data) {
StrAllocCopy(newdoc.post_data,
HTMainAnchor->post_data);
StrAllocCopy(newdoc.post_content_type,
HTMainAnchor->post_content_type);
} else {
FREE(newdoc.post_data);
}
newdoc.isHEAD = HTLoadedDocumentIsHEAD();
newdoc.safe = HTLoadedDocumentIsSafe();
newdoc.internal_link = FALSE;
} else {
StrAllocCopy(newdoc.address, curdoc.address);
StrAllocCopy(newdoc.title, curdoc.title);
StrAllocCopy(newdoc.post_data, curdoc.post_data);
StrAllocCopy(newdoc.post_content_type,
curdoc.post_content_type);
newdoc.isHEAD = curdoc.isHEAD;
newdoc.safe = curdoc.safe;
newdoc.internal_link = curdoc.internal_link;
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
}
cmd = LYK_PREV_DOC;
goto new_cmd;
}
override_LYresubmit_posts = TRUE;
goto try_again;
case NORMAL:
/*
* Marvelously, we got the document!
*/
LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */
LYinternal_flag = FALSE; /* Reset to default. - kw */
if (trace_mode_flag == TRUE) {
WWW_TraceFlag = TRUE;
trace_mode_flag = FALSE;
fprintf(tfp, "Turning TRACE back on.\n\n");
}
*prev_target = '\0'; /* Reset for this document. - FM */
/*
* If it's the first file and we're interactive,
* check whether it's a bookmark file which was
* not accessed via the -book switch. - FM
*/
if (((first_file == TRUE) &&
(dump_output_immediately == FALSE) &&
!(newdoc.bookmark && *newdoc.bookmark)) &&
((LYisLocalFile(newdoc.address) == TRUE) &&
!(strcmp((HText_getTitle() ? HText_getTitle() : ""),
BOOKMARK_TITLE))) &&
(temp = HTParse(newdoc.address, "",
PARSE_PATH+PARSE_PUNCTUATION)) != NULL) {
cp = wwwName(Home_Dir());
len = strlen(cp);
#ifdef VMS
if (!strncasecomp(temp, cp, len) &&
strlen(temp) > len)
#else
if (!strncmp(temp, cp, len) &&
strlen(temp) > len)
#endif /* VMS */
{
/*
* We're interactive and this might be a
* bookmark file entered as a startfile
* rather than invoked via -book. Check
* if it's in our bookmark file list, and
* if so, reload if with the relevant
* bookmark elements set. - FM
*/
if ((cp = (char *)calloc(1,
(strlen((char *)&temp[len]) + 2))) == NULL)
outofmem(__FILE__, "mainloop");
if (temp[len] == '/') {
if (strchr((char *)&temp[(len + 1)], '/')) {
sprintf(cp, ".%s", (char *)&temp[len]);
} else {
strcpy(cp, (char *)&temp[(len + 1)]);
}
} else {
strcpy(cp, (char *)&temp[len]);
}
for (i = 0; i <= MBM_V_MAXFILES; i++) {
if (MBM_A_subbookmark[i] &&
#ifdef VMS
!strcasecomp(cp, MBM_A_subbookmark[i])
#else
!strcmp(cp, MBM_A_subbookmark[i])
#endif /* VMS */
) {
StrAllocCopy(BookmarkPage,
MBM_A_subbookmark[i]);
break;
}
}
FREE(cp);
if (i <= MBM_V_MAXFILES) {
FREE(temp);
if (LYValidate) {
HTAlert(BOOKMARKS_DISABLED);
return(-1);
}
if ((temp = HTParse(newdoc.address, "",
PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION))) {
StrAllocCopy(newdoc.address, temp);
HTuncache_current_document();
FREE(curdoc.address);
StrAllocCat(newdoc.address,
wwwName(Home_Dir()));
StrAllocCat(newdoc.address, "/");
StrAllocCat(newdoc.address,
(strncmp(BookmarkPage, "./", 2) ?
BookmarkPage :
(BookmarkPage + 2)));
StrAllocCopy(newdoc.title, BOOKMARK_TITLE);
StrAllocCopy(newdoc.bookmark, BookmarkPage);
#ifdef USE_HASH
if (curdoc.style)
StrAllocCopy(newdoc.style, curdoc.style);
#endif
StrAllocCopy(startrealm, newdoc.address);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
FREE(temp);
if (!strcmp(homepage, startfile))
StrAllocCopy(homepage, newdoc.address);
StrAllocCopy(startfile, newdoc.address);
CTRACE(tfp, "Reloading as bookmarks=%s\n",
newdoc.address);
goto try_again;
}
}
}
cp = NULL;
}
FREE(temp);
if (traversal) {
/*
* During traversal build up lists of all links
* traversed. Traversal mode is a special
* feature for traversing http links in the web.
*/
if (traversal_link_to_add) {
/*
* Add the address we sought to TRAVERSE_FILE.
*/
if (!lookup(traversal_link_to_add))
add_to_table(traversal_link_to_add);
FREE(traversal_link_to_add);
}
if (curdoc.address && curdoc.title &&
strncmp(curdoc.address, "LYNXIMGMAP:", 11))
/*
* Add the address we got to TRAVERSE_FOUND_FILE.
*/
add_to_traverse_list(curdoc.address, curdoc.title);
}
/*
* If this was a LYNXDOWNLOAD, we still have curdoc,
* not a newdoc, so reset the address, title and
* positioning elements. - FM
*/
if (newdoc.address && curdoc.address &&
!strncmp(newdoc.address, "LYNXDOWNLOAD:", 13)) {
StrAllocCopy(newdoc.address, curdoc.address);
StrAllocCopy(newdoc.title, (curdoc.title ?
curdoc.title : ""));
StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
newdoc.internal_link = FALSE; /* can't be true. - kw */
}
/*
* Set Newline to the saved line. It contains the
* line the user was on if s/he has been in the file
* before, or it is 1 if this is a new file.
*/
#ifdef DISP_PARTIAL
/* Newline = newdoc.line; */
/* - already set and probably updated in partial mode */
/* incremental rendering stage already closed (but see below) */
if (Newline != Newline_partial || display_partial == TRUE) {
/* This is the case when we came from the history stack
* _and_ cached HText was used instead of HT*Copy() call.
* Set Newline and close partial mode here.
*/
Newline = Newline_partial;
display_partial = FALSE;
}
#else
Newline = newdoc.line; /* now here, no partial mode */
#endif
/*
* If we are going to a target line or
* the first page of a popped document,
* override any www_search line result.
*/
if (Newline > 1 || popped_doc == TRUE)
www_search_result = -1;
/*
* Make sure curdoc.line will not be equal
* to Newline, so we get a redraw.
*/
curdoc.line = -1;
#ifdef USE_PSRC
if (psrc_view)
HTMark_asSource(); /* this flag is not set, since when
displaying source, psrc_view is temporary unset when
writing the HTML header - and HTMainText is created
at that time.*/
#endif
break;
} /* end switch */
if (TRACE) {
if (!LYTraceLogFP || trace_mode_flag) {
sleep(AlertSecs); /* allow me to look at the results */
}
}
/*
* Set the files the same.
*/
StrAllocCopy(curdoc.address, newdoc.address);
StrAllocCopy(curdoc.post_data, newdoc.post_data);
StrAllocCopy(curdoc.post_content_type, newdoc.post_content_type);
StrAllocCopy(curdoc.bookmark, newdoc.bookmark);
#ifdef USE_HASH
StrAllocCopy(curdoc.style, HText_getStyle());
if (curdoc.style != NULL)
style_readFromFile (curdoc.style);
#endif
curdoc.isHEAD = newdoc.isHEAD;
curdoc.internal_link = newdoc.internal_link;
/*
* Set the remaining document elements and add to
* the visited links list. - FM
*/
if (ownerS_address != NULL) {
#ifndef USE_PSRC
if (HTOutputFormat == WWW_SOURCE && !HText_getOwner())
#else
if ( (LYpsrc ? psrc_view : HTOutputFormat == WWW_SOURCE)
&& !HText_getOwner() )
#endif
HText_setMainTextOwner(ownerS_address);
FREE(ownerS_address);
}
if (HText_getTitle()) {
StrAllocCopy(curdoc.title, HText_getTitle());
} else if (!dump_output_immediately) {
StrAllocCopy(curdoc.title, newdoc.title);
}
StrAllocCopy(owner_address, HText_getOwner());
curdoc.safe = HTLoadedDocumentIsSafe();
if (!dump_output_immediately) {
LYAddVisitedLink(&curdoc);
}
/*
* Reset WWW present mode so that if we were getting
* the source, we get rendered HTML from now on.
*/
HTOutputFormat = WWW_PRESENT;
#ifdef USE_PSRC
psrc_view = FALSE;
#endif
HTMLSetCharacterHandling(current_char_set); /* restore, for sure? */
/*
* Reset all of the other relevant flags. - FM
*/
LYUserSpecifiedURL = FALSE; /* only set for goto's and jumps's */
LYJumpFileURL = FALSE; /* only set for jump's */
LYNoRefererForThis = FALSE; /* always reset on return here */
reloading = FALSE; /* only set for RELOAD and RESUBMIT */
HEAD_request = FALSE; /* only set for HEAD requests */
LYPermitURL = FALSE; /* only for LYValidate or check_realm */
ForcePush = FALSE; /* only set for some PRINT requests. */
LYforce_HTML_mode = FALSE;
popped_doc = FALSE;
} /* end if (LYforce_no_cache || force_load || are_different(...)) */
if (dump_output_immediately) {
if (crawl) {
print_crawl_to_fd(stdout, curdoc.address, curdoc.title);
} else {
print_wwwfile_to_fd(stdout,0);
}
return(0);
}
/*
* If the recent_sizechange variable is set to TRUE
* then the window size changed recently.
*/
if (recent_sizechange) {
/*
* First we need to make sure the display library - curses, slang,
* whatever - gets notified about the change, and gets a chance
* to update external structures appropriately. Hopefully the
* stop_curses()/start_curses() sequence achieves this, at least
* if the display library has a way to get the new screen size
* from the OS.
* However, at least for ncurses, the update of the internal
* structures will come still too late - the changed screen
* size is detected in doupdate(), which would only be called
* (indirectly through the HText_pageDisplay below) after the
* WINDOW structures are already filled based on the old size.
* So we notify the ncurses library directly here. - kw
*/
#ifdef NCURSES_VERSION /* FIXME: check for specific version? */
resizeterm(LYlines, LYcols);
#else
stop_curses();
start_curses();
clear();
#endif
refresh_screen = TRUE; /* to force a redraw */
if (HTMainText) /* to REALLY force it... - kw */
HText_setStale(HTMainText);
recent_sizechange = FALSE;
if (user_mode == NOVICE_MODE) {
display_lines = LYlines-4;
} else {
display_lines = LYlines-2;
}
}
if (www_search_result != -1) {
/*
* This was a WWW search, set the line
* to the result of the search.
*/
Newline = www_search_result;
www_search_result = -1; /* reset */
}
if (first_file == TRUE) {
/*
* We can never again have the first file.
*/
first_file = FALSE;
/*
* Set the startrealm, and deal as best we can
* with preserving forced HTML mode for a local
* startfile. - FM
*/
temp = HTParse(curdoc.address, "",
PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION);
if (!temp || *temp == '\0') {
StrAllocCopy(startrealm, NO_NOTHING);
} else {
StrAllocCopy(startrealm, temp);
FREE(temp);
if (!(temp = HTParse(curdoc.address, "",
PARSE_PATH+PARSE_PUNCTUATION))) {
LYAddHtmlSep(&startrealm);
} else {
if (forced_HTML_mode &&
!dump_output_immediately &&
!curdoc.bookmark &&
!strncasecomp(curdoc.address, "file:", 5) &&
strlen(temp) > 1) {
/*
* We forced HTML for a local startfile which
* is not a bookmark file and has a path of at
* least two letters. If it doesn't have a
* suffix mapped to text/html, we'll set the
* entire path (including the lead slash) as a
* "suffix" mapped to text/html to ensure it is
* always treated as an HTML source file. We
* are counting on a tail match to this full path
* for some other URL fetched during the session
* having too low a probability to worry about,
* but it could happen. - FM
*/
HTAtom *encoding;
if (HTFileFormat(temp, &encoding, NULL) != WWW_HTML) {
HTSetSuffix(temp, "text/html", "8bit", 1.0);
}
}
if ((cp = strrchr(temp, '/')) != NULL) {
*(cp+1) = '\0';
StrAllocCat(startrealm, temp);
}
}
}
FREE(temp);
CTRACE(tfp, "Starting realm is '%s'\n\n", startrealm);
if (traversal) {
/*
* Set up the crawl output stuff.
*/
if (curdoc.address && !lookup(curdoc.address)) {
if (strncmp(curdoc.address, "LYNXIMGMAP:", 11))
crawl_ok = TRUE;
add_to_table(curdoc.address);
}
/*
* Set up the traversal_host comparison string.
*/
if (strncmp((curdoc.address ? curdoc.address : "NULL"),
"http", 4)) {
StrAllocCopy(traversal_host, NO_NOTHING);
} else if (check_realm) {
StrAllocCopy(traversal_host, startrealm);
} else {
temp = HTParse(curdoc.address, "",
PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION);
if (!temp || *temp == '\0') {
StrAllocCopy(traversal_host, NO_NOTHING);
} else {
StrAllocCopy(traversal_host, temp);
LYAddHtmlSep(&traversal_host);
}
FREE(temp);
}
CTRACE(tfp, "Traversal host is '%s'\n\n", traversal_host);
}
if (startfile) {
/*
* If homepage was not equated to startfile,
* make the homepage URL the first goto
* entry. - FM
*/
if (homepage && strcmp(startfile, homepage))
HTAddGotoURL(homepage);
/*
* If we are not starting up with startfile
* (e.g., had -book), or if we are using the
* startfile and it has no POST content, make
* the startfile URL a goto entry. - FM
*/
if (strcmp(startfile, newdoc.address) ||
newdoc.post_data == NULL)
HTAddGotoURL(startfile);
}
if (TRACE) {
refresh_screen = TRUE;
if (!LYTraceLogFP || trace_mode_flag) {
sleep(AlertSecs);
}
}
}
#ifdef SOURCE_CACHE
/*
* If the parse settings have changed since this HText was
* generated, we need to reparse and redraw it. -dsb
*
* Should be configured to avoid shock for experienced lynx users.
* Currently enabled for cached sources only.
*/
if (HTdocument_settings_changed()) {
if (HTcan_reparse_document()) {
HTUserMsg(gettext("Reparsing document under current settings..."));
if (HTreparse_document()) {}
} else {
/*
* Urk. I have no idea how to recover from a failure here.
* At a guess, I'll try reloading. -dsb
*/
/* currently disabled ***
HTUserMsg(gettext("Reparsing document under current settings..."));
cmd = LYK_RELOAD;
goto new_cmd;
*/
}
}
/*
* Trying to accomodate HTreparse_document() logic
* with mainloop events. Working out of force_load cycle
* set all the necessary flags here, from case NORMAL
* (see also LYK_SOURCE, some stuff implemented directly there).
*/
if (from_source_cache) {
from_source_cache = FALSE; /* done */
/*
* Make sure curdoc.line will not be equal
* to Newline, so we get a redraw.
*/
curdoc.line = -1;
}
#endif
/*
* If the curdoc.line is different than Newline then there must
* have been a change since last update. Run HText_pageDisplay()
* create a fresh screen of text out.
* All display_partial calls ends here for final redraw.
*/
if (curdoc.line != Newline) {
refresh_screen = FALSE;
HText_pageDisplay(Newline, prev_target);
#ifdef DIRED_SUPPORT
if (lynx_edit_mode && nlinks > 0 && !HTList_isEmpty(tagged))
showtags(tagged);
#endif /* DIRED_SUPPORT */
/*
* If more equals TRUE, then there is more info below this page.
*/
more = HText_canScrollDown();
curdoc.line = Newline = HText_getTopOfScreen()+1;
if (curdoc.title == NULL) {
/*
* If we don't yet have a title, try to get it,
* or set to that for newdoc.title. - FM
*/
if (HText_getTitle()) {
StrAllocCopy(curdoc.title, HText_getTitle());
} else {
StrAllocCopy(curdoc.title, newdoc.title);
}
}
if (arrowup) {
/*
* arrowup is set if we just came up from
* a page below.
*/
curdoc.link = nlinks - 1;
arrowup = FALSE;
} else {
curdoc.link = newdoc.link;
if (curdoc.link >= nlinks) {
curdoc.link = nlinks - 1;
} else if (curdoc.link < 0 && nlinks > 0) {
/*
* We may have popped a doc (possibly in local_dired)
* which didn't have any links when it was pushed, but
* does have links now (e.g., a file was created).
* Code below assumes that curdoc.link is valid and
* that (curdoc.link==-1) only occurs if (nlinks==0)
* is true. - KW
*/
curdoc.link = 0;
}
}
show_help = FALSE; /* reset */
newdoc.line = 1;
newdoc.link = 0;
curdoc.line = Newline; /* set */
}
/*
* Refresh the screen if necessary.
*/
if (refresh_screen) {
#if defined(FANCY_CURSES) || defined (USE_SLANG)
if (enable_scrollback) {
clear();
} else {
erase();
}
#else
clear();
#endif /* FANCY_CURSES || USE_SLANG */
HText_pageDisplay(Newline, prev_target);
#ifdef DIRED_SUPPORT
if (lynx_edit_mode && nlinks > 0 && !HTList_isEmpty(tagged))
showtags(tagged);
#endif /* DIRED_SUPPORT */
/*
* If more equals TRUE, then there is more info below this page.
*/
more = HText_canScrollDown();
/*
* Adjust curdoc.link as above; nlinks may have changed,
* if the refresh_screen flag was set as a result of
* a size change.
* Code below assumes that curdoc.link is valid and
* that (curdoc.link==-1) only occurs if (nlinks==0)
* is true. - kw
*/
if (curdoc.link >= nlinks) {
curdoc.link = nlinks - 1;
} else if (curdoc.link < 0 && nlinks > 0) {
curdoc.link = 0;
}
if (user_mode == NOVICE_MODE)
noviceline(more); /* print help message */
refresh_screen = FALSE;
}
/*
* Report unread or new mail, if appropriate.
*/
if (check_mail && !no_mail)
LYCheckMail();
/*
* If help is not on the screen,
* then put a message on the screen
* to tell the user other misc info.
*/
if (!show_help) {
show_main_statusline(links[curdoc.link]);
} else {
show_help = FALSE;
}
if (!(nlinks > 0 &&
links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
(links[curdoc.link].form->type == F_TEXT_TYPE ||
links[curdoc.link].form->type == F_TEXTAREA_TYPE)))
/*
* Highlight current link.
*/
highlight(ON, curdoc.link, prev_target);
if (traversal) {
/*
* Don't go interactively into forms,
* or accept keystrokes from the user
*/
if (crawl && crawl_ok) {
crawl_ok = FALSE;
#ifdef FNAMES_8_3
sprintf(cfile,"lnk%05d.dat",ccount);
#else
sprintf(cfile,"lnk%08d.dat",ccount);
#endif /* FNAMES_8_3 */
ccount = ccount + 1;
if ((cfp = LYNewTxtFile(cfile)) != NULL) {
print_crawl_to_fd(cfp,curdoc.address,curdoc.title);
fclose(cfp);
} else {
if (!dump_output_immediately)
cleanup();
#ifdef UNIX
if (dump_output_immediately)
fprintf(stderr,
gettext("Fatal error - could not open output file %s\n"),cfile);
else
#endif
printf(
gettext("Fatal error - could not open output file %s\n"),cfile);
if (!dump_output_immediately) {
exit_immediately(-1);
}
return(-1);
}
}
} else {
/*
* Normal, non-traversal handling.
*/
if (nlinks > 0 &&
links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
(links[curdoc.link].form->type == F_TEXT_TYPE ||
links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_PASSWORD_TYPE ||
links[curdoc.link].form->type == F_TEXTAREA_TYPE)) {
BOOLEAN use_last_tfpos;
/*
* Replace novice lines if in NOVICE_MODE.
*/
if (user_mode==NOVICE_MODE) {
move(LYlines-2,0); clrtoeol();
addstr(FORM_NOVICELINE_ONE);
move(LYlines-1,0); clrtoeol();
addstr(FORM_NOVICELINE_TWO);
}
use_last_tfpos = (real_cmd==LYK_LPOS_PREV_LINK ||
real_cmd==LYK_LPOS_NEXT_LINK);
real_c = change_form_link(&links[curdoc.link],
&newdoc, &refresh_screen,
links[curdoc.link].form->name,
links[curdoc.link].form->value,
use_last_tfpos, FALSE);
c = (real_c==LKC_DONE) ? DO_NOTHING : LKC_TO_C(real_c);
if (c != DO_NOTHING &&
peek_mouse_link() != -1 && peek_mouse_link() != -2)
old_c = 0;
if (peek_mouse_link() >= 0 &&
LKC_TO_LAC(keymap,real_c) != LYK_CHANGE_LINK) {
do_change_link(prev_target);
if ((c == '\n' || c == '\r') &&
links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
(links[curdoc.link].form->type == F_TEXT_TYPE ||
links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_PASSWORD_TYPE ||
links[curdoc.link].form->type == F_TEXTAREA_TYPE)) {
c = DO_NOTHING;
}
} else
switch (c) {
case '\n':
case '\r':
#ifdef AUTOGROW
/*
* If on the bottom line of a TEXTAREA, and the user hit
* the ENTER key, we add a new line/anchor automatically,
* positioning the cursor on it.
*
* If at the bottom of the screen, we effectively perform
* an LYK_DOWN_HALF-like operation, then move down to the
* new line we just added. --KED 02/14/99
*
* [There is some redundancy and non-standard indentation
* in the monster-if() below. This is intentional ... to
* try and improve the "readability" (such as it is).
* Caveat emptor to anyone trying to change it.]
*/
if ((links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type == F_TEXTAREA_TYPE)
/* &&
(peek_mouse_link() == -1) */
&&
((curdoc.link == nlinks-1)
||
((curdoc.link < nlinks-1) &&
!(links[curdoc.link+1].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link+1].form->type == F_TEXTAREA_TYPE))
||
((curdoc.link < nlinks-1) &&
((links[curdoc.link+1].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link+1].form->type == F_TEXTAREA_TYPE)
&&
((links[curdoc.link].form->number !=
links[curdoc.link+1].form->number) ||
(strcmp (links[curdoc.link].form->name,
links[curdoc.link+1].form->name) != 0)))))) {
HText_ExpandTextarea (&links[curdoc.link], 1);
if (links[curdoc.link].ly < display_lines) {
refresh_screen = TRUE;
} else {
Newline += (display_lines/2);
if (nlinks > 0 && curdoc.link > -1 &&
links[curdoc.link].ly > display_lines/2) {
newdoc.link = curdoc.link;
for (i = 0; links[i].ly <= (display_lines/2); i++)
--newdoc.link;
newdoc.link++;
}
}
}
#endif /* AUTOGROW */
/*
* Make return in input field (if it was returned
* by change_form_link) act as LYK_NEXT_LINK,
* independent of what key (if any) is mapped to
* LYK_NEXT_LINK. - kw
*/
c = LAC_TO_LKC0(LYK_NEXT_LINK);
break;
default:
if (old_c != c && old_c != real_c && c != real_c)
real_c = c;
}
} else {
/*
* Get a keystroke from the user.
* Save the last keystroke to avoid
* redundant error reporting.
*/
real_c = c = LYgetch(); /* get user input */
#ifndef VMS
if (c == 3) { /* ^C */
/*
* This shouldn't happen. We'll try to
* deal with whatever bug caused it. - FM
*/
signal(SIGINT, cleanup_sig);
old_c = 0;
cmd = LYK_QUIT;
goto new_cmd;
}
#endif /* !VMS */
if (LKC_HAS_ESC_MOD(c) && EditBinding(c) != LYE_FORM_PASS) {
/*
* If ESC + <key> was read (and not recognized as a
* terminal escape sequence for another key), ignore
* the ESC modifier and act on <key> only if the line
* editor binding would have passed the same ESC-modified
* lynxkeycode back to us if it had been pressed in a
* text input field. Otherwise set interesting part
* so that it will map to 0, to prevent that ESC + <key>
* acts like <key>, which might be unexpected. - kw
*/
c = (c & ~LKC_MASK) | LAC_TO_LKC(0);
}
if (old_c != real_c) {
old_c = 0;
}
}
}
#ifdef VMS
if (HadVMSInterrupt) {
HadVMSInterrupt = FALSE;
c = DO_NOTHING;
}
#else
if (recent_sizechange) {
if (c <= 0)
c = DO_NOTHING;
}
#endif /* VMS */
new_keyboard_input:
/*
* A goto point for new input without going
* back through the getch() loop.
*/
if (traversal) {
/*
* This is a special feature to traverse every http link
* derived from startfile and check for errors or create
* crawl output files. Only URL's that begin with
* "traversal_host" are searched - this keeps the search
* from crossing to other servers (a feature, not a bug!).
*/
BOOLEAN rlink_rejected = FALSE;
rlink_exists = (nlinks > 0 &&
links[curdoc.link].type != WWW_FORM_LINK_TYPE &&
links[curdoc.link].lname != NULL);
if (rlink_exists) {
rlink_rejected = lookup_reject(links[curdoc.link].lname);
rlink_allowed =
(!rlink_rejected &&
traversal_host && links[curdoc.link].lname &&
!strncmp(traversal_host,
(strncmp(links[curdoc.link].lname,
"LYNXIMGMAP:", 11)
?
links[curdoc.link].lname : (links[curdoc.link].lname + 11)),
strlen(traversal_host)));
} else {
rlink_allowed = FALSE;
}
if (rlink_exists && rlink_allowed) {
if (lookup(links[curdoc.link].lname)) {
if (more_links ||
(curdoc.link > -1 && curdoc.link < nlinks -1))
c= DNARROW;
else {
if (STREQ(curdoc.title,"Entry into main screen") ||
(nhist <= 0 )) {
if (!dump_output_immediately) {
cleanup();
exit_immediately(-1);
}
return(-1);
}
c = LTARROW;
}
} else {
StrAllocCopy(traversal_link_to_add,
links[curdoc.link].lname);
if (strncmp(traversal_link_to_add, "LYNXIMGMAP:", 11))
crawl_ok = TRUE;
c = RTARROW;
}
} else { /* no good right link, so only down and left arrow ok*/
if (rlink_exists /* && !rlink_rejected */)
/* uncomment in previous line to avoid duplicates - kw */
add_to_reject_list(links[curdoc.link].lname);
if (more_links ||
(curdoc.link > -1 && curdoc.link < nlinks-1))
c = DNARROW;
else {
/*
* curdoc.title doesn't always work, so
* bail out if the history list is empty.
*/
if (STREQ(curdoc.title,"Entry into main screen") ||
(nhist <= 0 )) {
if (!dump_output_immediately) {
cleanup();
exit_immediately(-1);
}
return(-1);
}
c = LTARROW;
}
} /* right link not NULL or link to another site*/
} /* traversal */
cmd = LKC_TO_LAC(keymap,c); /* adds 1 to map EOF to 0 */
#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
if (lynx_edit_mode && !no_dired_support && LKC_TO_LAC(key_override,c))
cmd = LKC_TO_LAC(key_override,c);
#endif /* DIRED_SUPPORT && OK_OVERRIDE */
real_cmd = cmd;
new_cmd: /*
* A goto point for new input without going
* back through the getch() loop.
*/
CTRACE_FLUSH(tfp);
switch(cmd) {
case 0: /* unmapped character */
default:
if (curdoc.link >= 0 && curdoc.link < nlinks &&
links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
(links[curdoc.link].form->type == F_TEXT_TYPE ||
links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_PASSWORD_TYPE ||
links[curdoc.link].form->type == F_TEXTAREA_TYPE))
show_main_statusline(links[curdoc.link]);
else if (more)
_statusline(MOREHELP);
else
_statusline(HELP);
show_help = TRUE;
if (TRACE) {
sprintf(cfile, "%d", c);
addstr(cfile); /* show the user input */
cfile[0] = '\0';
}
break;
case LYK_INTERRUPT:
/*
* No network transmission to interrupt - 'til we multithread.
*/
break;
case LYK_F_LINK_NUM:
c = '\0';
case LYK_1:
case LYK_2:
case LYK_3:
case LYK_4:
case LYK_5:
case LYK_6:
case LYK_7:
case LYK_8:
case LYK_9:
{
/*
* Get a number from the user and follow that link number.
*/
int lindx = ((nlinks > 0) ? curdoc.link : 0);
int number;
/* pass cur line num for use in follow_link_number()
* Note: Current line may not equal links[cur].line
*/
number = curdoc.line;
switch (follow_link_number(c, lindx, &newdoc, &number)) {
case DO_LINK_STUFF:
/*
* Follow a normal link.
*/
StrAllocCopy(newdoc.address, links[lindx].lname);
StrAllocCopy(newdoc.title, links[lindx].hightext);
#ifndef DONT_TRACK_INTERNAL_LINKS
/*
* For internal links, retain POST content if present.
* If we are on the List Page, prevent pushing it on
* the history stack. Otherwise set try_internal to
* signal that the top of the loop should attempt to
* reposition directly, without calling getfile. - kw
*/
if (links[lindx].type == WWW_INTERN_LINK_TYPE) {
LYinternal_flag = TRUE;
newdoc.internal_link = TRUE;
if (LYIsListpageTitle(curdoc.title ? curdoc.title : "") &&
0==strcmp(HTLoadedDocumentURL(), LYlist_temp_url())) {
if (!curdoc.post_data ||
/*
* Normal case - List Page is not associated
* with post data. - kw
*/
(!LYresubmit_posts && curdoc.post_data &&
history[nhist - 1].post_data &&
!strcmp(curdoc.post_data,
history[nhist - 1].post_data) &&
HText_getContentBase() &&
!strncmp(HText_getContentBase(),
strncmp(history[nhist - 1].address,
"LYNXIMGMAP:", 11) ?
history[nhist - 1].address :
history[nhist - 1].address + 11,
strlen(HText_getContentBase())))) {
/*
* Normal case - as best as we can check, the
* document at the top of the history stack
* seems to be the document the List Page is
* about (or a LYNXIMGMAP derived from it),
* and LYresubmit_posts is not set, so don't
* prompt here. If we actually have to repeat
* a POST because, against expectations, the
* underlying document isn't cached any more,
* HTAccess will prompt for confirmation,
* unless we had LYK_NOCACHE. - kw
*/
LYinternal_flag = TRUE;
} else {
HTLastConfirmCancelled(); /* reset flag */
if (!confirm_post_resub(newdoc.address,
newdoc.title,
(LYresubmit_posts &&
HText_POSTReplyLoaded(&newdoc)) ? 1 : 2,
2)) {
if (HTLastConfirmCancelled() ||
(LYresubmit_posts &&
!HText_POSTReplyLoaded(&newdoc))) {
/* cancel the whole thing */
LYforce_no_cache = FALSE;
reloading = FALSE;
StrAllocCopy(newdoc.address, curdoc.address);
StrAllocCopy(newdoc.title, curdoc.title);
newdoc.internal_link = curdoc.internal_link;
HTInfoMsg(CANCELLED);
if (nlinks > 0)
HText_pageDisplay(curdoc.line, prev_target);
break;
} else if (LYresubmit_posts) {
/* If LYresubmit_posts is set, and the
answer was No, and we have a cached
copy, then use it. - kw */
LYforce_no_cache = FALSE;
} else {
/* if No, but not ^C or ^G, drop
* the post data. Maybe the link
* wasn't meant to be internal after
* all, here we can recover from that
* assumption. - kw */
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
newdoc.internal_link = FALSE;
HTAlert(DISCARDING_POST_DATA);
}
}
}
/*
* Don't push the List Page if we follow an
* internal link given by it. - kw
*/
FREE(curdoc.address);
} else
try_internal = TRUE;
if (!(LYresubmit_posts && newdoc.post_data))
LYinternal_flag = TRUE;
force_load = TRUE;
break;
} else {
/*
* Free POST content if not an internal link. - kw
*/
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
}
#endif /* DONT_TRACK_INTERNAL_LINKS */
/*
* Might be an anchor in the same doc from a POST
* form. If so, don't free the content. -- FM
*/
if (are_different(&curdoc, &newdoc)) {
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
}
newdoc.internal_link = FALSE;
force_load = TRUE; /* force MainLoop to reload */
break;
case DO_GOTOLINK_STUFF:
/*
* Position on a normal link, don't follow it. - KW
*/
Newline = newdoc.line;
newdoc.line = 1;
if (Newline == curdoc.line) {
/*
* It's a link in the current page. - FM
*/
if (nlinks > 0 && curdoc.link > -1) {
if (curdoc.link == newdoc.link) {
/*
* It's the current link, and presumably
* reflects a typo in the statusline entry,
* so issue a statusline message for the
* typo-prone users (like me 8-). - FM
*/
StrAllocCopy(temp, user_input_buffer);
sprintf(user_input_buffer,
LINK_ALREADY_CURRENT, number);
HTUserMsg(user_input_buffer);
strcpy(user_input_buffer, temp);
FREE(temp);
} else {
/*
* It's a different link on this page,
* so turn the highlighting off, set the
* current link to the new link value from
* follow_link_number(), and re-initialize
* the new link value. - FM
*/
highlight(OFF, curdoc.link, prev_target);
curdoc.link = newdoc.link;
newdoc.link = 0;
}
}
}
break; /* nothing more to do */
case DO_GOTOPAGE_STUFF:
/*
* Position on a page in this document. - FM
*/
Newline = newdoc.line;
newdoc.line = 1;
if (Newline == curdoc.line) {
/*
* It's the current page, so issue a
* statusline message for the typo-prone
* users (like me 8-). - FM
*/
if (Newline <= 1) {
HTInfoMsg(ALREADY_AT_BEGIN);
} else if (!more) {
HTInfoMsg(ALREADY_AT_END);
} else {
StrAllocCopy(temp, user_input_buffer);
sprintf(user_input_buffer,
ALREADY_AT_PAGE, number);
HTUserMsg(user_input_buffer);
strcpy(user_input_buffer, temp);
FREE(temp);
}
}
break;
case PRINT_ERROR:
old_c = real_c;
HTUserMsg(BAD_LINK_NUM_ENTERED);
break;
}
break;
}
case LYK_SOURCE: /* toggle view source mode */
/*
* Check if this is a reply from a POST, and if so,
* seek confirmation if the safe element is not set. - FM
*/
if ((curdoc.post_data != NULL &&
curdoc.safe != TRUE) &&
confirm_post_resub(curdoc.address, curdoc.title,
1, 1) == FALSE) {
HTInfoMsg(CANCELLED);
break;
}
if (HTisDocumentSource()) {
HTOutputFormat = WWW_PRESENT;
#ifdef USE_PSRC
psrc_view = FALSE;
#endif
} else {
if (HText_getOwner())
StrAllocCopy(ownerS_address, HText_getOwner());
LYUCPushAssumed(HTMainAnchor);
#ifdef USE_PSRC
if (LYpsrc)
psrc_view = TRUE;
else
HTOutputFormat = WWW_SOURCE;
#else
HTOutputFormat = WWW_SOURCE;
#endif
}
#ifdef SOURCE_CACHE
if (HTreparse_document()) {
/*
* These normally get cleaned up after getfile() returns;
* since we're not calling getfile(), we have to clean them
* up ourselves. -dsb
*/
HTOutputFormat = WWW_PRESENT;
#ifdef USE_PSRC
if (psrc_view)
HTMark_asSource();
psrc_view = FALSE;
#endif
FREE(ownerS_address); /* not used with source_cache */
LYUCPopAssumed(); /* probably a right place here */
HTMLSetCharacterHandling(current_char_set); /* restore now */
break;
}
#endif
FREE(curdoc.address); /* so it doesn't get pushed */
LYforce_no_cache = TRUE;
break;
case LYK_RELOAD: /* control-R to reload and refresh */
/*
* Check if this is a reply from a POST, and if so,
* seek confirmation if the safe element is not set. - FM
*/
if ((curdoc.post_data != NULL &&
curdoc.safe != TRUE) &&
HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
HTInfoMsg(CANCELLED);
break;
}
/*
* Check to see if should reload source, or load html
*/
if (HTisDocumentSource()) {
force_old_UCLYhndl_on_reload = TRUE;
forced_UCLYhdnl = HTMainText_Get_UCLYhndl();
#ifndef USE_PSRC
HTOutputFormat = WWW_SOURCE;
#else
if (LYpsrc)
psrc_view = TRUE;
else
HTOutputFormat = WWW_SOURCE;
#endif
}
HEAD_request = HTLoadedDocumentIsHEAD();
HTuncache_current_document();
#ifdef NO_ASSUME_SAME_DOC
/*
* Don't assume the reloaded document will be the same. - FM
*/
newdoc.line = 1;
newdoc.link = 0;
#else
/*
* Do assume the reloaded document will be the same. - FM
* (I don't remember all the reasons why we couldn't assume
* this. As the problems show up, we'll try to fix them,
* or add warnings. - FM)
*/
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
#endif /* NO_ASSUME_SAME_DOC */
FREE(curdoc.address); /* so it doesn't get pushed */
#ifdef VMS
lynx_force_repaint();
#endif /* VMS */
/*
* Reload should force a cache refresh on a proxy.
* -- Ari L. <luotonen@dxcern.cern.ch>
*
* -- but only if this was really a reload requested by
* the user, not if we jumped here to handle reloading for
* INLINE_TOGGLE, IMAGE_TOGGLE, RAW_TOGGLE, etc. - KW
*/
if (real_cmd == LYK_RELOAD)
reloading = TRUE;
break;
case LYK_HISTORICAL: /* toggle 'historical' comments parsing */
#ifdef SOURCE_CACHE
if (!HTcan_reparse_document()) {
#endif
/*
* Check if this is a reply from a POST, and if so,
* seek confirmation of reload if the safe element
* is not set. - FM
*/
if ((curdoc.post_data != NULL &&
curdoc.safe != TRUE) &&
confirm_post_resub(curdoc.address, NULL,
0, 0) == FALSE) {
HTInfoMsg(WILL_NOT_RELOAD_DOC);
} else {
HTuncache_current_document();
StrAllocCopy(newdoc.address, curdoc.address);
FREE(curdoc.address);
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
}
#ifdef SOURCE_CACHE
} /* end if no bypass */
#endif
if (historical_comments)
historical_comments = FALSE;
else
historical_comments = TRUE;
if (minimal_comments) {
HTAlert(historical_comments ?
HISTORICAL_ON_MINIMAL_OFF : HISTORICAL_OFF_MINIMAL_ON);
} else {
HTAlert(historical_comments ?
HISTORICAL_ON_VALID_OFF : HISTORICAL_OFF_VALID_ON);
}
#ifdef SOURCE_CACHE
if (HTreparse_document()) {
break; /* OK */
}
#endif
break;
case LYK_MINIMAL: /* toggle 'minimal' comments parsing */
if (!historical_comments) {
#ifdef SOURCE_CACHE
if (!HTcan_reparse_document()) {
#endif
/*
* Check if this is a reply from a POST, and if so,
* seek confirmation of reload if the safe element
* is not set. - FM
*/
if ((curdoc.post_data != NULL &&
curdoc.safe != TRUE) &&
confirm_post_resub(curdoc.address, NULL,
0, 0) == FALSE) {
HTInfoMsg(WILL_NOT_RELOAD_DOC);
} else {
HTuncache_current_document();
StrAllocCopy(newdoc.address, curdoc.address);
FREE(curdoc.address);
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
}
}
#ifdef SOURCE_CACHE
} /* end if no bypass */
#endif
if (minimal_comments)
minimal_comments = FALSE;
else
minimal_comments = TRUE;
if (!historical_comments) {
HTAlert(minimal_comments ?
MINIMAL_ON_IN_EFFECT : MINIMAL_OFF_VALID_ON);
} else {
HTAlert(minimal_comments ?
MINIMAL_ON_BUT_HISTORICAL : MINIMAL_OFF_HISTORICAL_ON);
}
#ifdef SOURCE_CACHE
if (HTreparse_document()) {
break; /* OK */
}
#endif
break;
case LYK_SOFT_DQUOTES:
#ifdef SOURCE_CACHE
if (!HTcan_reparse_document()) {
#endif
/*
* Check if this is a reply from a POST, and if so,
* seek confirmation of reload if the safe element
* is not set. - FM
*/
if ((curdoc.post_data != NULL &&
curdoc.safe != TRUE) &&
confirm_post_resub(curdoc.address, NULL,
1, 1) == FALSE) {
HTInfoMsg(WILL_NOT_RELOAD_DOC);
} else {
HTuncache_current_document();
StrAllocCopy(newdoc.address, curdoc.address);
FREE(curdoc.address);
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
}
#ifdef SOURCE_CACHE
} /* end if no bypass */
#endif
if (soft_dquotes)
soft_dquotes = FALSE;
else
soft_dquotes = TRUE;
HTUserMsg(soft_dquotes ?
SOFT_DOUBLE_QUOTE_ON : SOFT_DOUBLE_QUOTE_OFF);
#ifdef SOURCE_CACHE
if (HTreparse_document()) {
break; /* OK */
}
#endif
break;
case LYK_SWITCH_DTD:
#ifdef SOURCE_CACHE
if (!HTcan_reparse_document()) {
#endif
/*
* Check if this is a reply from a POST, and if so,
* seek confirmation of reload if the safe element
* is not set. - FM, kw
*/
if ((curdoc.post_data != NULL &&
curdoc.safe != TRUE) &&
confirm_post_resub(curdoc.address, NULL,
1, 1) == FALSE) {
HTInfoMsg(WILL_NOT_RELOAD_DOC);
} else {
/*
* If currently viewing preparsed source, switching
* to the other DTD parsing may show source differences,
* so stay in source view - kw
*/
/* NOTE: this conditional can be considered incorrect -
current behaviour - when viewing source and
LYPreparsedSource==TRUE, pressing ^V will toggle parser mode
AND switch back from the source view to presentation view.-HV
*/
if (HTisDocumentSource() && LYPreparsedSource) {
#ifdef USE_PSRC
if (LYpsrc)
psrc_view = TRUE;
else
#endif
HTOutputFormat = WWW_SOURCE;
}
HTuncache_current_document();
StrAllocCopy(newdoc.address, curdoc.address);
FREE(curdoc.address);
#ifdef NO_ASSUME_SAME_DOC
newdoc.line = 1;
newdoc.link = 0;
#else
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
#endif /* NO_ASSUME_SAME_DOC */
}
#ifdef SOURCE_CACHE
} /* end if no bypass */
#endif
Old_DTD = !Old_DTD;
HTSwitchDTD(!Old_DTD);
HTUserMsg(Old_DTD ? USING_DTD_0 : USING_DTD_1);
#ifdef SOURCE_CACHE
if (HTcan_reparse_document()) {
if (HTisDocumentSource() && LYPreparsedSource) {
#ifdef USE_PSRC
if (LYpsrc)
psrc_view = TRUE;
else
#endif
HTOutputFormat = WWW_SOURCE;
}
if (HTreparse_document()) {
break;
}
} /* end if no bypass */
#endif
break;
#ifdef NOT_DONE_YET
case LYK_PIPE:
/* ignore for now */
break;
#endif /* NOT_DONE_YET */
case LYK_QUIT: /* quit */
if (LYQuitDefaultYes == TRUE) {
c = HTConfirmDefault(REALLY_QUIT_Y, YES);
} else {
c = HTConfirmDefault(REALLY_QUIT_N, NO);
}
if (LYQuitDefaultYes == TRUE) {
if (c != NO) {
return(0);
} else {
HTInfoMsg(NO_CANCEL);
}
} else if (c == YES) {
return(0);
} else {
HTInfoMsg(NO_CANCEL);
}
break;
case LYK_ABORT: /* don't ask the user about quitting */
return(0);
case LYK_NEXT_PAGE: /* next page */
if (more) {
Newline += display_lines;
} else if (curdoc.link < nlinks-1) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = nlinks-1; /* put on last link */
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(ALREADY_AT_END);
}
break;
case LYK_PREV_PAGE: /* page up */
if (Newline > 1) {
Newline -= display_lines;
} else if (curdoc.link > 0) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = 0; /* put on first link */
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(ALREADY_AT_BEGIN);
}
break;
case LYK_UP_TWO:
if (Newline > 1) {
int scrollamount = (Newline > 2 ? 2 : 1);
Newline -= scrollamount;
if (nlinks > 0 && curdoc.link > -1) {
if (links[curdoc.link].ly + scrollamount <= display_lines) {
newdoc.link = curdoc.link +
HText_LinksInLines(HTMainText,
Newline, scrollamount);
} else {
arrowup = TRUE;
}
}
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(ALREADY_AT_BEGIN);
}
break;
case LYK_DOWN_TWO:
if (more) {
Newline += 2;
if (nlinks > 0 && curdoc.link > -1 &&
links[curdoc.link].ly > 2) {
newdoc.link = curdoc.link;
for (i = 0; links[i].ly <= 2; i++)
--newdoc.link;
}
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(ALREADY_AT_END);
}
break;
case LYK_UP_HALF:
if (Newline > 1) {
int scrollamount = display_lines/2;
if (Newline - scrollamount < 1)
scrollamount = Newline - 1;
Newline -= scrollamount;
if (nlinks > 0 && curdoc.link > -1) {
if (links[curdoc.link].ly + scrollamount <= display_lines) {
newdoc.link = curdoc.link +
HText_LinksInLines(HTMainText,
Newline,
scrollamount);
} else {
arrowup = TRUE;
}
}
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(ALREADY_AT_BEGIN);
}
break;
case LYK_DOWN_HALF:
if (more) {
Newline += (display_lines/2);
if (nlinks > 0 && curdoc.link > -1 &&
links[curdoc.link].ly > display_lines/2) {
newdoc.link = curdoc.link;
for (i = 0; links[i].ly <= (display_lines/2); i++)
--newdoc.link;
}
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(ALREADY_AT_END);
}
break;
case LYK_REFRESH:
refresh_screen = TRUE;
lynx_force_repaint();
break;
case LYK_HOME:
if (curdoc.line > 1)
Newline = 1;
else {
cmd = LYK_PREV_PAGE;
goto new_cmd;
}
break;
case LYK_END:
if (more) {
Newline = HText_getNumOfLines() - display_lines + 3; /* go to end of file */
arrowup = TRUE; /* position on last link */
} else {
cmd = LYK_NEXT_PAGE;
goto new_cmd;
}
break;
case LYK_PREV_LINK:
case LYK_LPOS_PREV_LINK:
if (curdoc.link > 0) { /* previous link */
/*
* Unhighlight current link.
*/
highlight(OFF, curdoc.link, prev_target);
curdoc.link--;
} else if (!more &&
curdoc.link==0 && Newline==1) { /* at the top of list */
/*
* If there is only one page of data and the user
* goes off the top, then unhighlight the current
* link and just move the cursor to last link on
* the page.
*/
highlight(OFF, curdoc.link, prev_target);
curdoc.link = nlinks-1; /* the last link */
} else if (curdoc.line > 1) { /* previous page */
/*
* Go back to the previous page.
*/
int scrollamount = (Newline > display_lines ?
display_lines : Newline - 1);
Newline -= scrollamount;
if (scrollamount < display_lines &&
nlinks > 0 && curdoc.link == 0 &&
links[0].ly - 1 + scrollamount <= display_lines) {
newdoc.link = HText_LinksInLines(HTMainText,
1,
scrollamount) - 1;
} else {
arrowup = TRUE;
}
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(ALREADY_AT_BEGIN);
}
break;
case LYK_NEXT_LINK:
case LYK_LPOS_NEXT_LINK:
if (curdoc.link < nlinks-1) { /* next link */
highlight(OFF, curdoc.link, prev_target);
#ifdef FASTTAB
/*
* Move to different textarea if TAB in textarea.
*/
if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type == F_TEXTAREA_TYPE &&
c=='\t') {
int thisgroup = links[curdoc.link].form->number;
char *thisname = links[curdoc.link].form->name;
do curdoc.link++;
while ((curdoc.link < nlinks-1) &&
links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type == F_TEXTAREA_TYPE &&
links[curdoc.link].form->number == thisgroup &&
sametext(links[curdoc.link].form->name, thisname));
} else {
curdoc.link++;
}
#else
curdoc.link++;
#endif /* FASTTAB */
/*
* At the bottom of list and there is only one page.
* Move to the top link on the page.
*/
} else if (!more && Newline == 1 && curdoc.link == nlinks-1) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = 0;
} else if (more) { /* next page */
Newline += (display_lines);
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(ALREADY_AT_END);
}
break;
case LYK_FASTFORW_LINK:
{
int samepage = 0, nextlink = curdoc.link;
if (nlinks > 1) {
/*
* If in textarea, move to first link or field
* after it if there is one on this screen. - kw
*/
if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type == F_TEXTAREA_TYPE) {
int thisgroup = links[curdoc.link].form->number;
char *thisname = links[curdoc.link].form->name;
if (curdoc.link < nlinks-1 &&
!(links[nlinks-1].type == WWW_FORM_LINK_TYPE &&
links[nlinks-1].form->type == F_TEXTAREA_TYPE &&
links[nlinks-1].form->number == thisgroup &&
sametext(links[nlinks-1].form->name, thisname))) {
do nextlink++;
while
(links[nextlink].type == WWW_FORM_LINK_TYPE &&
links[nextlink].form->type == F_TEXTAREA_TYPE &&
links[nextlink].form->number == thisgroup &&
sametext(links[nextlink].form->name, thisname));
samepage = 1;
} else if (!more && Newline == 1 && curdoc.link > 0) {
nextlink = 0;
samepage = 1;
}
} else if (curdoc.link < nlinks-1) {
nextlink++;
samepage = 1;
} else if (!more && Newline == 1 && curdoc.link > 0) {
nextlink = 0;
samepage = 1;
}
}
if (samepage) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = nextlink;
break; /* and we are done. */
/*
* At the bottom of list and there is only one page.
* Move to the top link on the page.
*/
} else if (!more && Newline == 1 && curdoc.link == nlinks-1) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = 0;
} else if (more && /* need a later page */
HTGetLinkOrFieldStart(curdoc.link,
&Newline, &newdoc.link,
1, TRUE) != NO) {
Newline++; /* our line counting starts with 1 not 0 */
/* nothing more to do here */
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(NO_LINKS_BELOW);
}
break;
}
case LYK_FASTBACKW_LINK:
{
int samepage = 0, nextlink = curdoc.link;
int res;
if (nlinks > 1) {
/*
* If in textarea, move to first link or textarea group
* before it if there is one on this screen. - kw
*/
if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type == F_TEXTAREA_TYPE) {
int thisgroup = links[curdoc.link].form->number;
char *thisname = links[curdoc.link].form->name;
if (curdoc.link > 0 &&
!(links[0].type == WWW_FORM_LINK_TYPE &&
links[0].form->type == F_TEXTAREA_TYPE &&
links[0].form->number == thisgroup &&
sametext(links[0].form->name, thisname))) {
do nextlink--;
while
(links[nextlink].type == WWW_FORM_LINK_TYPE &&
links[nextlink].form->type == F_TEXTAREA_TYPE &&
links[nextlink].form->number == thisgroup &&
sametext(links[nextlink].form->name, thisname));
samepage = 1;
} else if (!more && Newline == 1 &&
(links[0].type == WWW_FORM_LINK_TYPE &&
links[0].form->type == F_TEXTAREA_TYPE &&
links[0].form->number == thisgroup &&
sametext(links[0].form->name, thisname)) &&
!(links[nlinks-1].type == WWW_FORM_LINK_TYPE &&
links[nlinks-1].form->type == F_TEXTAREA_TYPE &&
links[nlinks-1].form->number == thisgroup &&
sametext(links[nlinks-1].form->name, thisname))) {
nextlink = nlinks - 1;
samepage = 1;
} else if (!more && Newline == 1 && curdoc.link > 0) {
nextlink = 0;
samepage = 1;
}
} else if (curdoc.link > 0) {
nextlink--;
samepage = 1;
} else if (!more && Newline == 1) {
nextlink = nlinks - 1;
samepage = 1;
}
}
if (samepage) {
/*
* If the link as determined so far is part of a
* group of textarea fields, try to use the first
* of them that's on the screen instead. - kw
*/
if (nextlink > 0 &&
links[nextlink].type == WWW_FORM_LINK_TYPE &&
links[nextlink].form->type == F_TEXTAREA_TYPE) {
int thisgroup = links[nextlink].form->number;
char *thisname = links[nextlink].form->name;
if (links[0].type == WWW_FORM_LINK_TYPE &&
links[0].form->type == F_TEXTAREA_TYPE &&
links[0].form->number == thisgroup &&
sametext(links[0].form->name, thisname)) {
nextlink = 0;
} else
while
(nextlink > 1 &&
links[nextlink-1].type == WWW_FORM_LINK_TYPE &&
links[nextlink-1].form->type == F_TEXTAREA_TYPE &&
links[nextlink-1].form->number == thisgroup &&
sametext(links[nextlink-1].form->name, thisname)) {
nextlink--;
}
}
highlight(OFF, curdoc.link, prev_target);
curdoc.link = nextlink;
break; /* and we are done. */
} else if (Newline > 1 && /* need a previous page */
(res = HTGetLinkOrFieldStart(curdoc.link,
&Newline, &newdoc.link,
-1, TRUE)) != NO) {
if (res == LINK_DO_ARROWUP) {
/*
* It says we should use the normal PREV_LINK
* mechanism, so we'll do that. - kw
*/
if (nlinks > 0)
curdoc.link = 0;
cmd = LYK_PREV_LINK;
goto new_cmd;
}
Newline++; /* our line counting starts with 1 not 0 */
/* nothing more to do here */
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(NO_LINKS_ABOVE);
}
break;
}
case LYK_UP_LINK:
if (curdoc.link > 0 &&
(links[0].ly != links[curdoc.link].ly ||
!HText_LinksInLines(HTMainText, 1, Newline - 1))) {
/* more links before this on screen, and first of them on
a different line or no previous links before this screen? */
int newlink = -1;
for (i = curdoc.link; i >= 0; i--) {
if (links[i].ly < links[curdoc.link].ly) {
newlink = i;
break;
}
}
if (newlink > -1) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = newlink;
#ifdef NOTDEFINED
} else if (!more && Newline == 1 && curdoc.link == 0) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = (nlinks-1);
} else if (more) { /* next page */
Newline += (display_lines);
#else
} else if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_LINKS_ABOVE);
#endif /* NOTDEFINED */
}
#ifdef NOTDEFINED
/*
* At the bottom of list and there is only one page.
* Move to the top link on the page.
*/
} else if (!more && Newline == 1 && curdoc.link == (nlinks-1)) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = 0;
#endif /* NOTDEFINED */
} else if (curdoc.line > 1 && Newline > 1) { /* previous page */
int scrollamount = (Newline > display_lines ?
display_lines : Newline - 1);
Newline -= scrollamount;
if (scrollamount < display_lines &&
nlinks > 0 && curdoc.link > -1 &&
links[0].ly -1 + scrollamount <= display_lines) {
newdoc.link = HText_LinksInLines(HTMainText,
1,
scrollamount) - 1;
} else {
arrowup = TRUE;
}
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(ALREADY_AT_BEGIN);
}
break;
case LYK_DOWN_LINK:
if (curdoc.link < (nlinks-1)) { /* more links? */
int newlink = -1;
for (i = curdoc.link; i < nlinks; i++)
if (links[i].ly > links[curdoc.link].ly) {
newlink = i;
break;
}
if (newlink > -1) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = newlink;
#ifdef NOTDEFINED
} else if (!more &&
Newline == 1 && curdoc.link == (nlinks-1)) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = 0;
#endif /* NOTDEFINED */
} else if (more) { /* next page */
Newline += (display_lines);
} else if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_LINKS_BELOW);
break;
}
#ifdef NOTDEFINED
/*
* At the bottom of list and there is only one page.
* Move to the top link on the page.
*/
} else if (!more && Newline == 1 && curdoc.link == (nlinks-1)) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = 0;
#endif /* NOTDEFINED */
} else if (more) { /* next page */
Newline += (display_lines);
} else if (old_c != real_c) {
old_c = real_c;
HTInfoMsg(ALREADY_AT_END);
}
break;
case LYK_CHANGE_LINK:
do_change_link(prev_target);
break;
case LYK_RIGHT_LINK:
if (curdoc.link<nlinks-1 &&
links[curdoc.link].ly == links[curdoc.link+1].ly) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link++;
}
break;
case LYK_LEFT_LINK:
if (curdoc.link>0 &&
links[curdoc.link].ly == links[curdoc.link-1].ly) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link--;
}
break;
case LYK_COOKIE_JAR: /* show the cookie jar */
/*
* Don't do if already viewing the cookie jar.
*/
if (strcmp((curdoc.title ? curdoc.title : ""),
COOKIE_JAR_TITLE)) {
StrAllocCopy(newdoc.address, "LYNXCOOKIE:/");
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
LYforce_no_cache = TRUE;
if (LYValidate || check_realm) {
LYPermitURL = TRUE;
}
} else {
/*
* If already in the cookie jar, get out.
*/
cmd = LYK_PREV_DOC;
goto new_cmd;
}
break;
case LYK_HISTORY: /* show the history page */
if (curdoc.title && strcmp(curdoc.title, HISTORY_PAGE_TITLE)) {
/*
* Don't do this if already viewing history page.
*
* Push the current file so that the history list
* contains the current file for printing purposes.
* Pop the file afterwards to prevent multiple copies.
*/
if (TRACE && !LYUseTraceLog && LYCursesON) {
move(LYlines-1, LYcols-1); /* make sure cursor is down */
#ifdef USE_SLANG
addstr("\n");
#endif /* USE_SLANG */
refresh();
}
LYpush(&curdoc, ForcePush);
/*
* Print history options to file.
*/
if (showhistory(&newdoc.address) < 0) {
LYpop(&curdoc);
break;
}
StrAllocCopy(newdoc.title, HISTORY_PAGE_TITLE);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
newdoc.link = 1; /*@@@ bypass "recent statusline messages" link */
FREE(curdoc.address); /* so it doesn't get pushed */
refresh_screen = TRUE;
if (LYValidate || check_realm) {
LYPermitURL = TRUE;
}
break;
} /* end if strncmp */
/*
* Don't put break here so that if the backspace key
* is pressed in the history page, we fall though,
* i.e., it acts like a left arrow.
*/
case LYK_PREV_DOC: /* back up a level */
if (nhist > 0) { /* if there is anything to go back to */
/*
* Check if the previous document is a reply from a POST,
* and if so, seek confirmation of resubmission if the safe
* element is not set and the document is not still in the
* cache or LYresubmit_posts is set. If not confirmed and
* it is not the startfile, pop it so we go to the yet
* previous document, until we're OK or reach the startfile.
* If we reach the startfile and its not OK or we don't get
* confirmation, cancel. - FM
*/
DocAddress WWWDoc;
HTParentAnchor *tmpanchor;
HText *text;
BOOLEAN conf = FALSE, first = TRUE;
HTLastConfirmCancelled(); /* reset flag */
while (nhist > 0) {
conf = FALSE;
if (history[(nhist - 1)].post_data == NULL) {
break;
}
WWWDoc.address = history[(nhist - 1)].address;
WWWDoc.post_data = history[(nhist - 1)].post_data;
WWWDoc.post_content_type =
history[(nhist - 1)].post_content_type;
WWWDoc.bookmark = history[(nhist - 1)].bookmark;
WWWDoc.isHEAD = history[(nhist - 1)].isHEAD;
WWWDoc.safe = history[(nhist - 1)].safe;
tmpanchor = HTAnchor_parent(HTAnchor_findAddress(&WWWDoc));
if (HTAnchor_safe(tmpanchor)) {
break;
}
if (((text =
(HText *)HTAnchor_document(tmpanchor)) == NULL &&
(!strncmp(WWWDoc.address, "LYNXIMGMAP:", 11) ||
(conf = confirm_post_resub(WWWDoc.address,
history[(nhist - 1)].title,
0, 0))
== FALSE)) ||
((LYresubmit_posts && !conf &&
(NONINTERNAL_OR_PHYS_DIFFERENT(
(document *)&history[(nhist - 1)],
&curdoc) ||
NONINTERNAL_OR_PHYS_DIFFERENT(
(document *)&history[(nhist - 1)],
&newdoc))) &&
!confirm_post_resub(WWWDoc.address,
history[(nhist - 1)].title,
2, 2))) {
if (HTLastConfirmCancelled()) {
if (!first && curdoc.internal_link)
FREE(curdoc.address);
cmd = LYK_DO_NOTHING;
goto new_cmd;
}
if (nhist == 1) {
HTInfoMsg(CANCELLED);
old_c = 0;
cmd = LYK_DO_NOTHING;
goto new_cmd;
} else {
HTUserMsg2(WWW_SKIP_MESSAGE, WWWDoc.address);
do {
LYpop(&curdoc);
} while (nhist > 1 && !are_different(
(document *)&history[(nhist - 1)],
&curdoc));
first = FALSE; /* have popped at least one */
continue;
}
} else {
/*
* Break from loop; if user just confirmed to
* load again because document wasn't in cache,
* set LYforce_no_cache to avoid unnecessary
* repeat question down the road. - kw
*/
if (conf)
LYforce_no_cache = TRUE;
break;
}
}
if (!first)
curdoc.internal_link = FALSE;
/*
* Set newdoc.address to empty to pop a file.
*/
FREE(newdoc.address);
#ifdef DIRED_SUPPORT
if (lynx_edit_mode)
HTuncache_current_document();
#endif /* DIRED_SUPPORT */
} else if (child_lynx == TRUE) {
return(0); /* exit on left arrow in main screen */
} else if (old_c != real_c) {
old_c = real_c;
HTUserMsg(ALREADY_AT_FIRST);
}
break;
case LYK_NOCACHE: /* Force submission of form or link with no-cache */
if (nlinks > 0) {
if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type != F_SUBMIT_TYPE &&
links[curdoc.link].form->type != F_IMAGE_SUBMIT_TYPE &&
links[curdoc.link].form->type != F_TEXT_SUBMIT_TYPE) {
if (old_c == real_c)
break;
old_c = real_c;
HTUserMsg(NOT_ON_SUBMIT_OR_LINK);
break;
} else {
LYforce_no_cache = TRUE;
reloading = TRUE;
}
} /* fall through to LYK_ACTIVATE */
case LYK_ACTIVATE: /* follow a link */
case LYK_SUBMIT: /* follow a link, submit TEXT_SUBMIT input */
if (do_change_link(prev_target) == -1) {
LYforce_no_cache = FALSE;
reloading = FALSE;
continue; /* mouse stuff was confused, ignore - kw */
}
if (nlinks > 0) {
if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
/*
* Don't try to submit forms with bad actions. - FM
*/
if (links[curdoc.link].form->type == F_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE ||
links[curdoc.link].form->type ==
F_TEXT_SUBMIT_TYPE) {
/*
* Do nothing if it's disabled. - FM
*/
if (links[curdoc.link].form->disabled == YES) {
HTOutputFormat = WWW_PRESENT;
LYforce_no_cache = FALSE;
reloading = FALSE;
break;
}
/*
* Make sure we have an action. - FM
*/
if (!links[curdoc.link].form->submit_action ||
*links[curdoc.link].form->submit_action
== '\0') {
HTUserMsg(NO_FORM_ACTION);
HTOutputFormat = WWW_PRESENT;
LYforce_no_cache = FALSE;
reloading = FALSE;
break;
}
/*
* Check for no_mail if the form action
* is a mailto URL. - FM
*/
if (links[curdoc.link].form->submit_method
== URL_MAIL_METHOD && no_mail) {
HTAlert(FORM_MAILTO_DISALLOWED);
HTOutputFormat = WWW_PRESENT;
LYforce_no_cache = FALSE;
reloading = FALSE;
break;
}
/*
* Make sure this isn't a spoof in an account
* with restrictions on file URLs. - FM
*/
if (no_file_url &&
!strncasecomp(
links[curdoc.link].form->submit_action,
"file:", 5)) {
HTAlert(FILE_ACTIONS_DISALLOWED);
HTOutputFormat = WWW_PRESENT;
LYforce_no_cache = FALSE;
reloading = FALSE;
break;
}
/*
* Make sure this isn't a spoof attempt
* via an internal URL. - FM
*/
if (!strncasecomp(
links[curdoc.link].form->submit_action,
"LYNXCOOKIE:", 11) ||
#ifdef DIRED_SUPPORT
#ifdef OK_PERMIT
(!(strncasecomp(
links[curdoc.link].form->submit_action,
"LYNXDIRED:", 10)) &&
(no_dired_support ||
strncasecomp(
(links[curdoc.link].form->submit_action + 10),
"//PERMIT_LOCATION", 17) ||
strcmp(curdoc.address, LYPermitFileURL) ||
strcmp((curdoc.title ? curdoc.title : ""),
PERMIT_OPTIONS_TITLE))) ||
#else
!strncasecomp(
links[curdoc.link].form->submit_action,
"LYNXDIRED:", 10) ||
#endif /* OK_PERMIT */
#endif /* DIRED_SUPPORT */
!strncasecomp(
links[curdoc.link].form->submit_action,
"LYNXDOWNLOAD:", 13) ||
!strncasecomp(
links[curdoc.link].form->submit_action,
"LYNXHIST:", 9) ||
!strncasecomp(
links[curdoc.link].form->submit_action,
"LYNXKEYMAP:", 11) ||
!strncasecomp(
links[curdoc.link].form->submit_action,
"LYNXIMGMAP:", 11) ||
!strncasecomp(
links[curdoc.link].form->submit_action,
"LYNXPRINT:", 10) ||
!strncasecomp(
links[curdoc.link].form->submit_action,
"lynxexec:", 9) ||
!strncasecomp(
links[curdoc.link].form->submit_action,
"lynxprog:", 9)) {
HTAlert(SPECIAL_ACTION_DISALLOWED);
CTRACE(tfp, "LYMainLoop: Rejected '%s'\n",
links[curdoc.link].form->submit_action);
HTOutputFormat = WWW_PRESENT;
LYforce_no_cache = FALSE;
reloading = FALSE;
break;
}
#ifdef NOTDEFINED /* We're disabling form inputs instead of using this. - FM */
/*
* Check for enctype and let user know we
* don't yet support multipart/form-data - FM
*/
if (links[curdoc.link].form->submit_enctype) {
if (!strcmp(
links[curdoc.link].form->submit_enctype,
"multipart/form-data")) {
HTAlert(
gettext("Enctype multipart/form-data not yet supported! Cannot submit."));
HTOutputFormat = WWW_PRESENT;
LYforce_no_cache = FALSE;
reloading = FALSE;
break;
}
}
#endif /* NOTDEFINED */
if (check_realm) {
LYPermitURL = TRUE;
}
if (no_filereferer == TRUE &&
!strncmp(curdoc.address, "file:", 5)) {
LYNoRefererForThis = TRUE;
}
if (links[curdoc.link].form->submit_method
!= URL_MAIL_METHOD) {
StrAllocCopy(newdoc.title,
links[curdoc.link].hightext);
}
}
/*
* Normally we don't get here for text input fields,
* but it can happen as a result of mouse positioning.
* In that case the statusline will not have updated
* info, so update it now. - kw
*/
if (links[curdoc.link].form->type == F_TEXT_TYPE ||
links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_PASSWORD_TYPE ||
links[curdoc.link].form->type == F_TEXTAREA_TYPE) {
show_formlink_statusline(links[curdoc.link].form);
}
c = change_form_link(&links[curdoc.link],
&newdoc, &refresh_screen,
links[curdoc.link].form->name,
links[curdoc.link].form->value,
FALSE,
(real_cmd==LYK_SUBMIT ||
real_cmd==LYK_NOCACHE ||
real_cmd==LYK_DOWNLOAD ||
real_cmd==LYK_HEAD));
if (c != LKC_DONE || refresh_screen) {
/*
* Cannot have been a submit field for which
* newdoc was filled in. - kw
*/
if ((links[curdoc.link].form->type == F_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE) &&
links[curdoc.link].form->submit_method
!= URL_MAIL_METHOD) {
/*
* Try to undo change of newdoc.title done above.
*/
if (HText_getTitle()) {
StrAllocCopy(newdoc.title, HText_getTitle());
} else if (curdoc.title) {
StrAllocCopy(newdoc.title, curdoc.title);
}
}
} else {
if (HTOutputFormat == HTAtom_for("www/download") &&
newdoc.post_data != NULL &&
newdoc.safe == FALSE) {
if ((HText_POSTReplyLoaded(&newdoc) == TRUE) &&
HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
HTInfoMsg(CANCELLED);
HTOutputFormat = WWW_PRESENT;
LYforce_no_cache = FALSE;
StrAllocCopy(newdoc.address, curdoc.address);
StrAllocCopy(newdoc.title, curdoc.title);
StrAllocCopy(newdoc.post_data, curdoc.post_data);
StrAllocCopy(newdoc.post_content_type,
curdoc.post_content_type);
StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
newdoc.isHEAD = curdoc.isHEAD;
newdoc.safe = curdoc.safe;
newdoc.internal_link = curdoc.internal_link;
break;
}
}
/*
* Moved here from earlier to only apply when it
* should. Anyway, why should realm checking be
* overridden for form submissions, this seems to
* be an unnecessary loophole?? But that's the way
* it was, maybe there is some reason.
* However, at least make sure this doesn't weaken
* restrictions implied by -validate!
* - kw 1999-05-25
*/
if (check_realm && !LYValidate) {
LYPermitURL = TRUE;
}
}
if (c == LKC_DONE) {
c = DO_NOTHING;
} else if (c == 23) {
c = DO_NOTHING;
refresh_screen = TRUE;
} else
switch (LKC_TO_C(c)) {
case '\n':
case '\r':
/* Avoid getting stuck with repeatedly calling
** the second change_form_link() instead of the
** first for text input fields. - kw
*/
if (peek_mouse_link() == -1 ||
peek_mouse_link() == curdoc.link)
c = DO_NOTHING;
default:
break;
}
goto new_keyboard_input;
} else {
/*
* Not a forms link.
*
* Make sure this isn't a spoof in an account
* with restrictions on file URLs. - FM
*/
if (no_file_url &&
!strncmp(links[curdoc.link].lname, "file:", 5)) {
if (strncmp(curdoc.address, "file:", 5) &&
!((!strncmp(curdoc.address, "LYNXKEYMAP:", 11) ||
!strncmp(curdoc.address, "LYNXCOOKIE:", 11)) &&
!strncmp(links[curdoc.link].lname,
helpfilepath,
strlen(helpfilepath)))) {
HTAlert(FILE_SERVED_LINKS_DISALLOWED);
reloading = FALSE;
break;
} else if (curdoc.bookmark != NULL) {
HTAlert(FILE_BOOKMARKS_DISALLOWED);
reloading = FALSE;
break;
}
}
/*
* Make sure this isn't a spoof attempt
* via an internal URL in a non-internal
* document. - FM
*/
if ((!strncmp(links[curdoc.link].lname,
"LYNXCOOKIE:", 11) &&
strcmp((curdoc.title ? curdoc.title : ""),
COOKIE_JAR_TITLE)) ||
#ifdef DIRED_SUPPORT
(!strncmp(links[curdoc.link].lname,
"LYNXDIRED:", 10) &&
(strcmp(curdoc.address, LYDiredFileURL) ||
strcmp((curdoc.title ? curdoc.title : ""),
DIRED_MENU_TITLE)) &&
(strcmp(curdoc.address, LYPermitFileURL) ||
strcmp((curdoc.title ? curdoc.title : ""),
PERMIT_OPTIONS_TITLE)) &&
(strcmp(curdoc.address, LYUploadFileURL) ||
strcmp((curdoc.title ? curdoc.title : ""),
UPLOAD_OPTIONS_TITLE))) ||
#endif /* DIRED_SUPPORT */
(!strncmp(links[curdoc.link].lname,
"LYNXDOWNLOAD:", 13) &&
strcmp((curdoc.title ? curdoc.title : ""),
DOWNLOAD_OPTIONS_TITLE)) ||
(!strncmp(links[curdoc.link].lname,
"LYNXHIST:", 9) &&
strcmp((curdoc.title ? curdoc.title : ""),
HISTORY_PAGE_TITLE) &&
strcmp(curdoc.address, LYlist_temp_url())) ||
(!strncmp(links[curdoc.link].lname,
"LYNXPRINT:", 10) &&
strcmp((curdoc.title ? curdoc.title : ""),
PRINT_OPTIONS_TITLE))) {
HTAlert(SPECIAL_VIA_EXTERNAL_DISALLOWED);
HTOutputFormat = WWW_PRESENT;
LYforce_no_cache = FALSE;
reloading = FALSE;
break;
}
/*
* Follow a normal link or anchor.
*/
StrAllocCopy(newdoc.address, links[curdoc.link].lname);
StrAllocCopy(newdoc.title, links[curdoc.link].hightext);
#ifndef DONT_TRACK_INTERNAL_LINKS
/*
* For internal links, retain POST content if present.
* If we are on the List Page, prevent pushing it on
* the history stack. Otherwise set try_internal to
* signal that the top of the loop should attempt to
* reposition directly, without calling getfile. - kw
*/
/*
* Might be an internal link anchor in the same doc.
* If so, take the try_internal shortcut if we didn't
* fall through from LYK_NOCACHE. - kw
*/
newdoc.internal_link =
(links[curdoc.link].type == WWW_INTERN_LINK_TYPE);
if (newdoc.internal_link) {
/*
* Special case of List Page document with an
* internal link indication, which may really stand
* for an internal link within the document the
* List Page is about. - kw
*/
if ( 0==strcmp(curdoc.address, LYlist_temp_url()) &&
(LYIsListpageTitle(curdoc.title ? curdoc.title : ""))) {
if (!curdoc.post_data ||
/*
* Normal case - List Page is not associated
* with post data. - kw
*/
(!LYresubmit_posts && curdoc.post_data &&
history[nhist - 1].post_data &&
!strcmp(curdoc.post_data,
history[nhist - 1].post_data) &&
HText_getContentBase() &&
!strncmp(HText_getContentBase(),
strncmp(history[nhist - 1].address,
"LYNXIMGMAP:", 11) ?
history[nhist - 1].address :
history[nhist - 1].address + 11,
strlen(HText_getContentBase())))) {
/*
* Normal case - as best as we can check, the
* document at the top of the history stack
* seems to be the document the List Page is
* about (or a LYNXIMGMAP derived from it),
* and LYresubmit_posts is not set, so don't
* prompt here. If we actually have to repeat
* a POST because, against expectations, the
* underlying document isn't cached any more,
* HTAccess will prompt for confirmation,
* unless we had LYK_NOCACHE. - kw
*/
LYinternal_flag = TRUE;
} else {
HTLastConfirmCancelled(); /* reset flag */
if (!confirm_post_resub(newdoc.address,
newdoc.title,
(LYresubmit_posts &&
HText_POSTReplyLoaded(&newdoc)) ? 1 : 2,
2)) {
if (HTLastConfirmCancelled() ||
(LYresubmit_posts &&
cmd != LYK_NOCACHE &&
!HText_POSTReplyLoaded(&newdoc))) {
/* cancel the whole thing */
LYforce_no_cache = FALSE;
reloading = FALSE;
StrAllocCopy(newdoc.address, curdoc.address);
StrAllocCopy(newdoc.title, curdoc.title);
newdoc.internal_link = curdoc.internal_link;
HTInfoMsg(CANCELLED);
break;
} else if (LYresubmit_posts &&
cmd != LYK_NOCACHE) {
/* If LYresubmit_posts is set, and the
answer was No, and the key wasn't
NOCACHE, and we have a cached copy,
then use it. - kw */
LYforce_no_cache = FALSE;
} else {
/* if No, but not ^C or ^G, drop
* the post data. Maybe the link
* wasn't meant to be internal after
* all, here we can recover from that
* assumption. - kw */
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
newdoc.internal_link = FALSE;
HTAlert(DISCARDING_POST_DATA);
}
}
}
/*
* Don't push the List Page if we follow an
* internal link given by it. - kw
*/
FREE(curdoc.address);
} else if (cmd != LYK_NOCACHE) {
try_internal = TRUE;
}
if (!(LYresubmit_posts && newdoc.post_data))
LYinternal_flag = TRUE;
/* We still set force_load so that history pushing
** etc. will be done. - kw */
force_load = TRUE;
break;
} else {
/*
* Free POST content if not an internal link. - kw
*/
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
}
#endif /* TRACK_INTERNAL_LINKS */
/*
* Might be an anchor in the same doc from a POST
* form. If so, dont't free the content. -- FM
*/
if (are_different(&curdoc, &newdoc)) {
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
}
if (!no_jump && lynxjumpfile && curdoc.address &&
!strcmp(lynxjumpfile, curdoc.address)) {
LYJumpFileURL = TRUE;
LYUserSpecifiedURL = TRUE;
} else if ((curdoc.title &&
!strcmp(curdoc.title, HISTORY_PAGE_TITLE)) ||
curdoc.bookmark != NULL ||
(lynxjumpfile &&
!strcmp(lynxjumpfile, curdoc.address))) {
LYUserSpecifiedURL = TRUE;
} else if (no_filereferer == TRUE &&
!strncmp(curdoc.address, "file:", 5)) {
LYNoRefererForThis = TRUE;
}
newdoc.link = 0;
force_load = TRUE; /* force MainLoop to reload */
#ifdef USE_PSRC
psrc_view = FALSE; /* we get here if link is not internal */
#endif
#ifdef DIRED_SUPPORT
if (lynx_edit_mode) {
HTuncache_current_document();
/*
* Unescaping any slash chars in the URL,
* but avoid double unescaping and too-early
* unescaping of other chars. - KW
*/
HTUnEscapeSome(newdoc.address,"/");
strip_trailing_slash(newdoc.address);
}
#endif /* DIRED_SUPPORT */
if (!strncmp(curdoc.address, "LYNXCOOKIE:", 11)) {
HTuncache_current_document();
}
}
}
break;
case LYK_ELGOTO: /* edit URL of current link and go to it */
if (no_goto && !LYValidate) {
/*
* Go to not allowed. - FM
*/
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(GOTO_DISALLOWED);
}
break;
}
if (!(nlinks > 0 && curdoc.link > -1) ||
(links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type != F_SUBMIT_TYPE &&
links[curdoc.link].form->type != F_IMAGE_SUBMIT_TYPE &&
links[curdoc.link].form->type != F_TEXT_SUBMIT_TYPE)) {
/*
* No links on page, or not a normal link
* or form submit button. - FM
*/
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NOT_ON_SUBMIT_OR_LINK);
}
break;
}
if ((links[curdoc.link].type == WWW_FORM_LINK_TYPE) &&
(!links[curdoc.link].form->submit_action ||
*links[curdoc.link].form->submit_action == '\0')) {
/*
* Form submit button with no ACTION defined. - FM
*/
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_FORM_ACTION);
}
break;
}
#ifdef DIRED_SUPPORT
if (!strncmp(links[curdoc.link].lname,
"LYNXDIRED:", 10) ||
!strcmp(curdoc.address, LYDiredFileURL) ||
!strcmp((curdoc.title ? curdoc.title : ""),
DIRED_MENU_TITLE) ||
!strcmp(curdoc.address, LYPermitFileURL) ||
!strcmp((curdoc.title ? curdoc.title : ""),
PERMIT_OPTIONS_TITLE) ||
!strcmp(curdoc.address, LYUploadFileURL) ||
!strcmp((curdoc.title ? curdoc.title : ""),
UPLOAD_OPTIONS_TITLE)) {
/*
* Disallow editing of File Management URLs. - FM
*/
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(EDIT_FM_MENU_URLS_DISALLOWED);
}
break;
}
#endif /* DIRED_SUPPORT */
/*
* Save the current user_input_buffer string,
* and load the current link's address. - FM
*/
StrAllocCopy(temp, user_input_buffer);
LYstrncpy(user_input_buffer,
((links[curdoc.link].type == WWW_FORM_LINK_TYPE)
?
links[curdoc.link].form->submit_action : links[curdoc.link].lname),
(sizeof(user_input_buffer) - 1));
/*
* Offer the current link's URL for editing. - FM
*/
_statusline(EDIT_CURLINK_URL);
if (((ch = LYgetstr(user_input_buffer, VISIBLE,
sizeof(user_input_buffer), RECALL)) >= 0) &&
user_input_buffer[0] != '\0' &&
strcmp(user_input_buffer,
((links[curdoc.link].type == WWW_FORM_LINK_TYPE)
? links[curdoc.link].form->submit_action
: links[curdoc.link].lname))) {
if (!LYTrimStartfile(user_input_buffer)) {
LYRemoveBlanks(user_input_buffer);
}
if (user_input_buffer[0] != '\0') {
goto check_goto_URL;
}
}
/*
* User cancelled via ^G, a full deletion,
* or not modifying the URL. - FM
*/
HTInfoMsg(CANCELLED);
strcpy(user_input_buffer, temp);
FREE(temp);
break;
case LYK_ECGOTO: /* edit current URL and go to to it */
if (no_goto && !LYValidate) {
/*
* Go to not allowed. - FM
*/
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(GOTO_DISALLOWED);
}
break;
}
#ifdef DIRED_SUPPORT
if (!strcmp(curdoc.address, LYDiredFileURL) ||
!strcmp((curdoc.title ? curdoc.title : ""),
DIRED_MENU_TITLE) ||
!strcmp(curdoc.address, LYPermitFileURL) ||
!strcmp((curdoc.title ? curdoc.title : ""),
PERMIT_OPTIONS_TITLE) ||
!strcmp(curdoc.address, LYUploadFileURL) ||
!strcmp((curdoc.title ? curdoc.title : ""),
UPLOAD_OPTIONS_TITLE)) {
/*
* Disallow editing of File Management URLs. - FM
*/
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(EDIT_FM_MENU_URLS_DISALLOWED);
}
break;
}
#endif /* DIRED_SUPPORT */
/*
* Save the current user_input_buffer string,
* and load the current document's address.
*/
StrAllocCopy(temp, user_input_buffer);
LYstrncpy(user_input_buffer,
curdoc.address,
(sizeof(user_input_buffer) - 1));
/*
* Warn the user if the current document has POST
* data associated with it. - FM
*/
if (curdoc.post_data)
HTAlert(CURRENT_DOC_HAS_POST_DATA);
/*
* Offer the current document's URL for editing. - FM
*/
_statusline(EDIT_CURDOC_URL);
if (((ch = LYgetstr(user_input_buffer, VISIBLE,
sizeof(user_input_buffer), RECALL)) >= 0) &&
user_input_buffer[0] != '\0' &&
strcmp(user_input_buffer, curdoc.address)) {
if (!LYTrimStartfile(user_input_buffer)) {
LYRemoveBlanks(user_input_buffer);
}
if (user_input_buffer[0] != '\0') {
goto check_goto_URL;
}
}
/*
* User cancelled via ^G, a full deletion,
* or not modifying the URL. - FM
*/
HTInfoMsg(CANCELLED);
strcpy(user_input_buffer, temp);
FREE(temp);
break;
case LYK_GOTO: /* 'g' to goto a random URL */
if (no_goto && !LYValidate) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(GOTO_DISALLOWED);
}
break;
}
StrAllocCopy(temp, user_input_buffer);
if (!goto_buffer)
*user_input_buffer = '\0';
URLTotal = (Goto_URLs ? HTList_count(Goto_URLs) : 0);
if (goto_buffer && *user_input_buffer) {
recall = ((URLTotal > 1) ? RECALL : NORECALL);
URLNum = 0;
FirstURLRecall = FALSE;
} else {
recall = ((URLTotal >= 1) ? RECALL : NORECALL);
URLNum = URLTotal;
FirstURLRecall = TRUE;
}
/*
* Ask the user.
*/
_statusline(URL_TO_OPEN);
if ((ch = LYgetstr(user_input_buffer, VISIBLE,
sizeof(user_input_buffer), recall)) < 0 ) {
/*
* User cancelled the Goto via ^G.
* Restore user_input_buffer and break. - FM
*/
strcpy(user_input_buffer, temp);
FREE(temp);
HTInfoMsg(CANCELLED);
break;
}
check_recall:
/*
* Get rid of leading spaces (and any other spaces).
*/
if (!LYTrimStartfile(user_input_buffer)) {
LYRemoveBlanks(user_input_buffer);
}
if (*user_input_buffer == '\0' &&
!(recall && (ch == UPARROW || ch == DNARROW))) {
strcpy(user_input_buffer, temp);
FREE(temp);
HTInfoMsg(CANCELLED);
break;
}
if (recall && ch == UPARROW) {
if (FirstURLRecall) {
/*
* Use last URL in the list. - FM
*/
FirstURLRecall = FALSE;
URLNum = 0;
} else {
/*
* Go back to the previous URL in the list. - FM
*/
URLNum++;
}
if (URLNum >= URLTotal)
/*
* Roll around to the last URL in the list. - FM
*/
URLNum = 0;
if ((cp = (char *)HTList_objectAt(Goto_URLs,
URLNum)) != NULL) {
strcpy(user_input_buffer, cp);
if (goto_buffer && *temp &&
!strcmp(temp, user_input_buffer)) {
_statusline(EDIT_CURRENT_GOTO);
} else if ((goto_buffer && URLTotal == 2) ||
(!goto_buffer && URLTotal == 1)) {
_statusline(EDIT_THE_PREV_GOTO);
} else {
_statusline(EDIT_A_PREV_GOTO);
}
if ((ch = LYgetstr(user_input_buffer, VISIBLE,
sizeof(user_input_buffer),
recall)) < 0) {
/*
* User cancelled the Goto via ^G.
* Restore user_input_buffer and break. - FM
*/
strcpy(user_input_buffer, temp);
FREE(temp);
HTInfoMsg(CANCELLED);
break;
}
goto check_recall;
}
} else if (recall && ch == DNARROW) {
if (FirstURLRecall) {
/*
* Use the first URL in the list. - FM
*/
FirstURLRecall = FALSE;
URLNum = URLTotal - 1;
} else {
/*
* Advance to the next URL in the list. - FM
*/
URLNum--;
}
if (URLNum < 0)
/*
* Roll around to the first URL in the list. - FM
*/
URLNum = URLTotal - 1;
if ((cp=(char *)HTList_objectAt(Goto_URLs,
URLNum)) != NULL) {
strcpy(user_input_buffer, cp);
if (goto_buffer && *temp &&
!strcmp(temp, user_input_buffer)) {
_statusline(EDIT_CURRENT_GOTO);
} else if ((goto_buffer && URLTotal == 2) ||
(!goto_buffer && URLTotal == 1)) {
_statusline(EDIT_THE_PREV_GOTO);
} else {
_statusline(EDIT_A_PREV_GOTO);
}
if ((ch = LYgetstr(user_input_buffer, VISIBLE,
sizeof(user_input_buffer),
recall)) < 0) {
/*
* User cancelled the Goto via ^G.
* Restore user_input_buffer and break. - FM
*/
strcpy(user_input_buffer, temp);
FREE(temp);
HTInfoMsg(CANCELLED);
break;
}
goto check_recall;
}
}
check_goto_URL:
/* allow going to anchors*/
if (*user_input_buffer == '#' ) {
if ( user_input_buffer[1] &&
HTFindPoundSelector(user_input_buffer+1) ) {
/* HTFindPoundSelector will initialize www_search_result,
so we do nothing else. */
HTAddGotoURL(user_input_buffer);
}
break;
}
/*
* If its not a URL then make it one.
*/
StrAllocCopy(temp, user_input_buffer);
LYFillLocalFileURL((char **)&temp, "file://localhost");
LYEnsureAbsoluteURL((char **)&temp, "", TRUE);
sprintf(user_input_buffer, "%.*s",
(int)(sizeof(user_input_buffer) - 1), temp);
FREE(temp);
if ((no_file_url || no_goto_file) &&
!strncmp(user_input_buffer,"file:",5)) {
HTUserMsg(GOTO_FILE_DISALLOWED);
} else if ((no_shell || no_goto_lynxexec
#ifdef EXEC_LINKS
|| local_exec_on_local_files
#endif /* EXEC_LINKS */
) &&
!strncmp(user_input_buffer, "lynxexec:",9)) {
HTUserMsg(GOTO_EXEC_DISALLOWED);
} else if ((no_shell || no_goto_lynxprog
#ifdef EXEC_LINKS
|| local_exec_on_local_files
#endif /* EXEC_LINKS */
) &&
!strncmp(user_input_buffer, "lynxprog:",9)) {
HTUserMsg(GOTO_PROG_DISALLOWED);
} else if ((no_shell || no_goto_lynxcgi) &&
!strncmp(user_input_buffer, "lynxcgi:", 8)) {
HTUserMsg(GOTO_CGI_DISALLOWED);
} else if (LYValidate &&
strncmp(user_input_buffer, "http:", 5) &&
strncmp(user_input_buffer, "https:", 6)) {
HTUserMsg(GOTO_NON_HTTP_DISALLOWED);
} else if (no_goto_cso &&
!strncmp(user_input_buffer, "cso:", 4)) {
HTUserMsg(GOTO_CSO_DISALLOWED);
} else if (no_goto_finger &&
!strncmp(user_input_buffer, "finger:", 7)) {
HTUserMsg(GOTO_FINGER_DISALLOWED);
} else if (no_goto_ftp &&
!strncmp(user_input_buffer, "ftp:", 4)) {
HTUserMsg(GOTO_FTP_DISALLOWED);
} else if (no_goto_gopher &&
!strncmp(user_input_buffer, "gopher:", 7)) {
HTUserMsg(GOTO_GOPHER_DISALLOWED);
} else if (no_goto_http &&
!strncmp(user_input_buffer, "http:", 5)) {
HTUserMsg(GOTO_HTTP_DISALLOWED);
} else if (no_goto_https &&
!strncmp(user_input_buffer, "https:", 6)) {
HTUserMsg(GOTO_HTTPS_DISALLOWED);
} else if (no_goto_mailto &&
!strncmp(user_input_buffer, "mailto:", 7)) {
HTUserMsg(GOTO_MAILTO_DISALLOWED);
#ifndef DISABLE_NEWS
} else if (no_goto_news &&
!strncmp(user_input_buffer, "news:", 5)) {
HTUserMsg(GOTO_NEWS_DISALLOWED);
} else if (no_goto_nntp &&
!strncmp(user_input_buffer, "nntp:", 5)) {
HTUserMsg(GOTO_NNTP_DISALLOWED);
#endif
} else if (no_goto_rlogin &&
!strncmp(user_input_buffer, "rlogin:", 7)) {
HTUserMsg(GOTO_RLOGIN_DISALLOWED);
#ifndef DISABLE_NEWS
} else if (no_goto_snews &&
!strncmp(user_input_buffer, "snews:", 6)) {
HTUserMsg(GOTO_SNEWS_DISALLOWED);
#endif
} else if (no_goto_telnet &&
!strncmp(user_input_buffer, "telnet:", 7)) {
HTUserMsg(GOTO_TELNET_DISALLOWED);
} else if (no_goto_tn3270 &&
!strncmp(user_input_buffer, "tn3270:", 7)) {
HTUserMsg(GOTO_TN3270_DISALLOWED);
} else if (no_goto_wais &&
!strncmp(user_input_buffer, "wais:", 5)) {
HTUserMsg(GOTO_WAIS_DISALLOWED);
} else if (no_goto_configinfo &&
(!strncmp(user_input_buffer, "LYNXCFG:", 8) ||
!strncmp(user_input_buffer, "LYNXCOMPILEOPTS:", 16))) {
HTUserMsg(GOTO_SPECIAL_DISALLOWED);
} else if (!strncmp(user_input_buffer, "LYNXCOOKIE:", 11) ||
!strncmp(user_input_buffer, "LYNXDIRED:", 10) ||
!strncmp(user_input_buffer, "LYNXDOWNLOAD:", 13) ||
!strncmp(user_input_buffer, "LYNXOPTIONS:", 12) ||
!strncmp(user_input_buffer, "LYNXPRINT:", 10)) {
HTUserMsg(GOTO_SPECIAL_DISALLOWED);
} else {
StrAllocCopy(newdoc.address, user_input_buffer);
newdoc.isHEAD = FALSE;
/*
* Might be an anchor in the same doc from a POST
* form. If so, dont't free the content. -- FM
*/
if (are_different(&curdoc, &newdoc)) {
/*
* Make a name for this new URL.
*/
StrAllocCopy(newdoc.title, gettext("A URL specified by the user"));
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
force_load = TRUE;
#ifdef DIRED_SUPPORT
if (lynx_edit_mode)
HTuncache_current_document();
#endif /* DIRED_SUPPORT */
}
LYUserSpecifiedURL = TRUE;
HTAddGotoURL(newdoc.address);
}
break;
case LYK_DWIMHELP: /* show context-dependent help file */
/*
* Currently a different help file form the main
* 'helpfile' is shown only if current link is a
* text input form field. - kw
*/
if (curdoc.link >= 0 && curdoc.link < nlinks &&
links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
(links[curdoc.link].form->type == F_TEXT_TYPE ||
links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_PASSWORD_TYPE ||
links[curdoc.link].form->type == F_TEXTAREA_TYPE)) {
cshelpfile = LYLineeditHelpURL();
}
/* fall through to LYK_HELP */
case LYK_HELP: /* show help file */
if (cshelpfile == NULL)
cshelpfile = helpfile;
if (!STREQ(curdoc.address, cshelpfile)) {
/*
* Set the filename.
*/
StrAllocCopy(newdoc.address, cshelpfile);
/*
* Make a name for this help file.
*/
StrAllocCopy(newdoc.title, gettext("Help Screen"));
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
}
cshelpfile = NULL; /* reset pointer - kw */
break;
case LYK_INDEX: /* index file */
/*
* Make sure we are not in the index already.
*/
if (!STREQ(curdoc.address, indexfile)) {
if (indexfile[0]=='\0') { /* no defined index */
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_INDEX_FILE);
}
} else {
StrAllocCopy(newdoc.address, indexfile);
StrAllocCopy(newdoc.title, gettext("System Index")); /* name it */
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
} /* end else */
} /* end if */
break;
case LYK_MAIN_MENU: /* return to main screen */
/*
* If its already the homepage then don't reload it.
*/
if (!STREQ(curdoc.address,homepage)) {
if (HTConfirmDefault(CONFIRM_MAIN_SCREEN, NO) == YES) {
StrAllocCopy(newdoc.address, homepage);
StrAllocCopy(newdoc.title, gettext("Entry into main screen"));
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
highlight(OFF, curdoc.link, prev_target);
#ifdef DIRED_SUPPORT
if (lynx_edit_mode)
HTuncache_current_document();
#endif /* DIRED_SUPPORT */
}
} else {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(IN_MAIN_SCREEN);
}
}
break;
case LYK_OPTIONS: /* options screen */
#ifdef DIRED_SUPPORT
c = dir_list_style;
#endif /* DIRED_SUPPORT */
#ifndef NO_OPTION_MENU
if (!LYUseFormsOptions) {
BOOLEAN LYUseDefaultRawMode_flag = LYUseDefaultRawMode;
BOOLEAN LYSelectPopups_flag = LYSelectPopups;
BOOLEAN verbose_img_flag = verbose_img;
BOOLEAN keypad_mode_flag = keypad_mode;
BOOLEAN show_dotfiles_flag = show_dotfiles;
BOOLEAN user_mode_flag = user_mode;
int CurrentAssumeCharSet_flag = UCLYhndl_for_unspec;
int CurrentCharSet_flag = current_char_set;
int HTfileSortMethod_flag = HTfileSortMethod;
char *CurrentUserAgent = NULL;
char *CurrentNegoLanguage = NULL;
char *CurrentNegoCharset = NULL;
StrAllocCopy(CurrentUserAgent, (LYUserAgent ?
LYUserAgent : ""));
StrAllocCopy(CurrentNegoLanguage, (language ?
language : ""));
StrAllocCopy(CurrentNegoCharset, (pref_charset ?
pref_charset : ""));
LYoptions(); /** do the old-style options stuff **/
if (keypad_mode_flag != keypad_mode ||
(user_mode_flag != user_mode &&
(user_mode_flag == NOVICE_MODE ||
user_mode == NOVICE_MODE)) ||
(((HTfileSortMethod_flag != HTfileSortMethod) ||
#ifdef DIRED_SUPPORT
(c != dir_list_style) ||
#endif /* DIRED_SUPPORT */
(show_dotfiles_flag != show_dotfiles)) &&
(!strncmp(curdoc.address, "file:", 5) ||
!strncmp(curdoc.address, "ftp:", 4))) ||
CurrentCharSet_flag != current_char_set ||
CurrentAssumeCharSet_flag != UCLYhndl_for_unspec ||
verbose_img_flag != verbose_img ||
LYUseDefaultRawMode_flag != LYUseDefaultRawMode ||
LYSelectPopups_flag != LYSelectPopups ||
((strcmp(CurrentUserAgent, (LYUserAgent ?
LYUserAgent : "")) ||
strcmp(CurrentNegoLanguage, (language ?
language : "")) ||
strcmp(CurrentNegoCharset, (pref_charset ?
pref_charset : ""))) &&
(!strncmp(curdoc.address, "http", 4) ||
!strncmp(curdoc.address, "lynxcgi:", 8)))) {
/*
* Check if this is a reply from a POST, and if so,
* seek confirmation of reload if the safe element
* is not set. - FM
*/
if ((curdoc.post_data != NULL &&
curdoc.safe != TRUE) &&
confirm_post_resub(curdoc.address, curdoc.title,
2, 1) == FALSE) {
HTInfoMsg(WILL_NOT_RELOAD_DOC);
} else {
StrAllocCopy(newdoc.address, curdoc.address);
if (((strcmp(CurrentUserAgent, (LYUserAgent ?
LYUserAgent : "")) ||
strcmp(CurrentNegoLanguage,
(language ? language : "")) ||
strcmp(CurrentNegoCharset,
(pref_charset ? pref_charset : ""))) &&
(strncmp(curdoc.address, "http", 4) == 0 ||
strncmp(curdoc.address, "lynxcgi:", 8) == 0))) {
/*
* An option has changed which may influence
* content negotiation, and the resource is from
* a http or https or lynxcgi URL (the only protocols
* which currently do anything with this information).
* Set reloading = TRUE so that proxy caches will be
* flushed, which is necessary until the time when
* all proxies understand HTTP 1.1 Vary: and all
* Servers properly use it... Treat like
* case LYK_RELOAD (see comments there). - KW
*/
reloading = TRUE;
}
if (HTisDocumentSource()) {
#ifndef USE_PSRC
HTOutputFormat = WWW_SOURCE;
#else
if (LYpsrc)
psrc_view = TRUE;
else
HTOutputFormat = WWW_SOURCE;
#endif
}
#ifdef SOURCE_CACHE
if (reloading == FALSE) {
/* one more attempt to be smart enough: */
if (HTreparse_document()) {
FREE(CurrentUserAgent);
FREE(CurrentNegoLanguage);
FREE(CurrentNegoCharset);
break;
}
}
#endif
HEAD_request = HTLoadedDocumentIsHEAD();
HTuncache_current_document();
#ifdef NO_ASSUME_SAME_DOC
newdoc.line = 1;
newdoc.link = 0;
#else
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
#endif /* NO_ASSUME_SAME_DOC */
LYforce_no_cache = TRUE;
FREE(curdoc.address); /* So it doesn't get pushed. */
}
}
FREE(CurrentUserAgent);
FREE(CurrentNegoLanguage);
FREE(CurrentNegoCharset);
refresh_screen = TRUE; /* to repaint screen */
break;
} /* end if !LYUseFormsOptions */
#endif /* !NO_OPTION_MENU */
#ifndef NO_OPTION_FORMS
/*
* Generally stolen from LYK_COOKIE_JAR. Options menu handling is
* done in postoptions(), called from getfile() currently.
*
* postoptions() is also responsible for reloading the document
* before the 'options menu' but only when (a few) important
* options were changed.
*
* It is critical that post_data is freed here since the
* submission of changed options is done via the same protocol as
* LYNXOPTIONS:
*/
/*
* Don't do if already viewing options page.
*/
if (strcmp((curdoc.title ? curdoc.title : ""), OPTIONS_TITLE)) {
StrAllocCopy(newdoc.address, "LYNXOPTIONS:/");
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
LYforce_no_cache = TRUE;
/* change to 'if (check_realm && !LYValidate)' and
make change near top of getfile to forbid
using forms options menu with -validate: - kw */
if (LYValidate || check_realm) {
LYPermitURL = TRUE;
}
} else {
/*
* If already in the options menu, get out.
*/
cmd = LYK_PREV_DOC;
goto new_cmd;
}
#endif /* !NO_OPTION_FORMS */
break;
case LYK_INDEX_SEARCH: /* search for a user string */
if (is_www_index) {
/*
* Perform a database search.
*
* do_www_search will try to go out and get the document.
* If it returns TRUE, a new document was returned and is
* named in the newdoc.address.
*/
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
if (do_www_search(&newdoc) == NORMAL) {
/*
* Yah, the search succeeded.
*/
if (TRACE && !LYUseTraceLog && LYCursesON) {
/*
* Make sure cursor is down.
*/
move(LYlines-1, LYcols-1);
#ifdef USE_SLANG
addstr("\n");
#endif /* USE_SLANG */
refresh();
}
LYpush(&curdoc, ForcePush);
/*
* Make the curdoc.address the newdoc.address so that
* getfile doesn't try to get the newdoc.address.
* Since we have already gotten it.
*/
StrAllocCopy(curdoc.address, newdoc.address);
StrAllocCopy(newdoc.post_data, curdoc.post_data);
newdoc.internal_link = FALSE;
curdoc.line = -1;
Newline = 0;
refresh_screen = TRUE; /* redisplay it */
} else if (use_this_url_instead != NULL) {
/*
* Got back a redirecting URL. Check it out.
*/
_user_message("Using %s", use_this_url_instead);
/*
* Make a name for this URL.
*/
StrAllocCopy(newdoc.title,
"A URL specified by redirection");
StrAllocCopy(newdoc.address, use_this_url_instead);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
FREE(use_this_url_instead);
force_load = TRUE;
break;
} else {
/*
* Yuk, the search failed. Restore the old file.
*/
StrAllocCopy(newdoc.address, curdoc.address);
StrAllocCopy(newdoc.post_data, curdoc.post_data);
StrAllocCopy(newdoc.post_content_type,
curdoc.post_content_type);
StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
newdoc.isHEAD = curdoc.isHEAD;
newdoc.safe = curdoc.safe;
newdoc.internal_link = curdoc.internal_link;
}
} else if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NOT_ISINDEX);
}
break;
case LYK_WHEREIS: /* search within the document */
case LYK_NEXT: /* search for the next occurrence in the document */
/* user search */
{
BOOLEAN have_target_onscreen = (*prev_target != '\0' &&
HText_pageHasPrevTarget());
BOOL found;
int oldcur = curdoc.link; /* temporarily remember */
char *remember_old_target = NULL;
if (have_target_onscreen)
StrAllocCopy(remember_old_target, prev_target);
else
StrAllocCopy(remember_old_target, "");
if (cmd != LYK_NEXT) {
/*
* Reset prev_target to force prompting
* for a new search string and to turn
* off highlighting in no search string
* is entered by the user.
*/
*prev_target = '\0';
found = textsearch(&curdoc, prev_target, FALSE);
} else {
/*
* When the third argument is TRUE, the previous
* search string, if any, will be recalled from
* a buffer, loaded into prev_target, and used
* for the search without prompting for a new
* search string. This allows the LYK_NEXT
* command to repeat a search in a new document,
* after prev_target was reset on fetch of that
* document.
*/
found = textsearch(&curdoc, prev_target, TRUE);
}
/*
* Force a redraw to ensure highlighting of hits
* even when found on the same page, or clearing
* of highlighting is the default search string
* was erased without replacement. - FM
*/
/*
** Well let's try to avoid it at least in a few cases
** where it is not needed. - kw
*/
if (www_search_result >= 0 && www_search_result != curdoc.line) {
refresh_screen = TRUE; /* doesn't really matter */
} else if (!found) {
refresh_screen = have_target_onscreen;
} else if (!have_target_onscreen && found) {
refresh_screen = TRUE;
} else if (www_search_result == curdoc.line &&
curdoc.link == oldcur &&
curdoc.link >= 0 && nlinks > 0 &&
links[curdoc.link].ly >= (display_lines/3)) {
refresh_screen = TRUE;
} else if ((case_sensitive && 0!=strcmp(prev_target,
remember_old_target)) ||
(!case_sensitive && 0!=strcasecomp8(prev_target,
remember_old_target))) {
refresh_screen = TRUE;
}
FREE(remember_old_target);
}
break;
case LYK_COMMENT: /* reply by mail */
if (!owner_address &&
strncasecomp(curdoc.address, "http", 4)) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_OWNER);
}
} else if (no_mail) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(MAIL_DISALLOWED);
}
} else {
if (HTConfirmDefault(CONFIRM_COMMENT, NO)) {
if (!owner_address) {
/*
* No owner defined, so make a guess and
* and offer it to the user. - FM
*/
char *address = NULL;
temp = HTParse(curdoc.address, "", PARSE_PATH);
if (temp != NULL) {
HTUnEscape(temp);
if (*temp == '~' && strlen(temp) > 1) {
/*
* It's a ~user URL so guess user@host. - FM
*/
if ((cp = strchr((temp+1), '/')) != NULL)
*cp = '\0';
StrAllocCopy(address, "mailto:");
StrAllocCat(address, (temp+1));
StrAllocCat(address, "@");
}
FREE(temp);
}
if (address == NULL)
/*
* Wasn't a ~user URL so guess WebMaster@host. - FM
*/
StrAllocCopy(address, "mailto:WebMaster@");
temp = HTParse(curdoc.address, "", PARSE_HOST);
StrAllocCat(address, temp);
HTSprintf0(&temp, NO_OWNER_USE, address);
c = HTConfirmDefault(temp, NO);
FREE(temp);
if (c == YES) {
StrAllocCopy(owner_address, address);
FREE(address);
} else {
FREE(address);
break;
}
}
if (is_url(owner_address) != MAILTO_URL_TYPE) {
/*
* The address is a URL. Just follow the link.
*/
StrAllocCopy(newdoc.address, owner_address);
newdoc.internal_link = FALSE;
} else {
/*
* The owner_address is a mailto: URL.
*/
CONST char *kp = HText_getRevTitle();
CONST char *id = HText_getMessageID();
char *tmptitle = NULL;
if (!kp && HTMainAnchor) {
kp = HTAnchor_subject(HTMainAnchor);
if (kp && *kp) {
if (strncasecomp(kp, "Re: ", 4)) {
StrAllocCopy(tmptitle, "Re: ");
StrAllocCat(tmptitle, kp);
kp = tmptitle;
}
}
}
if (strchr(owner_address,':')!=NULL)
/*
* Send a reply. The address is after the colon.
*/
reply_by_mail(strchr(owner_address,':')+1,
curdoc.address,
(kp ? kp : ""), id);
else
reply_by_mail(owner_address, curdoc.address,
(kp ? kp : ""), id);
FREE(tmptitle);
refresh_screen = TRUE; /* to force a showpage */
}
}
}
break;
#ifdef DIRED_SUPPORT
case LYK_TAG_LINK: /* tag or untag the current link */
if (lynx_edit_mode && nlinks > 0 && !no_dired_support) {
if (!strcmp(links[curdoc.link].hightext, ".."))
break; /* Never tag the parent directory */
if (dir_list_style == MIXED_STYLE) {
if (!strcmp(links[curdoc.link].hightext, "../"))
break;
} else if (!strncmp(links[curdoc.link].hightext, "Up to ", 6))
break;
{
/*
* HTList-based management of tag list, see LYLocal.c - KW
*/
HTList * t1 = tagged;
char * tagname = NULL;
BOOLEAN found = FALSE;
while ((tagname = (char *)HTList_nextObject(t1)) != NULL) {
if (!strcmp(links[curdoc.link].lname, tagname)) {
found = TRUE;
HTList_removeObject(tagged, tagname);
FREE(tagname);
tagflag(OFF,curdoc.link);
break;
}
}
if (!found) {
if (tagged == NULL)
tagged = HTList_new();
tagname = NULL;
StrAllocCopy(tagname,links[curdoc.link].lname);
HTList_addObject(tagged,tagname);
tagflag(ON,curdoc.link);
}
}
if (curdoc.link < nlinks-1) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link++;
} else if (!more && Newline == 1 && curdoc.link == nlinks-1) {
highlight(OFF, curdoc.link, prev_target);
curdoc.link = 0;
} else if (more) { /* next page */
Newline += (display_lines);
}
}
break;
case LYK_MODIFY: /* rename a file or directory */
if (lynx_edit_mode && nlinks > 0 && !no_dired_support) {
int ret;
ret = local_modify(&curdoc, &newdoc.address);
if (ret == PERMIT_FORM_RESULT) { /* Permit form thrown up */
refresh_screen = TRUE;
} else if (ret) {
HTuncache_current_document();
StrAllocCopy(newdoc.address, curdoc.address);
FREE(curdoc.address);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
clear();
}
}
break;
case LYK_CREATE: /* create a new file or directory */
if (lynx_edit_mode && !no_dired_support) {
if (local_create(&curdoc)) {
HTuncache_current_document();
StrAllocCopy(newdoc.address, curdoc.address);
FREE(curdoc.address);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.line = curdoc.line;
newdoc.link = curdoc.link > -1 ? curdoc.link : 0;
clear();
}
}
break;
#endif /* DIRED_SUPPORT */
case LYK_DWIMEDIT: /* context-dependent edit */
#ifdef AUTOEXTEDIT
/*
* If we're in a forms TEXTAREA, invoke the editor on *its*
* contents, rather than attempting to edit the html source
* document. KED
*/
if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type == F_TEXTAREA_TYPE) {
cmd = LYK_EDIT_TEXTAREA;
goto new_cmd;
}
/*
* If we're in a forms TEXT type, tell user the request
* is bogus (though in reality, without this trap, if the
* document with the TEXT field is local, the editor *would*
* be invoked on the source .html file; eg, the o(ptions)
* form tempfile).
*
* [This is done to avoid possible user confusion, due to
* auto invocation of the editor on the TEXTAREA's contents
* via the above if() statement.]
*/
if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type == F_TEXT_TYPE) {
HTUserMsg (CANNOT_EDIT_FIELD);
break;
}
if (no_editor) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(ANYEDIT_DISABLED);
}
break;
} /* fall through */
#endif /* AUTOEXTEDIT */
case LYK_EDIT: /* edit */
if (no_editor) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(EDIT_DISABLED);
}
break;
}
#ifdef DIRED_SUPPORT
/*
* Allow the user to edit the link rather
* than curdoc in edit mode.
*/
if (lynx_edit_mode &&
editor && *editor != '\0' && !no_dired_support) {
if (nlinks > 0) {
cp = links[curdoc.link].lname;
if (is_url(cp) == FILE_URL_TYPE) {
cp = HTfullURL_toFile(cp);
StrAllocCopy(tp, cp);
FREE(cp);
if (stat(tp, &dir_info) == -1) {
HTAlert(NO_STATUS);
} else {
if (S_ISREG(dir_info.st_mode)) {
StrAllocCopy(tp, links[curdoc.link].lname);
HTUnEscapeSome(tp, "/");
if (edit_current_file(tp,
curdoc.link, Newline)) {
HTuncache_current_document();
StrAllocCopy(newdoc.address,
curdoc.address);
FREE(curdoc.address);
#ifdef NO_SEEK_OLD_POSITION
/*
* Go to top of file.
*/
newdoc.line = 1;
newdoc.link = 0;
#else
/*
* Seek old position,
* which probably changed.
*/
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
#endif /* NO_SEEK_OLD_POSITION */
clear(); /* clear the screen */
}
}
}
FREE(tp);
}
}
} else
#endif /* DIRED_SUPPORT */
if (editor && *editor != '\0') {
if (edit_current_file(newdoc.address, curdoc.link, Newline)) {
HTuncache_current_document();
LYforce_no_cache = TRUE; /*force reload of document */
FREE(curdoc.address); /* so it doesn't get pushed */
#ifdef NO_SEEK_OLD_POSITION
/*
* Go to top of file.
*/
newdoc.line = 1;
newdoc.link = 0;
#else
/*
* Seek old position, which probably changed.
*/
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
#endif /* NO_SEEK_OLD_POSITION */
clear(); /* clear the screen */
}
} else {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_EDITOR);
}
}
break;
case LYK_DEL_BOOKMARK: /* remove a bookmark file link */
#ifdef DIRED_SUPPORT
case LYK_REMOVE: /* remove files and directories */
c = NO;
if (lynx_edit_mode && nlinks > 0 && !no_dired_support) {
local_remove(&curdoc);
c = YES;
} else
#endif /* DIRED_SUPPORT */
if (curdoc.bookmark != NULL) {
if ((c = HTConfirmDefault(CONFIRM_BOOKMARK_DELETE,NO)) != YES)
break;
remove_bookmark_link(links[curdoc.link].anchor_number-1,
curdoc.bookmark);
} else { /* behave like REFRESH for backward compatibility */
refresh_screen = TRUE;
if (old_c != real_c) {
old_c = real_c;
lynx_force_repaint();
}
break;
}
if (c == YES) {
HTuncache_current_document();
StrAllocCopy(newdoc.address, curdoc.address);
FREE(curdoc.address);
newdoc.line = curdoc.line;
if (curdoc.link == nlinks-1) {
/*
* We deleted the last link on the page. - FM
*/
newdoc.link = curdoc.link-1;
} else {
newdoc.link = curdoc.link;
}
}
break;
#ifdef DIRED_SUPPORT
case LYK_INSTALL: /* install a file into system area */
if (lynx_edit_mode && nlinks > 0 && !no_dired_support)
local_install(NULL, links[curdoc.link].lname, &newdoc.address);
break;
#endif /* DIRED_SUPPORT */
case LYK_INFO: /* show document info */
/*
* Don't do if already viewing info page.
*/
if (strcmp((curdoc.title ? curdoc.title : ""),
SHOWINFO_TITLE)) {
if (do_change_link(prev_target) == -1)
break; /* mouse stuff was confused, ignore - kw */
if (showinfo(&curdoc, HText_getNumOfLines(),
&newdoc, owner_address) < 0)
break;
StrAllocCopy(newdoc.title, SHOWINFO_TITLE);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
LYforce_no_cache = TRUE;
if (LYValidate || check_realm)
LYPermitURL = TRUE;
} else {
/*
* If already in info page, get out.
*/
cmd = LYK_PREV_DOC;
goto new_cmd;
}
break;
case LYK_EDIT_TEXTAREA: /* use external editor on a TEXTAREA - KED */
if (no_editor) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(ANYEDIT_DISABLED);
}
break;
}
if (!editor || *editor == '\0') {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_EDITOR);
}
break;
}
/*
* See if the current link is in a form TEXTAREA.
*/
if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type == F_TEXTAREA_TYPE) {
/* stop screen */
stop_curses();
n = HText_ExtEditForm (&links[curdoc.link]);
/*
* TODO: Move cursor "n" lines from the current line to
* position it on the 1st trailing blank line in
* the now edited TEXTAREA. If the target line/
* anchor requires us to scroll up/down, position
* the target in the approximate center of the
* screen.
*/
/* curdoc.link += n;*/ /* works, except for page crossing, */
/* damnit; why is nothing ever easy */
/* start screen */
start_curses();
refresh_screen = TRUE;
} else {
HTInfoMsg (NOT_IN_TEXTAREA_NOEDIT);
}
break;
case LYK_GROW_TEXTAREA: /* add new lines to bottom of TEXTAREA - KED */
/*
* See if the current link is in a form TEXTAREA.
*/
if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type == F_TEXTAREA_TYPE) {
HText_ExpandTextarea (&links[curdoc.link], TEXTAREA_EXPAND_SIZE);
refresh_screen = TRUE;
} else {
HTInfoMsg (NOT_IN_TEXTAREA);
}
break;
case LYK_INSERT_FILE: /* insert file in TEXTAREA, above cursor - KED */
/*
* See if the current link is in a form TEXTAREA.
*/
if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->type == F_TEXTAREA_TYPE) {
/*
* Reject attempts to use this for gaining access to
* local files when such access is restricted:
* if no_file_url was set via the file_url restriction,
* if no_goto_file was set for the anonymous account,
* or if HTDirAccess was set to HT_DIR_FORBID or
* HT_DIR_SELECTIVE via the -nobrowse or -selective
* switches, it is assumed that inserting files or
* checking for existence of files needs to be denied. - kw
*/
if (no_file_url || no_goto_file ||
HTDirAccess == HT_DIR_FORBID ||
HTDirAccess == HT_DIR_SELECTIVE) {
if (old_c != real_c) {
old_c = real_c;
if (no_goto_file)
HTUserMsg(GOTO_FILE_DISALLOWED);
else
HTUserMsg(NOAUTH_TO_ACCESS_FILES);
HTInfoMsg(FILE_INSERT_CANCELLED);
}
break;
}
n = HText_InsertFile (&links[curdoc.link]);
/*
* TODO: Move cursor "n" lines from the current line to
* position it on the 1st line following the text
* that was inserted. If the target line/anchor
* requires us to scroll up/down, position the
* target in the approximate center of the screen.
*
* [Current behavior leaves cursor on the same line relative
* to the start of the TEXTAREA that it was on before the
* insertion. This is the same behavior that occurs with
* (my) editor, so this TODO will stay unimplemented.]
*/
refresh_screen = TRUE;
} else {
HTInfoMsg (NOT_IN_TEXTAREA);
}
break;
case LYK_PRINT: /* print the file */
if (LYValidate) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(PRINT_DISABLED);
}
break;
}
/*
* Don't do if already viewing print options page.
*/
if (strcmp((curdoc.title ? curdoc.title : ""),
PRINT_OPTIONS_TITLE)) {
if (print_options(&newdoc.address,
&curdoc.address, HText_getNumOfLines()) < 0)
break;
StrAllocCopy(newdoc.title, PRINT_OPTIONS_TITLE);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
ForcePush = TRUE; /* see LYpush() and print_options() */
if (check_realm)
LYPermitURL = TRUE;
refresh_screen = TRUE; /* redisplay */
}
break;
case LYK_LIST: /* list links in the current document */
/*
* Don't do if already viewing list page.
*/
if (!strcmp((curdoc.title ? curdoc.title : ""),
LIST_PAGE_TITLE)) {
/*
* Already viewing list page, so get out.
*/
cmd = LYK_PREV_DOC;
goto new_cmd;
}
/*
* Print list page to file.
*/
if (showlist(&newdoc, TRUE) < 0)
break;
StrAllocCopy(newdoc.title, LIST_PAGE_TITLE);
/*
* showlist will set newdoc's other fields. It may leave
* post_data intact so the list can be used to follow
* internal links in the current document even if it is
* a POST response. - kw
*/
refresh_screen = TRUE; /* redisplay */
if (LYValidate || check_realm) {
LYPermitURL = TRUE;
StrAllocCopy(lynxlistfile, newdoc.address);
}
break;
#ifdef EXP_ADDRLIST_PAGE
case LYK_ADDRLIST: /* always list URL's (only) */
/*
* Don't do if already viewing list addresses page.
*/
if (!strcmp((curdoc.title ? curdoc.title : ""),
ADDRLIST_PAGE_TITLE)) {
/*
* Already viewing list page, so get out.
*/
cmd = LYK_PREV_DOC;
goto new_cmd;
}
/*
* Print address list page to file.
*/
if (showlist(&newdoc, FALSE) < 0)
break;
StrAllocCopy(newdoc.title, ADDRLIST_PAGE_TITLE);
/*
* showlist will set newdoc's other fields. It may leave
* post_data intact so the list can be used to follow
* internal links in the current document even if it is
* a POST response. - kw
*/
refresh_screen = TRUE; /* redisplay */
if (LYValidate || check_realm) {
LYPermitURL = TRUE;
StrAllocCopy(lynxlistfile, newdoc.address);
}
break;
#endif /* EXP_ADDRLIST_PAGE */
case LYK_VLINKS: /* list links visited during the current session */
if (!strcmp((curdoc.title ? curdoc.title : ""),
VISITED_LINKS_TITLE)) {
/*
* Already viewing visited links page, so get out.
*/
cmd = LYK_PREV_DOC;
goto new_cmd;
}
/*
* Print visited links page to file.
*/
if (LYShowVisitedLinks(&newdoc.address) < 0) {
HTUserMsg(VISITED_LINKS_EMPTY);
break;
}
StrAllocCopy(newdoc.title, VISITED_LINKS_TITLE);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
refresh_screen = TRUE;
if (LYValidate || check_realm) {
LYPermitURL = TRUE;
StrAllocCopy(lynxlinksfile, newdoc.address);
}
break;
case LYK_TOOLBAR: /* go to Toolbar or Banner in current document */
if (!HText_hasToolbar(HTMainText)) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_TOOLBAR);
}
} else if (old_c != real_c) {
old_c = real_c;
if ((cp = strchr(curdoc.address, '#')) != NULL)
*cp = '\0';
toolbar = (char *)malloc(strlen(curdoc.address) +
strlen(LYToolbarName) + 2);
if (!toolbar)
outofmem(__FILE__, "mainloop");
sprintf(toolbar, "%s#%s", curdoc.address, LYToolbarName);
if (cp)
*cp = '#';
StrAllocCopy(newdoc.address, toolbar);
FREE(toolbar);
try_internal = TRUE;
force_load = TRUE; /* force MainLoop to reload */
}
break;
#if defined(DIRED_SUPPORT) || defined(VMS)
case LYK_DIRED_MENU: /* provide full file management menu */
#ifdef VMS
/*
* Check if the CSwing Directory/File Manager is available.
* Will be disabled if LYCSwingPath is NULL, zero-length,
* or "none" (case insensitive), if no_file_url was set via
* the file_url restriction, if no_goto_file was set for
* the anonymous account, or if HTDirAccess was set to
* HT_DIR_FORBID or HT_DIR_SELECTIVE via the -nobrowse
* or -selective switches. - FM
*/
if (!(LYCSwingPath && *LYCSwingPath) ||
!strcasecomp(LYCSwingPath, "none") ||
no_file_url || no_goto_file ||
HTDirAccess == HT_DIR_FORBID ||
HTDirAccess == HT_DIR_SELECTIVE) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(DFM_NOT_AVAILABLE);
}
break;
}
/*
* If we are viewing a local directory listing or a
* local file which is not temporary, invoke CSwing
* with the URL's directory converted to VMS path specs
* and passed as the argument, so we start up CSwing
* positioned on that node of the directory tree.
* Otherwise, pass the current default directory as
* the argument. - FM
*/
if (LYisLocalFile(curdoc.address) &&
strncasecomp(curdoc.address,
lynx_temp_space, strlen(lynx_temp_space))) {
/*
* We are viewing a local directory or a local file
* which is not temporary. - FM
*/
struct stat stat_info;
cp = HTParse(curdoc.address, "", PARSE_PATH|PARSE_PUNCTUATION);
HTUnEscape(cp);
if (HTStat(cp, &stat_info) == -1) {
CTRACE(tfp, "mainloop: Can't stat %s\n", cp);
FREE(cp);
temp = (char *)calloc(1, (strlen(LYCSwingPath) + 4));
if (temp == NULL)
outofmem(__FILE__, "mainloop");
sprintf(temp, "%s []", LYCSwingPath);
refresh_screen = TRUE; /* redisplay */
} else {
char *VMSdir = NULL;
if (S_ISDIR(stat_info.st_mode)) {
/*
* We're viewing a local directory. Make
* that the CSwing argument. - FM
*/
LYAddPathSep(&cp);
StrAllocCopy(VMSdir, HTVMS_name("", cp));
FREE(cp);
} else {
/*
* We're viewing a local file. Make it's
* directory the CSwing argument. - FM
*/
StrAllocCopy(VMSdir, HTVMS_name("", cp));
FREE(cp);
if ((cp = strrchr(VMSdir, ']')) != NULL) {
*(cp + 1) = '\0';
cp == NULL;
} else if ((cp = strrchr(VMSdir, ':')) != NULL) {
*(cp + 1) = '\0';
cp == NULL;
}
}
temp = (char *)calloc(1,
(strlen(LYCSwingPath) +
strlen(VMSdir) +
2));
if (temp == NULL)
outofmem(__FILE__, "mainloop");
sprintf(temp, "%s %s", LYCSwingPath, VMSdir);
FREE(VMSdir);
/*
* Uncache the current document in case we
* change, move, or delete it during the
* CSwing session. - FM
*/
HTuncache_current_document();
StrAllocCopy(newdoc.address, curdoc.address);
StrAllocCopy(newdoc.title,
curdoc.title ? curdoc.title : "");
StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
FREE(curdoc.address);
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
}
} else {
/*
* We're not viewing a local directory or file.
* Pass CSwing the current default directory as
* an argument and don't uncache the current
* document. - FM
*/
temp = (char *)calloc(1, (strlen(LYCSwingPath) + 4));
if (temp == NULL)
outofmem(__FILE__, "mainloop");
sprintf(temp, "%s []", LYCSwingPath);
refresh_screen = TRUE; /* redisplay */
}
stop_curses();
LYSystem(temp);
start_curses();
FREE(temp);
break;
#else
/*
* Don't do if not allowed or already viewing the menu.
*/
if (lynx_edit_mode && !no_dired_support &&
strcmp(curdoc.address, LYDiredFileURL) &&
strcmp((curdoc.title ? curdoc.title : ""),
DIRED_MENU_TITLE)) {
dired_options(&curdoc,&newdoc.address);
refresh_screen = TRUE; /* redisplay */
}
break;
#endif /* VMS */
#endif /* DIRED_SUPPORT || VMS*/
#ifdef USE_EXTERNALS
case LYK_EXTERN: /* use external program on url */
if ((nlinks > 0) && (links[curdoc.link].lname != NULL))
{
run_external(links[curdoc.link].lname);
refresh_screen = TRUE;
}
break;
#endif /* USE_EXTERNALS */
case LYK_ADD_BOOKMARK: /* add link to bookmark file */
if (LYValidate) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(BOOKMARKS_DISABLED);
}
break;
}
if (strcmp((curdoc.title ? curdoc.title : ""),
HISTORY_PAGE_TITLE) &&
strcmp((curdoc.title ? curdoc.title : ""),
SHOWINFO_TITLE) &&
strcmp((curdoc.title ? curdoc.title : ""),
PRINT_OPTIONS_TITLE) &&
#ifdef DIRED_SUPPORT
strcmp(curdoc.address, LYDiredFileURL) &&
strcmp((curdoc.title ? curdoc.title : ""),
DIRED_MENU_TITLE) &&
strcmp(curdoc.address, LYPermitFileURL) &&
strcmp((curdoc.title ? curdoc.title : ""),
PERMIT_OPTIONS_TITLE) &&
strcmp(curdoc.address, LYUploadFileURL) &&
strcmp((curdoc.title ? curdoc.title : ""),
UPLOAD_OPTIONS_TITLE) &&
#endif /* DIRED_SUPPORT */
strcmp((curdoc.title ? curdoc.title : ""),
DOWNLOAD_OPTIONS_TITLE) &&
strcmp((curdoc.title ? curdoc.title : ""),
COOKIE_JAR_TITLE) &&
strcmp((curdoc.title ? curdoc.title : ""),
OPTIONS_TITLE) &&
((nlinks <= 0) ||
(links[curdoc.link].lname != NULL &&
strncmp(links[curdoc.link].lname,
"LYNXHIST:", 9) &&
strncmp(links[curdoc.link].lname,
"LYNXPRINT:", 10) &&
strncmp(links[curdoc.link].lname,
"LYNXDIRED:", 10) &&
strncmp(links[curdoc.link].lname,
"LYNXDOWNLOAD:", 13) &&
strncmp(links[curdoc.link].lname,
"LYNXCOOKIE:", 11) &&
strncmp(links[curdoc.link].lname,
"LYNXOPTIONS:", 12) &&
strncmp(links[curdoc.link].lname,
"LYNXLIST:", 9)))) {
if (nlinks > 0) {
if (curdoc.post_data == NULL &&
curdoc.bookmark == NULL &&
!LYIsListpageTitle(curdoc.title ? curdoc.title : "") &&
strcmp((curdoc.title ? curdoc.title : ""),
VISITED_LINKS_TITLE)) {
/*
* The document doesn't have POST content,
* and is not a bookmark file, nor is the
* list or visited links page, so we can
* save either that or the link. - FM
*/
_statusline(BOOK_D_L_OR_CANCEL);
c = LYgetch_for(FOR_SINGLEKEY);
if (TOUPPER(c) == 'D') {
save_bookmark_link(curdoc.address, curdoc.title);
refresh_screen = TRUE; /* MultiBookmark support */
goto check_add_bookmark_to_self;
}
} else {
if (LYMultiBookmarks == FALSE &&
curdoc.bookmark != NULL &&
strstr(curdoc.address,
(*bookmark_page == '.'
?
(bookmark_page+1) : bookmark_page)) != NULL) {
/*
* If multiple bookmarks are disabled, offer
* the L)ink or C)ancel, but with wording
* which indicates that the link already
* exists in this bookmark file. - FM
*/
_statusline(MULTIBOOKMARKS_SELF);
} else if (curdoc.post_data != NULL &&
links[curdoc.link].type == WWW_INTERN_LINK_TYPE) {
/*
* Internal link, and document has POST content.
*/
HTUserMsg(NOBOOK_POST_FORM);
break;
} else {
/*
* Only offer the link in a document with
* POST content, or if the current document
* is a bookmark file and multiple bookmarks
* are enabled. - FM
*/
_statusline(BOOK_L_OR_CANCEL);
}
c = LYgetch_for(FOR_SINGLEKEY);
}
if (TOUPPER(c) == 'L') {
if (curdoc.post_data != NULL &&
links[curdoc.link].type == WWW_INTERN_LINK_TYPE) {
/*
* Internal link, and document has POST content.
*/
HTUserMsg(NOBOOK_POST_FORM);
break;
}
/*
* User does want to save the link. - FM
*/
if (links[curdoc.link].type != WWW_FORM_LINK_TYPE) {
save_bookmark_link(links[curdoc.link].lname,
links[curdoc.link].hightext);
refresh_screen = TRUE; /* MultiBookmark support */
} else {
HTUserMsg(NOBOOK_FORM_FIELD);
break;
}
} else {
break;
}
} else if (curdoc.post_data != NULL) {
/*
* No links, and document has POST content. - FM
*/
HTUserMsg(NOBOOK_POST_FORM);
break;
} else if (curdoc.bookmark != NULL) {
/*
* It's a bookmark file from which all
* of the links were deleted. - FM
*/
HTUserMsg(BOOKMARKS_NOLINKS);
break;
} else {
_statusline(BOOK_D_OR_CANCEL);
c = LYgetch_for(FOR_SINGLEKEY);
if (TOUPPER(c) == 'D') {
save_bookmark_link(curdoc.address, curdoc.title);
refresh_screen = TRUE; /* MultiBookmark support */
} else {
break;
}
}
check_add_bookmark_to_self:
if (curdoc.bookmark && BookmarkPage &&
!strcmp(curdoc.bookmark, BookmarkPage)) {
HTuncache_current_document();
StrAllocCopy(newdoc.address, curdoc.address);
StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
FREE(curdoc.address);
newdoc.line = curdoc.line;
newdoc.link = curdoc.link;
newdoc.internal_link = FALSE;
}
FREE(temp);
} else {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NOBOOK_HSML);
}
}
break;
case LYK_VIEW_BOOKMARK: /* v to view home page */
if (LYValidate) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(BOOKMARKS_DISABLED);
}
break;
}
/*
* See if a bookmark exists.
* If it does replace newdoc.address with it's name.
*/
if ((cp = get_bookmark_filename(&newdoc.address)) != NULL) {
if (*cp == '\0' || !strcmp(cp, " ") ||
!strcmp(curdoc.address, newdoc.address)) {
if (LYMultiBookmarks == TRUE)
refresh_screen = TRUE;
break;
}
LYforce_no_cache = TRUE; /*force the document to be reloaded*/
StrAllocCopy(newdoc.title, BOOKMARK_TITLE);
StrAllocCopy(newdoc.bookmark, BookmarkPage);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
} else {
if (old_c != real_c) {
old_c = real_c;
LYMBM_statusline(BOOKMARKS_NOT_OPEN);
sleep(AlertSecs);
if (LYMultiBookmarks == TRUE) {
refresh_screen = TRUE;
}
}
}
break;
case LYK_SHELL: /* shell escape */
if (!no_shell) {
stop_curses();
printf("%s\r\n", SPAWNING_MSG);
LYSystem(LYSysShell());
start_curses();
refresh_screen = TRUE; /* for an HText_pageDisplay() */
} else {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(SPAWNING_DISABLED);
}
}
break;
case LYK_DOWNLOAD:
/*
* Don't do if both download and disk_save are restricted.
*/
if (LYValidate ||
(no_download && !override_no_download && no_disk_save)) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(DOWNLOAD_DISABLED);
}
break;
}
/*
* Don't do if already viewing download options page.
*/
if (!strcmp((curdoc.title ? curdoc.title : ""),
DOWNLOAD_OPTIONS_TITLE))
break;
if (do_change_link(prev_target) == -1)
continue; /* mouse stuff was confused, ignore - kw */
if (nlinks > 0) {
if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
if (links[curdoc.link].form->type == F_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE) {
if (links[curdoc.link].form->submit_method ==
URL_MAIL_METHOD) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_DOWNLOAD_MAILTO_ACTION);
}
break;
}
if (!strncmp(links[curdoc.link].form->submit_action,
"LYNXOPTIONS:", 12)) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_DOWNLOAD_SPECIAL);
}
break;
}
HTOutputFormat = HTAtom_for("www/download");
LYforce_no_cache = TRUE;
cmd = LYK_ACTIVATE;
goto new_cmd;
}
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_DOWNLOAD_INPUT);
}
} else if (!strcmp((curdoc.title ? curdoc.title : ""),
COOKIE_JAR_TITLE)) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_DOWNLOAD_COOKIES);
}
} else if (!strcmp((curdoc.title ? curdoc.title : ""),
PRINT_OPTIONS_TITLE)) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_DOWNLOAD_PRINT_OP);
}
#ifdef DIRED_SUPPORT
} else if (!strcmp(curdoc.address, LYUploadFileURL) ||
!strcmp((curdoc.title ? curdoc.title : ""),
UPLOAD_OPTIONS_TITLE)) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_DOWNLOAD_UPLOAD_OP);
}
} else if (!strcmp(curdoc.address, LYPermitFileURL) ||
!strcmp((curdoc.title ? curdoc.title : ""),
PERMIT_OPTIONS_TITLE)) {
if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_DOWNLOAD_PERMIT_OP);
}
} else if (lynx_edit_mode && !no_dired_support) {
/*
* Don't bother making a /tmp copy of the local file.
*/
StrAllocCopy(temp, newdoc.address);
StrAllocCopy(newdoc.address, links[curdoc.link].lname);
if (LYdownload_options(&newdoc.address,
links[curdoc.link].lname) < 0)
StrAllocCopy(newdoc.address, temp);
else
newdoc.internal_link = FALSE;
FREE(temp);
#endif /* DIRED_SUPPORT */
} else if (!strcmp((curdoc.title ? curdoc.title : ""),
HISTORY_PAGE_TITLE) &&
!strncmp(links[curdoc.link].lname, "LYNXHIST:", 9)) {
int number = atoi(links[curdoc.link].lname+9);
if ((history[number].post_data != NULL &&
history[number].safe != TRUE) &&
HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
HTInfoMsg(CANCELLED);
break;
}
/*
* OK, we download from history page, restore URL from stack.
*/
StrAllocCopy(newdoc.address, history[number].address);
StrAllocCopy(newdoc.title, links[curdoc.link].hightext);
StrAllocCopy(newdoc.bookmark, history[number].bookmark);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
if (history[number].post_data)
StrAllocCopy(newdoc.post_data,
history[number].post_data);
if (history[number].post_content_type)
StrAllocCopy(newdoc.post_content_type,
history[number].post_content_type);
newdoc.isHEAD = history[number].isHEAD;
newdoc.safe = history[number].safe;
newdoc.internal_link = FALSE;
newdoc.link = 0;
HTOutputFormat = HTAtom_for("www/download");
LYUserSpecifiedURL = TRUE;
/*
* Force the document to be reloaded.
*/
LYforce_no_cache = TRUE;
} else if (!strncmp(links[curdoc.link].lname, "data:", 5)) {
if (old_c != real_c) {
old_c = real_c;
HTAlert(UNSUPPORTED_DATA_URL);
}
} else if (!strncmp(links[curdoc.link].lname,
"LYNXCOOKIE:", 11) ||
!strncmp(links[curdoc.link].lname,
"LYNXDIRED:", 10) ||
!strncmp(links[curdoc.link].lname,
"LYNXDOWNLOAD:", 13) ||
!strncmp(links[curdoc.link].lname,
"LYNXPRINT:", 10) ||
!strncmp(links[curdoc.link].lname,
"LYNXOPTIONS:", 12) ||
/* @@@ should next two be downloadable? - kw */
!strncmp(links[curdoc.link].lname,
"LYNXCFG:", 8) ||
!strncmp(links[curdoc.link].lname,
"LYNXCOMPILEOPTS:", 16) ||
!strncmp(links[curdoc.link].lname,
"lynxexec:", 9) ||
!strncmp(links[curdoc.link].lname,
"lynxprog:", 9)) {
HTUserMsg(NO_DOWNLOAD_SPECIAL);
} else if (!strncmp(links[curdoc.link].lname,
"mailto:", 7)) {
HTUserMsg(NO_DOWNLOAD_MAILTO_LINK);
/*
* From here on we could have a remote host, so check if
* that's allowed.
*
* We copy all these checks from getfile() to LYK_DOWNLOAD
* here because LYNXDOWNLOAD:// will NOT be pushing the
* previous document into the history stack so preserve
* getfile() from returning a wrong status (NULLFILE).
*/
} else if (local_host_only &&
!(LYisLocalHost(links[curdoc.link].lname) ||
LYisLocalAlias(links[curdoc.link].lname))) {
HTUserMsg(ACCESS_ONLY_LOCALHOST);
} else { /* Not a forms, options or history link */
/*
* Follow a normal link or anchor. Note that
* if it's an anchor within the same document,
* entire document will be downloaded.
*/
StrAllocCopy(newdoc.address, links[curdoc.link].lname);
StrAllocCopy(newdoc.title, links[curdoc.link].hightext);
#ifndef DONT_TRACK_INTERNAL_LINKS
/*
* Might be an internal link in the same doc from a
* POST form. If so, don't free the content. - kw
*/
if (links[curdoc.link].type != WWW_INTERN_LINK_TYPE)
#else
/*
* Might be an anchor in the same doc from a POST
* form. If so, don't free the content. -- FM
*/
if (are_different(&curdoc, &newdoc))
#endif /* TRACK_INTERNAL_LINKS */
{
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
}
newdoc.internal_link = FALSE;
newdoc.link = 0;
HTOutputFormat = HTAtom_for("www/download");
/*
* Force the document to be reloaded.
*/
LYforce_no_cache = TRUE;
}
} else if (old_c != real_c) {
old_c = real_c;
HTUserMsg(NO_DOWNLOAD_CHOICE);
}
break;
#ifdef DIRED_SUPPORT
case LYK_UPLOAD:
/*
* Don't do if already viewing upload options page.
*/
if (!strcmp(curdoc.address, LYUploadFileURL) ||
!strcmp((curdoc.title ? curdoc.title : ""),
UPLOAD_OPTIONS_TITLE))
break;
if (lynx_edit_mode && !no_dired_support) {
LYUpload_options((char **)&newdoc.address,
(char *)curdoc.address);
StrAllocCopy(newdoc.title, UPLOAD_OPTIONS_TITLE);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
/*
* Uncache the current listing so that it will
* be updated to included the uploaded file if
* placed in the current directory. - FM
*/
HTuncache_current_document();
}
break;
#endif /* DIRED_SUPPORT */
case LYK_TRACE_TOGGLE: /* Toggle TRACE mode. */
WWW_TraceFlag = ! WWW_TraceFlag;
if (LYOpenTraceLog())
HTUserMsg(WWW_TraceFlag ? TRACE_ON : TRACE_OFF);
break;
case LYK_TRACE_LOG: /* View TRACE log. */
/*
* Check whether we've started a TRACE log
* in this session. - FM
*/
if (LYTraceLogFP == NULL) {
HTUserMsg(NO_TRACELOG_STARTED);
break;
}
/*
* Don't do if already viewing the TRACE log. - FM
*/
if (!strcmp((curdoc.title ? curdoc.title : ""),
LYNX_TRACELOG_TITLE))
break;
/*
* If TRACE mode is on, turn it off during this fetch of the
* TRACE log, so we don't enter stuff about this fetch, and
* set a flag for turning it back on when we return to this
* loop. Note that we'll miss any messages about memory
* exhaustion if it should occur. It seems unlikely that
* anything else bad might happen, but if it does, we'll
* miss messages about that too. We also fflush(), close,
* and open it again, to make sure all stderr messages thus
* far will be in the log. - FM
*/
if (!LYReopenTracelog(&trace_mode_flag))
break;
LYLocalFileToURL (&(newdoc.address), LYTraceLogPath);
StrAllocCopy(newdoc.title, LYNX_TRACELOG_TITLE);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
if (LYValidate || check_realm) {
LYPermitURL = TRUE;
}
LYforce_no_cache = TRUE;
break;
case LYK_IMAGE_TOGGLE:
if (clickable_images)
clickable_images = FALSE;
else
clickable_images = TRUE;
HTUserMsg(clickable_images ?
CLICKABLE_IMAGES_ON : CLICKABLE_IMAGES_OFF);
#ifdef SOURCE_CACHE
if (HTreparse_document()) {
break;
}
#endif
cmd = LYK_RELOAD;
goto new_cmd;
case LYK_INLINE_TOGGLE:
if (pseudo_inline_alts)
pseudo_inline_alts = FALSE;
else
pseudo_inline_alts = TRUE;
HTUserMsg(pseudo_inline_alts ?
PSEUDO_INLINE_ALTS_ON : PSEUDO_INLINE_ALTS_OFF);
#ifdef SOURCE_CACHE
if (HTreparse_document()) {
break;
}
#endif
cmd = LYK_RELOAD;
goto new_cmd;
case LYK_RAW_TOGGLE:
if (HTLoadedDocumentCharset()) {
HTUserMsg(gettext("charset for this document specified explicitely, sorry..."));
break;
} else {
LYUseDefaultRawMode = !LYUseDefaultRawMode;
HTUserMsg(LYRawMode ? RAWMODE_OFF : RAWMODE_ON);
HTMLSetCharacterHandling(current_char_set);
#ifdef SOURCE_CACHE
if (HTreparse_document()) {
break;
}
#endif
cmd = LYK_RELOAD;
goto new_cmd;
}
case LYK_HEAD:
if (nlinks > 0 &&
(links[curdoc.link].type != WWW_FORM_LINK_TYPE ||
links[curdoc.link].form->type == F_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE ||
links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE)) {
/*
* We have links, and the current link is a
* normal link or a form's submit button. - FM
*/
_statusline(HEAD_D_L_OR_CANCEL);
c = LYgetch_for(FOR_SINGLEKEY);
if (TOUPPER(c) == 'D') {
char *scheme = strncmp(curdoc.address, "LYNXIMGMAP:", 11) ?
curdoc.address : curdoc.address + 11;
if (LYCanDoHEAD(scheme) != TRUE) {
HTUserMsg(DOC_NOT_HTTP_URL);
} else {
/*
* Check if this is a reply from a POST,
* and if so, seek confirmation if the
* safe element is not set. - FM
*/
if ((curdoc.post_data != NULL &&
curdoc.safe != TRUE) &&
HTConfirm(CONFIRM_POST_DOC_HEAD) == FALSE) {
HTInfoMsg(CANCELLED);
break;
}
HEAD_request = TRUE;
LYforce_no_cache = TRUE;
StrAllocCopy(newdoc.title, curdoc.title);
if (HTLoadedDocumentIsHEAD()) {
HTuncache_current_document();
FREE(curdoc.address);
} else {
StrAllocCat(newdoc.title, " - HEAD");
}
}
break;
} else if (TOUPPER(c) == 'L') {
if (links[curdoc.link].type != WWW_FORM_LINK_TYPE &&
strncmp(links[curdoc.link].lname, "http", 4) &&
strncmp(links[curdoc.link].lname,
"LYNXIMGMAP:http", 15) &&
LYCanDoHEAD(links[curdoc.link].lname) != TRUE &&
(links[curdoc.link].type != WWW_INTERN_LINK_TYPE ||
!curdoc.address ||
strncmp(curdoc.address, "http", 4))) {
HTUserMsg(LINK_NOT_HTTP_URL);
} else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->disabled) {
HTUserMsg(FORM_ACTION_DISABLED);
} else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
strncmp(links[curdoc.link].form->submit_action,
"lynxcgi:", 8) &&
strncmp(links[curdoc.link].form->submit_action,
"http", 4)) {
HTUserMsg(FORM_ACTION_NOT_HTTP_URL);
} else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
links[curdoc.link].form->submit_method ==
URL_POST_METHOD &&
HTConfirm(CONFIRM_POST_LINK_HEAD) == FALSE) {
HTInfoMsg(CANCELLED);
} else {
HEAD_request = TRUE;
LYforce_no_cache = TRUE;
cmd = LYK_ACTIVATE;
goto new_cmd;
}
break;
}
break;
} else {
/*
* We can offer only this document for a HEAD request.
* Check if this is a reply from a POST, and if so,
* seek confirmation if the safe element is not set. - FM
*/
if ((curdoc.post_data != NULL &&
curdoc.safe != TRUE) &&
HTConfirm(CONFIRM_POST_DOC_HEAD) == FALSE) {
HTInfoMsg(CANCELLED);
break;
} else if (nlinks > 0) {
/*
* The current link is a non-submittable form
* link, so prompt the user to make it clear
* that the HEAD request would be for the
* current document, not the form link. - FM
*/
_statusline(HEAD_D_OR_CANCEL);
c = LYgetch_for(FOR_SINGLEKEY);
} else {
/*
* No links, so we can just assume that
* the user wants a HEAD request for the
* current document. - FM
*/
c = 'D';
}
if (TOUPPER(c) == 'D') {
char *scheme = strncmp(curdoc.address, "LYNXIMGMAP:", 11) ?
curdoc.address : curdoc.address + 11;
/*
* The user didn't cancel, so check if
* a HEAD request is appropriate for the
* current document. - FM
*/
if (LYCanDoHEAD(scheme) != TRUE) {
HTUserMsg(DOC_NOT_HTTP_URL);
} else {
HEAD_request = TRUE;
LYforce_no_cache = TRUE;
StrAllocCopy(newdoc.title, curdoc.title);
if (HTLoadedDocumentIsHEAD()) {
HTuncache_current_document();
FREE(curdoc.address);
} else {
StrAllocCat(newdoc.title, " - HEAD");
}
}
}
}
break;
case LYK_TOGGLE_HELP:
if (user_mode == NOVICE_MODE) {
toggle_novice_line();
noviceline(more);
}
break;
case LYK_KEYMAP:
if (old_c != real_c) {
old_c = real_c;
StrAllocCopy(newdoc.address, "LYNXKEYMAP:");
StrAllocCopy(newdoc.title, CURRENT_KEYMAP_TITLE);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
/*
* If vi_keys changed, the keymap did too,
* so force no cache, and reset the flag. - FM
*/
if (vi_keys_flag != vi_keys ||
emacs_keys_flag != emacs_keys) {
LYforce_no_cache = TRUE;
vi_keys_flag = vi_keys;
emacs_keys_flag = emacs_keys;
}
#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
/*
* Remember whether we are in dired menu
* so we can display the right keymap.
*/
if (!no_dired_support) {
prev_lynx_edit_mode = lynx_edit_mode;
}
#endif /* DIRED_SUPPORT && OK_OVERRIDE */
LYforce_no_cache = TRUE;
}
break;
case LYK_JUMP:
{
char *ret;
if (no_jump || JThead == NULL) {
if (old_c != real_c) {
old_c = real_c;
if (no_jump)
HTUserMsg(JUMP_DISALLOWED);
else
HTUserMsg(NO_JUMPFILE);
}
} else {
LYJumpFileURL = TRUE;
if ((ret = LYJump(c)) != NULL) {
#ifdef PERMIT_GOTO_FROM_JUMP
if (!strncasecomp(ret, "Go ", 3)) {
LYJumpFileURL = FALSE;
StrAllocCopy(temp, user_input_buffer);
URLTotal = (Goto_URLs ?
HTList_count(Goto_URLs) : 0);
recall = ((URLTotal >= 1) ? RECALL : NORECALL);
URLNum = URLTotal;
FirstURLRecall = TRUE;
if (!strcasecomp(ret, "Go :")) {
if (recall) {
ch = UPARROW;
goto check_recall;
}
FREE(temp);
HTUserMsg(NO_RANDOM_URLS_YET);
break;
}
ret = HTParse((ret+3), startfile, PARSE_ALL);
strcpy(user_input_buffer, ret);
FREE(ret);
goto check_recall;
}
#endif /* PERMIT_GOTO_FROM_JUMP */
ret = HTParse(ret, startfile, PARSE_ALL);
if (!LYTrimStartfile(ret)) {
LYRemoveBlanks(user_input_buffer);
}
StrAllocCopy(newdoc.address, ret);
StrAllocCopy(lynxjumpfile, ret);
FREE(newdoc.post_data);
FREE(newdoc.post_content_type);
FREE(newdoc.bookmark);
newdoc.isHEAD = FALSE;
newdoc.safe = FALSE;
newdoc.internal_link = FALSE;
FREE(ret);
LYUserSpecifiedURL = TRUE;
} else {
LYJumpFileURL = FALSE;
}
}
}
break;
case LYK_CLEAR_AUTH:
if (old_c != real_c) {
old_c = real_c;
if (HTConfirm(CLEAR_ALL_AUTH_INFO)) {
FREE(authentication_info[0]);
FREE(authentication_info[1]);
FREE(proxyauth_info[0]);
FREE(proxyauth_info[1]);
HTClearHTTPAuthInfo();
#ifndef DISABLE_NEWS
HTClearNNTPAuthInfo();
#endif
#ifndef DISABLE_FTP
HTClearFTPPassword();
#endif
HTUserMsg(AUTH_INFO_CLEARED);
} else {
HTUserMsg(CANCELLED);
}
}
break;
case LYK_DO_NOTHING: /* pretty self explanatory */
break;
} /* end of BIG switch */
}
}
/*
* Ask a post resubmission prompt with some indication of what would
* be resubmitted, useful especially for going backward in history.
* Try to use parts of the address or, if given, the title, depending
* on how much fits on the statusline.
* if_imgmap and if_file indicate how to handle an address that is
* a "LYNXIMGMAP:", or a "file:" URL (presumably the List Page file),
* respectively: 0: auto-deny, 1: auto-confirm, 2: prompt.
* - kw
*/
PRIVATE BOOL confirm_post_resub ARGS4(
CONST char*, address,
CONST char*, title,
int, if_imgmap,
int, if_file)
{
size_t len1;
CONST char *msg = CONFIRM_POST_RESUBMISSION_TO;
char buf[240];
char *temp = NULL;
BOOL res;
size_t maxlen = LYcols - 6;
if (!address) {
return(NO);
} else if (!strncmp(address, "LYNXIMGMAP:", 11)) {
if (if_imgmap <= 0)
return(NO);
else if (if_imgmap == 1)
return(YES);
else
msg = CONFIRM_POST_LIST_RELOAD;
} else if (!strncmp(address, "file:", 5)) {
if (if_file <= 0)
return(NO);
else if (if_file == 1)
return(YES);
else
msg = CONFIRM_POST_LIST_RELOAD;
} else if (dump_output_immediately) {
return(NO);
}
if (maxlen >= sizeof(buf))
maxlen = sizeof(buf) - 1;
if ((len1 = strlen(msg)) +
strlen(address) <= maxlen) {
sprintf(buf, msg, address);
return HTConfirm(buf);
}
if (len1 + strlen(temp = HTParse(address, "",
PARSE_ACCESS+PARSE_HOST+PARSE_PATH
+PARSE_PUNCTUATION)) <= maxlen) {
sprintf(buf, msg, temp);
res = HTConfirm(buf);
FREE(temp);
return(res);
}
FREE(temp);
if (title && (len1 + strlen(title) <= maxlen)) {
sprintf(buf, msg, title);
return HTConfirm(buf);
}
if (len1 + strlen(temp = HTParse(address, "",
PARSE_ACCESS+PARSE_HOST
+PARSE_PUNCTUATION)) <= maxlen) {
sprintf(buf, msg, temp);
res = HTConfirm(buf);
FREE(temp);
return(res);
}
FREE(temp);
if ((temp = HTParse(address, "", PARSE_HOST)) && *temp &&
len1 + strlen(temp) <= maxlen) {
sprintf(buf, msg, temp);
res = HTConfirm(buf);
FREE(temp);
return(res);
}
FREE(temp);
return HTConfirm(CONFIRM_POST_RESUBMISSION);
}
PRIVATE int are_different ARGS2(
document *, doc1,
document *, doc2)
{
char *cp1, *cp2;
/*
* Do we have two addresses?
*/
if (!doc1->address || !doc2->address)
return (TRUE);
/*
* Do they differ in the type of request?
*/
if (doc1->isHEAD != doc2->isHEAD)
return (TRUE);
/*
* See if the addresses are different, making sure
* we're not tripped up by multiple anchors in the
* the same document from a POST form. -- FM
*/
if ((cp1 = strchr(doc1->address, '#')) != NULL)
*cp1 = '\0';
if ((cp2 = strchr(doc2->address, '#')) != NULL)
*cp2 = '\0';
/*
* Are the base addresses different?
*/
if (strcmp(doc1->address, doc2->address))
{
if (cp1)
*cp1 = '#';
if (cp2)
*cp2 = '#';
return(TRUE);
}
if (cp1)
*cp1 = '#';
if (cp2)
*cp2 = '#';
/*
* Do the docs have different contents?
*/
if (doc1->post_data)
{
if (doc2->post_data)
{
if (strcmp(doc1->post_data, doc2->post_data))
return(TRUE);
}
else
return(TRUE);
}
else
if (doc2->post_data)
return(TRUE);
/*
* We'll assume the two documents in fact are the same.
*/
return(FALSE);
}
/* This determines whether two docs are _physically_ different,
* meaning they are "from different files". - kw
*/
#ifndef DONT_TRACK_INTERNAL_LINKS
PRIVATE int are_phys_different ARGS2(
document *, doc1,
document *, doc2)
{
char *cp1, *cp2, *ap1 = doc1->address, *ap2 = doc2->address;
/*
* Do we have two addresses?
*/
if (!doc1->address || !doc2->address)
return (TRUE);
/*
* Do they differ in the type of request?
*/
if (doc1->isHEAD != doc2->isHEAD)
return (TRUE);
/*
* Skip over possible LYNXIMGMAP parts. - kw
*/
if (0==strncmp(doc1->address, "LYNXIMGMAP:", 11))
ap1 += 11;
if (0==strncmp(doc2->address, "LYNXIMGMAP:", 11))
ap2 += 11;
/*
* If there isn't any real URL in doc2->address, but maybe just
* a fragment, doc2 is assumed to be an internal reference in
* the same physical document, so return FALSE. - kw
*/
if (*ap2 == '\0' || *ap2 == '#')
return(FALSE);
/*
* See if the addresses are different, making sure
* we're not tripped up by multiple anchors in the
* the same document from a POST form. -- FM
*/
if ((cp1 = strchr(doc1->address, '#')) != NULL)
*cp1 = '\0';
if ((cp2 = strchr(doc2->address, '#')) != NULL)
*cp2 = '\0';
/*
* Are the base addresses different?
*/
if (strcmp(ap1, ap2))
{
if (cp1)
*cp1 = '#';
if (cp2)
*cp2 = '#';
return(TRUE);
}
if (cp1)
*cp1 = '#';
if (cp2)
*cp2 = '#';
/*
* Do the docs have different contents?
*/
if (doc1->post_data)
{
if (doc2->post_data)
{
if (strcmp(doc1->post_data, doc2->post_data))
return(TRUE);
}
else
return(TRUE);
}
else
if (doc2->post_data)
return(TRUE);
/*
* We'll assume the two documents in fact are the same.
*/
return(FALSE);
}
#endif
/*
* Utility for freeing the list of goto URLs. - FM
*/
#ifdef LY_FIND_LEAKS
PRIVATE void HTGotoURLs_free NOARGS
{
char *url;
HTList *cur = Goto_URLs;
if (cur != 0) {
while (NULL != (url = (char *)HTList_nextObject(cur))) {
FREE(url);
}
HTList_delete(Goto_URLs);
Goto_URLs = NULL;
}
}
#endif
/*
* Utility for listing Goto URLs, making any
* repeated URLs the most current in the list. - FM
*/
PUBLIC void HTAddGotoURL ARGS1(
char *, url)
{
char *new;
char *old;
HTList *cur;
if (!(url && *url))
return;
if ((new = (char *)calloc(1, (strlen(url) + 1))) == NULL)
outofmem(__FILE__, "HTAddGotoURL");
strcpy(new, url);
if (!Goto_URLs) {
Goto_URLs = HTList_new();
#ifdef LY_FIND_LEAKS
atexit(HTGotoURLs_free);
#endif
HTList_addObject(Goto_URLs, new);
return;
}
cur = Goto_URLs;
while (NULL != (old = (char *)HTList_nextObject(cur))) {
if (!strcmp(old, new)) {
HTList_removeObject(Goto_URLs, old);
FREE(old);
break;
}
}
HTList_addObject(Goto_URLs, new);
return;
}
/*
* When help is not on the screen,
* put a message on the screen
* to tell the user other misc info.
*/
PRIVATE void show_main_statusline ARGS1(
CONST linkstruct, curlink)
{
/*
* Make sure form novice lines are replaced.
*/
if (user_mode == NOVICE_MODE) {
noviceline(more);
}
if (HTisDocumentSource()) {
/*
* Currently displaying HTML source.
*/
_statusline(SOURCE_HELP);
/*
* If we are in forms mode then explicitly
* tell the user what each kind of link is.
*/
#ifdef INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE
} else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0) {
#else
#ifdef NORMAL_NON_FORM_LINK_STATUSLINES_FOR_ALL_USER_MODES
} else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0 &&
!(curlink.type & WWW_LINK_TYPE)) {
#else
} else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0 &&
!(user_mode == ADVANCED_MODE &&
(curlink.type & WWW_LINK_TYPE))) {
#endif /* NORMAL_NON_FORM_LINK_STATUSLINES_FOR_ALL_USER_MODES */
#endif /* INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE */
if (curlink.type == WWW_FORM_LINK_TYPE) {
show_formlink_statusline(curlink.form);
} else {
statusline(NORMAL_LINK_MESSAGE);
}
/*
* Let them know if it's an index -- very rare.
*/
if (is_www_index) {
move(LYlines-1, LYcols-8);
start_reverse();
addstr("-index-");
stop_reverse();
}
} else if (user_mode == ADVANCED_MODE && nlinks > 0) {
/*
* Show the URL or, for some internal links, the fragment
*/
char *cp = NULL;
if (curlink.type == WWW_INTERN_LINK_TYPE &&
strncmp(curlink.lname, "LYNXIMGMAP:", 11)) {
cp = strchr(curlink.lname, '#');
}
if (!cp)
cp = curlink.lname;
if (more) {
if (is_www_index)
_user_message("-more- -index- %s", cp);
else
_user_message("-more- %s", cp);
} else {
if (is_www_index)
_user_message("-index- %s", cp);
else
statusline(cp);
}
} else if (is_www_index && more) {
char buf[128];
sprintf(buf, WWW_INDEX_MORE_MESSAGE, key_for_func(LYK_INDEX_SEARCH));
_statusline(buf);
} else if (is_www_index) {
char buf[128];
sprintf(buf, WWW_INDEX_MESSAGE, key_for_func(LYK_INDEX_SEARCH));
_statusline(buf);
} else if (more) {
if (user_mode == NOVICE_MODE)
_statusline(MORE);
else
_statusline(MOREHELP);
} else {
_statusline(HELP);
}
/* turn off cursor since now it's probably on statusline -HV */
move((LYlines - 1), (LYcols - 1));
}
/*
* Public function for redrawing the statusline appropriate for the
* selected link. It should only be called at times when curdoc.link,
* nlinks, and the links[] array are valid. - kw
*/
PUBLIC void repaint_main_statusline NOARGS
{
if (curdoc.link >= 0 && curdoc.link < nlinks)
show_main_statusline(links[curdoc.link]);
}
PRIVATE void exit_immediately_with_error_message ARGS2(
int, state,
BOOLEAN, first_file)
{
char *buf = 0;
char *buf2 = 0;
if (first_file) {
/* print statusline messages as a hint, if any */
LYstatusline_messages_on_exit(&buf2);
}
if (state == NOT_FOUND)
{
HTSprintf0(&buf, "%s\n%s %s\n",
buf2,
gettext("lynx: Can't access startfile"),
/*
* hack: if we fail in HTAccess.c
* avoid duplicating URL, oh.
*/
strstr(buf2, gettext("Can't Access")) ? "" : startfile);
}
if (state == NULLFILE)
{
HTSprintf0(&buf, "%s\n%s\n%s\n",
buf2,
gettext("lynx: Start file could not be found or is not text/html or text/plain"),
gettext(" Exiting..."));
}
FREE(buf2);
if (!dump_output_immediately)
cleanup();
#ifdef UNIX
if (dump_output_immediately) {
fprintf(stderr, buf);
} else
#endif /* UNIX */
{
SetOutputMode( O_TEXT );
printf(buf);
SetOutputMode( O_BINARY );
}
FREE(buf);
if (!dump_output_immediately) {
exit_immediately(-1);
}
/* else: return(-1) in mainloop */
}