about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>2004-07-01 00:09:10 -0400
committerThomas E. Dickey <dickey@invisible-island.net>2004-07-01 00:09:10 -0400
commitceb4156db8546c98875607dd91a799101b02c22f (patch)
tree23470c5e32d7f12c3346806358dcb2503d2ce282 /src
parent06cddc6badf9b4a4791361cfbeffc5b1e2d2d6a6 (diff)
downloadlynx-snapshots-ceb4156db8546c98875607dd91a799101b02c22f.tar.gz
snapshot of project "lynx", label v2-8-6dev_5
Diffstat (limited to 'src')
-rw-r--r--src/AttrList.h3
-rw-r--r--src/GridText.c12
-rw-r--r--src/GridText.h1
-rw-r--r--src/HTFWriter.c76
-rw-r--r--src/HTInit.c356
-rw-r--r--src/LYCurses.c4
-rw-r--r--src/LYGlobalDefs.h2
-rw-r--r--src/LYList.c4
-rw-r--r--src/LYMain.c159
-rw-r--r--src/LYMainLoop.c19
-rw-r--r--src/LYReadCFG.c2
-rw-r--r--src/LYShowInfo.c10
-rw-r--r--src/LYStyle.c4
-rw-r--r--src/LYUtils.c41
-rw-r--r--src/Xsystem.c19
15 files changed, 476 insertions, 236 deletions
diff --git a/src/AttrList.h b/src/AttrList.h
index 16c44047..c466714d 100644
--- a/src/AttrList.h
+++ b/src/AttrList.h
@@ -44,7 +44,8 @@ extern void _internal_HTC(HText *text, int style, int dir);
 extern char class_string[TEMPSTRINGSIZE];
 
 /* stack of attributes during page rendering */
-extern int last_styles[128];
+#define MAX_LAST_STYLES 128
+extern int last_styles[MAX_LAST_STYLES];
 extern int last_colorattr_ptr;
 
 #endif
diff --git a/src/GridText.c b/src/GridText.c
index ee8117fc..8ede1e6c 100644
--- a/src/GridText.c
+++ b/src/GridText.c
@@ -6878,6 +6878,18 @@ const char *HText_getServer(void)
 	    HTAnchor_server(HTMainText->node_anchor) : 0);
 }
 
+#ifdef EXP_HTTP_HEADERS
+/*
+ * Returns the full text of HTTP headers, if available, for the current
+ * document.
+ */
+const char *HText_getHttpHeaders(void)
+{
+    return (HTMainText ?
+	    HTAnchor_http_headers(HTMainText->node_anchor) : 0);
+}
+#endif
+
 /*
  * HText_pageDisplay displays a screen of text
  * starting from the line 'line_num'-1.
diff --git a/src/GridText.h b/src/GridText.h
index 9049ce67..242ca376 100644
--- a/src/GridText.h
+++ b/src/GridText.h
@@ -96,6 +96,7 @@ extern void HTCheckFnameForCompression(char **fname,
 				       BOOLEAN strip_ok);
 extern const char *HText_getLastModified(void);
 extern const char *HText_getDate(void);
+extern const char *HText_getHttpHeaders(void);
 extern const char *HText_getServer(void);
 extern const char *HText_getOwner(void);
 extern const char *HText_getContentBase(void);
diff --git a/src/HTFWriter.c b/src/HTFWriter.c
index 2054cab7..893c2daa 100644
--- a/src/HTFWriter.c
+++ b/src/HTFWriter.c
@@ -21,6 +21,7 @@
 #include <UCDefs.h>
 #include <HTAlert.h>
 #include <HTFile.h>
+#include <HTInit.h>
 #include <HTPlain.h>
 
 #include <LYStrings.h>
@@ -513,14 +514,6 @@ HTStream *HTFWriter_new(FILE *fp)
     return me;
 }
 
-static void chrcat(char *result,
-		   int ch)
-{
-    result += strlen(result);
-    *result++ = (char) ch;
-    *result = 0;
-}
-
 /*	Make system command from template
  *	---------------------------------
  *
@@ -530,68 +523,17 @@ static char *mailcap_substitute(HTParentAnchor *anchor,
 				HTPresentation *pres,
 				char *fnam)
 {
-    int pass;
-    int skip;
-    size_t need = 0;
-    char *result = 0;
-    char *s;
-    char *repl;
-
-    for (pass = 0; pass < 2; pass++) {
-	for (s = pres->command; *s; s++) {
-	    if (*s == '%') {
-		repl = 0;
-		skip = 0;
-		if (s[1] == 't') {
-		    repl = pres->rep->name;
-		    skip = 1;
-		} else if (s[1] == 's') {
-		    repl = fnam;
-		    skip = 1;
-		} else if (!strncasecomp(s + 1, "{charset}", 9)) {
-		    repl = anchor->charset;
-		    skip = 9;
-		} else if (!strncasecomp(s + 1, "{encoding}", 10)) {
-		    repl = anchor->content_encoding;
-		    skip = 10;
-		}
-		if (skip != 0) {
-		    if (repl == 0)
-			repl = "";
-		    if (pass) {
-			strcat(result, repl);
-		    } else {
-			need += strlen(repl);
-		    }
-		    s += skip;
-		} else {
-		    if (pass) {
-			chrcat(result, *s);
-		    } else {
-			need++;
-		    }
-		}
-	    } else {
-		if (pass) {
-		    chrcat(result, *s);
-		} else {
-		    need++;
-		}
-	    }
-	}
-	if (pass == 0) {
-	    if ((result = malloc(need + 1)) == 0)
-		outofmem(__FILE__, "mailcap_substitute");
-	    *result = 0;
-	}
-    }
+    char *result = LYMakeMailcapCommand(pres->command,
+					anchor->content_type_params,
+					fnam);
+
 #if defined(UNIX)
     /* if we don't have a "%s" token, expect to provide the file via stdin */
