about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorThomas E. Dickey <dickey@invisible-island.net>2003-01-22 10:09:18 -0500
committerThomas E. Dickey <dickey@invisible-island.net>2003-01-22 10:09:18 -0500
commit533c7482785176296637df81cd1a6318a0c29f97 (patch)
treee50cece290409516ee62f08c8912863f5f1ba80a /src
parent490d581c911f53008a7eaaed72b655cf40071b03 (diff)
downloadlynx-snapshots-533c7482785176296637df81cd1a6318a0c29f97.tar.gz
snapshot of project "lynx", label v2-8-5dev_13
Diffstat (limited to 'src')
-rw-r--r--src/GridText.c700
-rw-r--r--src/GridText.h4
-rw-r--r--src/HTML.c84
-rw-r--r--src/HTML.h1
-rw-r--r--src/LYBookmark.h1
-rw-r--r--src/LYCgi.c2
-rw-r--r--src/LYCharUtils.c122
-rw-r--r--src/LYCharUtils.h7
-rw-r--r--src/LYClean.c12
-rw-r--r--src/LYCookie.c4
-rw-r--r--src/LYCurses.c6
-rw-r--r--src/LYCurses.h16
-rw-r--r--src/LYDownload.c11
-rw-r--r--src/LYGlobalDefs.h5
-rw-r--r--src/LYHistory.c60
-rw-r--r--src/LYJump.c2
-rw-r--r--src/LYJump.h1
-rw-r--r--src/LYKeymap.c4
-rw-r--r--src/LYLeaks.c308
-rw-r--r--src/LYList.c10
-rw-r--r--src/LYLocal.c5
-rw-r--r--src/LYMail.c65
-rw-r--r--src/LYMail.h1
-rw-r--r--src/LYMain.c21
-rw-r--r--src/LYMainLoop.c2
-rw-r--r--src/LYNews.h1
-rw-r--r--src/LYOptions.c10
-rw-r--r--src/LYPrint.c13
-rw-r--r--src/LYPrint.h1
-rw-r--r--src/LYReadCFG.c110
-rw-r--r--src/LYShowInfo.c2
-rw-r--r--src/LYShowInfo.h1
-rw-r--r--src/LYStrings.c60
-rw-r--r--src/LYStrings.h2
-rw-r--r--src/LYStyle.c6
-rw-r--r--src/LYUpload.c10
-rw-r--r--src/LYUtils.c485
-rw-r--r--src/LYUtils.h5
38 files changed, 1263 insertions, 897 deletions
diff --git a/src/GridText.c b/src/GridText.c
index e070f164..d5189c46 100644
--- a/src/GridText.c
+++ b/src/GridText.c
@@ -98,8 +98,14 @@ struct _HTStream {			/* only know it as object */
 };
 
 #define TITLE_LINES  1
+
 #define IS_UTF_EXTRA(ch) (text->T.output_utf8 && \
 			  (UCH((ch))&0xc0) == 0x80)
+
+#define IS_UTF8_EXTRA(ch) (!(text && text->T.output_utf8) || \
+			  !is8bits(ch) || \
+			  (UCH(line->data[i] & 0xc0) == 0xc0))
+
 /* a test in compact form: how many extra UTF-8 chars after initial? - kw */
 #define UTF8_XNEGLEN(c) (c&0xC0? 0 :c&32? 1 :c&16? 2 :c&8? 3 :c&4? 4 :c&2? 5:0)
 #define UTF_XLEN(c) UTF8_XNEGLEN(((char)~(c)))
@@ -149,8 +155,30 @@ PUBLIC int LYsb_begin = -1;
 PUBLIC int LYsb_end = -1;
 #endif
 
+#ifndef VMS			/* VMS has a better way - right? - kw */
+#define CHECK_FREE_MEM
+#endif
+
+#ifdef CHECK_FREE_MEM
+PRIVATE void * LY_check_calloc PARAMS((size_t nmemb, size_t size));
+#define LY_CALLOC LY_check_calloc
+#else
+  /* using the regular calloc */
+#define LY_CALLOC calloc
+#endif
+
+/*
+ * The HTPool.data[] array has to align the same as malloc() would, to make the
+ * ALLOC_POOL scheme portable.  For many platforms, that is the same as the
+ * number of bytes in a pointer.  It may be larger, e.g., on machines which
+ * have more stringent requirements for floating point.  32-bits are plenty for
+ * representing styles, but we may need 64-bit or 128-bit alignment.
+ *
+ * The real issue is that performance is degraded if the alignment is not met,
+ * and some platforms such as Tru64 generate lots of warning messages.
+ */
+#define ALIGN_SIZE     8
 
