diff -pru dillo.orig/dillorc dillo.cache.new/dillorc
--- dillo.orig/dillorc	Thu May 30 12:50:07 2002
+++ dillo.cache.new/dillorc	Sat Jun  1 22:06:00 2002
@@ -3,18 +3,21 @@
 # Copy this file to ~/.dillo/dillorc and edit to your tastes.
 # Lines that start with a '#' are comments.
 
-
 #-------------------------------------------------------------------------
-#                             FIRST SECTION                             :)
+#                           MEMORY SECTION
 #-------------------------------------------------------------------------
 
-# Set the desired initial browser size
-geometry=640x550
-
 # Dicache is where the Decompressed Images are cached (not the original ones).
 # If you have a lot of memory and a slow CPU, use YES, otherwise use NO
 use_dicache=NO
 
+# Set the desired size for cache. Dillo will _try_ to keep at most
+# `cache_size' bytes of data in _memory_ cache, this does not mean Dillo
+# will only this much memory to run. In bytes. Default is 5242880 (5 MiB).
+# To disable to use of cache use the value '00'.
+#cache_size=3145728
+#cache_size=00
+cache_size=5242880
 
 #-------------------------------------------------------------------------
 #                           RENDERING SECTION
@@ -91,6 +94,9 @@ force_visited_color=YES
 #-------------------------------------------------------------------------
 #                        USER INTERFACE SECTION
 #-------------------------------------------------------------------------
+
+# Set the desired initial browser size
+geometry=640x550
 
 # Size of dillo panel (used to enlarge the browsing area)
 # tiny   :  recommended for iPAQ (with small_icons)
diff -pru dillo.orig/src/IO/about.c dillo.cache.new/src/IO/about.c
--- dillo.orig/src/IO/about.c	Thu May 30 21:37:04 2002
+++ dillo.cache.new/src/IO/about.c	Sat Jun  1 21:48:01 2002
@@ -117,7 +117,7 @@ and chances are you'll not be disappoint
 /*
  * Send the splash screen through the IO using a pipe.
  */
