From eda45fcd34189e6844babde1ebc60c083b1b09da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= jaakko.keranen@iki.fi
Date: Wed, 27 Jan 2021 21:28:25 +0200
Subject: [PATCH 1/1] Added preference for maximum cache size
Rather than simply limiting each tab's cache to 50 most recent URLs, there is now a user-configurable maximum size. If more content is cached, the oldest/largest responses will be removed from memory.
The default maximum cache size is 10 MB.
IssueID #109
src/app.c | 42 +++++++++++++++++++++++++++++++++++++++++-
src/app.h | 18 ++++++++++--------
src/history.c | 43 +++++++++++++++++++++++++++++++++++++++++++
src/history.h | 2 ++
src/prefs.c | 1 +
src/prefs.h | 1 +
src/ui/util.c | 19 ++++++++++++++-----
src/ui/window.c | 1 +
8 files changed, 113 insertions(+), 14 deletions(-)
diff --git a/src/app.c b/src/app.c
index 5d27618b..82628c9c 100644
--- a/src/app.c
+++ b/src/app.c
@@ -194,6 +194,7 @@ static iString *serializePrefs_App_(const iApp *d) {
appendFormat_String(str, "zoom.set arg:%d\n", d->prefs.zoomPercent);
appendFormat_String(str, "smoothscroll arg:%d\n", d->prefs.smoothScrolling);
appendFormat_String(str, "imageloadscroll arg:%d\n", d->prefs.loadImageInsteadOfScrolling);
appendFormat_String(str, "decodeurls arg:%d\n", d->prefs.decodeUserVisibleURLs);
appendFormat_String(str, "linewidth.set arg:%d\n", d->prefs.lineWidth);
appendFormat_String(str, "prefs.biglede.changed arg:%d\n", d->prefs.bigFirstParagraph);
@@ -321,6 +322,7 @@ iObjectList *listDocuments_App(void) {
static void saveState_App_(const iApp *d) {
iUnused(d);
iFile *f = newCStr_File(concatPath_CStr(dataDir_App_, stateFileName_App_));
if (open_File(f, writeOnly_FileMode)) {
writeData_File(f, magicState_App_, 4);
@@ -503,7 +505,7 @@ const iString *debugInfo_App(void) {
iString *msg = collectNew_String();
format_String(msg, "# Debug information\n");
appendFormat_String(msg, "## Documents\n");
iDocumentWidget *doc = k.object;
appendFormat_String(msg, "### Tab %zu: %s\n",
childIndex_Widget(constAs_Widget(doc)->parent, k.object),
@@ -857,6 +859,8 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) {
isSelected_Widget(findChild_Widget(d, "prefs.ostheme")));
postCommandf_App("decodeurls arg:%d",
isSelected_Widget(findChild_Widget(d, "prefs.decodeurls")));
postCommandf_App("cachesize.set arg:%d",
toInt_String(text_InputWidget(findChild_Widget(d, "prefs.cachesize"))));
postCommandf_App("proxy.gemini address:%s",
cstr_String(text_InputWidget(findChild_Widget(d, "prefs.proxy.gemini"))));
postCommandf_App("proxy.gopher address:%s",
@@ -940,6 +944,33 @@ iDocumentWidget *newTab_App(const iDocumentWidget *duplicateOf, iBool switchToNe
return doc;
}
+void trimCache_App(void) {
cacheSize += cacheSize_History(history_DocumentWidget(i.object));
iDocumentWidget *doc = i.object;
const size_t pruned = pruneLeastImportant_History(history_DocumentWidget(doc));
if (pruned) {
cacheSize -= pruned;
wasPruned = iTrue;
}
next_ObjectListIterator(&i);
if (!i.value) {
if (!wasPruned) break;
wasPruned = iFalse;
init_ObjectListIterator(&i, docs);
}
+}
static iBool handleIdentityCreationCommands_(iWidget *dlg, const char *cmd) {
iApp *d = &app_;
if (equal_Command(cmd, "ident.temp.changed")) {
@@ -1154,6 +1185,13 @@ iBool handleCommand_App(const char *cmd) {
postCommandf_App("theme.changed auto:1");
return iTrue;
}
d->prefs.maxCacheSize = arg_Command(cmd);
if (d->prefs.maxCacheSize <= 0) {
d->prefs.maxCacheSize = 0;
}
return iTrue;
else if (equal_Command(cmd, "proxy.gemini")) {
setCStr_String(&d->prefs.geminiProxy, suffixPtr_Command(cmd, "address"));
return iTrue;
@@ -1331,6 +1369,8 @@ iBool handleCommand_App(const char *cmd) {
dlg, format_CStr("prefs.saturation.%d", (int) (d->prefs.saturation * 3.99f))),
selected_WidgetFlag,
iTrue);
setText_InputWidget(findChild_Widget(dlg, "prefs.cachesize"),
collectNewFormat_String("%d", d->prefs.maxCacheSize));
setToggle_Widget(findChild_Widget(dlg, "prefs.decodeurls"), d->prefs.decodeUserVisibleURLs);
setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.gemini"), &d->prefs.geminiProxy);
setText_InputWidget(findChild_Widget(dlg, "prefs.proxy.gopher"), &d->prefs.gopherProxy);
diff --git a/src/app.h b/src/app.h
index 0e8351aa..efaf0a3e 100644
--- a/src/app.h
+++ b/src/app.h
@@ -61,20 +61,20 @@ void refresh_App (void);
iBool isRefreshPending_App (void);
uint32_t elapsedSinceLastTicker_App (void); /* milliseconds */
-const iPrefs * prefs_App (void);
-iBool forceSoftwareRender_App(void);
-enum iColorTheme colorTheme_App (void);
-const iString * schemeProxy_App (iRangecc scheme);
-iBool willUseProxy_App (const iRangecc scheme);
-iMimeHooks * mimeHooks_App (void);
iGmCerts * certs_App (void);
iVisited * visited_App (void);
iBookmarks * bookmarks_App (void);
+iMimeHooks * mimeHooks_App (void);
iDocumentWidget * document_App (void);
iObjectList * listDocuments_App (void);
-iDocumentWidget * document_Command (const char *cmd);
iDocumentWidget * newTab_App (const iDocumentWidget *duplicateOf, iBool switchToNew);
+void trimCache_App (void);
+const iPrefs * prefs_App (void);
+iBool forceSoftwareRender_App(void);
+enum iColorTheme colorTheme_App (void);
+const iString * schemeProxy_App (iRangecc scheme);
+iBool willUseProxy_App (const iRangecc scheme);
typedef void (*iTickerFunc)(iAny *);
@@ -91,5 +91,7 @@ iLocalDef void postCommandString_App(const iString *command) {
}
}
+iDocumentWidget * document_Command (const char *cmd);
void openInDefaultBrowser_App (const iString *url);
void revealPath_App (const iString *path);
diff --git a/src/history.c b/src/history.c
index 202549a9..59d515dc 100644
--- a/src/history.c
+++ b/src/history.c
@@ -27,6 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
#include <the_Foundation/mutex.h>
#include <the_Foundation/path.h>
#include <the_Foundation/stringset.h>
+#include <math.h>
static const size_t maxStack_History_ = 50; /* back/forward navigable items */
@@ -285,6 +286,48 @@ void setCachedResponse_History(iHistory *d, const iGmResponse *response) {
unlock_Mutex(d->mtx);
}
+size_t cacheSize_History(const iHistory *d) {
const iRecentUrl *url = i.value;
if (url->cachedResponse) {
cached += size_Block(&url->cachedResponse->body);
}
+}
+size_t pruneLeastImportant_History(iHistory *d) {
const iRecentUrl *url = i.value;
if (url->cachedResponse) {
const double urlScore =
size_Block(&url->cachedResponse->body) *
pow(secondsSince_Time(&now, &url->cachedResponse->when) / 60.0, 1.25);
if (urlScore > score) {
chosen = index_ArrayConstIterator(&i);
score = urlScore;
}
}
iRecentUrl *url = at_Array(&d->recent, chosen);
delta = size_Block(&url->cachedResponse->body);
delete_GmResponse(url->cachedResponse);
url->cachedResponse = NULL;
+}
const iStringArray *searchContents_History(const iHistory *d, const iRegExp *pattern) {
iStringArray *urls = iClob(new_StringArray());
lock_Mutex(d->mtx);
diff --git a/src/history.h b/src/history.h
index 4c6507e3..7c2684f1 100644
--- a/src/history.h
+++ b/src/history.h
@@ -56,6 +56,7 @@ iBool goForward_History (iHistory *);
iRecentUrl *recentUrl_History (iHistory *, size_t pos);
iRecentUrl *mostRecentUrl_History (iHistory *);
iRecentUrl *findUrl_History (iHistory *, const iString *url);
+size_t pruneLeastImportant_History (iHistory *);
const iStringArray * searchContents_History (const iHistory *, const iRegExp pattern); / chronologically ascending */
@@ -67,6 +68,7 @@ const iRecentUrl *
constMostRecentUrl_History (const iHistory *);
const iGmResponse *
cachedResponse_History (const iHistory *);
+size_t cacheSize_History (const iHistory *);
iString * debugInfo_History (const iHistory *);
diff --git a/src/prefs.c b/src/prefs.c
index 188938a2..ce32962b 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -34,6 +34,7 @@ void init_Prefs(iPrefs *d) {
d->smoothScrolling = iTrue;
d->loadImageInsteadOfScrolling = iFalse;
d->decodeUserVisibleURLs = iTrue;
d->font = nunito_TextFont;
d->headingFont = nunito_TextFont;
d->monospaceGemini = iFalse;
diff --git a/src/prefs.h b/src/prefs.h
index 07298eac..1c3274d9 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -49,6 +49,7 @@ struct Impl_Prefs {
iBool loadImageInsteadOfScrolling;
/* Network */
iBool decodeUserVisibleURLs;
iString geminiProxy;
iString gopherProxy;
iString httpProxy;
diff --git a/src/ui/util.c b/src/ui/util.c
index 7fc27130..91945db8 100644
--- a/src/ui/util.c
+++ b/src/ui/util.c
@@ -1090,7 +1090,7 @@ iWidget *makePreferences_Widget(void) {
}
/* Colors. */ {
appendTwoColumnPage_(tabs, "Colors", '3', &headings, &values);
makeTwoColumnHeading_("PAGE CONTENTS", headings, values);
makeTwoColumnHeading_("PAGE CONTENT", headings, values);
for (int i = 0; i < 2; ++i) {
const iBool isDark = (i == 0);
const char *mode = isDark ? "dark" : "light";
@@ -1121,6 +1121,7 @@ iWidget *makePreferences_Widget(void) {
}
/* Layout. */ {
appendTwoColumnPage_(tabs, "Style", '4', &headings, &values);
makeTwoColumnHeading_("FONTS", headings, values);
/* Fonts. */ {
iWidget *fonts;
addChild_Widget(headings, iClob(makeHeading_Widget("Heading font:")));
@@ -1140,8 +1141,7 @@ iWidget *makePreferences_Widget(void) {
addChild_Widget(mono, iClob(makeToggle_Widget("prefs.mono.gopher"))), "Gopher");
addChildFlags_Widget(values, iClob(mono), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag);
}
addChild_Widget(headings, iClob(makePadding_Widget(2 * gap_UI)));
addChild_Widget(values, iClob(makePadding_Widget(2 * gap_UI)));
makeTwoColumnHeading_("PARAGRAPH", headings, values);
addChild_Widget(headings, iClob(makeHeading_Widget("Line width:")));
iWidget *widths = new_Widget();
/* Line widths. */ {
@@ -1162,10 +1162,19 @@ iWidget *makePreferences_Widget(void) {
addChild_Widget(headings, iClob(makeHeading_Widget("Big 1st paragaph:")));
addChild_Widget(values, iClob(makeToggle_Widget("prefs.biglede")));
}
appendTwoColumnPage_(tabs, "Network", '5', &headings, &values);
addChild_Widget(headings, iClob(makeHeading_Widget("Decode paths:")));
addChild_Widget(headings, iClob(makeHeading_Widget("Cache size:")));
iWidget *cacheGroup = new_Widget(); {
iInputWidget *cache = new_InputWidget(4);
setSelectAllOnFocus_InputWidget(cache, iTrue);
setId_Widget(addChild_Widget(cacheGroup, iClob(cache)), "prefs.cachesize");
addChildFlags_Widget(cacheGroup, iClob(new_LabelWidget("MB", NULL)), frameless_WidgetFlag);
}
addChildFlags_Widget(values, iClob(cacheGroup), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag);
addChild_Widget(headings, iClob(makeHeading_Widget("Decode URLs:")));
addChild_Widget(values, iClob(makeToggle_Widget("prefs.decodeurls")));
makeTwoColumnHeading_("PROXIES", headings, values);
addChild_Widget(headings, iClob(makeHeading_Widget("Gemini proxy:")));
setId_Widget(addChild_Widget(values, iClob(new_InputWidget(0))), "prefs.proxy.gemini");
addChild_Widget(headings, iClob(makeHeading_Widget("Gopher proxy:")));
diff --git a/src/ui/window.c b/src/ui/window.c
index 2e38512b..66994e79 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -397,6 +397,7 @@ static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) {
if (equal_Command(cmd, "document.changed")) {
iInputWidget *url = findWidget_App("url");
const iString *urlStr = collect_String(suffix_Command(cmd, "url"));
trimCache_App();
visitUrl_Visited(visited_App(), urlStr, 0);
postCommand_App("visited.changed"); /* sidebar will update */
setText_InputWidget(url, urlStr);
--
2.25.1
text/plain
This content has been proxied by September (3851b).