-    if (strstr(pres->command, "%s") == 0) {
+    if (!LYMailcapUsesPctS(pres->command)) {
 	char *prepend = 0;
 	char *format = "( %s ) < %s";
 
-	HTSprintf(&prepend, "( %s", pres->command);	/* ...avoid quoting */
+	HTSprintf(&prepend, "( %s", result);	/* ...avoid quoting */
 	HTAddParam(&prepend, format, 2, fnam);	/* ...to quote if needed */
 	FREE(result);
 	result = prepend;
@@ -1107,8 +1049,8 @@ HTStream *HTCompressed(HTPresentation *pres,
 	    StrAllocCopy(type, anchor->content_encoding);
 	}
 	format = HTAtom_for(type);
-	FREE(type)
-	    FREE(uncompress_mask);
+	FREE(type);
+	FREE(uncompress_mask);
 	me = HTStreamStack(format, pres->rep_out, sink, anchor);
 	return me;
     }
diff --git a/src/HTInit.c b/src/HTInit.c
index dd22b887..a1380cd7 100644
--- a/src/HTInit.c
+++ b/src/HTInit.c
@@ -38,7 +38,7 @@ static int HTLoadExtensionsConfigFile(char *fn);
        HTSetSuffix5(suffix, mimetype, type, description, 1.0)
 
 #define SET_PRESENT(mimetype, command, quality, delay) \
-  HTSetPresentation(mimetype, command, quality, delay, 0.0, 0, media)
+  HTSetPresentation(mimetype, command, 0, quality, delay, 0.0, 0, media)
 
 #define SET_EXTERNL(rep_in, rep_out, command, quality) \
     HTSetConversion(rep_in, rep_out, command, quality, 3.0, 0.0, 0, mediaEXT)
@@ -115,6 +115,7 @@ void HTFormatInit(void)
     SET_INTERNL("application/html", "text/x-c", HTMLToC, 0.5);
     SET_INTERNL("application/html", "text/plain", HTMLToPlain, 0.5);
     SET_INTERNL("application/html", "www/present", HTMLPresent, 2.0);
+    SET_INTERNL("application/xhtml+xml", "www/present", HTMLPresent, 2.0);
     SET_INTERNL("application/html", "www/source", HTPlainPresent, 1.0);
     SET_INTERNL("application/x-wais-source", "www/source", HTPlainPresent, 1.0);
     SET_INTERNL("application/x-wais-source", "www/present", HTWSRCConvert, 2.0);
@@ -457,52 +458,260 @@ static int ProcessMailcapEntry(FILE *fp, struct MailcapEntry *mc, AcceptMedia me
     if (PassesTest(mc)) {
 	CTRACE((tfp, "ProcessMailcapEntry Setting up conversion %s : %s\n",
 		mc->contenttype, mc->command));
-	HTSetPresentation(mc->contenttype, mc->command, mc->quality,
+	HTSetPresentation(mc->contenttype,
+			  mc->command,
+			  mc->testcommand,
+			  mc->quality,
 			  3.0, 0.0, mc->maxbytes, media);
     }
     FREE(mc->command);
+    FREE(mc->testcommand);
     FREE(mc->contenttype);
 
     return (1);
 }
 
-static void BuildCommand(char **pBuf,
-			 size_t Bufsize,
-			 char *controlstring,
-			 char *TmpFileName,
-			 size_t TmpFileLen)
+#define L_CURL '{'
+#define R_CURL '}'
+
+static const char *LYSkipQuoted(const char *s)
+{
+    int escaped = 0;
+
+    ++s;			/* skip first quote */
+    while (*s != 0) {
+	if (escaped) {
+	    escaped = 0;
+	} else if (*s == '\\') {
+	    escaped = 1;
+	} else if (*s == '"') {
+	    ++s;
+	    break;
+	}
+	++s;
+    }
+    return s;
+}
+
+/*
+ * Note: the tspecials[] here are those defined for Content-Type header, so
+ * this function is not really general-purpose.
+ */
+static const char *LYSkipToken(const char *s)
+{
+    static const char tspecials[] = "\"()<>@,;:\\/[]?.=";
+
+    while (*s != '\0' && !WHITE(*s) && strchr(tspecials, *s) == 0) {
+	++s;
+    }
+    return s;
+}
+
+static const char *LYSkipValue(const char *s)
 {
-    char *from, *to;
+    if (*s == '"')
+	s = LYSkipQuoted(s);
+    else
+	s = LYSkipToken(s);
+    return s;
+}
+
+/*
+ * Copy the value from the source, dequoting if needed.
+ */
+static char *LYCopyValue(const char *s)
+{
+    const char *t;
+    char *result = 0;
+    int j, k;
+
+    if (*s == '"') {
+	t = LYSkipQuoted(s);
+	StrAllocCopy(result, s + 1);
+	result[t - s - 2] = '\0';
+	for (j = k = 0;; ++j, ++k) {
+	    if (result[j] == '\\') {
+		++j;
+	    }
+	    if ((result[k] = result[j]) == '\0')
+		break;
+	}
+    } else {
+	t = LYSkipToken(s);
+	StrAllocCopy(result, s);
+	result[t - s] = '\0';
+    }
+    return result;
+}
+
+/*
+ * The "Content-Type:" field, contains zero or more parameters after a ';'.
+ * Return the value of the named parameter, or null.
+ */
+static char *LYGetContentType(const char *name,
+			      const char *params)
+{
+    char *result = 0;
+
+    if (params != 0) {
+	if (name != 0) {
+	    size_t length = strlen(name);
+	    const char *test = strchr(params, ';');	/* skip type/subtype */
+	    const char *next;
+
+	    while (test != 0) {
+		BOOL found = FALSE;
+
+		++test;		/* skip the ';' */
+		test = LYSkipCBlanks(test);
+		next = LYSkipToken(test);
+		if ((next - test) == (int) length
+		    && !strncmp(test, name, length)) {
+		    found = TRUE;
+		}
+		test = LYSkipCBlanks(next);
+		if (*test == '=') {
+		    ++test;
+		    test = LYSkipCBlanks(test);
+		    if (found) {
+			result = LYCopyValue(test);
+			break;
+		    } else {
+			test = LYSkipValue(test);
+		    }
+		    test = LYSkipCBlanks(test);
+		}
+		if (*test != ';') {
+		    break;	/* we're lost */
+		}
+	    }
+	} else {		/* return the content-type */
+	    StrAllocCopy(result, params);
+	    *LYSkipNonBlanks(result) = '\0';
+	}
+    }
+    return result;
+}
+
+/*
+ * Check if the command uses a "%s" substitution.  We need to know this, to
+ * decide when to create temporary files, etc.
+ */
+BOOL LYMailcapUsesPctS(const char *controlstring)
+{
+    int result = FALSE;
+    const char *from;
+    const char *next;
     int prefixed = 0;
+    int escaped = 0;
+
+    for (from = controlstring; *from != '\0'; from++) {
+	if (escaped) {
+	    escaped = 0;
+	} else if (*from == '\\') {
+	    escaped = 1;
+	} else if (prefixed) {
+	    prefixed = 0;
+	    switch (*from) {
+	    case '%':		/* not defined */
+	    case 'n':
+	    case 'F':
+	    case 't':
+		break;
+	    case 's':
+		result = TRUE;
+		break;
+	    case L_CURL:
+		next = strchr(from, R_CURL);
+		if (next != 0) {
+		    from = next;
+		    break;
+		}
+		/* FALLTHRU */
+	    default:
+		break;
+	    }
+	} else if (*from == '%') {
+	    prefixed = 1;
+	}
+    }
+    return result;
+}
 
-    for (from = controlstring, to = *pBuf; *from != '\0'; from++) {
-	if (prefixed) {
+/*
+ * Build the command string for testing or executing a mailcap entry.
+ * If a substitution from the Content-Type header is requested but no
+ * parameters are available, return -1, otherwise 0.
+ *
+ * This does not support multipart %n or %F (does this apply to lynx?)
+ */
+static int BuildCommand(HTChunk *cmd,
+			const char *controlstring,
+			const char *TmpFileName,
+			const char *params)
+{
+    int result = 0;
+    size_t TmpFileLen = strlen(TmpFileName);
+    const char *from;
+    const char *next;
+    char *name, *value;
+    int prefixed = 0;
+    int escaped = 0;
+
+    for (from = controlstring; *from != '\0'; from++) {
+	if (escaped) {
+	    escaped = 0;
+	    HTChunkPutc(cmd, *from);
+	} else if (*from == '\\') {
+	    escaped = 1;
+	} else if (prefixed) {
 	    prefixed = 0;
 	    switch (*from) {
-	    case '%':
-		*to++ = '%';
+	    case '%':		/* not defined */
+		HTChunkPutc(cmd, *from);
 		break;
 	    case 'n':
 		/* FALLTHRU */
 	    case 'F':
 		CTRACE((tfp, "BuildCommand: Bad mailcap \"test\" clause: %s\n",
 			controlstring));
-		/* FALLTHRU */
+		break;
+	    case 't':
+		if ((value = LYGetContentType(NULL, params)) != 0) {
+		    HTChunkPuts(cmd, value);
+		    FREE(value);
+		}
+		break;
 	    case 's':
 		if (TmpFileLen && TmpFileName) {
-		    if ((to - *pBuf) + TmpFileLen + 1 > Bufsize) {
-			*to = '\0';
-			CTRACE((tfp,
-				"BuildCommand: Too long mailcap \"test\" clause,\n"));
-			CTRACE((tfp, "              ignoring: %s%s...\n",
-				*pBuf, TmpFileName));
-			**pBuf = '\0';
-			return;
-		    }
-		    strcpy(to, TmpFileName);
-		    to += strlen(TmpFileName);
+		    HTChunkPuts(cmd, TmpFileName);
 		}
 		break;
+	    case L_CURL:
+		next = strchr(from, R_CURL);
+		if (next != 0) {
+		    if (params != 0) {
+			++from;
+			name = 0;
+			HTSprintf0(&name, "%.*s", next - from, from);
+			if ((value = LYGetContentType(name, params)) != 0) {
+			    HTChunkPuts(cmd, value);
+			    FREE(value);
+			} else {
+			    if (!strcmp(name, "charset")) {
+				HTChunkPuts(cmd, "ISO-8859-1");
+			    } else {
+				CTRACE((tfp, "BuildCommand no value for %s\n", name));
+			    }
+			}
+			FREE(name);
+		    } else {
+			result = -1;
+		    }
+		    from = next;
+		    break;
+		}
+		/* FALLTHRU */
 	    default:
 		CTRACE((tfp,
 			"BuildCommand: Ignoring unrecognized format code in mailcap file '%%%c'.\n",
@@ -512,18 +721,66 @@ static void BuildCommand(char **pBuf,
 	} else if (*from == '%') {
 	    prefixed = 1;
 	} else {
-	    *to++ = *from;
+	    HTChunkPutc(cmd, *from);
 	}
-	if (to >= *pBuf + Bufsize) {
-	    (*pBuf)[Bufsize - 1] = '\0';
-	    CTRACE((tfp, "BuildCommand: Too long mailcap \"test\" clause,\n"));
-	    CTRACE((tfp, "              ignoring: %s...\n",
-		    *pBuf));
-	    **pBuf = '\0';
-	    return;
+    }
+    HTChunkTerminate(cmd);
+    return result;
+}
+
+/*
+ * Build the mailcap test-command and execute it.  This is only invoked when
+ * we cannot tell just by looking at the command if it would succeed.
+ *
+ * Returns 0 for success, -1 for error and 1 for deferred.
+ */
+int LYTestMailcapCommand(const char *testcommand,
+			 const char *params)
+{
+    int result;
+    char TmpFileName[LY_MAXPATH];
+    HTChunk *expanded = 0;
+
+    if (LYMailcapUsesPctS(testcommand)) {
+	if (LYOpenTemp(TmpFileName, HTML_SUFFIX, "w") == 0)
+	    ExitWithError(CANNOT_OPEN_TEMP);
+	LYCloseTemp(TmpFileName);
+    } else {
+	/* We normally don't need a temp file name - kw */
+	TmpFileName[0] = '\0';
+    }
+    expanded = HTChunkCreate(1024);
+    if ((result = BuildCommand(expanded, testcommand, TmpFileName, params)) != 0) {
+	result = 1;
+	CTRACE((tfp, "PassesTest: Deferring test command: %s\n", expanded->data));
+    } else {
+	CTRACE((tfp, "PassesTest: Executing test command: %s\n", expanded->data));
+	if ((result = LYSystem(expanded->data)) != 0) {
+	    result = -1;
+	    CTRACE((tfp, "PassesTest: Test failed!\n"));
+	} else {
+	    CTRACE((tfp, "PassesTest: Test passed!\n"));
 	}
     }
-    *to = '\0';
+
+    HTChunkFree(expanded);
+    LYRemoveTemp(TmpFileName);
+
+    return result;
+}
+
+char *LYMakeMailcapCommand(const char *command,
+			   const char *params,
+			   const char *filename)
+{
+    HTChunk *expanded = 0;
+    char *result = 0;
+
+    expanded = HTChunkCreate(1024);
+    BuildCommand(expanded, command, filename, params);
+    StrAllocCopy(result, expanded->data);
+    HTChunkFree(expanded);
+    return result;
 }
 
 #define RTR_forget      0
@@ -574,7 +831,6 @@ static int RememberTestResult(int mode, char *cmd, int result)
 static int PassesTest(struct MailcapEntry *mc)
 {
     int result;
-    char *cmd, TmpFileName[LY_MAXPATH];
 
     /*
      *  Make sure we have a command
@@ -631,28 +887,7 @@ static int PassesTest(struct MailcapEntry *mc)
 
     result = RememberTestResult(RTR_lookup, mc->testcommand, 0);
     if (result == -1) {
-	/*
-	 *  Build the command and execute it.
-	 */
-	if (strchr(mc->testcommand, '%')) {
-	    if (LYOpenTemp(TmpFileName, HTML_SUFFIX, "w") == 0)
-		ExitWithError(CANNOT_OPEN_TEMP);
-	    LYCloseTemp(TmpFileName);
-	} else {
-	    /* We normally don't need a temp file name - kw */
-	    TmpFileName[0] = '\0';
-	}
-	cmd = (char *) malloc(1024);
-	if (!cmd)
-	    ExitWithError(MEMORY_EXHAUSTED_ABORT);
-	BuildCommand(&cmd, 1024,
-		     mc->testcommand,
-		     TmpFileName,
-		     strlen(TmpFileName));
-	CTRACE((tfp, "PassesTest: Executing test command: %s\n", cmd));
-	result = LYSystem(cmd);
-	FREE(cmd);
-	LYRemoveTemp(TmpFileName);
+	result = LYTestMailcapCommand(mc->testcommand, NULL);
 	RememberTestResult(RTR_add, mc->testcommand, result ? 1 : 0);
     }
 
@@ -660,15 +895,16 @@ static int PassesTest(struct MailcapEntry *mc)
      *  Free the test command as well since
      *  we wont be needing it anymore.
      */
-    FREE(mc->testcommand);
+    if (result != 1)
+	FREE(mc->testcommand);
 
-    if (result) {
+    if (result < 0) {
 	CTRACE((tfp, "PassesTest: Test failed!\n"));
-    } else {
+    } else if (result == 0) {
 	CTRACE((tfp, "PassesTest: Test passed!\n"));
     }
 
-    return (result == 0);
+    return (result >= 0);
 }
 
 static int ProcessMailcapFile(char *file, AcceptMedia media)
diff --git a/src/LYCurses.c b/src/LYCurses.c
index 00b8093d..3d6646ac 100644
--- a/src/LYCurses.c
+++ b/src/LYCurses.c
@@ -474,12 +474,12 @@ void curses_w_style(WINDOW * win, int style,
 	break;
 
     case STACK_ON:		/* remember the current attributes */
-	if (last_colorattr_ptr > 127) {
+	if (last_colorattr_ptr >= MAX_LAST_STYLES) {
 	    CTRACE2(TRACE_STYLE, (tfp, "........... %s (0x%x) %s\r\n",
 				  "attribute cache FULL, dropping last",
 				  last_styles[last_colorattr_ptr],
 				  "in LynxChangeStyle(curses_w_style)"));
-	    last_colorattr_ptr = 127;
+	    last_colorattr_ptr = MAX_LAST_STYLES - 1;
 	}
 	last_styles[last_colorattr_ptr++] = LYgetattrs(win);
 	/* don't cache style changes for active links */
diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h
index 00531225..d28b66a4 100644
--- a/src/LYGlobalDefs.h
+++ b/src/LYGlobalDefs.h
@@ -226,6 +226,8 @@ extern BOOLEAN telnet_ok;
 extern BOOLEAN verbose_img;	/* display filenames of images?     */
 extern BOOLEAN vi_keys;		/* TRUE to turn on vi-like key movement */
 
+extern HTList *Goto_URLs;
+
 extern char *LYRequestReferer;	/* Referer, may be set in getfile() */
 extern char *LYRequestTitle;	/* newdoc.title in calls to getfile() */
 extern char *LYTransferName;	/* abbreviation for Kilobytes */
diff --git a/src/LYList.c b/src/LYList.c
index c0c1eebd..845d82cc 100644
--- a/src/LYList.c
+++ b/src/LYList.c
@@ -116,7 +116,7 @@ int showlist(DocInfo *newdoc, BOOLEAN titles)
 	     * HIDDENLINKS_MERGE in GridText.c - kw
 	     */
 	    if (fields_are_numbered()) {
-		HText_FormDescNumber(cnt, (char **) &desc);
+		HText_FormDescNumber(cnt, &desc);
 		fprintf(fp0,
 			"<li><a id=%d href=\"#%d\">form field</a> = <em>%s</em>\n",
 			cnt, cnt, desc);
@@ -277,7 +277,7 @@ void printlist(FILE *fp, BOOLEAN titles)
 		 * won't create a forward link to the form.  - FM && LE
 		 */
 		if (fields_are_numbered()) {
-		    HText_FormDescNumber(cnt, (char **) &desc);
+		    HText_FormDescNumber(cnt, &desc);
 		    fprintf(fp, "%4d. form field = %s\n", cnt, desc);
 		}
 		continue;
diff --git a/src/LYMain.c b/src/LYMain.c
index b146daf2..c2a6175d 100644
--- a/src/LYMain.c
+++ b/src/LYMain.c
@@ -593,11 +593,7 @@ static HTList *LYStdinArgs = NULL;
 #define OPTNAME_ALLOW_DASHES 1
 #endif
 
-#if EXTENDED_OPTION_LOGIC
-static BOOLEAN no_options_further = FALSE;	/* set to TRUE after '--' argument */
-#endif
-
-static BOOL parse_arg(char **arg, unsigned mask, int *i);
+static BOOL parse_arg(char **arg, unsigned mask, int *countp);
 static void print_help_and_exit(int exit_status) GCC_NORETURN;
 static void print_help_strings(const char *name,
 			       const char *help,
@@ -828,20 +824,6 @@ static void FixCharacters(void)
 }
 #endif /* EBCDIC */
 
-static int argncmp(char *str,
-		   char *what)
-{
-    if (str[0] == '-' && str[1] == '-')
-	++str;
-#if OPTNAME_ALLOW_DASHES
-    return strncmp(str, what, strlen(what));
-#else
-    ++str;
-    ++what;			/*skip leading dash in both strings */
-    return !strn_dash_equ(str, what, strlen(what));
-#endif
-}
-
 static void tildeExpand(char **pathname,
 			BOOLEAN embedded)
 {
@@ -1064,14 +1046,7 @@ int main(int argc,
      * Act on -help NOW, so we only output the help and exit.  - FM
      */
     for (i = 1; i < argc; i++) {
-	if (argncmp(argv[i], "-help") == 0) {
-	    parse_arg(&argv[i], 1, &i);
-	}
-#ifdef SH_EX
-	if (strncmp(argv[i], "-show_cfg", 9) == 0) {
-	    show_cfg = TRUE;
-	}
-#endif
+	parse_arg(&argv[i], 1, &i);
     }
 
 #ifdef LY_FIND_LEAKS
@@ -1585,10 +1560,11 @@ int main(int argc,
      * it's not an absolute URL, make it one. - FM
      */
     StrAllocCopy(LynxHome, startfile);
-    LYEnsureAbsoluteURL((char **) &LynxHome, "LynxHome", FALSE);
+    LYEnsureAbsoluteURL(&LynxHome, "LynxHome", FALSE);
 
     /*
      * Process any command line arguments not already handled.  - FM
+     * May set startfile as a side-effect.
      */
     for (i = 1; i < argc; i++) {
 	parse_arg(&argv[i], 4, &i);
@@ -1978,7 +1954,7 @@ int main(int argc,
      * If startfile is a file URL and the host is defaulted, force in
      * "//localhost", and if it's not an absolute URL, make it one.  - FM
      */
-    LYEnsureAbsoluteURL((char **) &startfile, "STARTFILE", FALSE);
+    LYEnsureAbsoluteURL(&startfile, "STARTFILE", FALSE);
 
     /*
      * If homepage was specified and is a file URL with the host defaulted,
@@ -1986,7 +1962,7 @@ int main(int argc,
      * FM
      */
     if (homepage) {
-	LYEnsureAbsoluteURL((char **) &homepage, "HOMEPAGE", FALSE);
+	LYEnsureAbsoluteURL(&homepage, "HOMEPAGE", FALSE);
     }
 
     /*
@@ -2046,6 +2022,10 @@ int main(int argc,
     LYOpenlog(syslog_txt);
 #endif
 
+    if (x_display != NULL && *x_display != '\0') {
+	LYisConfiguredForX = TRUE;
+    }
+
     /*
      * Here's where we do all the work.
      */
@@ -2063,18 +2043,36 @@ int main(int argc,
 		    keypad_mode = LINKS_ARE_NUMBERED;
 	    }
 	}
-
-	if (x_display != NULL && *x_display != '\0') {
-	    LYisConfiguredForX = TRUE;
-	}
 	if (dump_output_width > 0) {
 	    LYcols = dump_output_width;
 	}
+	/*
+	 * Normal argument processing puts non-options (URLs) into the Goto
+	 * history.  Use this to dump all of the pages listed on the command
+	 * line, or (if none are listed) via the startfile mechanism.
+	 * history.
+	 */
+#ifdef EXTENDED_STARTFILE_RECALL
+	HTAddGotoURL(startfile);
+	for (i = HTList_count(Goto_URLs) - 1; i >= 0; --i) {
+	    StrAllocCopy(startfile, (char *) HTList_objectAt(Goto_URLs, i));
+	    CTRACE((tfp, "dumping %d:%d %s\n",
+		    i + 1, HTList_count(Goto_URLs), startfile));
+	    status = mainloop();
+	    if (!nolist &&
+		!crawl &&	/* For -crawl it has already been done! */
+		links_are_numbered())
+		printlist(stdout, FALSE);
+	    if (i != 0)
+		printf("\n");
+	}
+#else
 	status = mainloop();
 	if (!nolist &&
 	    !crawl &&		/* For -crawl it has already been done! */
 	    links_are_numbered())
 	    printlist(stdout, FALSE);
+#endif
 #ifdef USE_PERSISTENT_COOKIES
 	/*
 	 * We want to save cookies picked up when in immediate dump mode. 
@@ -2088,9 +2086,6 @@ int main(int argc,
 	/*
 	 * Start an INTERACTIVE session.  - FM
 	 */
-	if (x_display != NULL && *x_display != '\0') {
-	    LYisConfiguredForX = TRUE;
-	}
 #ifdef USE_COLOR_STYLE
 	cache_tag_styles();
 #endif
@@ -2654,6 +2649,8 @@ static int get_data_fun(char *next_arg GCC_UNUSED)
 	StrAllocCat(*get_data, buf);
     }
 
+    CTRACE((tfp, "get_data:%s\n", *get_data));
+    CTRACE((tfp, "get_data:%s\n", form_get_data));
     return 0;
 }
 
@@ -3094,6 +3091,18 @@ static int version_fun(char *next_arg GCC_UNUSED)
     HTSprintf(&result, "libwww-FM %s,", HTLibraryVersion);
     append_ssl_version(&result, " ");
 #endif /* USE_SSL */
+
+#if defined(NCURSES) && defined(HAVE_CURSES_VERSION)
+    HTSprintf(&result, ", %s", curses_version());
+#if defined(WIDEC_CURSES)
+    HTSprintf(&result, "(wide)");
+#endif
+#elif defined(PDCURSES) && defined(PDC_BUILD)
+    HTSprintf(&result, ", pdcurses %.3f", PDC_BUILD * 0.001);
+#elif defined(USE_SLANG) && defined(SLANG_VERSION_STRING)
+    HTSprintf(&result, ", s-lang %s", SLANG_VERSION_STRING);
+#endif
+
     printf("%s\n", result);
     free(result);
 
@@ -3410,7 +3419,7 @@ keys (may be incompatible with some curses packages)"
       "disable ftp access"
    ),
    PARSE_FUN(
-      "get_data",	6|FUNCTION_ARG,		get_data_fun,
+      "get_data",	2|FUNCTION_ARG,		get_data_fun,
       "user data for get forms, read from stdin,\nterminated by '---' on a line"
    ),
    PARSE_SET(
@@ -3418,7 +3427,7 @@ keys (may be incompatible with some curses packages)"
       "send a HEAD request"
    ),
    PARSE_FUN(
-      "help",		5|FUNCTION_ARG,		help_fun,
+      "help",		1|FUNCTION_ARG,		help_fun,
       "print this usage message"
    ),
    PARSE_FUN(
@@ -3563,7 +3572,7 @@ keys (may be incompatible with some curses packages)"
    ),
 #ifdef SOCKS
    PARSE_SET(
-      "nosocks",	6|UNSET_ARG,		socks_flag,
+      "nosocks",	2|UNSET_ARG,		socks_flag,
       "don't use SOCKS proxy for this session"
    ),
 #endif
@@ -3609,7 +3618,7 @@ with partial-display logic"
       "toggles handling of single-choice SELECT options via\npopup windows or as lists of radio buttons"
    ),
    PARSE_FUN(
-      "post_data",	6|FUNCTION_ARG,		post_data_fun,
+      "post_data",	2|FUNCTION_ARG,		post_data_fun,
       "user data for post forms, read from stdin,\nterminated by '---' on a line"
    ),
    PARSE_SET(
@@ -3684,7 +3693,7 @@ with the PREV_DOC command or from the History List"
    ),
 #ifdef SH_EX
    PARSE_SET(
-      "show_cfg",	4|SET_ARG,		show_cfg,
+      "show_cfg",	1|SET_ARG,		show_cfg,
       "Show `LYNX.CFG' setting"
    ),
 #endif
@@ -3998,49 +4007,77 @@ static int arg_eqs_parse(const char *a,
 #define is_true(s)  (*s == '1' || *s == '+' || !strcmp(s, "on"))
 #define is_false(s) (*s == '0' || *s == '-' || !strcmp(s, "off"))
 
+/*
+ * Parse an option.
+ *	argv[] points to the beginning of the unprocessed options.
+ *	mask is used to select certain options which must be processed
+ *		before others.
+ *	countp (if nonnull) points to an index into argv[], which is updated
+ *		to reflect option values which are also parsed.
+ */
 static BOOL parse_arg(char **argv,
 		      unsigned mask,
-		      int *i)
+		      int *countp)
 {
     Config_Type *p;
     char *arg_name;
 
 #if EXTENDED_STARTFILE_RECALL
-    static BOOLEAN had_nonoption = FALSE;
+    static char *nonoption = 0;
+    static BOOLEAN no_options_further = FALSE;	/* set to TRUE after '--' argument */
 #endif
 
     arg_name = argv[0];
+    CTRACE((tfp, "parse_arg(arg_name=%s, mask=%d, count=%d)\n",
+	    arg_name, mask, countp ? *countp : -1));
+
+#if EXTENDED_STARTFILE_RECALL
+    if (mask == ((countp != 0) ? 0 : 1)) {
+	no_options_further = FALSE;
+	/* want to reset nonoption when beginning scan for --stdin */
+	if (nonoption != 0) {
+	    FREE(nonoption);
+	}
+    }
+#endif
 
     /*
      * Check for a command line startfile.  - FM
      */
-#if !EXTENDED_OPTION_LOGIC
-    if (*arg_name != '-')
-#else
-    if (*arg_name != '-' || no_options_further == TRUE)
+    if (*arg_name != '-'
+#if EXTENDED_OPTION_LOGIC
+	|| no_options_further == TRUE
 #endif
-    {
+	) {
 #if EXTENDED_STARTFILE_RECALL
-	if (had_nonoption && !dump_output_immediately) {
-	    HTAddGotoURL(startfile);	/* startfile was set by a previous arg */
+	/*
+	 * On the last pass (mask==4), check for cases where we may want to
+	 * provide G)oto history for multiple startfiles.
+	 */
+	if (mask == 4) {
+	    if (nonoption != 0) {
+		LYEnsureAbsoluteURL(&nonoption, "NONOPTION", FALSE);
+		HTAddGotoURL(nonoption);
+		FREE(nonoption);
+	    }
+	    StrAllocCopy(nonoption, arg_name);
 	}
-	had_nonoption = TRUE;
 #endif
 	StrAllocCopy(startfile, arg_name);
 	LYEscapeStartfile(&startfile);
 #ifdef _WINDOWS			/* 1998/01/14 (Wed) 20:11:17 */
 	HTUnEscape(startfile);
 	{
-	    char *p;
+	    char *q = startfile;
 
-	    p = startfile;
-	    while (*p++) {
-		if (*p == '|')
-		    *p = ':';
+	    while (*q++) {
+		if (*q == '|')
+		    *q = ':';
 	    }
 	}
 #endif
-	return (BOOL) (i != 0);
+	CTRACE((tfp, "parse_arg startfile:%s\n", startfile));
+	return (BOOL) (countp != 0);
     }
 #if EXTENDED_OPTION_LOGIC
     if (strcmp(arg_name, "--") == 0) {
@@ -4063,7 +4100,7 @@ static BOOL parse_arg(char **argv,
     if (*arg_name == '-')
 	++arg_name;
 
-    CTRACE((tfp, "parse_arg(%s)\n", arg_name));
+    CTRACE((tfp, "parse_arg lookup(%s)\n", arg_name));
 
     p = Arg_Table;
     while (p->name != 0) {
@@ -4081,8 +4118,8 @@ static BOOL parse_arg(char **argv,
 	if (p->type & NEED_NEXT_ARG) {
 	    if (next_arg == 0) {
 		next_arg = argv[1];
-		if ((i != 0) && (next_arg != 0))
-		    (*i)++;
+		if ((countp != 0) && (next_arg != 0))
+		    (*countp)++;
 	    }
 	    CTRACE((tfp, "...arg:%s\n", next_arg != 0 ? next_arg : "<null>"));
 	}
diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c
index 86ba2249..71f0b0aa 100644
--- a/src/LYMainLoop.c
+++ b/src/LYMainLoop.c
@@ -2983,13 +2983,17 @@ static BOOLEAN handle_LYK_HEAD(int *cmd)
 
 static void handle_LYK_HELP(const char **cshelpfile)
 {
+    char *my_value = NULL;
+
     if (*cshelpfile == NULL)
 	*cshelpfile = helpfile;
-    if (!STREQ(curdoc.address, *cshelpfile)) {
+    StrAllocCopy(my_value, *cshelpfile);
+    LYEnsureAbsoluteURL(&my_value, *cshelpfile, FALSE);
+    if (!STREQ(curdoc.address, my_value)) {
 	/*
 	 * Set the filename.
 	 */
-	set_address(&newdoc, *cshelpfile);
+	set_address(&newdoc, my_value);
 	/*
 	 * Make a name for this help file.
 	 */
@@ -3000,6 +3004,7 @@ static void handle_LYK_HELP(const char **cshelpfile)
 	newdoc.safe = FALSE;
 	newdoc.internal_link = FALSE;
     }
+    FREE(my_value);
     *cshelpfile = NULL;		/* reset pointer - kw */
 }
 
@@ -7421,7 +7426,7 @@ static void HTGotoURLs_free(void)
  */
 void HTAddGotoURL(char *url)
 {
-    char *new = NULL;
+    char *copy = NULL;
     char *old;
     HTList *cur;
 
@@ -7429,26 +7434,26 @@ void HTAddGotoURL(char *url)
 	return;
 
     CTRACE((tfp, "HTAddGotoURL %s\n", url));
-    StrAllocCopy(new, url);
+    StrAllocCopy(copy, url);
 
     if (!Goto_URLs) {
 	Goto_URLs = HTList_new();
 #ifdef LY_FIND_LEAKS
 	atexit(HTGotoURLs_free);
 #endif
-	HTList_addObject(Goto_URLs, new);
+	HTList_addObject(Goto_URLs, copy);
 	return;
     }
 
     cur = Goto_URLs;
     while (NULL != (old = (char *) HTList_nextObject(cur))) {
-	if (!strcmp(old, new)) {
+	if (!strcmp(old, copy)) {
 	    HTList_removeObject(Goto_URLs, old);
 	    FREE(old);
 	    break;
 	}
     }
-    HTList_addObject(Goto_URLs, new);
+    HTList_addObject(Goto_URLs, copy);
 
     return;
 }
diff --git a/src/LYReadCFG.c b/src/LYReadCFG.c
index 65e9cd34..83fd3def 100644
--- a/src/LYReadCFG.c
+++ b/src/LYReadCFG.c
@@ -925,7 +925,7 @@ static int system_editor_fun(char *value)
 }
 
 #define SetViewer(mime_type, viewer) \
-    HTSetPresentation(mime_type, viewer, 1.0, 3.0, 0.0, 0, mediaCFG)
+    HTSetPresentation(mime_type, viewer, 0, 1.0, 3.0, 0.0, 0, mediaCFG)
 
 static int viewer_fun(char *value)
 {
diff --git a/src/LYShowInfo.c b/src/LYShowInfo.c
index 63bf70dd..4686dc7a 100644
--- a/src/LYShowInfo.c
+++ b/src/LYShowInfo.c
@@ -60,7 +60,8 @@ char *LYVersionDate(void)
  * LYShowInfo prints a page of info about the current file and the link that
  * the cursor is on.
  */
-int LYShowInfo(DocInfo *doc, int size_of_file,
+int LYShowInfo(DocInfo *doc,
+	       int size_of_file,
 	       DocInfo *newdoc,
 	       char *owner_address)
 {
@@ -424,6 +425,13 @@ int LYShowInfo(DocInfo *doc, int size_of_file,
 	} else
 	    fprintf(fp0, "<h2>%s</h2>", gettext("No Links on the current page"));
 
+#ifdef EXP_HTTP_HEADERS
+	if ((cp = HText_getHttpHeaders()) != 0) {
+	    fprintf(fp0, "<h2>%s</h2>", gettext("Server Headers:"));
+	    fprintf(fp0, "<pre>%s</pre>", cp);
+	}
+#endif
+
 #ifdef DIRED_SUPPORT
     }
 #endif /* DIRED_SUPPORT */
diff --git a/src/LYStyle.c b/src/LYStyle.c
index a40e1429..5e97d8aa 100644
--- a/src/LYStyle.c
+++ b/src/LYStyle.c
@@ -1,6 +1,6 @@
 /* character level styles for Lynx
  * (c) 1996 Rob Partington -- donated to the Lyncei (if they want it :-)
- * @Id: LYStyle.c 1.56 Thu, 06 May 2004 17:31:33 -0700 dickey @
+ * @Id: LYStyle.c 1.57 Wed, 30 Jun 2004 16:55:04 -0700 dickey @
  */
 #include <HTUtils.h>
 #include <HTML.h>
@@ -28,7 +28,7 @@
 static void style_initialiseHashTable(void);
 
 /* stack of attributes during page rendering */
-int last_styles[128] =
+int last_styles[MAX_LAST_STYLES] =
 {0};
 int last_colorattr_ptr = 0;
 
diff --git a/src/LYUtils.c b/src/LYUtils.c
index 47dbcb29..a1dd074d 100644
--- a/src/LYUtils.c
+++ b/src/LYUtils.c
@@ -3927,7 +3927,7 @@ void LYConvertToURL(char **AllocatedString,
 		if (strchr(old_string, '[') ||
 		    ((cp = strchr(old_string, ':')) != NULL &&
 		     !isdigit(UCH(cp[1]))) ||
-		    !LYExpandHostForURL((char **) &old_string,
+		    !LYExpandHostForURL(&old_string,
 					URLDomainPrefixes,
 					URLDomainSuffixes)) {
 		    /*
@@ -3945,7 +3945,7 @@ void LYConvertToURL(char **AllocatedString,
 		     * Assume a URL is wanted, so guess the scheme with
 		     * "http://" as the default.  - FM
 		     */
-		    if (!LYAddSchemeForURL((char **) &old_string, "http://")) {
+		    if (!LYAddSchemeForURL(&old_string, "http://")) {
 			StrAllocCopy(*AllocatedString, "http://");
 			StrAllocCat(*AllocatedString, old_string);
 		    } else {
@@ -3964,7 +3964,7 @@ void LYConvertToURL(char **AllocatedString,
 	    if (strchr(old_string, '[') ||
 		((cp = strchr(old_string, ':')) != NULL &&
 		 !isdigit(UCH(cp[1]))) ||
-		!LYExpandHostForURL((char **) &old_string,
+		!LYExpandHostForURL(&old_string,
 				    URLDomainPrefixes,
 				    URLDomainSuffixes)) {
 		/*
@@ -3980,7 +3980,7 @@ void LYConvertToURL(char **AllocatedString,
 		 * Assume a URL is wanted, so guess the scheme with "http://"
 		 * as the default.  - FM
 		 */
-		if (!LYAddSchemeForURL((char **) &old_string, "http://")) {
+		if (!LYAddSchemeForURL(&old_string, "http://")) {
 		    StrAllocCopy(*AllocatedString, "http://");
 		    StrAllocCat(*AllocatedString, old_string);
 		} else {
@@ -4204,10 +4204,10 @@ void LYConvertToURL(char **AllocatedString,
 		    }
 		}
 #endif
-		if (LYExpandHostForURL((char **) &old_string,
+		if (LYExpandHostForURL(&old_string,
 				       URLDomainPrefixes,
 				       URLDomainSuffixes)) {
-		    if (!LYAddSchemeForURL((char **) &old_string, "http://")) {
+		    if (!LYAddSchemeForURL(&old_string, "http://")) {
 			StrAllocCopy(*AllocatedString, "http://");
 			StrAllocCat(*AllocatedString, old_string);
 		    } else {
@@ -7557,6 +7557,12 @@ void get_clip_release()
 #define WSABASEERR 10000
 #endif
 
+#ifdef ENABLE_IPV6
+#define WSOCK_NAME  "ws2_32"
+#else
+#define WSOCK_NAME  "wsock32"
+#endif
+
 /*
  * Description: the windows32 version of perror()
  *
@@ -7577,6 +7583,7 @@ char *w32_strerror(DWORD ercode)
     HMODULE hModule;
     int i, msg_type;
     unsigned char *p, *q, tmp_buff[256];
+    DWORD rc;
 
     hModule = NULL;
     msg_type = FORMAT_MESSAGE_FROM_SYSTEM;
@@ -7589,22 +7596,20 @@ char *w32_strerror(DWORD ercode)
      * Special code for winsock error handling.
      */
     if (ercode > WSABASEERR) {
-	hModule = GetModuleHandle("wsock32");
-	if (hModule == NULL)
-	    ercode = GetLastError();
-	else
+	hModule = GetModuleHandle(WSOCK_NAME);
+	if (hModule)
 	    msg_type = FORMAT_MESSAGE_FROM_HMODULE;
     }
     /*
-     * message handling
+     * message handling. If not found in module, retry from system.
      */
-    FormatMessage(msg_type,
-		  hModule,
-		  ercode,
-		  LANG_NEUTRAL,
-		  msg_buff,
-		  sizeof(msg_buff),
-		  NULL);
+    rc = FormatMessage(msg_type, hModule, ercode, LANG_NEUTRAL,
+		       msg_buff, sizeof(msg_buff), NULL);
+
+    if (rc == 0 && msg_type == FORMAT_MESSAGE_FROM_HMODULE) {
+	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ercode,
+		      LANG_NEUTRAL, msg_buff, sizeof(msg_buff), NULL);
+    }
 
     strcpy(tmp_buff, msg_buff);
     p = q = tmp_buff;
diff --git a/src/Xsystem.c b/src/Xsystem.c
index 806633d9..55acacd7 100644
--- a/src/Xsystem.c
+++ b/src/Xsystem.c
@@ -1,4 +1,4 @@
-/* @Id: Xsystem.c 1.13 Thu, 06 May 2004 17:31:33 -0700 dickey @
+/* @Id: Xsystem.c 1.14 Wed, 30 Jun 2004 16:55:04 -0700 dickey @
  *	like system("cmd") but return with exit code of "cmd"
  *	for Turbo-C/MS-C/LSI-C
  *  This code is in the public domain.
@@ -25,21 +25,14 @@
  *
  */
 #include <LYUtils.h>
+#include <LYStrings.h>
 
-#if 0
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
+#ifdef DOSPATH
 #include <io.h>
-#include <process.h>
-#ifndef __CYGWIN__
-#include <dos.h>
-#endif
+#else
+extern char *mktemp(char *);
 #endif
 
-#include <LYStrings.h>
-
 #ifndef USECMDLINE
 #define USECMDLINE	0
 #endif
@@ -53,8 +46,6 @@
 
 #define STR_MAX 512		/* MAX command line */
 
-extern char *mktemp(char *);
-
 #define isk1(c)  ((0x81 <= UCH(c) && UCH(c) <= 0x9F) || (0xE0 <= UCH(c) && UCH(c) <= 0xFC))
 #define isq(c)   ((c) == '"')
 #define isspc(c) ((c) == ' ' || (c) == '\t')