-static void About_send_splash(ChainLink *Info, DilloUrl *Url)
+static void About_send(ChainLink *Info, DilloUrl *Url, char *data)
 {
    void *link;
    gint SplashPipe[2];
@@ -134,9 +134,9 @@ static void About_send_splash(ChainLink 
    /* send splash */
    io1 = a_IO_new(SpInfo->FD_Write);
    io1->Op = IOWrite;
-   io1->IOVec.iov_base = Splash;
-   io1->IOVec.iov_len  = strlen(Splash);
-   io1->Flags |= IOFlag_ForceClose;
+   io1->IOVec.iov_base = data;
+   io1->IOVec.iov_len  = strlen(data);
+   io1->Flags |= IOFlag_ForceClose | IOFlag_FreeIOVec;
    io1->ExtData = NULL;
    link = a_Chain_link_new(a_About_ccc, Info, CCC_FWD, a_IO_ccc);
    a_IO_ccc(OpStart, 1, link, io1, NULL);
@@ -166,7 +166,16 @@ static gint About_get(ChainLink *Info, v
    tail = URL_PATH(Url);
 
    if (!strcmp(tail, "splash")) {
-      About_send_splash(Info, Url);
+      About_send(Info, Url, g_strdup(Splash));
+      return 1;
+   }
+   if (!strcmp(tail, "cache")) {
+      About_send(Info, Url, a_Cache_list_entries());
+      return 1;
+   }
+   if (!strcmp(tail, "cache-clear")) {
+      a_Cache_clear();
+      About_send(Info, Url, a_Cache_list_entries());
       return 1;
    }
    if (!strcmp(tail, "jwz"))
diff -pru dillo.orig/src/cache.c dillo.cache.new/src/cache.c
--- dillo.orig/src/cache.c	Wed Apr 10 21:10:36 2002
+++ dillo.cache.new/src/cache.c	Sat Jun  1 21:46:08 2002
@@ -31,6 +31,8 @@
 #include "interface.h"
 #include "nav.h"
 #include "cookies.h"
+#include "prefs.h"
+#include "history.h"
 
 #define NULLKey 0
 
@@ -62,6 +64,9 @@ typedef struct {
  */
 /* A hash for cached data. Holds pointers to CacheData_t structs */
 static GHashTable *CacheHash = NULL;
+static GList *CacheLRU = NULL;
+static gint cache_size_total; /* invariant: cache_size_total is the sum of 
+                               * the memory used by cached data */
 
 /* A list for cache clients.
  * Although implemented as a list, we'll call it ClientQueue  --Jcid */
@@ -219,6 +224,7 @@ static CacheData_t *Cache_entry_add(cons
 
    Cache_entry_init(new_entry, Url);  /* Set safe values */
    g_hash_table_insert(CacheHash, (gpointer)new_entry->Url, new_entry);
+   CacheLRU = g_list_prepend(CacheLRU, new_entry);
    return new_entry;
 }
 
@@ -237,6 +243,8 @@ static CacheData_t *Cache_entry_search(c
  */
 static void Cache_entry_free(CacheData_t *entry)
 {
+   cache_size_total -= entry->TotalSize;
+   CacheLRU = g_list_remove(CacheLRU, entry);   
    a_Url_free((DilloUrl *)entry->Url);
    g_free((gchar *)entry->Type);
    g_string_free(entry->Header, TRUE);
@@ -259,7 +267,7 @@ static gint Cache_entry_remove_raw(Cache
       !g_slist_find_custom(ClientQueue, url, Cache_client_url_cmp), 0);
 
    /* remove from dicache */
-   a_Dicache_invalidate_entry(url);
+   a_Dicache_invalidate_entry(entry->Url);
 
    /* remove from cache */
    g_hash_table_remove(CacheHash, entry->Url);
@@ -293,10 +301,85 @@ static void Cache_entry_remove(CacheData
    }
 }
 
+/*
+ * "Touch" this entry, i.e. reorder this entry to the beginning of the list.
+ */
+static void Cache_LRU_touch_entry(CacheData_t *entry)
+{
+   CacheLRU = g_list_remove(CacheLRU, entry);
+   CacheLRU = g_list_prepend(CacheLRU, entry);
+}
+
+char *a_Cache_list_entries(void)
+{
+   gchar *data, *line, *tmp;
+   GList *list_entry;
+   gint i = 1;
+
+   data = g_strdup_printf("
+Content-type: text/html
+
+<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">
+<html>
+<head>
+<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">
+</head>
+
+<body  bgcolor=\"white\">
+
+<h1>Dillo's Cache</h1>
+
+This page lists current cache usage inside Dillo. Since this is a LRU queue,
+the most  recently accessed URLs are at the top, and the least recently used
+are at the bottom, subject to removal.
+<p>
+Number of items in cache: <b>%d</b> <br>
+Current cache size: <b>%d bytes</b> <br>
+Maximum specified size (in dillorc): <b>%d bytes</b> <br>
+<p>
+<center>
+If you'd like to <b>clear the cache</b>, please click 
+<a href=\"about:cache-clear\">here</a>.
+<p>
+<table WIDTH=\"90%%\" BORDER=2 CELLSPACING=0 CELLPADDING=2>
+<tr><td>Number</td><td> URL </td><td>Size (in bytes)</td>", 
+   g_list_length(CacheLRU), cache_size_total, prefs.cache_size);
+
+   list_entry = g_list_first(CacheLRU);
+   while (list_entry) {
+      line = g_strdup_printf("<tr><td>%d</td><td>%s</td><td>%d</td>\n", i++,
+			     URL_STR(((CacheData_t *)list_entry->data)->Url),
+			     ((CacheData_t *)list_entry->data)->TotalSize);
+      tmp = data;
+      data = g_strconcat(data, line, NULL);
+      g_free(tmp);
+      list_entry = g_list_next(list_entry);
+   }
+
+   tmp = data;
+   data = g_strconcat(data, "</table>\n</center>\n\n</body>\n</html>\n", NULL);
+   g_free(tmp);
+
+   return data;
+}
 
 /* Misc. operations ------------------------------------------------------- */
 
 /*
+ * Determine if any browser window is viewing this URL
+ */
+static gboolean Cache_browser_window_search(const DilloUrl *url)
+{
+   gint i;
+
+   for (i = 0; i < num_bw; i++)
+      if ( a_Nav_stack_ptr(browser_window[i]) != -1 )
+	 if (!a_Url_cmp(a_History_get_url(NAV_TOP(browser_window[i])), url))
+	    return TRUE;
+   return FALSE;
+}
+
+/*
  * Given an entry (url), remove all its clients (by url or host).
  */
 static void Cache_stop_clients(DilloUrl *url, gint ByHost)
@@ -373,6 +456,7 @@ static gint Cache_open_url(DilloWeb *Web
    } else {
       /* Feed our client with cached data */
       ClientKey = Cache_client_enqueue(entry->Url, Web, Call, CbData);
+      Cache_LRU_touch_entry(entry);
       Cache_delayed_process_queue(entry);
    }
    return ClientKey;
@@ -705,6 +789,7 @@ static void Cache_process_io(int Op, voi
 
    /* Keep track of this entry's io */
    entry->io = io;
+   cache_size_total += io->Status;
 
    if ( Op == IOClose ) {
       if (entry->Flags & CA_GotLength && entry->TotalSize != entry->ValidSize){
@@ -731,7 +816,8 @@ static void Cache_process_io(int Op, voi
       /* Haven't got the whole header yet */
       len = Cache_get_header(io, entry);
       if ( entry->Flags & CA_GotHeader ) {
-         /* Let's scan, allocate, and set things according to header info */
+         cache_size_total -= len;
+	 /* Let's scan, allocate, and set things according to header info */
          Cache_parse_header(entry, io, len);
          /* Now that we have it parsed, let's update our clients */
          Cache_process_queue(entry);
@@ -880,6 +966,20 @@ static void Cache_process_queue(CacheDat
       }
    } /* for */
 
+   /* Oops, we have to free some entries */
+   if (cache_size_total > prefs.cache_size) {
+      GList *list_entry = g_list_last(CacheLRU);
+      
+      while (cache_size_total > prefs.cache_size && list_entry) {
+	 CacheData_t *free_entry = (CacheData_t *)list_entry->data;
+	 if (!Cache_browser_window_search(free_entry->Url) &&
+	     !g_slist_find_custom(ClientQueue, (gpointer)free_entry->Url,
+				     Cache_client_url_cmp))
+	    Cache_entry_remove(free_entry, NULL);
+	 list_entry = g_list_previous(list_entry);
+      }
+   }
+   
    Busy = FALSE;
    DEBUG_MSG(1, "QueueSize ====> %d\n", g_slist_length(ClientQueue));
 }
@@ -1076,6 +1176,23 @@ Cache_remove_hash_entry(gpointer key, gp
    return TRUE;
 }
 
+static gboolean
+Cache_remove_hash_free_entry(gpointer key, gpointer value, gpointer user_data)
+{
+   if (!Cache_browser_window_search(((CacheData_t *)value)->Url) &&
+       !g_slist_find_custom(ClientQueue, (gpointer)((CacheData_t *)value)->Url,
+			    Cache_client_url_cmp)) {
+      Cache_entry_free((CacheData_t *)value);
+      return TRUE;
+   }
+   return FALSE;
+}
+
+void a_Cache_clear(void)
+{
+   g_hash_table_foreach_remove(CacheHash,
+			       (GHRFunc)Cache_remove_hash_free_entry, NULL);
+}
 
 /*
  * Memory deallocator (only called at exit time)
diff -pru dillo.orig/src/cache.h dillo.cache.new/src/cache.h
--- dillo.orig/src/cache.h	Wed Feb 20 13:07:57 2002
+++ dillo.cache.new/src/cache.h	Sat Jun  1 21:22:55 2002
@@ -52,9 +52,11 @@ void a_Cache_init(void);
 gint a_Cache_open_url(void *Web, CA_Callback_t Call, void *CbData);
 char *a_Cache_url_read(const DilloUrl *url, gint *size);
 void a_Cache_freeall(void);
+void a_Cache_clear(void);
 void a_Cache_null_client(int Op, CacheClient_t *Client);
 void a_Cache_stop_client(gint Key);
 
+char *a_Cache_list_entries(void);
 
 #endif /* __CACHE_H__ */
 
diff -pru dillo.orig/src/prefs.c dillo.cache.new/src/prefs.c
--- dillo.orig/src/prefs.c	Wed Apr  3 20:20:34 2002
+++ dillo.cache.new/src/prefs.c	Sat Jun  1 12:02:15 2002
@@ -52,6 +52,7 @@ static const struct {
    { "small_icons", DRC_TOKEN_SMALL_ICONS },
    { "limit_text_width", DRC_TOKEN_LIMIT_TEXT_WIDTH },
    { "font_factor", DRC_TOKEN_FONT_FACTOR },
+   { "cache_size", DRC_TOKEN_CACHE_SIZE },
    { "use_dicache", DRC_TOKEN_USE_DICACHE },
    { "show_back", DRC_TOKEN_SHOW_BACK },
    { "show_forw", DRC_TOKEN_SHOW_FORW },
@@ -175,6 +176,9 @@ static guint Prefs_parser(GScanner *scan
    case DRC_TOKEN_LIMIT_TEXT_WIDTH:
       prefs.limit_text_width = (strcmp(scanner->value.v_string, "YES") == 0);
       break;
+   case DRC_TOKEN_CACHE_SIZE:
+     prefs.cache_size = strtol(scanner->value.v_string, NULL, 10);
+     break;
    case DRC_TOKEN_USE_DICACHE:
       prefs.use_dicache = (strcmp(scanner->value.v_string, "YES") == 0);
       break;
@@ -339,6 +343,7 @@ void a_Prefs_init(void)
    prefs.limit_text_width = FALSE;
    prefs.font_factor = 1.0;
    prefs.use_dicache = FALSE;
+   prefs.cache_size = 5242880; /* 5MiB */
    prefs.show_back=TRUE;
    prefs.show_forw=TRUE;
    prefs.show_home=TRUE;
Only in dillo.cache.new/src: prefs.c.~1.36.~
diff -pru dillo.orig/src/prefs.h dillo.cache.new/src/prefs.h
--- dillo.orig/src/prefs.h	Wed Apr  3 20:20:34 2002
+++ dillo.cache.new/src/prefs.h	Sat Jun  1 12:03:08 2002
@@ -42,6 +42,7 @@ typedef enum {
    DRC_TOKEN_FONT_FACTOR,
    DRC_TOKEN_SHOW_ALT,
    DRC_TOKEN_LIMIT_TEXT_WIDTH,
+   DRC_TOKEN_CACHE_SIZE,
    DRC_TOKEN_USE_DICACHE,
    DRC_TOKEN_SHOW_BACK,
    DRC_TOKEN_SHOW_FORW,
@@ -84,6 +85,7 @@ struct _DilloPrefs {
    gboolean small_icons;
    gboolean limit_text_width;
    gdouble font_factor;
+   gint cache_size;
    gboolean use_dicache;
    gboolean show_back;
    gboolean show_forw;