-    /*try to fit in 32bit */
 typedef struct {
 	unsigned int	direction:2;   /* on or off */
 	unsigned int	horizpos:14;   /* horizontal position of this change */
@@ -163,10 +191,12 @@ typedef struct {
 static HTStyleChange stylechanges_buffers[2][MAX_STYLES_ON_LINE];
 #endif
 
-enum { POOL_SIZE = (8192 - 4*sizeof(void*) - sizeof(struct _HTPool*) - sizeof(int)) / sizeof(HTStyleChange) };
+typedef HTStyleChange pool_data;
+
+enum { POOL_SIZE = (8192 - 4*sizeof(void*) - sizeof(struct _HTPool*) - sizeof(int)) / sizeof(pool_data) };
 
 typedef struct _HTPool {
-    HTStyleChange   data[POOL_SIZE];
+    pool_data  data[POOL_SIZE];
     struct _HTPool* prev;
     int used;
 } HTPool;
@@ -203,103 +233,93 @@ to be very efficient.
 lines, anchors, and FormInfo. Arrays of HTStyleChange are stored as is,
 other objects are stored using a cast.]
 
- Pool are referenced by pointer to the chunk that contains free slots. Macros
-that allocate memory in pools update that pointer if needed.
- There are 3 macros that deal with pools - POOL_NEW, POOL_FREE and
-ALLOC_IN_POOL.
- Here is a description of those macros as C++ functions (with names mentioned
-above and with use of C++ references)
-
-void ALLOC_IN_POOL( P*& pool, pool_type, int toalloc, T*& ptr)
-    - allocates 'toalloc' items in the pool of type 'pool_type' pointed by
-    'pool', sets the pointer 'ptr' to the "allocated" memory and updates 'pool'
-    if necessary. Sets 'ptr' to NULL if fails.
-
-void POOL_NEW( pool_type  , P*& ptr)
-    Initializes a pool of type 'pool_type' pointed by 'ptr', updating 'ptr'.
-    Sets 'ptr' to NULL if fails.
-
-void POOL_FREE( pool_type , P*& ptr)
-    Frees a pool of type 'pool_type' pointed by ptr. Sets ptr to NULL.
+ Pool is referenced by the pointer to the last chunk that contains free slots.
+Functions that allocate memory in pool update that pointer if needed.
+There are 3 functions - POOL_NEW, POOL_FREE, and ALLOC_IN_POOL.
 
       - VH
 
 *************************************************************************/
+
+#define POOLallocstyles(ptr, n)     ptr = ALLOC_IN_POOL(&HTMainText->pool, n * sizeof(pool_data))
+#define POOLallocHTLine(ptr, size)  ptr = (HTLine*) ALLOC_IN_POOL(&HTMainText->pool, LINE_SIZE(size))
+#define POOLallocstring(ptr, len)   ptr = (char*) ALLOC_IN_POOL(&HTMainText->pool, len + 1)
+#define POOLtypecalloc(T,ptr)	    ptr = (T*) ALLOC_IN_POOL(&HTMainText->pool, sizeof(T))
+
+/**************************************************************************/
 /*
- * void ALLOC_IN_POOL( P*& pool, pool_type, int toalloc, T*& ptr)
- *     - allocates 'toalloc' items in the pool of type 'pool_type' pointed by
- *     'pool', sets the pointer 'ptr' to the "allocated" memory and updates
- *     'pool' if necessary.  Sets 'ptr' to NULL if fails.
+ *   Allocates 'n' items in the pool of type 'HTPool' pointed by 'poolptr'.
+ *   Returns a pointer to the "allocated" memory or NULL if fails.
+ *   Updates 'poolptr' if necessary.
  */
-#define ALLOC_IN_POOL(pool,pool_type,toalloc,ptr) \
-    if (!pool) {					\
-	ptr = NULL;					\
-    } else {						\
-	if (POOL_SIZE - pool->used >= toalloc) {	\
-	    ptr = pool->data + pool->used;		\
-	    pool->used += toalloc;			\
-	} else {					\
-	    pool_type* newpool = (pool_type*)LY_CALLOC(1, sizeof(pool_type)); \
-	    if (!newpool) {				\
-		ptr = NULL;				\
-	    } else {					\
-		newpool->prev = pool;			\
-		newpool->used = toalloc;		\
-		ptr = newpool->data;			\
-		pool = newpool;				\
-	   }						\
-	}						\
+PRIVATE pool_data* ALLOC_IN_POOL ARGS2(
+	HTPool**,	ppoolptr,
+	unsigned,	request)
+{
+    HTPool* pool = *ppoolptr;
+    pool_data* ptr;
+    unsigned n;
+    unsigned j;
+
+    if (!pool) {
+	ptr = NULL;
+    } else {
+	n = request;
+	if (n == 0)
+	    n = 1;
+	j = (n % ALIGN_SIZE);
+	if (j != 0)
+	    n += (ALIGN_SIZE - j);
+	n /= sizeof(pool_data);
+	if (POOL_SIZE >= (pool->used + n)) {
+	    ptr = pool->data + pool->used;
+	    pool->used += n;
+	} else {
+	    HTPool* newpool = (HTPool*)LY_CALLOC(1, sizeof(HTPool));
+	    if (!newpool) {
+		ptr = NULL;
+	    } else {
+		newpool->prev = pool;
+		newpool->used = n;
+		ptr = newpool->data;
+		pool = newpool;
+	   }
+	}
     }
+    *ppoolptr = pool;
+    return ptr;
+}
+
 /*
- * void POOL_NEW( pool_type  , P*& ptr)
- *     Initializes a pool of type 'pool_type' pointed by 'ptr', updating 'ptr'.
- *     Sets 'ptr' to NULL if fails.
+ *   Returns a pointer to initialized pool of type 'HTPool', or NULL if fails.
  */
-#define POOL_NEW(pool_type,ptr)				\
-    {							\
-	ptr = (pool_type*)LY_CALLOC(1, sizeof(pool_type)); \
-	if (ptr) {					\
-	    ptr->prev = NULL;				\
-	    ptr->used = 0;				\
-	}						\
+PRIVATE HTPool* POOL_NEW NOARGS
+{
+    HTPool* poolptr = (HTPool*)LY_CALLOC(1, sizeof(HTPool));
+    if (poolptr) {
+	(poolptr)->prev = NULL;
+	(poolptr)->used = 0;
     }
+    return poolptr;
+}
+
 /*
- * void POOL_FREE( pool_type, P*& ptr)
- *     Frees a pool of type 'pool_type' pointed by ptr. Sets ptr to NULL.
+ *   Frees a pool of type 'HTPool' pointed by poolptr.
  */
-#define POOL_FREE(pool_type,ptr)			\
-    {							\
-	pool_type* cur = ptr;				\
-	pool_type* prev;				\
-	while (cur) {					\
-	    prev = cur->prev;				\
-	    FREE(cur);					\
-	    cur = prev;					\
-	}						\
-	ptr = NULL;					\
+PRIVATE void POOL_FREE ARGS1(
+	HTPool*,	poolptr)
+{
+    HTPool* cur = poolptr;
+    HTPool* prev;
+    while (cur) {
+	prev = cur->prev;
+	free(cur);
+	cur = prev;
     }
-/**************************************************************************/
+}
 
-#define _sz_           sizeof(HTStyleChange)      /* 4 */
-#define _round_up_(x)  (x%_sz_ ? x/_sz_ + 1: x/_sz_)
-
-#define POOLallocstyles(ptr, N)     ALLOC_IN_POOL(HTMainText->pool,HTPool,\
-					N,				\
-					ptr)
-#define POOLallocHTLine(ptr, size)  { HTStyleChange* _tmp_;		\
-				      int N = _round_up_(LINE_SIZE(size));  \
-				      ALLOC_IN_POOL(HTMainText->pool,HTPool,\
-					N,      \
-					_tmp_); \
-				      ptr = (HTLine*)_tmp_; \
-				    }
-#define POOLtypecalloc(T,ptr)	    { HTStyleChange* _tmp_;		\
-				      int N = _round_up_(sizeof(T));	\
-				      ALLOC_IN_POOL(HTMainText->pool,HTPool,\
-					N,	\
-					_tmp_);	\
-				      ptr = (T*)_tmp_;	\
-				    }
+/**************************************************************************/
+/**************************************************************************/
 
 typedef struct _line {
 	struct _line    *next;
@@ -315,7 +335,20 @@ typedef struct _line {
 
 
 #define LINE_SIZE(l) (sizeof(HTLine)+(l))	/* Allow for terminator */
-#define allocHTLine(l) (HTLine *)calloc(1, LINE_SIZE(l))
+
+/*
+ * Last line buffer; the second is used in split_line(). Not in pool!
+ * We cannot wrap in middle of multibyte sequences, so allocate 2 extra
+ * for a workspace.  This is stored in the HText, to prevent confusion
+ * between different documents.  Note also that it is declared with an
+ * HTLine at the beginning so pointers will be properly aligned.
+ */
+typedef struct {
+	HTLine	base;
+	char    data[MAX_LINE+2];
+} HTLineTemp;
+
+#define TEMP_LINE(p,n) ((HTLine *)&(p->temp_line[n]))
 
 typedef struct _TextAnchor {
 	struct _TextAnchor *	next;
@@ -349,6 +382,7 @@ struct _HText {
 	HTParentAnchor *	node_anchor;
 
 	HTLine *		last_line;
+	HTLineTemp		temp_line[2];
 	int			Lines;		/* Number of them */
 	TextAnchor *		first_anchor;	/* double-linked on demand */
 	TextAnchor *		last_anchor;
@@ -382,6 +416,7 @@ struct _HText {
 	int			last_lineno_last_disp_partial;
 #endif
 	STable_info *		stbl;
+	HTList *		enclosed_stbl;
 
 	HTkcode			kcode;			/* Kanji code? */
 	HTkcode			specified_kcode;	/* Specified Kanji code */
@@ -493,8 +528,6 @@ PUBLIC void mark_justify_start_position ARGS1(void*,text)
 	HTCJK == NOCJK && !in_DT && \
 	can_justify_here && can_justify_this_line && !form_in_htext )
 
-#else
-#define last_anchor_of_previous_line (TextAnchor*)0
 #endif /* EXP_JUSTIFY_ELTS */
 
 
@@ -535,123 +568,16 @@ PUBLIC  HTList * search_queries = NULL;  /* isindex and whereis queries   */
 #ifdef LY_FIND_LEAKS
 PRIVATE void free_all_texts NOARGS;
 #endif
-PRIVATE int HText_TrueLineSize PARAMS((
+
+PRIVATE BOOL HText_TrueEmptyLine PARAMS((
 	HTLine *	line,
 	HText *		text,
 	BOOL		IgnoreSpaces));
 
-#ifndef VMS			/* VMS has a better way - right? - kw */
-#define CHECK_FREE_MEM
-#endif
-
-/*
- * Set the initial highlight information for a given anchor.
- */
-PRIVATE void LYSetHiText ARGS3(
-	TextAnchor *,	a,
-	char *,		text,
-	int,		len)
-{
-    unsigned have = a->lites.hl_len;
-
-    if (a->lites.hl_info != NULL) {
-	while (have-- != 0) {
-	    if ((int) (have + 1) < a->lites.hl_len) {
-		FREE(a->lites.hl_info[have].hl_text);
-	    }
-	}
-	FREE(a->lites.hl_info);
-    }
-    FREE(a->lites.hl_base.hl_text);
-    a->lites.hl_len = 0;
-
-    if (text != NULL) {
-	StrnAllocCopy(a->lites.hl_base.hl_text, text, len);
-	a->lites.hl_len = 1;
-    }
-}
-
-/*
- * Add highlight information for the next line of a anchor.
- */
-PRIVATE void LYAddHiText ARGS3(
-	TextAnchor *,	a,
-	char *,		text,
-	int,		x)
-{
-    HiliteInfo *have = a->lites.hl_info;
-    unsigned need = (a->lites.hl_len - 1);
-    unsigned want = ++(a->lites.hl_len) * sizeof(HiliteInfo);
-
-    if (have != NULL) {
-	have = (HiliteInfo *) realloc(have, want);
-    } else {
-	have = (HiliteInfo *) malloc(want);
-    }
-    a->lites.hl_info = have;
-
-    have[need].hl_text = NULL;
-    StrAllocCopy(have[need].hl_text, text);
-    have[need].hl_x = x;
-}
-
-/*
- * Get the highlight text, counting from zero.
- */
-PRIVATE char *LYGetHiTextStr ARGS2(
-	TextAnchor *,	a,
-	int,		count)
-{
-    char *result;
-
-    if (count >= a->lites.hl_len)
-	result = NULL;
-    else if (count > 0)
-	result = a->lites.hl_info[count - 1].hl_text;
-    else
-	result = a->lites.hl_base.hl_text;
-    return result;
-}
-
-/*
- * Get the X-ordinate at which to draw the corresponding highlight-text
- */
-PRIVATE int LYGetHiTextPos ARGS2(
-	TextAnchor *,	a,
-	int,		count)
-{
-    int result;
-
-    if (count >= a->lites.hl_len)
-	result = -1;
-    else if (count > 0)
-	result = a->lites.hl_info[count - 1].hl_x;
-    else
-	result = a->line_pos;
-    return result;
-}
-
-/*
- * Copy highlighting information from anchor 'a' to 'b'.
- */
-PRIVATE void LYCopyHiText ARGS2(
-	TextAnchor *,	a,
-	TextAnchor *,	b)
-{
-    int count;
-    char *s;
-
-    LYSetHiText(a, NULL, 0);
-    for (count = 0; ; ++count) {
-	if ((s = LYGetHiTextStr(b, count)) == NULL)
-	    break;
-	if (count == 0) {
-	    LYSetHiText(a, s, strlen(s));
-	} else {
-	    LYAddHiText(a, s, LYGetHiTextPos(b, count));
-	}
-    }
-}
+PRIVATE int HText_TrueLineSize PARAMS((
+	HTLine *	line,
+	HText *		text,
+	BOOL		IgnoreSpaces));
 
 #ifdef CHECK_FREE_MEM
 
@@ -723,7 +649,6 @@ PRIVATE void * LY_check_calloc ARGS2(
 	HText * t = (HText *) HTList_objectAt(loaded_texts, i);
 	if (t == HTMainText)
 	    t = NULL;		/* shouldn't happen */
-	{
 	CTRACE((tfp, "\nBUG *** Emergency freeing document %d/%d for '%s'%s!\n",
 		    i + 1, n,
 		    ((t && t->node_anchor &&
@@ -732,7 +657,6 @@ PRIVATE void * LY_check_calloc ARGS2(
 		    ((t && t->node_anchor &&
 		      t->node_anchor->post_data) ?
 		     " with POST data" : "")));
-	}
 	HTList_removeObjectAt(loaded_texts, i);
 	HText_free(t);
 	if (mem_is_avail(4, nmemb * size)) {
@@ -758,14 +682,119 @@ PRIVATE void * LY_check_calloc ARGS2(
     return (calloc(nmemb, size));
 }
 
-#define LY_CALLOC LY_check_calloc
+#endif /* CHECK_FREE_MEM */
+
+/*
+ * Clear highlight information for a given anchor
+ * (text was allocated in the pool).
+ */
+PRIVATE void LYClearHiText ARGS1(
+	TextAnchor *,	a)
+{
+    FREE(a->lites.hl_info);
 
-#else  /* CHECK_FREE_MEM */
+    a->lites.hl_base.hl_text = NULL;
+    a->lites.hl_len = 0;
+}
 
-  /* using the regular calloc */
-#define LY_CALLOC calloc
+/*
+ * Set the initial highlight information for a given anchor.
+ */
+PRIVATE void LYSetHiText ARGS3(
+	TextAnchor *,	a,
+	char *,		text,
+	int,		len)
+{
+    if (text != NULL) {
+	POOLallocstring(a->lites.hl_base.hl_text, len);
+	memcpy(a->lites.hl_base.hl_text, text, len);
+	*(a->lites.hl_base.hl_text + len) = '\0';
 
-#endif /* CHECK_FREE_MEM */
+	a->lites.hl_len = 1;
+    }
+}
+
+/*
+ * Add highlight information for the next line of a anchor.
+ */
+PRIVATE void LYAddHiText ARGS3(
+	TextAnchor *,	a,
+	char *,		text,
+	int,		x)
+{
+    HiliteInfo *have = a->lites.hl_info;
+    unsigned need = (a->lites.hl_len - 1);
+    unsigned want = (a->lites.hl_len += 1) * sizeof(HiliteInfo);
+
+    if (have != NULL) {
+	have = (HiliteInfo *) realloc(have, want);
+    } else {
+	have = (HiliteInfo *) malloc(want);
+    }
+    a->lites.hl_info = have;
+
+    POOLallocstring(have[need].hl_text, strlen(text));
+    strcpy(have[need].hl_text, text);
+    have[need].hl_x = x;
+}
+
+/*
+ * Get the highlight text, counting from zero.
+ */
+PRIVATE char *LYGetHiTextStr ARGS2(
+	TextAnchor *,	a,
+	int,		count)
+{
+    char *result;
+
+    if (count >= a->lites.hl_len)
+	result = NULL;
+    else if (count > 0)
+	result = a->lites.hl_info[count - 1].hl_text;
+    else
+	result = a->lites.hl_base.hl_text;
+    return result;
+}
+
+/*
+ * Get the X-ordinate at which to draw the corresponding highlight-text
+ */
+PRIVATE int LYGetHiTextPos ARGS2(
+	TextAnchor *,	a,
+	int,		count)
+{
+    int result;
+
+    if (count >= a->lites.hl_len)
+	result = -1;
+    else if (count > 0)
+	result = a->lites.hl_info[count - 1].hl_x;
+    else
+	result = a->line_pos;
+    return result;
+}
+
+/*
+ * Copy highlighting information from anchor 'b' to 'a'.
+ */
+PRIVATE void LYCopyHiText ARGS2(
+	TextAnchor *,	a,
+	TextAnchor *,	b)
+{
+    int count;
+    char *s;
+
+    LYClearHiText(a);
+    for (count = 0; ; ++count) {
+	if ((s = LYGetHiTextStr(b, count)) == NULL)
+	    break;
+	if (count == 0) {
+	    LYSetHiText(a, s, strlen(s));
+	} else {
+	    LYAddHiText(a, s, LYGetHiTextPos(b, count));
+	}
+    }
+}
 
 PRIVATE void HText_getChartransInfo ARGS1(
 	HText *,	me)
@@ -877,14 +906,14 @@ PUBLIC HText *	HText_new ARGS1(
 #endif /* VMS && VAXC && !__DECC */
     }
 
-    POOL_NEW(HTPool, self->pool);
+    self->pool = POOL_NEW();
     if (!self->pool)
 	outofmem(__FILE__, "HText_New");
-    line = self->last_line = allocHTLine(MAX_LINE);
-    if (line == NULL)
-	outofmem(__FILE__, "HText_New");
+
+    line = self->last_line = TEMP_LINE(self, 0);
     line->next = line->prev = line;
     line->offset = line->size = 0;
+    line->data[line->size] = '\0';
 #ifdef USE_COLOR_STYLE
     line->numstyles = 0;
     line->styles = stylechanges_buffers[0];
@@ -1058,24 +1087,6 @@ PUBLIC void HText_free ARGS1(
 
     HTAnchor_setDocument(self->node_anchor, (HyperDoc *)0);
 
-    while (YES) {	/* Free off line array */
-	HTLine * l = self->last_line;
-	if (l) {
-	    l->next->prev = l->prev;
-	    l->prev->next = l->next;	/* Unlink l */
-	    self->last_line = l->prev;
-	    if (l != self->last_line) {
-		FREE(l);
-	    } else {
-		free(l);
-	    }
-	}
-	if (l == self->last_line) {	/* empty */
-	    l = self->last_line = NULL;
-	    break;
-	}
-    }
-
     while (self->first_anchor) {		/* Free off anchor array */
 	TextAnchor * l = self->first_anchor;
 	self->first_anchor = l->next;
@@ -1126,7 +1137,7 @@ PUBLIC void HText_free ARGS1(
 	    FREE(l->input_field->accept_cs);
 	}
 
-	LYSetHiText(l, NULL, 0);
+	LYClearHiText(l);
     }
     FormList_delete(self->forms);
 
@@ -1184,7 +1195,7 @@ PUBLIC void HText_free ARGS1(
 	    HTMainAnchor = NULL;
     }
 
-    POOL_FREE(HTPool, self->pool);
+    POOL_FREE(self->pool);
     FREE(self);
 }
 
@@ -1323,7 +1334,7 @@ PRIVATE int display_line ARGS4(
 	while (current_style < line->numstyles &&
 	       i >= (int) (CStyle.horizpos + line->offset + 1))
 	{
-	    LynxChangeStyle (CStyle.style,CStyle.direction);
+	    LynxChangeStyle (CStyle.style, CStyle.direction);
 	    current_style++;
 	}
 #endif
@@ -2430,7 +2441,7 @@ PRIVATE int set_style_by_embedded_chars ARGS4(
 PRIVATE void move_anchors_in_region ARGS7(
     HTLine *,		line,
     int,		line_number,
-    TextAnchor **,	prev_anchor,
+    TextAnchor **,	prev_anchor,	/*updates++*/
     int *,		prev_head_processed,
     int,		sbyte,
     int,		ebyte,
@@ -2496,9 +2507,9 @@ PRIVATE void move_anchors_in_region ARGS7(
  *  in appropriate places - so that characters at/after the old
  *  position end up at/after the new position, for each pair, if possible.
  *  Some necessary changes for anchors starting on this line are also done
- *  here if needed.
+ *  here if needed. Updates 'prev_anchor' internally.
  *  Returns a newly allocated HTLine* if changes were made
- *    (caller has to free the old one).
+ *    (lines allocated in pool, caller should not free the old one).
  *  Returns NULL if no changes needed.  (Remove-spaces code may be buggy...)
  * - kw
  */
@@ -2506,7 +2517,7 @@ PRIVATE HTLine * insert_blanks_in_line ARGS7(
     HTLine *,		line,
     int,		line_number,
     HText *,		text,
-    TextAnchor *,	prev_anchor,
+    TextAnchor **,	prev_anchor,	/*updates++*/
     int,		ninserts,
     int *,		oldpos,		/* Measured in cells */
     int *,		newpos)		/* Likewise */
@@ -2533,16 +2544,20 @@ PRIVATE HTLine * insert_blanks_in_line ARGS7(
 	    added_chars = newpos[ip] - oldpos[ip];
     if (line->size + added_chars > MAX_LINE - 2)
 	return NULL;
-    if (line == text->last_line)
-	mod_line = allocHTLine(MAX_LINE);
-    else
-	mod_line = allocHTLine(line->size + added_chars);
+    if (line == text->last_line) {
+	if (line == TEMP_LINE(text, 0))
+	   mod_line = TEMP_LINE(text, 1);
+	else
+	   mod_line = TEMP_LINE(text, 0);
+    } else {
+	POOLallocHTLine(mod_line, line->size + added_chars);
+    }
     if (!mod_line)
 	return NULL;
-    if (!prev_anchor)
-	prev_anchor = text->first_anchor;
-    head_processed = (prev_anchor && prev_anchor->line_num < line_number);
-    memcpy(mod_line, line, LINE_SIZE(1));
+    if (!*prev_anchor)
+	*prev_anchor = text->first_anchor;
+    head_processed = (*prev_anchor && (*prev_anchor)->line_num < line_number);
+    memcpy(mod_line, line, LINE_SIZE(0));
     t = newdata = mod_line->data;
     ip = 0;
     while (ip <= ninserts) {
@@ -2572,7 +2587,7 @@ PRIVATE HTLine * insert_blanks_in_line ARGS7(
 
 	/* Now s is at the "displayed" char, pre is before the style change */
 	if (ip)				/* Fix anchor positions */
-	    move_anchors_in_region(line, line_number, &prev_anchor,
+	    move_anchors_in_region(line, line_number, prev_anchor /*updates++*/,
 				   &head_processed,
 				   copied - line->data, pre - line->data,
 				   shift);
@@ -2600,8 +2615,8 @@ PRIVATE HTLine * insert_blanks_in_line ARGS7(
     while (pre < s)	/* Copy remaining style-codes */
 	*t++ = *pre++;
     /* Check whether the last anchor continues on the next line */
-    if (head_processed && prev_anchor && prev_anchor->line_num == line_number)
-	prev_anchor->extent += shift;
+    if (head_processed && *prev_anchor && (*prev_anchor)->line_num == line_number)
+	(*prev_anchor)->extent += shift;
     *t = '\0';
     mod_line->size = t - newdata;
     return mod_line;
@@ -2654,18 +2669,24 @@ PRIVATE void split_line ARGS2(
     int TailTrim = 0;
     int s, s_post, s_pre, t_underline = underline_on, t_bold = bold_on;
     char *p;
-    HTLine * previous = text->last_line;
     int ctrl_chars_on_previous_line = 0;
     int utfxtra_on_previous_line = UTFXTRA_ON_THIS_LINE;
     char * cp;
-    /* can't wrap in middle of multibyte sequences, so allocate 2 extra */
-    HTLine * line = (HTLine *)LY_CALLOC(1, LINE_SIZE(MAX_LINE)+2);
+
+    HTLine * previous = text->last_line;
+    HTLine * line;
 
     /*
-     *  Make new line.
+     *  Set new line.
      */
+    if (previous == TEMP_LINE(text, 0))
+	line = TEMP_LINE(text, 1);
+    else
+	line = TEMP_LINE(text, 0);
     if (line == NULL)
-	outofmem(__FILE__, "split_line_1");
+	return;
+    memset(line, 0, LINE_SIZE(0));
+
     ctrl_chars_on_this_line = 0; /*reset since we are going to a new line*/
     utfxtra_on_this_line = 0;	/*reset too, we'll count them*/
     text->LastChar = ' ';
@@ -2924,7 +2945,7 @@ PRIVATE void split_line ARGS2(
 		}
 		if ( to < line->styles + MAX_STYLES_ON_LINE - 1
 		     && to[1].direction == STACK_OFF
-		     && to[1].horizpos <= SpecialAttrChars
+		     && to[1].horizpos <= (unsigned) SpecialAttrChars
 		     && to[1].style == scan->style )
 		    to++;
 		else if (to >= line->styles) {
@@ -2956,7 +2977,7 @@ PRIVATE void split_line ARGS2(
 
     {
     HTLine* temp;
-    temp = allocHTLine(previous->size);
+    POOLallocHTLine(temp, previous->size);
     if (!temp)
 	outofmem(__FILE__, "split_line_2");
     memcpy(temp, previous, LINE_SIZE(previous->size));
@@ -2966,7 +2987,6 @@ PRIVATE void split_line ARGS2(
 	outofmem(__FILE__, "split_line_2");
     memcpy(temp->styles, previous->styles, sizeof(HTStyleChange)*previous->numstyles);
 #endif
-    FREE(previous);
     previous = temp;
     }
 
@@ -3243,7 +3263,7 @@ PRIVATE void split_line ARGS2(
 		i++;
 	    }
 	    jline = insert_blanks_in_line(previous, CurLine, text,
-					  last_anchor_of_previous_line,
+					  &last_anchor_of_previous_line /*updates++*/,
 					  ht_num_runs - 1, oldpos, newpos);
 	    free((char*)oldpos);
 	    if (jline == NULL)
@@ -3251,26 +3271,14 @@ PRIVATE void split_line ARGS2(
 	    previous->next->prev = jline;
 	    previous->prev->next = jline;
 
-	    FREE(previous);
-
 	    previous = jline;
 	}
 	{ /* (ht_num_runs==1) */
-	    /* keep maintaining 'last_anchor_of_previous_line' */
-	    TextAnchor* a2 = last_anchor_of_previous_line;
 	    if (justify_start_position) {
 		char* p2 = previous->data;
 		for( ; p2 < previous->data + justify_start_position; ++p2)
 		    *p2 = (*p2 == HT_NON_BREAK_SPACE ? ' ' : *p2);
 	    }
-
-	    if (!a2)
-		a2 = text->first_anchor;
-	    else
-		a2 = a2->next; /* 1st anchor on line we justify */
-
-	    for (; a2 && a2->line_num <= text->Lines-1;
-		last_anchor_of_previous_line = a2, a2 = a2->next);
 	}
     } else {
 	if (REALLY_CAN_JUSTIFY(text) ) {
@@ -3322,9 +3330,7 @@ PRIVATE void blank_lines ARGS2(
 	HText *,	text,
 	int,		newlines)
 {
-    BOOL IgnoreSpaces = FALSE;
-
-    if (!HText_LastLineSize(text, IgnoreSpaces)) { /* No text on current line */
+    if (HText_LastLineEmpty(text, FALSE)) { /* No text on current line */
 	HTLine * line = text->last_line->prev;
 
 #ifdef USE_COLOR_STYLE
@@ -3333,8 +3339,8 @@ PRIVATE void blank_lines ARGS2(
 	    return;			/* Do not add a blank line at start */
 #endif
 
-	while ((line != text->last_line) &&
-	       (HText_TrueLineSize(line, text, IgnoreSpaces) == 0)) {
+	while (line != text->last_line &&
+			HText_TrueEmptyLine(line, text, FALSE)) {
 	    if (newlines == 0)
 		break;
 	    newlines--;		/* Don't bother: already blank */
@@ -4356,7 +4362,7 @@ PUBLIC void _internal_HTC ARGS3(HText *,text, int,style, int,dir)
 
 	if (line->numstyles > 0 && dir == 0 &&
 	    line->styles[line->numstyles-1].direction &&
-	    line->styles[line->numstyles-1].style == style &&
+	    line->styles[line->numstyles-1].style == (unsigned) style &&
 	    (int) line->styles[line->numstyles-1].horizpos
 	    == (int)line->size - ctrl_chars_on_this_line) {
 	    /*
@@ -4488,7 +4494,7 @@ PRIVATE int HText_insertBlanksInStblLines ARGS2(
 	    }
 	}
 	if (line == me->last_line) {
-	    if (line->size == 0 || !HText_TrueLineSize(line, me, FALSE))
+	    if (line->size == 0 || HText_TrueEmptyLine(line, me, FALSE))
 		continue;
 	    /*
 	     *  Last ditch effort to end the table with a line break,
@@ -4517,7 +4523,7 @@ PRIVATE int HText_insertBlanksInStblLines ARGS2(
 	    continue;
 	}
 	mod_line = insert_blanks_in_line(line, lineno, me,
-					 me->last_anchor_before_stbl,
+					 &me->last_anchor_before_stbl /*updates++*/,
 					 ninserts, oldpos, newpos);
 	if (mod_line) {
 	    if (line == me->last_line) {
@@ -4530,7 +4536,6 @@ PRIVATE int HText_insertBlanksInStblLines ARGS2(
 	    lines_changed++;
 	    if (line == first_line)
 		first_line = mod_line;
-	    free(line);
 	    line = mod_line;
 #ifdef DISP_PARTIAL
 	    /*
@@ -4733,6 +4738,25 @@ PUBLIC void HText_startStblTABLE ARGS2(
     }
 }
 
+#ifdef EXP_NESTED_TABLES
+PRIVATE void free_enclosed_stbl ARGS1(
+	HText *,	me)
+{
+    if (me->enclosed_stbl != NULL) {
+	HTList *list = me->enclosed_stbl;
+	STable_info *stbl;
+	while (NULL != (stbl = (STable_info *)HTList_nextObject(list))) {
+	    CTRACE((tfp, "endStblTABLE: finally free %p\n", me->stbl));
+	    Stbl_free(stbl);
+	}
+	HTList_delete(me->enclosed_stbl);
+	me->enclosed_stbl = NULL;
+    }
+}
+#else
+#define free_enclosed_stbl(me) /* nothing */
+#endif
+
 /*	Finish simple table handling
  *	Return TRUE if the table is nested inside another table.
  */
@@ -4744,11 +4768,14 @@ PUBLIC int HText_endStblTABLE ARGS1(
 
     if (!me || !me->stbl) {
 	CTRACE((tfp, "endStblTABLE: ignored.\n"));
+	free_enclosed_stbl(me);
 	return FALSE;
     }
     CTRACE((tfp, "endStblTABLE: ok, will try.\n"));
+
     ncols = Stbl_finishTABLE(me->stbl);
     CTRACE((tfp, "endStblTABLE: ncols = %d.\n", ncols));
+
     if (ncols > 0) {
 	lines_changed = HText_insertBlanksInStblLines(me, ncols);
 	CTRACE((tfp, "endStblTABLE: changed %d lines, done.\n", lines_changed));
@@ -4759,19 +4786,33 @@ PUBLIC int HText_endStblTABLE ARGS1(
 	NumOfLines_partial -= lines_changed;  /* fake */
 #endif  /* DISP_PARTIAL */
     }
+
 #ifdef EXP_NESTED_TABLES
     if (nested_tables) {
 	enclosing = Stbl_get_enclosing(me->stbl);
 	me->last_anchor_before_stbl = Stbl_get_last_anchor_before(me->stbl);
-    } else
-#endif
-    Stbl_free(me->stbl);
-#ifdef EXP_NESTED_TABLES
-    if (nested_tables)
+	if (enclosing == NULL) {
+	    Stbl_free(me->stbl);
+	    free_enclosed_stbl(me);
+	} else {
+	    if (me->enclosed_stbl == NULL)
+		me->enclosed_stbl = HTList_new();
+	    HTList_addObject(me->enclosed_stbl, me->stbl);
+	    CTRACE((tfp, "endStblTABLE: postpone free %p\n", me->stbl));
+	}
 	me->stbl = enclosing;
-    else
-#endif
+    } else {
+	Stbl_free(me->stbl);
+	me->stbl = NULL;
+    }
+#else
+    Stbl_free(me->stbl);
     me->stbl = NULL;
+#endif
+
+    CTRACE((tfp, "endStblTABLE: have%s enclosing table (%p)\n",
+	    enclosing == 0 ? " NO" : "", enclosing));
+
     return enclosing != 0;
 }
 
@@ -5541,7 +5582,6 @@ PUBLIC void HText_endAppend ARGS1(
 	 */
 	next_to_the_last_line->next = line_ptr;
 	line_ptr->prev = next_to_the_last_line;
-	FREE(text->last_line);
 	text->last_line = next_to_the_last_line;
 	text->Lines--;
 	CTRACE((tfp, "GridText: New bottom line: `%s'\n",
@@ -5660,7 +5700,7 @@ re_parse:
 	 *  done the trimming & adjusting for this anchor, so avoid
 	 *  doing it a second time. - kw
 	 */
-	if ((hilite_str = LYGetHiTextStr(anchor_ptr, 0)) != NULL)
+	if (LYGetHiTextStr(anchor_ptr, 0) != NULL)
 	    continue;
 
 	if (anchor_ptr->line_pos > (int) line_ptr->size) {
@@ -5724,10 +5764,12 @@ re_parse:
 	if (line_ptr->data
 	 && anchor_ptr->extent > 0
 	 && anchor_ptr->line_pos >= 0) {
+	    LYClearHiText(anchor_ptr);
 	    LYSetHiText(anchor_ptr,
 			&line_ptr->data[anchor_ptr->line_pos],
 			anchor_ptr->extent);
 	} else {
+	    LYClearHiText(anchor_ptr);
 	    LYSetHiText(anchor_ptr, "", 0);
 	}
 
@@ -5747,7 +5789,7 @@ re_parse:
 
 	    if (!final
 	     && count_line >= stop_before) {
-		LYSetHiText(anchor_ptr, NULL, 0);
+		LYClearHiText(anchor_ptr);
 		break;
 	    } else if (line_ptr2 == text->last_line) {
 		break;
@@ -8440,6 +8482,15 @@ PUBLIC int HText_LastLineSize ARGS2(
     return HText_TrueLineSize(text->last_line, text, IgnoreSpaces);
 }
 
+PUBLIC BOOL HText_LastLineEmpty ARGS2(
+	HText *,	text,
+	BOOL,		IgnoreSpaces)
+{
+    if (!text || !text->last_line || !text->last_line->size)
+	return TRUE;
+    return HText_TrueEmptyLine(text->last_line, text, IgnoreSpaces);
+}
+
 PUBLIC int HText_LastLineOffset ARGS1(
 	HText *,	text)
 {
@@ -8461,6 +8512,22 @@ PUBLIC int HText_PreviousLineSize ARGS2(
     return HText_TrueLineSize(line, text, IgnoreSpaces);
 }
 
+PUBLIC BOOL HText_PreviousLineEmpty ARGS2(
+	HText *,	text,
+	BOOL,		IgnoreSpaces)
+{
+    HTLine * line;
+
+    if (!text || !text->last_line)
+	return TRUE;
+    if (!(line = text->last_line->prev))
+	return TRUE;
+    return HText_TrueEmptyLine(line, text, IgnoreSpaces);
+}
+
+/*
+ * Compute the "true" line size.
+ */
 PRIVATE int HText_TrueLineSize ARGS3(
 	HTLine *,	line,
 	HText *,	text,
@@ -8475,9 +8542,7 @@ PRIVATE int HText_TrueLineSize ARGS3(
     if (IgnoreSpaces) {
 	for (i = 0; i < line->size; i++) {
 	    if (!IsSpecialAttrChar(UCH(line->data[i])) &&
-		(!(text && text->T.output_utf8) ||
-		 !is8bits(line->data[i]) ||
-		 (UCH((line->data[i] & 0xc0)) == 0xc0)) &&
+		IS_UTF8_EXTRA(line->data[i]) &&
 		!isspace(UCH(line->data[i])) &&
 		UCH(line->data[i]) != HT_NON_BREAK_SPACE &&
 		UCH(line->data[i]) != HT_EN_SPACE) {
@@ -8487,9 +8552,7 @@ PRIVATE int HText_TrueLineSize ARGS3(
     } else {
 	for (i = 0; i < line->size; i++) {
 	    if (!IsSpecialAttrChar(line->data[i]) &&
-		(!(text && text->T.output_utf8) ||
-		 !is8bits(line->data[i]) ||
-		 (UCH(line->data[i] & 0xc0) == 0xc0))) {
+		IS_UTF8_EXTRA(line->data[i])) {
 		true_size++;
 	    }
 	}
@@ -8497,6 +8560,42 @@ PRIVATE int HText_TrueLineSize ARGS3(
     return true_size;
 }
 
+/*
+ * Tell if the line is really empty.  This is invoked much more often than
+ * HText_TrueLineSize(), and most lines are not empty.  So it is faster to
+ * do this check than to check if the line size happens to be zero.
+ */
+PRIVATE BOOL HText_TrueEmptyLine ARGS3(
+	HTLine *,	line,
+	HText *,	text,
+	BOOL,		IgnoreSpaces)
+{
+    size_t i;
+
+    if (!(line && line->size))
+	return TRUE;
+
+    if (IgnoreSpaces) {
+	for (i = 0; i < line->size; i++) {
+	    if (!IsSpecialAttrChar(UCH(line->data[i])) &&
+		IS_UTF8_EXTRA(line->data[i]) &&
+		!isspace(UCH(line->data[i])) &&
+		UCH(line->data[i]) != HT_NON_BREAK_SPACE &&
+		UCH(line->data[i]) != HT_EN_SPACE) {
+		return FALSE;
+	    }
+	}
+    } else {
+	for (i = 0; i < line->size; i++) {
+	    if (!IsSpecialAttrChar(line->data[i]) &&
+		IS_UTF8_EXTRA(line->data[i])) {
+		return FALSE;
+	    }
+	}
+    }
+    return TRUE;
+}
+
 PUBLIC void HText_NegateLineOne ARGS1(
 	HText *,	text)
 {
@@ -8538,7 +8637,6 @@ PUBLIC void HText_RemovePreviousLine ARGS1(
     previous->next = text->last_line;
     text->last_line->prev = previous;
     text->Lines--;
-    FREE(line);
 }
 
 /*
@@ -8587,7 +8685,7 @@ PUBLIC void HText_setTabID ARGS2(
     HTList * cur = text->tabs;
     HTList * last = NULL;
 
-    if (!text || !name || !*name)
+    if (!text || isEmpty(name))
 	return;
 
     if (!cur) {
@@ -9337,7 +9435,7 @@ PUBLIC int HText_beginInput ARGS3(
     a->link_type = INPUT_ANCHOR;
     a->show_anchor = YES;
 
-    LYSetHiText(a, NULL, 0);
+    LYClearHiText(a);
     a->extent = 2;
 
     a->input_field = f;
@@ -9981,6 +10079,7 @@ PRIVATE unsigned check_form_specialchars ARGS1(
     return result;
 }
 
+#ifdef EXP_FILE_UPLOAD
 PRIVATE CONST char *guess_content_type ARGS1(CONST char *, filename)
 {
     HTAtom *encoding;
@@ -9990,6 +10089,7 @@ PRIVATE CONST char *guess_content_type ARGS1(CONST char *, filename)
 	    ? format->name
 	    : "text/plain";
 }
+#endif
 
 /*
  *  HText_SubmitForm - generate submit data from form fields.
@@ -11726,7 +11826,7 @@ PRIVATE void insert_new_textarea_anchor ARGS2(
      *  Clone and initialize the struct's needed to add a new TEXTAREA
      *  anchor.
      */
-    l = allocHTLine(MAX_LINE);
+    POOLallocHTLine(l, MAX_LINE);
     POOLtypecalloc(TextAnchor, a);
     POOLtypecalloc(FormInfo, f);
     if (a == NULL || l == NULL || f == NULL)
@@ -12550,7 +12650,7 @@ PUBLIC int HText_InsertFile ARGS1(
 	    break;
     }
 
-    l = allocHTLine(MAX_LINE);
+    POOLallocHTLine(l, MAX_LINE);
     POOLtypecalloc(TextAnchor, a);
     POOLtypecalloc(FormInfo, f);
     if (a == NULL || l == NULL || f == NULL)
diff --git a/src/GridText.h b/src/GridText.h
index 7f2ce6af..83bbbb23 100644
--- a/src/GridText.h
+++ b/src/GridText.h
@@ -58,8 +58,6 @@ US-ASCII control characters <32 which are not defined in Unicode standard
 
 extern int HTCurSelectGroupType;
 extern char * HTCurSelectGroupSize;
-extern HText * HTMainText;		/* Equivalent of main window */
-extern HTParentAnchor * HTMainAnchor;	/* Anchor for HTMainText */
 
 #if defined(VMS) && defined(VAXC) && !defined(__DECC)
 extern int HTVirtualMemorySize;
@@ -161,6 +159,8 @@ extern char * HTLoadedDocumentBookmark NOPARAMS;
 extern int HText_LastLineSize PARAMS((HText *me, BOOL IgnoreSpaces));
 extern int HText_LastLineOffset PARAMS((HText *me));
 extern int HText_PreviousLineSize PARAMS((HText *me, BOOL IgnoreSpaces));
+extern BOOL HText_LastLineEmpty PARAMS((HText *me, BOOL IgnoreSpaces));
+extern BOOL HText_PreviousLineEmpty PARAMS((HText *me, BOOL IgnoreSpaces));
 extern void HText_NegateLineOne PARAMS((HText *text));
 extern BOOL HText_inLineOne PARAMS((HText *text));
 extern void HText_RemovePreviousLine PARAMS((HText *text));
diff --git a/src/HTML.c b/src/HTML.c
index 9698e568..93e0cdb2 100644
--- a/src/HTML.c
+++ b/src/HTML.c
@@ -1667,9 +1667,11 @@ PRIVATE int HTML_start_element ARGS6(
 	     */
 	    if (me->inBASE && *isindex_href != '\0' && *isindex_href != '#')
 		action = HTParse(isindex_href, me->base_href, PARSE_ALL);
-	    if (!(action && *action))
+	    if (isEmpty(action)) {
+		FREE(action);
 		action = HTParse(isindex_href,
 				 me->node_anchor->address, PARSE_ALL);
+	    }
 	    FREE(isindex_href);
 
 	    if (action && *action) {
@@ -2080,8 +2082,8 @@ PRIVATE int HTML_start_element ARGS6(
 	   * Otherwise, don't do anything. -DH 980814, TD 980827
 	   */
 	if ((LYCollapseBRs == FALSE &&
-	     HText_PreviousLineSize(me->text, FALSE)) ||
-	    HText_LastLineSize(me->text, FALSE)) {
+	     !HText_PreviousLineEmpty(me->text, FALSE)) ||
+	    !HText_LastLineEmpty(me->text, FALSE)) {
 	    HText_setLastChar(me->text, ' ');  /* absorb white space */
 	    HText_appendCharacter(me->text, '\r');
 	}
@@ -2113,10 +2115,10 @@ PRIVATE int HTML_start_element ARGS6(
 	     *	the last line are blank. - FM
 	     */
 	    UPDATE_STYLE;
-	    if (HText_LastLineSize(me->text, FALSE)) {
+	    if (!HText_LastLineEmpty(me->text, FALSE)) {
 		HText_setLastChar(me->text, ' ');  /* absorb white space */
 		HText_appendCharacter(me->text, '\r');
-	    } else if (!HText_PreviousLineSize(me->text, FALSE)) {
+	    } else if (HText_PreviousLineEmpty(me->text, FALSE)) {
 		HText_RemovePreviousLine(me->text);
 	    }
 	    me->in_word = NO;
@@ -2575,7 +2577,7 @@ PRIVATE int HTML_start_element ARGS6(
 	CHECK_ID(HTML_GEN_ID);
 	HText_setLastChar(me->text, ' ');  /* absorb white space */
 	if (!me->style_change)	{
-	    if (HText_LastLineSize(me->text, FALSE)) {
+	    if (!HText_LastLineEmpty(me->text, FALSE)) {
 		HText_appendCharacter(me->text, '\r');
 	    } else {
 		HText_NegateLineOne(me->text);
@@ -3019,32 +3021,15 @@ PRIVATE int HTML_start_element ARGS6(
 	     */
 	    me->inBoldA = TRUE;
 
-	    CHECK_FOR_INTERN(intern_flag,value[HTML_A_HREF]);
-	    if (present[HTML_A_ISMAP]) /*???*/
-		intern_flag = FALSE;
+	    StrAllocCopy(href, value[HTML_A_HREF]);
+	    CHECK_FOR_INTERN(intern_flag,href);  /*NULL, '\0', or '#'*/
 
-	    if (intern_flag) {
-		/*** FAST WAY: ***/
-		StrAllocCopy(href, value[HTML_A_HREF]);
-		if (href && *href)
-		    TRANSLATE_AND_UNESCAPE_TO_STD(&href);
-		if (!href || !*href)
-		    StrAllocCopy(href, "#"); /*extreme case*/
+	    if (intern_flag) { /*** FAST WAY: ***/
+		if (isEmpty(href))
+		    StrAllocCopy(href, "#");
+		TRANSLATE_AND_UNESCAPE_TO_STD(&href);
 
 	    } else {
-		/*
-		 * Prepare to do housekeeping on the reference.	 - FM
-		 */
-		if (!value[HTML_A_HREF] || *value[HTML_A_HREF] == '\0') {
-		    StrAllocCopy(href, me->node_anchor->address);
-		} else if (*value[HTML_A_HREF] == '#') {
-		    StrAllocCopy(href, me->node_anchor->address);
-		    if (strlen(value[HTML_A_HREF]) > 1) {
-			StrAllocCat(href, value[HTML_A_HREF]);
-		    }
-		} else {
-		    StrAllocCopy(href, value[HTML_A_HREF]);
-		}
 		url_type = LYLegitimizeHREF(me, &href, TRUE, TRUE);
 
 		/*
@@ -3060,24 +3045,25 @@ PRIVATE int HTML_start_element ARGS6(
 		/*
 		 * Check whether a base tag is in effect.  - FM
 		 */
-		if ((me->inBASE && *href != '\0' && *href != '#') &&
-		     (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
-		      *temp != '\0')
+		if (me->inBASE) {
 		    /*
 		     * Use reference related to the base.
 		     */
-		    StrAllocCopy(href, temp);
-		FREE(temp);
+		    temp = href;
+		    href = HTParse(temp, me->base_href, PARSE_ALL);
+		    FREE(temp);
+		}
 
-	        /*
+		/*
 		 * Check whether to fill in localhost.  - FM
 		 */
-		 LYFillLocalFileURL(&href,
-				    ((*href != '\0' && *href != '#' &&
-				     me->inBASE)
-				     ? me->base_href
-				     : me->node_anchor->address));
+		LYFillLocalFileURL(&href,
+				   (me->inBASE
+				    ? me->base_href
+				    : me->node_anchor->address));
 	    }
+	    if (present[HTML_A_ISMAP]) /*???*/
+		intern_flag = FALSE;
 	} else {
 	    if (bold_name_anchors == TRUE) {
 		me->inBoldA = TRUE;
@@ -3086,7 +3072,7 @@ PRIVATE int HTML_start_element ARGS6(
 
 	if (present && present[HTML_A_TYPE] && value[HTML_A_TYPE]) {
 	    StrAllocCopy(temp, value[HTML_A_TYPE]);
-	    if (!intern_flag && href &&
+	    if (!intern_flag &&
 		!strcasecomp(value[HTML_A_TYPE], HTAtom_name(HTInternalLink)) &&
 		!LYIsUIPage3(me->node_anchor->address, UIP_LIST_PAGE, 0) &&
 		!LYIsUIPage3(me->node_anchor->address, UIP_ADDRLIST_PAGE, 0) &&
@@ -3809,7 +3795,7 @@ PRIVATE int HTML_start_element ARGS6(
 				  me->base_href : me->node_anchor->address));
 	    if (!(url_type = is_url(href))) {
 		temp = HTParse(href, me->node_anchor->address, PARSE_ALL);
-		if (!(temp && *temp)) {
+		if (isEmpty(temp)) {
 		   FREE(href);
 		   FREE(temp);
 		   break;
@@ -4242,7 +4228,7 @@ PRIVATE int HTML_start_element ARGS6(
 	    FREE(base);
 	    FREE(code);
 
-	    if (href && *href) {
+	    if (!isEmpty(href)) {
 		if (me->inA) {
 		    if (me->inBoldA == TRUE && me->inBoldH == FALSE)
 			HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
@@ -5811,7 +5797,7 @@ PRIVATE int HTML_start_element ARGS6(
 	    HTML_end_element(me, HTML_U, include);
 	}
 	UPDATE_STYLE;
-	if (HText_LastLineSize(me->text, FALSE)) {
+	if (!HText_LastLineEmpty(me->text, FALSE)) {
 	    HText_setLastChar(me->text, ' ');  /* absorb white space */
 	    HText_appendCharacter(me->text, '\r');
 	}
@@ -7558,12 +7544,16 @@ End_Object:
 				me->DivisionAlignments[me->Division_Level];
 	change_paragraph_style(me, me->sp->style);
 	UPDATE_STYLE;
+
 #ifdef EXP_NESTED_TABLES
 	if (nested_tables) {
 	    me->inTABLE = HText_endStblTABLE(me->text);
-	} else
-#endif
+	} else {
+	    HText_endStblTABLE(me->text);
+	}
+#else
 	HText_endStblTABLE(me->text);
+#endif
 
 	me->current_default_alignment = me->sp->style->alignment;
 	if (me->List_Nesting_Level >= 0)
@@ -7573,7 +7563,7 @@ End_Object:
 /* These TABLE related elements may now not be SGML_EMPTY. - kw */
     case HTML_TR:
 	HText_endStblTR(me->text);
-	if (HText_LastLineSize(me->text, FALSE)) {
+	if (!HText_LastLineEmpty(me->text, FALSE)) {
 	    HText_setLastChar(me->text, ' ');  /* absorb next white space */
 	    HText_appendCharacter(me->text, '\r');
 	}
diff --git a/src/HTML.h b/src/HTML.h
index 81cbfbcc..bbf9de45 100644
--- a/src/HTML.h
+++ b/src/HTML.h
@@ -285,4 +285,3 @@ extern int HTLoadError PARAMS((
 	CONST char *	message));
 
 #endif /* HTML_H */
-
diff --git a/src/LYBookmark.h b/src/LYBookmark.h
index 681777e5..e90a2e45 100644
--- a/src/LYBookmark.h
+++ b/src/LYBookmark.h
@@ -18,4 +18,3 @@ extern void save_bookmark_link PARAMS((char *address, char *title));
 extern void set_default_bookmark_page PARAMS((char * value));
 
 #endif /* LYBOOKMARK_H */
-
diff --git a/src/LYCgi.c b/src/LYCgi.c
index 8f80eec0..08350424 100644
--- a/src/LYCgi.c
+++ b/src/LYCgi.c
@@ -160,7 +160,7 @@ PRIVATE int LYLoadCGI ARGS4(
     char *pgm_buff = NULL;		/* PATH_INFO extraction buffer       */
     char *path_translated;		/* From document_root/path_info      */
 
-    if (!arg || !*arg || strlen(arg) <= 8) {
+    if (isEmpty(arg) || strlen(arg) <= 8) {
 	HTAlert(BAD_REQUEST);
 	status = -2;
 	return(status);
diff --git a/src/LYCharUtils.c b/src/LYCharUtils.c
index 752934d5..0a537f40 100644
--- a/src/LYCharUtils.c
+++ b/src/LYCharUtils.c
@@ -64,7 +64,7 @@ PUBLIC void LYEntify ARGS2(
     int in_sjis = 0;
 #endif
 
-    if (p == NULL || *p == '\0')
+    if (isEmpty(p))
 	return;
 
     /*
@@ -390,7 +390,7 @@ PUBLIC void LYFillLocalFileURL ARGS2(
 {
     char * temp = NULL;
 
-    if (*href == NULL || *(*href) == '\0')
+    if (isEmpty(*href))
 	return;
 
     if (!strcmp(*href, "//") || !strncmp(*href, "///", 3)) {
@@ -1107,7 +1107,7 @@ PUBLIC char ** LYUCFullyTranslateString ARGS9(
     /*
     **	Make sure we have a non-empty string. - FM
     */
-    if (!str || *str == NULL || **str == '\0')
+    if (!str || isEmpty(*str))
 	return str;
 
     /*
@@ -2032,6 +2032,78 @@ PUBLIC BOOL LYUCTranslateBackFormData ARGS4(
 }
 
 /*
+ * Parse a parameter from an HTML META tag, i.e., the CONTENT.
+ */
+PUBLIC char *LYParseTagParam ARGS2(
+	char *,		from,
+	char *,		name)
+{
+    size_t len = strlen(name);
+    char *result = NULL;
+    char *string = from;
+
+    do {
+	if ((string = strchr(string, ';')) == NULL)
+	    return NULL;
+	while (*string != '\0' && (*string == ';' || isspace(UCH(*string)))) {
+	    string++;
+	}
+	if (strlen(string) < len) return NULL;
+    } while (strncasecomp(string, name, len) != 0);
+    string += len;
+    while (*string != '\0' && (UCH(isspace(*string)) || *string == '=')) {
+	string++;
+    }
+
+    StrAllocCopy(result, string);
+    len = 0;
+    while (isprint(UCH(string[len])) && string[len] != ';') {
+	len++;
+    }
+    result[len] = '\0';
+
+    /*
+     * Strip single quotes, just in case.
+     */
+    if (len > 2 && result[0] == '\'' && result[len-1] == result[0]) {
+	result[len-1] = '\0';
+	for (string = result; (string[0] = string[1]) != '\0'; ++string)
+	    ;
+    }
+    return result;
+}
+
+/*
+ * Given a refresh-URL content string, parses the delay time and the URL
+ * string.  Ignore the remainder of the content.
+ */
+PUBLIC void LYParseRefreshURL ARGS3(
+	char *,		content,
+	char **,	p_seconds,
+	char **,	p_address)
+{
+    char *cp;
+    char *cp1 = NULL;
+    char *Seconds = NULL;
+
+    /*
+     *  Look for the Seconds field. - FM
+     */
+    cp = LYSkipBlanks(content);
+    if (*cp && isdigit(UCH(*cp))) {
+	cp1 = cp;
+	while (*cp1 && isdigit(UCH(*cp1)))
+	    cp1++;
+	StrnAllocCopy(Seconds, cp, cp1 - cp);
+    }
+    *p_seconds = Seconds;
+    *p_address = LYParseTagParam(content, "URL");
+
+    CTRACE((tfp, "LYParseRefreshURL\n\tcontent: %s\n\tseconds: %s\n\taddress: %s\n",
+	   content, NonNull(*p_seconds), NonNull(*p_address)));
+}
+
+/*
 **  This function processes META tags in HTML streams. - FM
 */
 PUBLIC void LYHandleMETA ARGS4(
@@ -2414,38 +2486,9 @@ PUBLIC void LYHandleMETA ARGS4(
     } else if (!strcasecomp(NonNull(http_equiv), "Refresh")) {
 	char *Seconds = NULL;
 
-	/*
-	 *  Look for the Seconds field. - FM
-	 */
-	cp = LYSkipBlanks(content);
-	if (*cp && isdigit(UCH(*cp))) {
-	    cp1 = cp;
-	    while (*cp1 && isdigit(UCH(*cp1)))
-		cp1++;
-	    if (*cp1)
-		*cp1++ = '\0';
-	    StrAllocCopy(Seconds, cp);
-	}
+	LYParseRefreshURL(content, &Seconds, &href);
+
 	if (Seconds) {
-	    /*
-	     *	We have the seconds field.
-	     *	Now look for a URL field - FM
-	     */
-	    while (*cp1) {
-		if (!strncasecomp(cp1, "URL", 3)) {
-		    cp = (cp1 + 3);
-		    while (*cp && (*cp == '=' || isspace(UCH(*cp))))
-			cp++;
-		    cp1 = cp;
-		    while (*cp1 && !isspace(UCH(*cp1)))
-			cp1++;
-		    *cp1 = '\0';
-		    if (*cp)
-			StrAllocCopy(href, cp);
-		    break;
-		}
-		cp1++;
-	    }
 	    if (href) {
 		/*
 		 *  We found a URL field, so check it out. - FM
@@ -2497,6 +2540,7 @@ PUBLIC void LYHandleMETA ARGS4(
 	    /*
 	     *	Check for an anchor in http or https URLs. - FM
 	     */
+	    cp = NULL;
 #ifndef DONT_TRACK_INTERNAL_LINKS
 	    /* id_string seems to be used wrong below if given.
 	       not that it matters much.  avoid setting it here. - kw */
@@ -2676,7 +2720,7 @@ PUBLIC void LYHandlePlike ARGS6(
 	     *	to start a newline, if needed, then fall through
 	     *	to handle attributes. - FM
 	     */
-	    if (HText_LastLineSize(me->text, FALSE)) {
+	    if (!HText_LastLineEmpty(me->text, FALSE)) {
 		HText_setLastChar(me->text, ' ');  /* absorb white space */
 		HText_appendCharacter(me->text, '\r');
 	    }
@@ -2962,7 +3006,7 @@ PUBLIC int LYLegitimizeHREF ARGS4(
     char *pound = NULL;
     char *fragment = NULL;
 
-    if (!me || !href || *href == NULL || *(*href) == '\0')
+    if (!me || !href || isEmpty(*href))
 	return(url_type);
 
     if (!LYTrimStartfile(*href)) {
@@ -3256,11 +3300,11 @@ PUBLIC void LYEnsureDoubleSpace ARGS1(
     if (!me || !me->text)
 	return;
 
-    if (HText_LastLineSize(me->text, FALSE)) {
+    if (!HText_LastLineEmpty(me->text, FALSE)) {
 	HText_setLastChar(me->text, ' ');  /* absorb white space */
 	HText_appendCharacter(me->text, '\r');
 	HText_appendCharacter(me->text, '\r');
-    } else if (HText_PreviousLineSize(me->text, FALSE)) {
+    } else if (!HText_PreviousLineEmpty(me->text, FALSE)) {
 	HText_setLastChar(me->text, ' ');  /* absorb white space */
 	HText_appendCharacter(me->text, '\r');
     } else if (me->List_Nesting_Level >= 0) {
@@ -3281,7 +3325,7 @@ PUBLIC void LYEnsureSingleSpace ARGS1(
     if (!me || !me->text)
 	return;
 
-    if (HText_LastLineSize(me->text, FALSE)) {
+    if (!HText_LastLineEmpty(me->text, FALSE)) {
 	HText_setLastChar(me->text, ' ');  /* absorb white space */
 	HText_appendCharacter(me->text, '\r');
     } else if (me->List_Nesting_Level >= 0) {
diff --git a/src/LYCharUtils.h b/src/LYCharUtils.h
index 4ca20000..8fad7644 100644
--- a/src/LYCharUtils.h
+++ b/src/LYCharUtils.h
@@ -55,6 +55,13 @@ extern void LYAddMETAcharsetToFD PARAMS((
 extern void LYformTitle PARAMS((
 	char **		dst,
 	CONST char *	src));
+extern char *LYParseTagParam PARAMS((
+	char *		from,
+	char *		name));
+extern void LYParseRefreshURL PARAMS((
+	char *		content,
+	char **		p_seconds,
+	char **		p_address));
 
 #ifdef Lynx_HTML_Handler
 extern int OL_CONTINUE;		/* flag for whether CONTINUE is set */
diff --git a/src/LYClean.c b/src/LYClean.c
index cbdb820f..9c7a3012 100644
--- a/src/LYClean.c
+++ b/src/LYClean.c
@@ -157,7 +157,6 @@ PUBLIC void cleanup_files NOARGS
 
 PUBLIC void cleanup NOARGS
 {
-    int i;
 #ifdef VMS
     extern BOOLEAN DidCleanup;
 #endif /* VMS */
@@ -205,14 +204,17 @@ PUBLIC void cleanup NOARGS
 #endif
 
     cleanup_files();
-    for (i = 0; i < nhist; i++) {
-	LYFreeDocInfo(&HDOC(i));
-    }
-    nhist = 0;
 #ifdef VMS
     ttclose();
     DidCleanup = TRUE;
 #endif /* VMS */
 
+    /*
+     * If we're looking at memory leaks, hang onto the trace file, since there
+     * is no memory freed in this function, and it is a nuisance to not be able
+     * to trace the cleanup activity -TD
+     */
+#ifndef LY_FIND_LEAKS
     LYCloseTracelog();
+#endif
 }
diff --git a/src/LYCookie.c b/src/LYCookie.c
index d5cf0f38..6de3cf55 100644
--- a/src/LYCookie.c
+++ b/src/LYCookie.c
@@ -325,8 +325,8 @@ PRIVATE domain_entry * find_domain_entry ARGS1(
     }
     CTRACE((tfp, "find_domain_entry(%s) bv:%d, invcheck_bv:%d\n",
 		 name,
-		 de ? de->bv : -1,
-		 de ? de->invcheck_bv : -1));
+		 de ? (int) de->bv : -1,
+		 de ? (int) de->invcheck_bv : -1));
     return de;
 }
 
diff --git a/src/LYCurses.c b/src/LYCurses.c
index 7fe777f4..c2bf87e1 100644
--- a/src/LYCurses.c
+++ b/src/LYCurses.c
@@ -615,9 +615,11 @@ PRIVATE struct {
  */
 PRIVATE int get_color_pair ARGS1(int, n)
 {
+#ifdef USE_CURSES_PAIR_0
     if (lynx_color_pairs[n].fg == default_fg
      && lynx_color_pairs[n].bg == default_bg)
     	return 0;
+#endif
     return COLOR_PAIR(n);
 }
 
@@ -1058,7 +1060,9 @@ PUBLIC void start_curses NOARGS
 		lynx_setup_colors();
 	    }
 #else
+#if defined(HAVE_USE_DEFAULT_COLORS)
 	    lynx_default_colors();
+#endif /* HAVE_USE_DEFAULT_COLORS */
 #endif /* EXP_ASSUMED_COLOR */
 #endif /* USE_DEFAULT_COLORS */
 	}
@@ -1423,7 +1427,7 @@ PUBLIC BOOLEAN setup ARGS1(
 	    LYTrimTrailing(buffer);
 	}
 
-	if (buffer == 0 || *buffer == 0)
+	if (isEmpty(buffer))
 	    StrAllocCopy(buffer,"vt100");
 
 	HTSprintf0(&term_putenv,"TERM=%.106s", buffer);
diff --git a/src/LYCurses.h b/src/LYCurses.h
index e07d0e8f..db732a96 100644
--- a/src/LYCurses.h
+++ b/src/LYCurses.h
@@ -211,6 +211,9 @@ typedef struct {
 #  if defined(NCURSES) && defined(HAVE_NCURSES_TERM_H)
 #    include <ncurses/term.h>
 #  else
+#   if defined(HAVE_NCURSESW_NCURSES_H) || defined(HAVE_NCURSES_NCURSES_H) || defined(HAVE_XCURSES)
+#     undef HAVE_TERM_H			/* only use one in comparable path! */
+#   endif
 #   if defined(HAVE_TERM_H)
 #    include <term.h>
 #   endif
@@ -258,6 +261,19 @@ typedef struct {
 #undef USE_CURSES_PADS
 #endif
 
+/*
+ * Most implementations of curses treat pair 0 specially, as the default
+ * foreground and background color.  Also, the COLORS variable corresponds to
+ * the total number of colors.
+ *
+ * PDCurses does not follow these rules.  Its COLORS variable claims it has
+ * 8 colors, but it actually implements 16.  That makes it hard to optimize
+ * color settings against color pair 0 in a portable fashion.
+ */
+#if defined(COLOR_CURSES) && !(defined(PDCURSES) || defined(HAVE_XCURSES))
+#define USE_CURSES_PAIR_0
+#endif
+
 #endif /* USE_SLANG */
 
 #ifdef USE_SLANG
diff --git a/src/LYDownload.c b/src/LYDownload.c
index 311bedbe..eb379746 100644
--- a/src/LYDownload.c
+++ b/src/LYDownload.c
@@ -485,16 +485,9 @@ PUBLIC int LYdownload_options ARGS2(
     StrAllocCopy(sug_filename, *newfile);
     change_sug_filename(sug_filename);
 
-    if (LYReuseTempfiles) {
-	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, BIN_W);
-    } else {
-	LYRemoveTemp(tempfile);
-	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, BIN_W);
-    }
-    if (fp0 == NULL) {
-	HTAlert(CANNOT_OPEN_TEMP);
+    if ((fp0 = InternalPageFP(tempfile, TRUE)) == 0)
 	return(-1);
-    }
+ 
     StrAllocCopy(downloaded_url, *newfile);
     LYLocalFileToURL(newfile, tempfile);
 
diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h
index 821e9f94..4b769a77 100644
--- a/src/LYGlobalDefs.h
+++ b/src/LYGlobalDefs.h
@@ -185,6 +185,7 @@ extern BOOLEAN LYShowCursor;	/* Show the cursor or hide it?	    */
 extern BOOLEAN LYShowTransferRate;
 extern BOOLEAN LYUseDefShoCur;	/* Command line -show_cursor toggle */
 extern BOOLEAN LYUserSpecifiedURL;  /* URL from a goto or document? */
+extern BOOLEAN LYfind_leaks;
 extern BOOLEAN LYforce_HTML_mode;
 extern BOOLEAN LYforce_no_cache;
 extern BOOLEAN LYinternal_flag; /* don't need fresh copy, was internal link */
@@ -511,6 +512,10 @@ extern BOOLEAN LYNoCore;
 extern BOOLEAN restore_sigpipe_for_children;
 #endif /* !VMS */
 
+#if defined(USE_COLOR_STYLE)
+extern char *lynx_lss_file;
+#endif
+
 extern int HTNoDataOK;		/* HT_NO_DATA-is-ok hack */
 extern BOOLEAN FileInitAlreadyDone;
 
diff --git a/src/LYHistory.c b/src/LYHistory.c
index 0a9a91c5..ff27686e 100644
--- a/src/LYHistory.c
+++ b/src/LYHistory.c
@@ -41,6 +41,11 @@ PRIVATE VisitedLink *Last_by_first;
 int nhist_extra;
 
 #ifdef LY_FIND_LEAKS
+PRIVATE int already_registered_free_messages_stack = 0;
+PRIVATE int already_registered_clean_all_history = 0;
+#endif
+
+#ifdef LY_FIND_LEAKS
 /*
  *  Utility for freeing the list of visited links. - FM
  */
@@ -296,17 +301,33 @@ PUBLIC void LYFreeDocInfo ARGS1(
 /*
  *  Free the information in the last history entry.
  */
-PRIVATE void clean_extra NOARGS
+PRIVATE void clean_extra_history NOARGS
 {
-    trace_history("clean_extra");
+    trace_history("clean_extra_history");
     nhist += nhist_extra;
     while (nhist_extra > 0) {
 	nhist--;
 	LYFreeDocInfo(&HDOC(nhist));
 	nhist_extra--;
     }
-    trace_history("...clean_extra");
+    trace_history("...clean_extra_history");
+}
+
+/*
+ * Free the entire history stack, for auditing memory leaks.
+ */
+#ifdef LY_FIND_LEAKS
+PRIVATE void clean_all_history NOARGS
+{
+    trace_history("clean_all_history");
+    clean_extra_history();
+    while (nhist > 0) {
+	nhist--;
+	LYFreeDocInfo(&HDOC(nhist));
+    }
+    trace_history("...clean_all_history");
 }
+#endif
 
 /* FIXME What is the relationship to are_different() from the mainloop?! */
 PRIVATE int are_identical ARGS2(
@@ -374,7 +395,13 @@ PUBLIC int LYpush ARGS2(
 	return 1;
     }
 
-    clean_extra();
+    clean_extra_history();
+#ifdef LY_FIND_LEAKS
+    if (!already_registered_clean_all_history) {
+	already_registered_clean_all_history = 1;
+	atexit(clean_all_history);
+    }
+#endif
 
     /*
      *	OK, push it if we have stack space.
@@ -506,7 +533,7 @@ PUBLIC void LYpop ARGS1(
 	DocInfo *,	doc)
 {
     if (nhist > 0) {
-	clean_extra();
+	clean_extra_history();
 	nhist--;
 
 	LYFreeDocInfo(doc);
@@ -615,16 +642,8 @@ PUBLIC int showhistory ARGS1(
     int x = 0;
     FILE *fp0;
 
-    if (LYReuseTempfiles) {
-	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
-    } else {
-	LYRemoveTemp(tempfile);
-	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
-    }
-    if (fp0 == NULL) {
-	HTAlert(CANNOT_OPEN_TEMP);
+    if ((fp0 = InternalPageFP(tempfile, TRUE)) == 0)
 	return(-1);
-    }
 
     LYLocalFileToURL(newfile, tempfile);
 
@@ -791,16 +810,8 @@ PUBLIC int LYShowVisitedLinks ARGS1(
     if (!cur)
 	return(-1);
 
-    if (LYReuseTempfiles) {
-	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
-    } else {
-	LYRemoveTemp(tempfile);
-	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
-    }
-    if (fp0 == NULL) {
-	HTAlert(CANNOT_OPEN_TEMP);
+    if ((fp0 = InternalPageFP(tempfile, TRUE)) == 0)
 	return(-1);
-    }
 
     LYLocalFileToURL(newfile, tempfile);
     LYRegisterUIPage(*newfile, UIP_VLINKS);
@@ -943,9 +954,6 @@ PUBLIC int LYShowVisitedLinks ARGS1(
 #define STATUSBUFSIZE   40
 PRIVATE char * buffstack[STATUSBUFSIZE];
 PRIVATE int topOfStack = 0;
-#ifdef LY_FIND_LEAKS
-PRIVATE int already_registered_free_messages_stack = 0;
-#endif
 
 #ifdef LY_FIND_LEAKS
 PRIVATE void free_messages_stack NOARGS
diff --git a/src/LYJump.c b/src/LYJump.c
index 97a0a072..7d04f27b 100644
--- a/src/LYJump.c
+++ b/src/LYJump.c
@@ -375,7 +375,7 @@ PRIVATE unsigned LYRead_Jumpfile ARGS1(struct JumpTable *, jtp)
     char *cp;
     unsigned i;
 
-    if (jtp->file == NULL || *(jtp->file) == '\0')
+    if (isEmpty(jtp->file))
 	return 0;
 
     CTRACE((tfp, "Read Jumpfile %s\n", jtp->file));
diff --git a/src/LYJump.h b/src/LYJump.h
index 3a82b075..25e8d16b 100644
--- a/src/LYJump.h
+++ b/src/LYJump.h
@@ -27,4 +27,3 @@ extern BOOL LYJumpInit PARAMS((char *config));
 extern char *LYJump PARAMS((int key));
 
 #endif /* LYJUMP_H */
-
diff --git a/src/LYKeymap.c b/src/LYKeymap.c
index 7a51bcfa..a436bc67 100644
--- a/src/LYKeymap.c
+++ b/src/LYKeymap.c
@@ -1193,12 +1193,12 @@ PUBLIC int LYStringToKeycode ARGS1 (
     } else if (len > 2 && !strncasecomp(src, "0x", 2)) {
 	char *dst = 0;
 	key = strtol(src, &dst, 0);
-	if (dst == 0 || *dst != 0)
+	if (isEmpty(dst))
 	    key = -1;
     } else if (len > 6 && !strncasecomp(src, "key-", 4)) {
 	char *dst = 0;
 	key = strtol(src + 4, &dst, 0);
-	if (dst == 0 || *dst != 0)
+	if (isEmpty(dst))
 	    key = -1;
     }
     if (key < 0) {
diff --git a/src/LYLeaks.c b/src/LYLeaks.c
index 3f014d33..84ef77f3 100644
--- a/src/LYLeaks.c
+++ b/src/LYLeaks.c
@@ -2,6 +2,11 @@
 **	Copyright (c) 1994, University of Kansas, All Rights Reserved
 **
 **	This code will be used only if LY_FIND_LEAKS is defined.
+**
+**  Revision History:
+**	05-26-94	created Lynx 2-3-1 Garrett Arch Blythe
+**	10-30-97	modified to handle StrAllocCopy() and
+**			  StrAllocCat(). - KW & FM
 */
 
 /*
@@ -13,15 +18,142 @@
 #include <LYexit.h>
 #include <LYLeaks.h>
 #include <LYUtils.h>
+#include <LYGlobalDefs.h>
+
+#ifdef LY_FIND_LEAKS
 
 PRIVATE AllocationList *ALp_RunTimeAllocations = NULL;
 
-PRIVATE void AddToList PARAMS((
-	AllocationList *	ALp_new));
-PRIVATE AllocationList *FindInList PARAMS((
-	void *			vp_find));
-PRIVATE void RemoveFromList PARAMS((
-	AllocationList *	ALp_del));
+#define LEAK_SUMMARY
+
+#ifdef LEAK_SUMMARY
+
+PRIVATE long now_allocated = 0;
+PRIVATE long peak_alloced = 0;
+
+PRIVATE long total_alloced = 0;
+PRIVATE long total_freed = 0;
+
+PRIVATE long count_mallocs = 0;
+PRIVATE long count_frees = 0;
+
+PRIVATE void CountMallocs ARGS1(long, size)
+{
+    ++count_mallocs;
+    total_alloced += size;
+    now_allocated += size;
+    if (peak_alloced < now_allocated)
+	peak_alloced = now_allocated;
+}
+
+PRIVATE void CountFrees ARGS1(long, size)
+{
+    ++count_frees;
+    total_freed += size;
+    now_allocated -= size;
+}
+#else
+#define CountMallocs() ++count_mallocs
+#define CountFrees() /* nothing */
+#endif
+
+/*
+**  Purpose:	Add a new allocation item to the list.
+**  Arguments:		ALp_new The new item to add.
+**  Return Value:	void
+**  Remarks/Portability/Dependencies/Restrictions:
+**		Static function made to make code reusable in projects beyond
+**		Lynx (some might ask why not use HTList).
+**  Revision History:
+**	05-26-94	created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PRIVATE void AddToList ARGS1(
+	AllocationList *,	ALp_new)
+{
+    /*
+     *	Just make this the first item in the list.
+     */
+    ALp_new->ALp_Next = ALp_RunTimeAllocations;
+    ALp_RunTimeAllocations = ALp_new;
+}
+
+/*
+**  Purpose:	Find the place in the list where vp_find is currently
+**		tracked.
+**  Arguments:		vp_find A pointer to look for in the list.
+**  Return Value:	AllocationList *	Either vp_find's place in the
+**						list or NULL if not found.
+**  Remarks/Portability/Dependencies/Restrictions:
+**		Static function made to make code reusable in projects outside
+**		of Lynx (some might ask why not use HTList).
+**  Revision History:
+**	05-26-94	created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PRIVATE AllocationList *FindInList ARGS1(
+	void *,		vp_find)
+{
+    AllocationList *ALp_find = ALp_RunTimeAllocations;
+
+    /*
+     *	Go through the list of allocated pointers until end of list
+     *		or vp_find is found.
+     */
+    while (ALp_find != NULL) {
+	if (ALp_find->vp_Alloced == vp_find) {
+	    break;
+	}
+	ALp_find = ALp_find->ALp_Next;
+    }
+
+    return(ALp_find);
+}
+
+/*
+**  Purpose:	Remove the specified item from the list.
+**  Arguments:		ALp_del The item to remove from the list.
+**  Return Value:	void
+**  Remarks/Portability/Dependencies/Restrictions:
+**		Static function made to make code reusable in projects outside
+**		of Lynx (some might ask why not use HTList).
+**  Revision History:
+**	05-26-94	created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PRIVATE void RemoveFromList ARGS1(
+	AllocationList *,	ALp_del)
+{
+    AllocationList *ALp_findbefore = ALp_RunTimeAllocations;
+
+    /*
+     *	There is one special case, where the item to remove is the
+     *		first in the list.
+     */
+    if (ALp_del == ALp_findbefore) {
+	ALp_RunTimeAllocations = ALp_del->ALp_Next;
+	return;
+    }
+
+    /*
+     *	Loop through checking all of the next values, if a match
+     *	don't continue.  Always assume the item will be found.
+     */
+    while (ALp_findbefore->ALp_Next != ALp_del) {
+	ALp_findbefore = ALp_findbefore->ALp_Next;
+    }
+
+    /*
+     *	We are one item before the one to get rid of.
+     *	Get rid of it.
+     */
+    ALp_findbefore->ALp_Next = ALp_del->ALp_Next;
+}
+
+/*
+ *  Make the malloc-sequence available for debugging/tracing.
+ */
+PUBLIC long LYLeakSequence NOARGS
+{
+    return count_mallocs;
+}
 
 /*
 **  Purpose:	Print a report of all memory left unallocated by
@@ -36,10 +168,6 @@ PRIVATE void RemoveFromList PARAMS((
 **		in main.
 **		All output of this function is sent to the file defined in
 **		the header LYLeaks.h (LEAKAGE_SINK).
-**  Revision History:
-**	05-26-94	created Lynx 2-3-1 Garrett Arch Blythe
-**	10-30-97	modified to handle StrAllocCopy() and
-**			  StrAllocCat(). - KW & FM
 */
 PUBLIC void LYLeaks NOARGS
 {
@@ -47,6 +175,9 @@ PUBLIC void LYLeaks NOARGS
     size_t st_total = (size_t)0;
     FILE *Fp_leakagesink;
 
+    if (LYfind_leaks == FALSE)
+	return;
+
     /*
      *	Open the leakage sink to take all the output.
      *	Recreate the file each time.
@@ -76,6 +207,9 @@ PUBLIC void LYLeaks NOARGS
 	     */
 	    fprintf(Fp_leakagesink, "%s.\n",
 		    gettext("Invalid pointer detected."));
+	    fprintf(Fp_leakagesink, "%s\t%ld\n",
+		    gettext("Sequence:"),
+		    ALp_head->st_Sequence);
 	    fprintf(Fp_leakagesink, "%s\t%p\n",
 		    gettext("Pointer:"), ALp_head->vp_BadRequest);
 
@@ -113,6 +247,9 @@ PUBLIC void LYLeaks NOARGS
 
 	    fprintf(Fp_leakagesink, "%s\n",
 		    gettext("Memory leak detected."));
+	    fprintf(Fp_leakagesink, "%s\t%ld\n",
+		    gettext("Sequence:"),
+		    ALp_head->st_Sequence);
 	    fprintf(Fp_leakagesink, "%s\t%p\n",
 		    gettext("Pointer:"),
 		    ALp_head->vp_Alloced);
@@ -166,12 +303,21 @@ PUBLIC void LYLeaks NOARGS
      *	Give a grand total of the leakage.
      *	Close the output file.
      */
-    fprintf(Fp_leakagesink, "\n%s\t%u\n",
+    fprintf(Fp_leakagesink, "%s\t%u\n",
 	    gettext("Total memory leakage this run:"),
 	    (unsigned)st_total);
+#ifdef LEAK_SUMMARY
+    fprintf(Fp_leakagesink, "%s\t%ld\n", gettext("Peak allocation"), peak_alloced);
+    fprintf(Fp_leakagesink, "%s\t%ld\n", gettext("Bytes allocated"), total_alloced);
+    fprintf(Fp_leakagesink, "%s\t%ld\n", gettext("Total mallocs"), count_mallocs);
+    fprintf(Fp_leakagesink, "%s\t%ld\n", gettext("Total frees"), count_frees);
+#endif
     fclose(Fp_leakagesink);
 
     HTSYS_purge(LEAKAGE_SINK);
+#if defined(NCURSES) && defined(HAVE__NC_FREEALL)
+    _nc_freeall();
+#endif
 }
 
 /*
@@ -196,10 +342,16 @@ PUBLIC void *LYLeakMalloc ARGS3(
 	CONST char *,	cp_File,
 	CONST short,	ssi_Line)
 {
+    void *vp_malloc;
+
+    if (LYfind_leaks == FALSE)
+	return (void *)malloc(st_bytes);
+
     /*
      *	Do the actual allocation.
      */
-    void *vp_malloc = (void *)malloc(st_bytes);
+    vp_malloc = (void *)malloc(st_bytes);
+    CountMallocs(st_bytes);
 
     /*
      *	Only on successful allocation do we track any information.
@@ -219,6 +371,7 @@ PUBLIC void *LYLeakMalloc ARGS3(
 	 *  There is no need to allocate more memory for the
 	 *  file name as it is a static string anyhow.
 	 */
+	ALp_new->st_Sequence = count_mallocs;
 	ALp_new->vp_Alloced = vp_malloc;
 	ALp_new->st_Bytes = st_bytes;
 	ALp_new->SL_memory.cp_FileName = cp_File;
@@ -238,7 +391,7 @@ PUBLIC void *LYLeakMalloc ARGS3(
 **		after a call to malloc or calloc or an equivalent
 **		function which may or may not have already created
 **		a list entry.
-**  Arguments:	vp_malloc	The pointer to newly allocate memory.
+**  Arguments:	vp_malloc	The pointer to newly allocated memory.
 **  Arguments:	st_bytes	The size of the allocation requested
 **				in bytes.
 **		cp_File		The file from which the request for
@@ -260,6 +413,10 @@ PUBLIC AllocationList *LYLeak_mark_malloced ARGS4(
 	CONST short,	ssi_Line)
 {
     AllocationList *ALp_new = NULL;
+
+    if (LYfind_leaks == FALSE)
+	return NULL;
+
     /*
      *	The actual allocation has already been done!
      *
@@ -324,10 +481,16 @@ PUBLIC void *LYLeakCalloc ARGS4(
 	CONST char *,	cp_File,
 	CONST short,	ssi_Line)
 {
+    void *vp_calloc;
+
+    if (LYfind_leaks == FALSE)
+	return (void *)calloc(st_number, st_bytes);
+
     /*
      *	Allocate the requested memory.
      */
-    void *vp_calloc = (void *)calloc(st_number, st_bytes);
+    vp_calloc = (void *)calloc(st_number, st_bytes);
+    CountMallocs(st_bytes);
 
     /*
      *	Only if the allocation was a success do we track information.
@@ -348,6 +511,7 @@ PUBLIC void *LYLeakCalloc ARGS4(
 	 *  There is no need to allocate memory for the file
 	 *  name as it is a static string anyway.
 	 */
+	ALp_new->st_Sequence = count_mallocs;
 	ALp_new->vp_Alloced = vp_calloc;
 	ALp_new->st_Bytes = (st_number * st_bytes);
 	ALp_new->SL_memory.cp_FileName = cp_File;
@@ -393,6 +557,9 @@ PUBLIC void *LYLeakRealloc ARGS4(
     void *vp_realloc;
     AllocationList *ALp_renew;
 
+    if (LYfind_leaks == FALSE)
+	return (void *)realloc(vp_Alloced, st_newBytes);
+
     /*
      *	If we are asked to resize a NULL pointer, this is just a
      *	malloc call.
@@ -439,7 +606,11 @@ PUBLIC void *LYLeakRealloc ARGS4(
      *	If not NULL, record the information.
      */
     vp_realloc = (void *)realloc(vp_Alloced, st_newBytes);
+    CountMallocs(st_newBytes);
+    CountFrees(ALp_renew->st_Bytes);
+
     if (vp_realloc != NULL) {
+	ALp_renew->st_Sequence = count_mallocs;
 	ALp_renew->vp_Alloced = vp_realloc;
 	ALp_renew->st_Bytes = st_newBytes;
 
@@ -531,6 +702,11 @@ PUBLIC void LYLeakFree ARGS3(
 {
     AllocationList *ALp_free;
 
+    if (LYfind_leaks == FALSE) {
+	free(vp_Alloced);
+	return;
+    }
+
     /*
      *	Find the pointer in the allocated list.
      *	If not found, bad pointer.
@@ -567,6 +743,7 @@ PUBLIC void LYLeakFree ARGS3(
 	 *  Free off the memory.
 	 *  Take entry out of allocation list.
 	 */
+	CountFrees(ALp_free->st_Bytes);
 	RemoveFromList(ALp_free);
 	FREE(ALp_free);
 	FREE(vp_Alloced);
@@ -643,6 +820,7 @@ PUBLIC char * LYLeakSACat ARGS4(
 }
 
 #if defined(LY_FIND_LEAKS) && defined(LY_FIND_LEAKS_EXTENDED)
+
 PUBLIC CONST char * leak_cp_File_hack = __FILE__;
 PUBLIC short leak_ssi_Line_hack = __LINE__;
 
@@ -702,6 +880,11 @@ PRIVATE char * LYLeakSAVsprintf ARGS6(
     if (!dest)
 	return NULL;
 
+    if (LYfind_leaks == FALSE) {
+	StrAllocVsprintf(dest, inuse, fmt, ap);
+	return (*dest);
+    }
+
     vp_oldAlloced = *dest;
     if (!vp_oldAlloced) {
 	StrAllocVsprintf(dest, inuse, fmt, ap);
@@ -862,94 +1045,9 @@ PUBLIC HTSprintflike *Get_htsprintf0_fn ARGS2(
     return &LYLeakHTSprintf0;
 }
 
-#endif /* not LY_FIND_LEAKS and LY_FIND_LEAKS_EXTENDED */
-
-/*
-**  Purpose:	Add a new allocation item to the list.
-**  Arguments:		ALp_new The new item to add.
-**  Return Value:	void
-**  Remarks/Portability/Dependencies/Restrictions:
-**		Static function made to make code reusable in projects beyond
-**		Lynx (some might ask why not use HTList).
-**  Revision History:
-**	05-26-94	created Lynx 2-3-1 Garrett Arch Blythe
-*/
-PRIVATE void AddToList ARGS1(
-	AllocationList *,	ALp_new)
-{
-    /*
-     *	Just make this the first item in the list.
-     */
-    ALp_new->ALp_Next = ALp_RunTimeAllocations;
-    ALp_RunTimeAllocations = ALp_new;
-}
-
-/*
-**  Purpose:	Find the place in the list where vp_find is currently
-**		tracked.
-**  Arguments:		vp_find A pointer to look for in the list.
-**  Return Value:	AllocationList *	Either vp_find's place in the
-**						list or NULL if not found.
-**  Remarks/Portability/Dependencies/Restrictions:
-**		Static function made to make code reusable in projects outside
-**		of Lynx (some might ask why not use HTList).
-**  Revision History:
-**	05-26-94	created Lynx 2-3-1 Garrett Arch Blythe
-*/
-PRIVATE AllocationList *FindInList ARGS1(
-	void *,		vp_find)
-{
-    AllocationList *ALp_find = ALp_RunTimeAllocations;
-
-    /*
-     *	Go through the list of allocated pointers until end of list
-     *		or vp_find is found.
-     */
-    while (ALp_find != NULL) {
-	if (ALp_find->vp_Alloced == vp_find) {
-	    break;
-	}
-	ALp_find = ALp_find->ALp_Next;
-    }
-
-    return(ALp_find);
-}
-
-/*
-**  Purpose:	Remove the specified item from the list.
-**  Arguments:		ALp_del The item to remove from the list.
-**  Return Value:	void
-**  Remarks/Portability/Dependencies/Restrictions:
-**		Static function made to make code reusable in projects outside
-**		of Lynx (some might ask why not use HTList).
-**  Revision History:
-**	05-26-94	created Lynx 2-3-1 Garrett Arch Blythe
-*/
-PRIVATE void RemoveFromList ARGS1(
-	AllocationList *,	ALp_del)
-{
-    AllocationList *ALp_findbefore = ALp_RunTimeAllocations;
-
-    /*
-     *	There is one special case, where the item to remove is the
-     *		first in the list.
-     */
-    if (ALp_del == ALp_findbefore) {
-	ALp_RunTimeAllocations = ALp_del->ALp_Next;
-	return;
-    }
-
-    /*
-     *	Loop through checking all of the next values, if a match
-     *	don't continue.  Always assume the item will be found.
-     */
-    while (ALp_findbefore->ALp_Next != ALp_del) {
-	ALp_findbefore = ALp_findbefore->ALp_Next;
-    }
-
-    /*
-     *	We are one item before the one to get rid of.
-     *	Get rid of it.
-     */
-    ALp_findbefore->ALp_Next = ALp_del->ALp_Next;
-}
+#endif /* LY_FIND_LEAKS and LY_FIND_LEAKS_EXTENDED */
+#else
+/* Standard C forbids an empty file */
+void no_leak_checking NOPARAMS;
+void no_leak_checking NOARGS { }
+#endif /* LY_FIND_LEAKS */
diff --git a/src/LYList.c b/src/LYList.c
index e9777988..724f5689 100644
--- a/src/LYList.c
+++ b/src/LYList.c
@@ -62,16 +62,8 @@ PUBLIC int showlist ARGS2(
 	return(-1);
     }
 
-    if (LYReuseTempfiles && titles == last_titles) {
-	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
-    } else {
-	LYRemoveTemp(tempfile);
-	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
-    }
-    if (fp0 == NULL) {
-	HTUserMsg(CANNOT_OPEN_TEMP);
+    if ((fp0 = InternalPageFP(tempfile, titles == last_titles)) == 0)
 	return(-1);
-    }
 
     LYLocalFileToURL(&(newdoc->address), tempfile);
 
diff --git a/src/LYLocal.c b/src/LYLocal.c
index db733817..94fe9964 100644
--- a/src/LYLocal.c
+++ b/src/LYLocal.c
@@ -1952,11 +1952,8 @@ PUBLIC int dired_options ARGS2(
     struct dired_menu *mp;
     char buf[2048];
 
-    LYRemoveTemp(tempfile);
-    if ((fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w")) == NULL) {
-	HTAlert(gettext("Unable to open file management menu file."));
+    if ((fp0 = InternalPageFP(tempfile, FALSE)) == 0)
 	return(0);
-    }
 
     /*
      *  Make the tempfile a URL.
diff --git a/src/LYMail.c b/src/LYMail.c
index 7e8731cb..b0fb8034 100644
--- a/src/LYMail.c
+++ b/src/LYMail.c
@@ -399,7 +399,9 @@ PRIVATE char *blat_cmd(
 #if USE_VMS_MAILER
 PUBLIC BOOLEAN LYMailPMDF(void)
 {
-    return !strncasecomp(system_mail, "PMDF SEND", 9);
+    return (system_mail != 0)
+	    ? !strncasecomp(system_mail, "PMDF SEND", 9)
+	    : FALSE;
 }
 
 /*
@@ -456,12 +458,14 @@ PRIVATE void remove_quotes (char * string)
 PUBLIC FILE *LYPipeToMailer NOARGS
 {
     char *buffer = NULL;
-    FILE *fp;
+    FILE *fp = NULL;
 
-    HTSprintf0(&buffer, "%s %s", system_mail, system_mail_flags);
-    fp = popen(buffer, "w");
-    CTRACE((tfp, "popen(%s) %s\n", buffer, fp != 0 ? "OK" : "FAIL"));
-    FREE(buffer);
+    if (LYSystemMail()) {
+	HTSprintf0(&buffer, "%s %s", system_mail, system_mail_flags);
+	fp = popen(buffer, "w");
+	CTRACE((tfp, "popen(%s) %s\n", buffer, fp != 0 ? "OK" : "FAIL"));
+	FREE(buffer);
+    }
     return fp;
 }
 #else	/* DOS, Win32, etc. */
@@ -479,6 +483,9 @@ PUBLIC int LYSendMailFile ARGS5(
 #endif /* __DJGPP__ */
     int code;
 
+    if (!LYSystemMail())
+	return 0;
+
 #if USE_BLAT_MAILER
     if (mail_is_blat)
 	StrAllocCopy(cmd,
@@ -542,10 +549,10 @@ PUBLIC int LYSendMailFile ARGS5(
 **  mailform() sends form content to the mailto address(es). - FM
 */
 PUBLIC void mailform ARGS4(
-    CONST char *, 	mailto_address,
-    CONST char *, 	mailto_subject,
-    CONST char *, 	mailto_content,
-    CONST char *, 	mailto_type)
+    CONST char *,	mailto_address,
+    CONST char *,	mailto_subject,
+    CONST char *,	mailto_content,
+    CONST char *,	mailto_type)
 {
     FILE *fd;
     char *address = NULL;
@@ -573,6 +580,9 @@ PUBLIC void mailform ARGS4(
 	NONNULL(mailto_content),
 	NONNULL(mailto_type)));
 
+    if (!LYSystemMail())
+	return;
+
     if (!mailto_address || !mailto_content) {
 	HTAlert(BAD_FORM_MAILTO);
 	return;
@@ -870,9 +880,9 @@ cleanup:
 */
 PUBLIC void mailmsg ARGS4(
 	int,		cur,
-	char *, 	owner_address,
-	char *, 	filename,
-	char *, 	linkname)
+	char *,		owner_address,
+	char *,		filename,
+	char *,		linkname)
 {
     FILE *fd, *fp;
     char *address = NULL;
@@ -898,6 +908,9 @@ PUBLIC void mailmsg ARGS4(
 
 #endif /* VMS */
 
+    if (!LYSystemMail())
+	return;
+
 #ifdef ALERTMAIL
     if (owner_address == NULL) {
 	owner_address = ALERTMAIL;
@@ -905,9 +918,8 @@ PUBLIC void mailmsg ARGS4(
     }
 #endif
 
-    if (owner_address == NULL || *owner_address == '\0') {
+    if (isEmpty(owner_address))
 	return;
-    }
     if ((cp = (char *)strchr(owner_address,'\n')) != NULL) {
 #ifdef ALERTMAIL
 	if (skip_parsing)
@@ -1097,8 +1109,8 @@ PUBLIC void mailmsg ARGS4(
 **  a comment from the users to the owner
 */
 PUBLIC void reply_by_mail ARGS4(
-	char *, 	mail_address,
-	char *, 	filename,
+	char *,		mail_address,
+	char *,		filename,
 	CONST char *,	title,
 	CONST char *,	refid)
 {
@@ -1143,6 +1155,9 @@ PUBLIC void reply_by_mail ARGS4(
 
     term_letter = FALSE;
 
+    if (!LYSystemMail())
+	return;
+
     if (isEmpty(mail_address)) {
 	HTAlert(NO_ADDRESS_IN_MAILTO_URL);
 	return;
@@ -1471,7 +1486,7 @@ PUBLIC void reply_by_mail ARGS4(
 	    BOOLEAN is_preparsed = (BOOL) (LYPreparsedSource &&
 				    HTisDocumentSource());
 	    if (HTConfirm(is_preparsed
-	    	? INC_PREPARSED_MSG_PROMPT
+		? INC_PREPARSED_MSG_PROMPT
 		: INC_ORIG_MSG_PROMPT) == YES) {
 		print_wwwfile_to_fd(fd, (BOOL) !is_preparsed);
 	    }
@@ -1704,7 +1719,7 @@ PUBLIC void reply_by_mail ARGS4(
 cancelled:
     HTInfoMsg(CANCELLED);
     LYCloseTempFP(fd);		/* Close the tmpfile.	*/
-    scrollok(LYwin,FALSE); 	/* Stop scrolling.	*/
+    scrollok(LYwin,FALSE);	/* Stop scrolling.	*/
 cleanup:
     signal(SIGINT, cleanup_sig);
     term_letter = FALSE;
@@ -1729,3 +1744,15 @@ cleanup:
     FREE(body);
     return;
 }
+
+/*
+ * Check that we have configured values for system mailer.
+ */
+PUBLIC BOOLEAN LYSystemMail NOARGS
+{
+    if (system_mail == 0 || !strcmp(system_mail, "unknown")) {
+	HTAlert(gettext("No system mailer configured"));
+	return FALSE;
+    }
+    return TRUE;
+}
diff --git a/src/LYMail.h b/src/LYMail.h
index ec887318..9d93d0e1 100644
--- a/src/LYMail.h
+++ b/src/LYMail.h
@@ -29,6 +29,7 @@
 
 extern BOOLEAN term_letter;
 
+extern BOOLEAN LYSystemMail NOPARAMS;
 extern BOOLEAN LYMailPMDF NOPARAMS;
 extern FILE *LYPipeToMailer NOPARAMS;
 extern int LYSendMailFile PARAMS((
diff --git a/src/LYMain.c b/src/LYMain.c
index 0e8733a8..2792bdd9 100644
--- a/src/LYMain.c
+++ b/src/LYMain.c
@@ -290,6 +290,7 @@ PUBLIC BOOLEAN local_host_only = FALSE;
 PUBLIC BOOLEAN override_no_download = FALSE;
 PUBLIC BOOLEAN show_dotfiles = FALSE;	/* From rcfile if no_dotfiles is false */
 PUBLIC BOOLEAN LYforce_HTML_mode = FALSE;
+PUBLIC BOOLEAN LYfind_leaks = TRUE;
 
 #ifdef __DJGPP__
 PUBLIC BOOLEAN watt_debug = FALSE;	/* WATT-32 debugging */
@@ -597,7 +598,7 @@ PRIVATE void reset_break(void)
 #endif /* __DJGPP__ */
 
 #if defined(WIN_EX)
-PUBLIC int is_windows_nt(void)
+PRIVATE int is_windows_nt(void)
 {
     DWORD version;
 
@@ -1057,7 +1058,11 @@ PUBLIC int main ARGS2(
     StrAllocCopy(language, PREFERRED_LANGUAGE);
     StrAllocCopy(pref_charset, PREFERRED_CHARSET);
     StrAllocCopy(system_mail, SYSTEM_MAIL);
+#ifdef SYSTEM_MAIL_FLAGS
     StrAllocCopy(system_mail_flags, SYSTEM_MAIL_FLAGS);
+#else
+    StrAllocCopy(system_mail_flags, "");
+#endif
     StrAllocCopy(LYUserAgent, LYNX_NAME);
     StrAllocCat(LYUserAgent, "/");
     StrAllocCat(LYUserAgent, LYNX_VERSION);
@@ -2953,7 +2958,7 @@ G)oto's" },
     CONST char *value;
     BOOLEAN found, first;
 
-    if (next_arg == 0 || *next_arg == '\0') {
+    if (isEmpty(next_arg)) {
 	SetOutputMode( O_TEXT );
 	for (j = 0; j < TABLESIZE(Usage); j++) {
 	    printf("%s\n", Usage[j]);
@@ -3328,6 +3333,12 @@ keys (may be incompatible with some curses packages)"
       "include all versions of files in local VMS directory\nlistings"
    ),
 #endif
+#ifdef LY_FIND_LEAKS
+   PARSE_SET(
+      "find_leaks",	4|TOGGLE_ARG,		LYfind_leaks,
+      "toggles memory-leak checking"
+   ),
+#endif
    PARSE_SET(
       "force_empty_hrefless_a",	4|SET_ARG,	force_empty_hrefless_a,
       "\nforce HREF-less 'A' elements to be empty (close them as\nsoon as they are seen)"
@@ -3424,6 +3435,12 @@ keys (may be incompatible with some curses packages)"
       "minimal",	4|TOGGLE_ARG,		minimal_comments,
       "toggles minimal versus valid comment parsing"
    ),
+#ifdef EXP_NESTED_TABLES
+   PARSE_SET(
+      "nested_tables",	4|TOGGLE_ARG,		nested_tables,
+      "toggles nested-tables logic"
+   ),
+#endif
 #ifndef DISABLE_NEWS
    PARSE_FUN(
       "newschunksize",	4|NEED_FUNCTION_ARG,	newschunksize_fun,
diff --git a/src/LYMainLoop.c b/src/LYMainLoop.c
index 9260f128..e57b882c 100644
--- a/src/LYMainLoop.c
+++ b/src/LYMainLoop.c
@@ -6941,7 +6941,7 @@ new_cmd:  /*
 			s = links[curdoc.link].lname;
 		} else
 		    s = curdoc.address;
-		if (!s && !*s)
+		if (isEmpty(s))
 		    HTInfoMsg("Current URL is empty.");
 		if (put_clip(s))
 		    HTInfoMsg("Copy to clipboard failed.");
diff --git a/src/LYNews.h b/src/LYNews.h
index 9eaa8e13..096062d3 100644
--- a/src/LYNews.h
+++ b/src/LYNews.h
@@ -10,4 +10,3 @@ extern BOOLEAN term_message;
 extern char *LYNewsPost PARAMS((char *newsgroups, BOOLEAN followup));
 
 #endif /* LYNEWSPOST_H */
-
diff --git a/src/LYOptions.c b/src/LYOptions.c
index 8f763e1b..0fc62491 100644
--- a/src/LYOptions.c
+++ b/src/LYOptions.c
@@ -3162,16 +3162,8 @@ PRIVATE int gen_options ARGS1(
     size_t cset_len = 0;
     size_t text_len = LYscreenWidth() > 45 ? LYscreenWidth() - 38 : 7;	/* cf: PutLabel */
 
-    if (LYReuseTempfiles) {
-	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
-    } else {
-	LYRemoveTemp(tempfile);
-	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
-    }
-    if (fp0 == NULL) {
-	HTAlert(UNABLE_TO_OPEN_TEMPFILE);
+    if ((fp0 = InternalPageFP(tempfile, TRUE)) == 0)
 	return(NOT_FOUND);
-    }
 
     LYLocalFileToURL(newfile, tempfile);
 
diff --git a/src/LYPrint.c b/src/LYPrint.c
index 72e96659..9f92ab35 100644
--- a/src/LYPrint.c
+++ b/src/LYPrint.c
@@ -497,6 +497,9 @@ PRIVATE void send_file_to_mail ARGS3(
     char *subject = NULL;
     char user_response[LINESIZE];
 
+    if (!LYSystemMail())
+	return;
+
     if (LYPreparsedSource && first_mail_preparsed &&
 	HTisDocumentSource()) {
 	if (HTConfirmDefault(CONFIRM_MAIL_SOURCE_PREPARSED, NO) == YES) {
@@ -1263,16 +1266,8 @@ PUBLIC int print_options ARGS3(
     FILE *fp0;
     lynx_list_item_type *cur_printer;
 
-    if (LYReuseTempfiles) {
-	fp0 = LYOpenTempRewrite(my_temp, HTML_SUFFIX, "w");
-    } else {
-	LYRemoveTemp(my_temp);
-	fp0 = LYOpenTemp(my_temp, HTML_SUFFIX, "w");
-    }
-    if (fp0 == NULL) {
-	HTAlert(UNABLE_TO_OPEN_PRINTOP_FILE);
+    if ((fp0 = InternalPageFP(my_temp, TRUE)) == 0)
 	return(-1);
-    }
 
     LYLocalFileToURL(newfile, my_temp);
 
diff --git a/src/LYPrint.h b/src/LYPrint.h
index 622b09f4..249b12b6 100644
--- a/src/LYPrint.h
+++ b/src/LYPrint.h
@@ -11,4 +11,3 @@ extern int print_options PARAMS((char **newfile,
 extern char * GetFileName NOPARAMS;
 
 #endif /* LYPRINT_H */
-
diff --git a/src/LYReadCFG.c b/src/LYReadCFG.c
index 0c96100b..b67b08f8 100644
--- a/src/LYReadCFG.c
+++ b/src/LYReadCFG.c
@@ -239,14 +239,9 @@ PUBLIC int match_item_by_name ARGS3(
 int default_fg = DEFAULT_COLOR;
 int default_bg = DEFAULT_COLOR;
 #else
-#ifdef PDCURSES
-int default_fg = 15;
-int default_bg = COLOR_BLACK;
-#else
 int default_fg = COLOR_WHITE;
 int default_bg = COLOR_BLACK;
 #endif
-#endif
 
 PRIVATE CONST char *Color_Strings[16] =
 {
@@ -1123,7 +1118,7 @@ PRIVATE int parse_html_src_spec ARGS3(
     * message.
     */
     char* ts2;
-    if ( !value || !*value) return 0; /* silently ignoring*/
+    if (isEmpty(value)) return 0; /* silently ignoring*/
 
 #define BS() html_src_bad_syntax(value,option_name)
 
@@ -1215,7 +1210,7 @@ PRIVATE int read_htmlsrc_tagname_xform ARGS1( char*,str)
 
 /* This table is searched ignoring case */
 PRIVATE Config_Type Config_Table [] =
-{ 
+{
      PARSE_SET(RC_ACCEPT_ALL_COOKIES,   LYAcceptAllCookies),
      PARSE_TIM(RC_ALERTSECS,            AlertSecs),
      PARSE_SET(RC_ALWAYS_RESUBMIT_POSTS, LYresubmit_posts),
@@ -1587,35 +1582,31 @@ PRIVATE char *actual_filename ARGS3(
     char *,	parent_filename,
     char *,	dft_filename)
 {
-    static char *my_filename;
+    char *my_filename = NULL;
 
-    if (my_filename != 0) {
-	FREE(my_filename);
-    }
     if (!LYisAbsPath(cfg_filename)
      && !(parent_filename == 0 && LYCanReadFile(cfg_filename))) {
 	if (!strncmp(cfg_filename, "~/", 2)) {
 	    HTSprintf0(&my_filename, "%s%s", Home_Dir(), cfg_filename+1);
-	    cfg_filename = my_filename;
 	} else {
 	    if (parent_filename != 0) {
 		StrAllocCopy(my_filename, parent_filename);
 		*LYPathLeaf (my_filename) = '\0';
 		StrAllocCat(my_filename, cfg_filename);
 	    }
-	    if (my_filename != 0 && LYCanReadFile(my_filename)) {
-		cfg_filename = my_filename;
-	    } else {
+	    if (my_filename == 0 || !LYCanReadFile(my_filename)) {
 		StrAllocCopy(my_filename, dft_filename);
 		*LYPathLeaf (my_filename) = '\0';
 		StrAllocCat(my_filename, cfg_filename);
-		if (LYCanReadFile(my_filename)) {
-		    cfg_filename = my_filename;
+		if (!LYCanReadFile(my_filename)) {
+		    StrAllocCopy(my_filename, cfg_filename);
 		}
 	    }
 	}
+    } else {
+	StrAllocCopy(my_filename, cfg_filename);
     }
-    return cfg_filename;
+    return my_filename;
 }
 
 PUBLIC FILE *LYOpenCFG ARGS3(
@@ -1623,9 +1614,14 @@ PUBLIC FILE *LYOpenCFG ARGS3(
     char *,	parent_filename,
     char *,	dft_filename)
 {
-    cfg_filename = actual_filename(cfg_filename, parent_filename, dft_filename);
-    CTRACE((tfp, "opening config file %s\n", cfg_filename));
-    return fopen(cfg_filename, TXT_R);
+    char *my_file = actual_filename(cfg_filename, parent_filename, dft_filename);
+    FILE *result;
+
+    CTRACE((tfp, "opening config file %s\n", my_file));
+    result = fopen(my_file, TXT_R);
+    FREE(my_file);
+
+    return result;
 }
 
 #define NOPTS_ ( TABLESIZE(Config_Table) - 1 )
@@ -1888,7 +1884,10 @@ PRIVATE void do_read_cfg ARGS5(
 
 #ifndef NO_CONFIG_INFO
 	    if (fp0 != 0  &&  !no_lynxcfg_xinfo) {
-		LYLocalFileToURL(&url, actual_filename(value, cfg_filename, LYNX_CFG_FILE));
+		char *my_file = actual_filename(value, cfg_filename, LYNX_CFG_FILE);
+
+		LYLocalFileToURL(&url, my_file);
+		FREE(my_file);
 		StrAllocCopy(cp1, value);
 		if (strchr(value, '&') || strchr(value, '<')) {
 		    LYEntify(&cp1, TRUE);
@@ -2033,6 +2032,16 @@ PUBLIC void read_cfg ARGS4(
     do_read_cfg(cfg_filename, parent_filename, nesting_level, fp0, NULL);
 }
 
+#ifndef NO_CONFIG_INFO
+PRIVATE void extra_cfg_link ARGS3(
+	FILE *,	fp,
+	char *,	href,
+	char *,	name)
+{
+    fprintf(fp, "<a href=\"%s\">%s</a>",
+	    href, name);
+}
+#endif /* NO_CONFIG_INFO */
 
 /*
  *  Show rendered lynx.cfg data without comments, LYNXCFG:/ internal page.
@@ -2135,17 +2144,9 @@ PUBLIC int lynx_cfg_infopage ARGS1(
     }
     if (lynxcfginfo_url == 0) {
 
-	if (LYReuseTempfiles) {
-	    fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
-	} else {
-	    if (tempfile[0])
-		LYRemoveTemp(tempfile);
-	    fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
-	}
-	if (fp0 == NULL) {
-	    HTAlert(CANNOT_OPEN_TEMP);
+	if ((fp0 = InternalPageFP(tempfile, TRUE)) == 0)
 	    return(NOT_FOUND);
-	}
+
 	LYLocalFileToURL(&lynxcfginfo_url, tempfile);
 
 	LYforce_no_cache = TRUE;  /* don't cache this doc */
@@ -2178,14 +2179,34 @@ PUBLIC int lynx_cfg_infopage ARGS1(
 			     gettext("for more comments."));
 	    }
 
-#if defined(HAVE_CONFIG_H) && !defined(NO_CONFIG_INFO)
-	    if (!no_compileopts_info) {
-		fprintf(fp0, "%s <a href=\"%s\">%s</a>\n\n",
-			SEE_ALSO,
-			STR_LYNXCFLAGS,
-			COMPILE_OPT_SEGMENT);
-	    }
+#ifndef NO_CONFIG_INFO
+#if defined(HAVE_CONFIG_H) && defined(USE_COLOR_STYLE)
+	    if (!no_compileopts_info && !no_lynxcfg_xinfo) {
+		fprintf(fp0, "%s</pre><ul><li>", SEE_ALSO);
+		extra_cfg_link(fp0, STR_LYNXCFLAGS, COMPILE_OPT_SEGMENT);
+
+		fprintf(fp0, "<li>");
+		LYLocalFileToURL(&temp, lynx_lss_file);
+		extra_cfg_link(fp0, temp, COLOR_STYLE_SEGMENT);
+		fprintf(fp0, "</ul><pre>\n");
+	    } else
+#endif
+	    {
+		fprintf(fp0, "%s ", SEE_ALSO);
+#if defined(HAVE_CONFIG_H)
+		if (!no_compileopts_info) {
+		    extra_cfg_link(fp0, STR_LYNXCFLAGS, COMPILE_OPT_SEGMENT);
+		}
 #endif
+#if defined(USE_COLOR_STYLE)
+		if (!no_lynxcfg_xinfo) {
+		    LYLocalFileToURL(&temp, lynx_lss_file);
+		    extra_cfg_link(fp0, temp, COLOR_STYLE_SEGMENT);
+		}
+#endif
+		fprintf(fp0, "\n\n");
+	    }
+#endif /* NO_CONFIG_INFO */
 
 	    /** a new experimental link ... **/
 	    if (user_mode == ADVANCED_MODE)
@@ -2279,16 +2300,9 @@ PUBLIC int lynx_compile_opts ARGS1(
 	}
     }
     if (configinfo_url == NULL) {
-	if (LYReuseTempfiles) {
-	    fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
-	} else {
-	    LYRemoveTemp(tempfile);
-	    fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
-	}
-	if (fp0 == NULL) {
-	    HTAlert(CANNOT_OPEN_TEMP);
+	if ((fp0 = InternalPageFP(tempfile, TRUE)) == 0)
 	    return(NOT_FOUND);
-	}
+
 	LYLocalFileToURL(&configinfo_url, tempfile);
 
 	BeginInternalPage (fp0, CONFIG_DEF_TITLE, NULL);
diff --git a/src/LYShowInfo.c b/src/LYShowInfo.c
index 9939a3e5..596e753c 100644
--- a/src/LYShowInfo.c
+++ b/src/LYShowInfo.c
@@ -281,7 +281,7 @@ PUBLIC int LYShowInfo ARGS4(
     } else {
       LYUCcharset * p_in = HTAnchor_getUCInfoStage(HTMainAnchor,
 							     UCT_STAGE_PARSER);
-      if (!p_in || !(p_in->MIMEname) || !*(p_in->MIMEname) ||
+      if (!p_in || isEmpty(p_in->MIMEname) ||
 	   HTAnchor_getUCLYhndl(HTMainAnchor, UCT_STAGE_PARSER) < 0) {
 	   p_in = HTAnchor_getUCInfoStage(HTMainAnchor, UCT_STAGE_MIME);
       }
diff --git a/src/LYShowInfo.h b/src/LYShowInfo.h
index f95247fa..623eaf44 100644
--- a/src/LYShowInfo.h
+++ b/src/LYShowInfo.h
@@ -12,4 +12,3 @@ extern int LYShowInfo PARAMS((DocInfo *doc, int size_of_file, DocInfo *newdoc,
 							char *owner_address));
 
 #endif /* LYSHOWINFO_H */
-
diff --git a/src/LYStrings.c b/src/LYStrings.c
index 02615488..b981540c 100644
--- a/src/LYStrings.c
+++ b/src/LYStrings.c
@@ -535,7 +535,7 @@ PRIVATE int set_clicked_link ARGS4(
 		c = LAC_TO_LKC0(LYK_CHANGE_LINK);
 	}
 	else {
-	   if (2*y > LYlines){ 		/* Bottom Half of the screen */
+	   if (2*y > LYlines){		/* Bottom Half of the screen */
 	      if (4*y < 3*LYlines){
 		c = LAC_TO_LKC0(LYK_DOWN_TWO);	/* Third quarter */
 	      } else
@@ -2144,8 +2144,6 @@ re_read:
 		}
 #else /* pdcurses version */
 
-	/* _WINDOWS 1997/10/18 (Sat) 19:41:59 */
-
 #define H_CMD_AREA	6
 #define HIST_CMD_2	12
 #define V_CMD_AREA	1
@@ -2162,39 +2160,7 @@ re_read:
 		c = -1;
 		mouse_link = -1;
 
-		if (system_is_NT) {
-		/* for Windows NT */
-		  request_mouse_pos();
-
-		  if (BUTTON_STATUS(1) & BUTTON_PRESSED) {
-			if (MOUSE_Y_POS > (LYlines - V_CMD_AREA)) {
-			    /* Screen BOTTOM */
-			    if (MOUSE_X_POS < left) {
-				c = LTARROW;		p = "<-";
-			    } else if (MOUSE_X_POS < HIST_CMD_2) {
-				c = RTARROW;		p = "->";
-			    } else if (MOUSE_X_POS > right) {
-				c = 'z';		p = "Cancel";
-			    } else {
-				c = PGDOWN;		p = "PGDOWN";
-			    }
-			} else if (MOUSE_Y_POS < V_CMD_AREA) {
-			    /* Screen TOP */
-			    if (MOUSE_X_POS < left) {
-				c = LTARROW;		p = "<-";
-			    } else if (MOUSE_X_POS < HIST_CMD_2) {
-				c = RTARROW;		p = "->";
-			    } else if (MOUSE_X_POS > right) {
-				c = 'z';		p = "Cancel";
-			    } else {
-				c = PGUP;		p = "PGUP";
-			    }
-			} else {
-			    c = set_clicked_link(MOUSE_X_POS, MOUSE_Y_POS, FOR_PANEL, 1);
-			}
-		    }
-		} else {
-		    /* for Windows 95 */
+		if (!system_is_NT) {
 		    tick_count = GetTickCount();
 
 		    /* Guard Mouse button miss click */
@@ -2204,15 +2170,18 @@ re_read:
 		    } else {
 			old_click = tick_count;
 		    }
-		    request_mouse_pos();
-		    if (MOUSE_Y_POS > (LYlines - V_CMD_AREA)) {
+		}
+		request_mouse_pos();
+
+		if (BUTTON_STATUS(1) & BUTTON_PRESSED) {
+		    if (MOUSE_Y_POS > (LYlines - V_CMD_AREA - 1)) {
 			/* Screen BOTTOM */
 			if (MOUSE_X_POS < left) {
 			    c = LTARROW;	p = "<-";
 			} else if (MOUSE_X_POS < HIST_CMD_2) {
 			    c = RTARROW;	p = "->";
 			} else if (MOUSE_X_POS > right) {
-			    c = '\b';		p = "History";
+			    c = 'z';		p = "Cancel";
 			} else {
 			    c = PGDOWN;		p = "PGDOWN";
 			}
@@ -2480,16 +2449,19 @@ PUBLIC BOOLEAN LYRemoveNewlines ARGS1(
 /*
  * Remove ALL whitespace from a string (including embedded blanks).
  */
-PUBLIC void LYRemoveBlanks ARGS1(
+PUBLIC char * LYRemoveBlanks ARGS1(
 	char *,		buffer)
 {
     if (buffer != 0) {
 	size_t i, j;
-	for (i = j = 0; buffer[i]; i++)
+	for (i = j = 0; buffer[i]; i++) {
 	    if (!isspace(UCH((buffer[i]))))
 		buffer[j++] = buffer[i];
+	}
 	buffer[j] = 0;
+	return buffer+j;
     }
+    return NULL;
 }
 
 /*
@@ -4993,7 +4965,7 @@ PUBLIC char *LYstrsep ARGS2(
 {
     char *tmp, *out;
 
-    if (!stringp || !*stringp)		/* nothing to do? */
+    if (isEmpty(stringp))		/* nothing to do? */
 	return 0;			/* then don't fall on our faces */
 
     out = *stringp;			/* save the start of the string */
@@ -5746,7 +5718,7 @@ PUBLIC int LYReadCmdKey ARGS1(
 			++tmp;
 		    }
 		    if (*tmp != '\0') {
-		    	*tmp++ = '\0';
+			*tmp++ = '\0';
 			tmp = LYSkipBlanks(tmp);
 		    }
 		    CTRACE((tfp, "LYSetConfigValue(%s, %s)\n", src, tmp));
@@ -5757,7 +5729,7 @@ PUBLIC int LYReadCmdKey ARGS1(
 	}
 	if (feof(cmd_script)) {
 	    fclose(cmd_script);
-	    cmd_script = 0;    
+	    cmd_script = 0;
 	}
 	if (ch >= 0) {
 	    LYSleepReplay();
diff --git a/src/LYStrings.h b/src/LYStrings.h
index 3fcb443e..6bbff9db 100644
--- a/src/LYStrings.h
+++ b/src/LYStrings.h
@@ -306,7 +306,7 @@ extern void LYUpperCase PARAMS((
 	char *		buffer));
 extern BOOLEAN LYRemoveNewlines PARAMS((
 	char *		buffer));
-extern void LYRemoveBlanks PARAMS((
+extern char * LYRemoveBlanks PARAMS((
 	char *		buffer));
 extern char * LYSkipBlanks PARAMS((
 	char *		buffer));
diff --git a/src/LYStyle.c b/src/LYStyle.c
index fde9473a..b6d71ea2 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.50 Sun, 06 Oct 2002 17:43:28 -0700 dickey @
+ * @Id: LYStyle.c 1.51 Wed, 22 Jan 2003 01:43:13 -0800 dickey @
  */
 #include <HTUtils.h>
 #include <HTML.h>
@@ -192,7 +192,9 @@ PRIVATE void parse_attributes ARGS5(
 
 	if (fA < MAX_COLOR
 	 && bA < MAX_COLOR
+#ifdef USE_CURSES_PAIR_0
 	 && (fA != default_fg || bA != default_bg)
+#endif
 	 && curPair < 255) {
 	    if (our_pairs[iBold][iBlink][iFg][iBg] != 0) {
 		curPair = our_pairs[iBold][iBlink][iFg][iBg];
@@ -505,7 +507,7 @@ PRIVATE int style_readFromFileREC ARGS2(
     int len;
 
     CTRACE2(TRACE_STYLE, (tfp, "CSS:Reading styles from file: %s\n", lss_filename ? lss_filename : "?!? empty ?!?"));
-    if (lss_filename == NULL || *lss_filename == '\0')
+    if (isEmpty(lss_filename))
 	return -1;
     if ((fh = LYOpenCFG(lss_filename, parent_filename, LYNX_LSS_FILE)) == 0) {
 	/* this should probably be an alert or something */
diff --git a/src/LYUpload.c b/src/LYUpload.c
index 1667e937..d8b0d10d 100644
--- a/src/LYUpload.c
+++ b/src/LYUpload.c
@@ -185,16 +185,8 @@ PUBLIC int LYUpload_options ARGS2(
     static char curloc[LY_MAXPATH];
     char *cp;
 
-    if (LYReuseTempfiles) {
-	fp0 = LYOpenTempRewrite(tempfile, HTML_SUFFIX, "w");
-    } else {
-	LYRemoveTemp(tempfile);
-	fp0 = LYOpenTemp(tempfile, HTML_SUFFIX, "w");
-    }
-    if (fp0 == NULL) {
-	HTAlert(CANNOT_OPEN_TEMP);
+    if ((fp0 = InternalPageFP(tempfile, TRUE)) == 0)
 	return(-1);
-    }
 
 #ifdef VMS
     strcpy(curloc, "/sys$login");
diff --git a/src/LYUtils.c b/src/LYUtils.c
index 5fbe1965..291751bd 100644
--- a/src/LYUtils.c
+++ b/src/LYUtils.c
@@ -250,7 +250,7 @@ PUBLIC void LYAddHilite ARGS3(
     HiliteList *list = &(links[cur].list);
     HiliteInfo *have = list->hl_info;
     unsigned need = (list->hl_len - 1);
-    unsigned want = ++(list->hl_len) * sizeof(HiliteInfo);
+    unsigned want = (list->hl_len += 1) * sizeof(HiliteInfo);
 
     if (have != NULL) {
 	have = realloc(have, want);
@@ -1951,7 +1951,7 @@ PUBLIC int LYCheckForProxyURL ARGS1(
     /*
      *	Don't crash on an empty argument.
      */
-    if (cp == NULL || *cp == '\0')
+    if (isEmpty(cp))
 	return(NOT_A_URL_TYPE);
 
     /* kill beginning spaces */
@@ -2011,6 +2011,12 @@ static BOOLEAN compare_type ARGS3(
     return FALSE;
 }
 
+#define DoubleHtmlSep(s) (LYIsHtmlSep((s)[0]) && LYIsHtmlSep((s)[1]))
+#define compare_two(tst,cmp,len,limit) \
+	((len + 2) <= limit \
+	&& DoubleHtmlSep(tst + len) \
+	&& compare_type(tst, cmp, len))
+
 /*
 **  Must recognize a URL and return the type.
 **  If recognized, based on a case-insensitive
@@ -2029,11 +2035,13 @@ PUBLIC int is_url ARGS1(
     char *cp = filename;
     char *cp1;
     int result = NOT_A_URL_TYPE;
+    int len;
+    int limit;
 
     /*
      *	Don't crash on an empty argument.
      */
-    if (cp == NULL || *cp == '\0')
+    if (isEmpty(cp))
 	return(result);
 
     /*
@@ -2057,228 +2065,300 @@ PUBLIC int is_url ARGS1(
     if (*cp == ':' || LYIsHtmlSep(*cp)) {
 	result = NOT_A_URL_TYPE;
 
-#ifndef DISABLE_NEWS
-    } else if (compare_type(cp, STR_NEWS_URL, LEN_NEWS_URL)) {
-	result = NEWS_URL_TYPE;
-
-    } else if (compare_type(cp, STR_NNTP_URL, LEN_NNTP_URL)) {
-	result = NNTP_URL_TYPE;
-
-    } else if (compare_type(cp, STR_SNEWS_URL, LEN_SNEWS_URL)) {
-	result = SNEWS_URL_TYPE;
-
-    } else if (compare_type(cp, "newspost:", 9)) {
-	/*
-	 *  Special Lynx type to handle news posts.
-	 */
-	result = NEWSPOST_URL_TYPE;
+    } else {
+	limit = strlen(cp);
+	switch (*cp) {
+	case 'L':
+	case 'l':
+	    /*
+	     *  Lynx internal pages ("LYNXfoo:" or "lynxfoo:")
+	     *  start with 'l' or 'L', other URLs aren't.
+	     */
+	    if (compare_type(cp, STR_LYNXEXEC, LEN_LYNXEXEC)) {
+		/*
+		 *  Special External Lynx type to handle execution
+		 *  of commands or scripts which require a pause to
+		 *  read the screen upon completion.
+		 */
+		result = LYNXEXEC_URL_TYPE;
 
-    } else if (compare_type(cp, "newsreply:", 10)) {
-	/*
-	 *  Special Lynx type to handle news replies (followups).
-	 */
-	result = NEWSREPLY_URL_TYPE;
+	    } else if (compare_type(cp, STR_LYNXPROG, LEN_LYNXPROG)) {
+		/*
+		 *  Special External Lynx type to handle execution
+		 *  of commands, scripts or programs with do not
+		 *  require a pause to read screen upon completion.
+		 */
+		result = LYNXPROG_URL_TYPE;
 
-    } else if (compare_type(cp, "snewspost:", 10)) {
-	/*
-	 *  Special Lynx type to handle snews posts.
-	 */
-	result = NEWSPOST_URL_TYPE;
+	    } else if (compare_type(cp, STR_LYNXCGI, LEN_LYNXCGI)) {
+		/*
+		 *  Special External Lynx type to handle cgi scripts.
+		 */
+		result = LYNXCGI_URL_TYPE;
 
-    } else if (compare_type(cp, "snewsreply:", 11)) {
-	/*
-	 *  Special Lynx type to handle snews replies (followups).
-	 */
-	result = NEWSREPLY_URL_TYPE;
-#endif
+	    } else if (compare_type(cp, STR_LYNXPRINT, LEN_LYNXPRINT)) {
+		/*
+		 *  Special Internal Lynx type.
+		 */
+		result = LYNXPRINT_URL_TYPE;
 
-    } else if (compare_type(cp, STR_MAILTO_URL, LEN_MAILTO_URL)) {
-	result = MAILTO_URL_TYPE;
+	    } else if (compare_type(cp, STR_LYNXOPTIONS, LEN_LYNXOPTIONS)) {
+		/*
+		 *  Special Internal Lynx type.
+		 */
+		result = LYNXOPTIONS_URL_TYPE;
 
-#ifndef DISABLE_BIBP
-    } else if (compare_type(cp, STR_BIBP_URL, LEN_BIBP_URL)) {
-	result = BIBP_URL_TYPE;
-#endif
+	    } else if (compare_type(cp, STR_LYNXCFG, LEN_LYNXCFG)) {
+		/*
+		 *  Special Internal Lynx type.
+		 */
+		result = LYNXCFG_URL_TYPE;
 
-    } else if (compare_type(cp, STR_FILE_URL, LEN_FILE_URL)) {
-	if (LYisLocalFile(cp)) {
-	    result = FILE_URL_TYPE;
-	} else if (LYIsHtmlSep(cp[5]) && LYIsHtmlSep(cp[6])) {
-	    result = FTP_URL_TYPE;
-	} else {
-	    result = NOT_A_URL_TYPE;
-	}
+	    } else if (compare_type(cp, STR_LYNXMESSAGES, LEN_LYNXMESSAGES)) {
+		/*
+		 *  Special Internal Lynx type.
+		 */
+		result = LYNXMESSAGES_URL_TYPE;
 
-    } else if (compare_type(cp, "data:", 5)) {
-	result = DATA_URL_TYPE;
+	    } else if (compare_type(cp, STR_LYNXCFLAGS, LEN_LYNXCFLAGS)) {
+		/*
+		 *  Special Internal Lynx type.
+		 */
+		result = LYNXCOMPILE_OPTS_URL_TYPE;
 
-    } else if (compare_type(cp, STR_LYNXEXEC, LEN_LYNXEXEC)) {
-	/*
-	 *  Special External Lynx type to handle execution
-	 *  of commands or scripts which require a pause to
-	 *  read the screen upon completion.
-	 */
-	result = LYNXEXEC_URL_TYPE;
+	    } else if (compare_type(cp, STR_LYNXDOWNLOAD, LEN_LYNXDOWNLOAD)) {
+		/*
+		 *  Special Internal Lynx type.
+		 */
+		result = LYNXDOWNLOAD_URL_TYPE;
 
-    } else if (compare_type(cp, STR_LYNXPROG, LEN_LYNXPROG)) {
-	/*
-	 *  Special External Lynx type to handle execution
-	 *  of commands, scripts or programs with do not
-	 *  require a pause to read screen upon completion.
-	 */
-	result = LYNXPROG_URL_TYPE;
+	    } else if (compare_type(cp, STR_LYNXDIRED, LEN_LYNXDIRED)) {
+		/*
+		 *  Special Internal Lynx type.
+		 */
+		result = LYNXDIRED_URL_TYPE;
 
-    } else if (compare_type(cp, STR_LYNXCGI, LEN_LYNXCGI)) {
-	/*
-	 *  Special External Lynx type to handle cgi scripts.
-	 */
-	result = LYNXCGI_URL_TYPE;
+	    } else if (compare_type(cp, STR_LYNXHIST, LEN_LYNXHIST)) {
+		/*
+		 *  Special Internal Lynx type.
+		 */
+		result = LYNXHIST_URL_TYPE;
 
-    } else if (compare_type(cp, STR_LYNXPRINT, LEN_LYNXPRINT)) {
-	/*
-	 *  Special Internal Lynx type.
-	 */
-	result = LYNXPRINT_URL_TYPE;
+	    } else if (compare_type(cp, STR_LYNXKEYMAP, LEN_LYNXKEYMAP)) {
+		/*
+		 *  Special Internal Lynx type.
+		 */
+		result = LYNXKEYMAP_URL_TYPE;
 
-    } else if (compare_type(cp, STR_LYNXOPTIONS, LEN_LYNXOPTIONS)) {
-	/*
-	 *  Special Internal Lynx type.
-	 */
-	result = LYNXOPTIONS_URL_TYPE;
+	    } else if (compare_type(cp, STR_LYNXIMGMAP, LEN_LYNXIMGMAP)) {
+		/*
+		 *  Special Internal Lynx type.
+		 */
+		/* force lower/uppercase of next part */
+		(void)is_url(&cp[LEN_LYNXIMGMAP]);
+		result = LYNXIMGMAP_URL_TYPE;
 
-    } else if (compare_type(cp, STR_LYNXCFG, LEN_LYNXCFG)) {
-	/*
-	 *  Special Internal Lynx type.
-	 */
-	result = LYNXCFG_URL_TYPE;
+	    } else if (compare_type(cp, STR_LYNXCOOKIE, LEN_LYNXCOOKIE)) {
+		/*
+		 *  Special Internal Lynx type.
+		 */
+		result = LYNXCOOKIE_URL_TYPE;
+	    }
+	    break;
+#ifndef DISABLE_NEWS
+	    /*
+	     *  NEWSfoo: schemes -
+	     */
+	case 'N':
+	case 'n':
+	    if (compare_type(cp, STR_NEWS_URL, LEN_NEWS_URL)) {
+		result = NEWS_URL_TYPE;
 
-    } else if (compare_type(cp, STR_LYNXMESSAGES, LEN_LYNXMESSAGES)) {
-	/*
-	 *  Special Internal Lynx type.
-	 */
-	result = LYNXMESSAGES_URL_TYPE;
+	    } else if (compare_type(cp, STR_NNTP_URL, LEN_NNTP_URL)) {
+		result = NNTP_URL_TYPE;
 
-    } else if (compare_type(cp, STR_LYNXCFLAGS, LEN_LYNXCFLAGS)) {
-	/*
-	 *  Special Internal Lynx type.
-	 */
-	result = LYNXCOMPILE_OPTS_URL_TYPE;
+	    } else if (compare_type(cp, "newspost:", 9)) {
+		/*
+		 *  Special Lynx type to handle news posts.
+		 */
+		result = NEWSPOST_URL_TYPE;
 
-    } else if (compare_type(cp, STR_LYNXDOWNLOAD, LEN_LYNXDOWNLOAD)) {
-	/*
-	 *  Special Internal Lynx type.
-	 */
-	result = LYNXDOWNLOAD_URL_TYPE;
+	    } else if (compare_type(cp, "newsreply:", 10)) {
+		/*
+		 *  Special Lynx type to handle news replies (followups).
+		 */
+		result = NEWSREPLY_URL_TYPE;
+	    }
+	    break;
 
-    } else if (compare_type(cp, STR_LYNXDIRED, LEN_LYNXDIRED)) {
-	/*
-	 *  Special Internal Lynx type.
-	 */
-	result = LYNXDIRED_URL_TYPE;
+	    /*
+	     *  SNEWSfoo: schemes -
+	     */
+	case 'S':
+	case 's':
+	    if (compare_type(cp, STR_SNEWS_URL, LEN_SNEWS_URL)) {
+		result = SNEWS_URL_TYPE;
 
-    } else if (compare_type(cp, STR_LYNXHIST, LEN_LYNXHIST)) {
-	/*
-	 *  Special Internal Lynx type.
-	 */
-	result = LYNXHIST_URL_TYPE;
+	    } else if (compare_type(cp, "snewspost:", 10)) {
+		/*
+		 *  Special Lynx type to handle snews posts.
+		 */
+		result = NEWSPOST_URL_TYPE;
 
-    } else if (compare_type(cp, STR_LYNXKEYMAP, LEN_LYNXKEYMAP)) {
-	/*
-	 *  Special Internal Lynx type.
-	 */
-	result = LYNXKEYMAP_URL_TYPE;
+	    } else if (compare_type(cp, "snewsreply:", 11)) {
+		/*
+		 *  Special Lynx type to handle snews replies (followups).
+		 */
+		result = NEWSREPLY_URL_TYPE;
+	    }
+	    break;
+#endif
+	case 'M':
+	case 'm':
+	    if (compare_type(cp, STR_MAILTO_URL, LEN_MAILTO_URL)) {
+		result = MAILTO_URL_TYPE;
+	    }
+	    break;
 
-    } else if (compare_type(cp, STR_LYNXIMGMAP, LEN_LYNXIMGMAP)) {
-	/*
-	 *  Special Internal Lynx type.
-	 */
-	(void)is_url(&cp[11]);	/* forces lower/uppercase of next part */
-	result = LYNXIMGMAP_URL_TYPE;
+	case 'F':
+	case 'f':
+	    if (compare_type(cp, STR_FILE_URL, len = LEN_FILE_URL)) {
+		if (LYisLocalFile(cp)) {
+		    result = FILE_URL_TYPE;
+		} else if (DoubleHtmlSep(cp + len)) {
+		    result = FTP_URL_TYPE;
+		}
+	    }
+#ifndef DISABLE_FTP
+	    else if (compare_two(cp, STR_FTP_URL, LEN_FTP_URL, limit)) {
+		result = FTP_URL_TYPE;
+	    }
+#endif
+#ifndef DISABLE_FINGER
+	    else if (compare_two(cp, STR_FINGER_URL, LEN_FINGER_URL, limit)) {
+		result = FINGER_URL_TYPE;
+	    }
+#endif
+	    break;
 
-    } else if (compare_type(cp, STR_LYNXCOOKIE, LEN_LYNXCOOKIE)) {
-	/*
-	 *  Special Internal Lynx type.
-	 */
-	result = LYNXCOOKIE_URL_TYPE;
+	case 'B':
+	case 'b':
+#ifndef DISABLE_BIBP
+	    if (compare_type(cp, STR_BIBP_URL, LEN_BIBP_URL)) {
+		result = BIBP_URL_TYPE;
+	    }
+#endif
+	    break;
 
-    } else if (strlen(cp) >= 3
-	    && strstr((cp+3), "://") == NULL) {
-	/*
-	 *  If it doesn't contain "://", and it's not one of the
-	 *  the above, it can't be a URL with a scheme we know,
-	 *  so check if it's an unknown scheme for which proxying
-	 *  has been set up. - FM
-	 */
-	if ((cp1 = strstr(cp, ":")) != NULL
-	 && (cp1 - cp) > 1		/* exclude DOS-style device:/path */
-	 && LYisAbsPath(cp1+1)) {
-	    result = NCFTP_URL_TYPE;
-	} else {
-	    result = LYCheckForProxyURL(filename);
-	}
+	case 'D':
+	case 'd':
+	    if (compare_type(cp, "data:", 5)) {
+		result = DATA_URL_TYPE;
+	    }
+	    break;
 
-    } else if (compare_type(cp, STR_HTTP_URL, LEN_HTTP_URL)) {
-	result = HTTP_URL_TYPE;
+	default:
+	    if (limit >= 3
+	    && ((cp1 = strchr(cp + 3, ':')) == NULL
+	     || !DoubleHtmlSep(cp1 + 1))) {
+		/*
+		 * If it doesn't contain "://", and it's not one of the the
+		 * above, it can't be a URL with a scheme we know, so check if
+		 * it's an unknown scheme for which proxying has been set up. 
+		 * - FM
+		 */
+		if (cp1 != NULL
+		 && (cp1 - cp) > 1	/* exclude DOS-style device:/path */
+		 && LYisAbsPath(cp1+1)) {
+		    result = NCFTP_URL_TYPE;
+		}
 
-    } else if (compare_type(cp, STR_HTTPS_URL, LEN_HTTPS_URL)) {
-	result = HTTPS_URL_TYPE;
+	    } else {
+		switch (*cp) {
+		case 'H':
+		case 'h':
+		    if (compare_type(cp, STR_HTTP_URL, LEN_HTTP_URL)) {
+			result = HTTP_URL_TYPE;
+
+		    } else if (compare_type(cp, STR_HTTPS_URL, LEN_HTTPS_URL)) {
+			result = HTTPS_URL_TYPE;
+		    }
+		    break;
 
 #ifndef DISABLE_GOPHER
-    } else if (compare_type(cp, STR_GOPHER_URL, LEN_GOPHER_URL)) {
-	if (strlen(cp) >= 11
-	 && (cp1 = strchr(cp+11,'/')) != NULL) {
-
-	    if (TOUPPER(*(cp1+1)) == 'H' || *(cp1+1) == 'w')
-		/* if this is a gopher html type */
-		result = HTML_GOPHER_URL_TYPE;
-	    else if (*(cp1+1) == 'T' || *(cp1+1) == '8')
-		result = TELNET_GOPHER_URL_TYPE;
-	    else if (*(cp1+1) == '7')
-		result = INDEX_GOPHER_URL_TYPE;
-	    else
-		result = GOPHER_URL_TYPE;
-	} else {
-	    result = GOPHER_URL_TYPE;
-	}
-#endif
-
-#ifndef DISABLE_FTP
-    } else if (compare_type(cp, STR_FTP_URL, LEN_FTP_URL)) {
-	result = FTP_URL_TYPE;
+		case 'G':
+		case 'g':
+		    if (compare_type(cp, STR_GOPHER_URL, LEN_GOPHER_URL)) {
+			if (strlen(cp) >= 11
+			 && (cp1 = strchr(cp+11,'/')) != NULL) {
+
+			    if (TOUPPER(*(cp1+1)) == 'H' || *(cp1+1) == 'w')
+				/* if this is a gopher html type */
+				result = HTML_GOPHER_URL_TYPE;
+			    else if (*(cp1+1) == 'T' || *(cp1+1) == '8')
+				result = TELNET_GOPHER_URL_TYPE;
+			    else if (*(cp1+1) == '7')
+				result = INDEX_GOPHER_URL_TYPE;
+			    else
+				result = GOPHER_URL_TYPE;
+			} else {
+			    result = GOPHER_URL_TYPE;
+			}
+		    }
+		    break;
 #endif
+		case 'W':
+		case 'w':
+		    if (compare_type(cp, STR_WAIS_URL, LEN_WAIS_URL)) {
+			result = WAIS_URL_TYPE;
+		    }
+		    break;
 
-    } else if (compare_type(cp, STR_WAIS_URL, LEN_WAIS_URL)) {
-	result = WAIS_URL_TYPE;
-
-    } else if (compare_type(cp, STR_TELNET_URL, LEN_TELNET_URL)) {
-	result = TELNET_URL_TYPE;
-
-    } else if (compare_type(cp, STR_TN3270_URL, LEN_TN3270_URL)) {
-	result = TN3270_URL_TYPE;
-
-    } else if (compare_type(cp, STR_RLOGIN_URL, LEN_RLOGIN_URL)) {
-	result = RLOGIN_URL_TYPE;
+		case 'T':
+		case 't':
+		    if (compare_type(cp, STR_TELNET_URL, LEN_TELNET_URL)) {
+			result = TELNET_URL_TYPE;
 
-    } else if (compare_type(cp, STR_CSO_URL, LEN_CSO_URL)) {
-	result = CSO_URL_TYPE;
+		    } else if (compare_type(cp, STR_TN3270_URL, LEN_TN3270_URL)) {
+			result = TN3270_URL_TYPE;
+		    }
+		    break;
 
-#ifndef DISABLE_FINGER
-    } else if (compare_type(cp, STR_FINGER_URL, LEN_FINGER_URL)) {
-	result = FINGER_URL_TYPE;
-#endif
+		case 'R':
+		case 'r':
+		    if (compare_type(cp, STR_RLOGIN_URL, LEN_RLOGIN_URL)) {
+			result = RLOGIN_URL_TYPE;
+		    }
+		    break;
 
-    } else if (compare_type(cp, "afs:", 4)) {
-	result = AFS_URL_TYPE;
+		case 'C':
+		case 'c':
+		    if (compare_type(cp, STR_CSO_URL, LEN_CSO_URL)) {
+			result = CSO_URL_TYPE;
+		    }
+		    break;
 
-    } else if (compare_type(cp, "prospero:", 9)) {
-	result = PROSPERO_URL_TYPE;
+		case 'A':
+		case 'a':
+		    if (compare_type(cp, "afs:", 4)) {
+			result = AFS_URL_TYPE;
+		    }
+		    break;
 
-    } else {
+		case 'P':
+		case 'p':
+		    if (compare_type(cp, "prospero:", 9)) {
+			result = PROSPERO_URL_TYPE;
+		    }
+		    break;
+		}
+	    }
+	}
 	/*
-	 *  Check if it's an unknown scheme for which
-	 *  proxying has been set up. - FM
+	 * Check if it is an unknown scheme for which proxying has been set up. 
 	 */
-	result = LYCheckForProxyURL(filename);
+	if (result == NOT_A_URL_TYPE)
+	    result = LYCheckForProxyURL(filename);
     }
     return result;
 }
@@ -3680,7 +3760,8 @@ PUBLIC void LYEnsureAbsoluteURL ARGS3(
 		    NonNull(name), (name ? " " : ""), *href));
 	LYConvertToURL(href, fixit);
     }
-    if (non_empty(temp = HTParse(*href, "", PARSE_ALL)))
+    temp = HTParse(*href, "", PARSE_ALL);
+    if (non_empty(temp))
 	StrAllocCopy(*href, temp);
     FREE(temp);
 }
@@ -6585,6 +6666,28 @@ PUBLIC void LYLocalFileToURL ARGS2(
     StrAllocCat(*target, leaf);
 }
 
+/*
+ * Open a temporary file for internal-pages, optionally reusing an existing
+ * filename.
+ */
+PUBLIC FILE *InternalPageFP ARGS2(
+	char *, filename,
+	int,	reuse_flag)
+{
+    FILE *fp;
+
+    if (LYReuseTempfiles && reuse_flag) {
+	fp = LYOpenTempRewrite(filename, HTML_SUFFIX, BIN_W);
+    } else {
+	LYRemoveTemp(filename);
+	fp = LYOpenTemp(filename, HTML_SUFFIX, BIN_W);
+    }
+    if (fp == NULL) {
+	HTAlert(CANNOT_OPEN_TEMP);
+    }
+    return fp;
+}
+
 PUBLIC void BeginInternalPage ARGS3(
 	FILE *, fp0,
 	char*, Title,
diff --git a/src/LYUtils.h b/src/LYUtils.h
index e1be5c52..9e1ee115 100644
--- a/src/LYUtils.h
+++ b/src/LYUtils.h
@@ -119,7 +119,9 @@ extern BOOLEAN LYisLocalHost PARAMS((char *filename));
 extern BOOLEAN LYisRootPath PARAMS((char *path));
 extern BOOLEAN inlocaldomain NOPARAMS;
 extern CONST char *Home_Dir NOPARAMS;
-extern CONST char *index_to_restriction PARAMS(( int	inx));
+extern CONST char *index_to_restriction PARAMS((int inx));
+extern CONST char *wwwName PARAMS((CONST char *pathname));
+extern FILE *InternalPageFP PARAMS((char * filename, int reuse_flag));
 extern FILE *LYAppendToTxtFile PARAMS((char * name));
 extern FILE *LYNewBinFile PARAMS((char * name));
 extern FILE *LYNewTxtFile PARAMS((char * name));
@@ -136,7 +138,6 @@ extern char *LYSysShell NOPARAMS;
 extern char *LYgetXDisplay NOPARAMS;
 extern char *strip_trailing_slash PARAMS((char * my_dirname));
 extern char *trimPoundSelector PARAMS((char * address));
-extern CONST char *wwwName PARAMS((CONST char *pathname));
 extern int HTCheckForInterrupt NOPARAMS;
 extern int LYCheckForProxyURL PARAMS((char *filename));
 extern int LYConsoleInputFD PARAMS((BOOLEAN need_selectable));