From 90c944ac0ca82ece56d61bfa6274c31decc95358 Mon Sep 17 00:00:00 2001 From: Jaakko Keränen Date: Thu, 6 Aug 2020 14:40:08 +0300 Subject: Fetch content from cache when navigating back --- src/history.c | 272 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 151 insertions(+), 121 deletions(-) (limited to 'src/history.c') diff --git a/src/history.c b/src/history.c index de0c36ca..a2c4271f 100644 --- a/src/history.c +++ b/src/history.c @@ -8,136 +8,165 @@ static const size_t maxStack_History_ = 50; /* back/forward navigable items */ static const size_t maxAgeVisited_History_ = 3600 * 24 * 30; /* one month */ -void init_HistoryItem(iHistoryItem *d) { - initCurrent_Time(&d->when); +void init_RecentUrl(iRecentUrl *d) { init_String(&d->url); d->scrollY = 0; + d->cachedResponse = NULL; } -void deinit_HistoryItem(iHistoryItem *d) { +void deinit_RecentUrl(iRecentUrl *d) { deinit_String(&d->url); + delete_GmResponse(d->cachedResponse); } -struct Impl_History { - iArray stack; /* TODO: should be specific to a DocumentWidget */ - size_t stackPos; /* zero at the latest item */ - iSortedArray visitedUrls; -}; +void init_VisitedUrl(iVisitedUrl *d) { + initCurrent_Time(&d->when); + init_String(&d->url); +} -iDefineTypeConstruction(History) +void deinit_VisitedUrl(iVisitedUrl *d) { + deinit_String(&d->url); +} -static int cmpUrl_HistoryItem_(const void *a, const void *b) { - return cmpString_String(&((const iHistoryItem *) a)->url, &((const iHistoryItem *) b)->url); +static int cmpUrl_VisitedUrl_(const void *a, const void *b) { + return cmpString_String(&((const iVisitedUrl *) a)->url, &((const iVisitedUrl *) b)->url); } -static int cmpNewer_HistoryItem_(const void *insert, const void *existing) { - return seconds_Time(&((const iHistoryItem *) insert )->when) > - seconds_Time(&((const iHistoryItem *) existing)->when); +static int cmpNewer_VisitedUrl_(const void *insert, const void *existing) { + return seconds_Time(&((const iVisitedUrl *) insert )->when) > + seconds_Time(&((const iVisitedUrl *) existing)->when); } +/*----------------------------------------------------------------------------------------------*/ + +struct Impl_History { + iArray recent; /* TODO: should be specific to a DocumentWidget */ + size_t recentPos; /* zero at the latest item */ + iSortedArray visited; +}; + +iDefineTypeConstruction(History) + void init_History(iHistory *d) { - init_Array(&d->stack, sizeof(iHistoryItem)); - d->stackPos = 0; - init_SortedArray(&d->visitedUrls, sizeof(iHistoryItem), cmpUrl_HistoryItem_); + init_Array(&d->recent, sizeof(iRecentUrl)); + d->recentPos = 0; + init_SortedArray(&d->visited, sizeof(iVisitedUrl), cmpUrl_VisitedUrl_); } void deinit_History(iHistory *d) { clear_History(d); - deinit_Array(&d->stack); -} - -static void writeItems_(const iArray *items, iFile *f) { - iString *line = new_String(); - iConstForEach(Array, i, items) { - const iHistoryItem *item = i.value; - iDate date; - init_Date(&date, &item->when); - format_String(line, - "%04d-%02d-%02dT%02d:%02d:%02d %04x %s\n", - date.year, - date.month, - date.day, - date.hour, - date.minute, - date.second, - item->scrollY, - cstr_String(&item->url)); - writeData_File(f, cstr_String(line), size_String(line)); - } - delete_String(line); + deinit_Array(&d->recent); + deinit_SortedArray(&d->visited); } void save_History(const iHistory *d, const char *dirPath) { + iString *line = new_String(); iFile *f = newCStr_File(concatPath_CStr(dirPath, "recent.txt")); if (open_File(f, writeOnly_FileMode | text_FileMode)) { - writeItems_(&d->stack, f); + iConstForEach(Array, i, &d->recent) { + const iRecentUrl *item = i.value; + format_String(line, "%04x %s\n", item->scrollY, cstr_String(&item->url)); + writeData_File(f, cstr_String(line), size_String(line)); + } } iRelease(f); f = newCStr_File(concatPath_CStr(dirPath, "visited.txt")); if (open_File(f, writeOnly_FileMode | text_FileMode)) { - writeItems_(&d->visitedUrls.values, f); - } - iRelease(f); -} - -static void loadItems_(iArray *items, iFile *f, double maxAge) { - const iRangecc src = range_Block(collect_Block(readAll_File(f))); - iRangecc line = iNullRange; - iTime now; - initCurrent_Time(&now); - while (nextSplit_Rangecc(&src, "\n", &line)) { - int y, m, D, H, M, S, scroll = 0; - sscanf(line.start, "%04d-%02d-%02dT%02d:%02d:%02d %04x", &y, &m, &D, &H, &M, &S, &scroll); - if (!y) break; - iHistoryItem item; - init_HistoryItem(&item); - item.scrollY = scroll; - init_Time( - &item.when, - &(iDate){ .year = y, .month = m, .day = D, .hour = H, .minute = M, .second = S }); - if (maxAge > 0.0 && secondsSince_Time(&now, &item.when) > maxAge) { - continue; /* Too old. */ + iConstForEach(Array, i, &d->visited.values) { + const iVisitedUrl *item = i.value; + iDate date; + init_Date(&date, &item->when); + format_String(line, + "%04d-%02d-%02dT%02d:%02d:%02d %s\n", + date.year, + date.month, + date.day, + date.hour, + date.minute, + date.second, + cstr_String(&item->url)); + writeData_File(f, cstr_String(line), size_String(line)); } - initRange_String(&item.url, (iRangecc){ line.start + 25, line.end }); - pushBack_Array(items, &item); } + iRelease(f); + delete_String(line); } void load_History(iHistory *d, const char *dirPath) { iFile *f = newCStr_File(concatPath_CStr(dirPath, "recent.txt")); if (open_File(f, readOnly_FileMode | text_FileMode)) { - loadItems_(&d->stack, f, 0); + const iRangecc src = range_Block(collect_Block(readAll_File(f))); + iRangecc line = iNullRange; + while (nextSplit_Rangecc(&src, "\n", &line)) { + iRangecc nonwhite = line; + trim_Rangecc(&nonwhite); + if (isEmpty_Range(&nonwhite)) continue; + int scroll = 0; + sscanf(nonwhite.start, "%04x", &scroll); + iRecentUrl item; + init_RecentUrl(&item); + item.scrollY = scroll; + initRange_String(&item.url, (iRangecc){ nonwhite.start + 5, nonwhite.end }); + pushBack_Array(&d->recent, &item); + } } iRelease(f); f = newCStr_File(concatPath_CStr(dirPath, "visited.txt")); if (open_File(f, readOnly_FileMode | text_FileMode)) { - loadItems_(&d->visitedUrls.values, f, maxAgeVisited_History_); + const iRangecc src = range_Block(collect_Block(readAll_File(f))); + iRangecc line = iNullRange; + iTime now; + initCurrent_Time(&now); + while (nextSplit_Rangecc(&src, "\n", &line)) { + int y, m, D, H, M, S; + sscanf(line.start, "%04d-%02d-%02dT%02d:%02d:%02d ", &y, &m, &D, &H, &M, &S); + if (!y) break; + iVisitedUrl item; + init_VisitedUrl(&item); + init_Time( + &item.when, + &(iDate){ .year = y, .month = m, .day = D, .hour = H, .minute = M, .second = S }); + if (secondsSince_Time(&now, &item.when) > maxAgeVisited_History_) { + continue; /* Too old. */ + } + initRange_String(&item.url, (iRangecc){ line.start + 20, line.end }); + insert_SortedArray(&d->visited, &item); + } } iRelease(f); } void clear_History(iHistory *d) { - iForEach(Array, s, &d->stack) { - deinit_HistoryItem(s.value); + iForEach(Array, s, &d->recent) { + deinit_RecentUrl(s.value); } - clear_Array(&d->stack); - iForEach(Array, v, &d->visitedUrls.values) { - deinit_HistoryItem(v.value); + clear_Array(&d->recent); + iForEach(Array, v, &d->visited.values) { + deinit_VisitedUrl(v.value); } - clear_SortedArray(&d->visitedUrls); + clear_SortedArray(&d->visited); } -iHistoryItem *itemAtPos_History(iHistory *d, size_t pos) { - if (isEmpty_Array(&d->stack)) return NULL; - return &value_Array(&d->stack, size_Array(&d->stack) - 1 - pos, iHistoryItem); +iRecentUrl *recentUrl_History(iHistory *d, size_t pos) { + if (isEmpty_Array(&d->recent)) return NULL; + return &value_Array(&d->recent, size_Array(&d->recent) - 1 - pos, iRecentUrl); } -iHistoryItem *item_History(iHistory *d) { - return itemAtPos_History(d, d->stackPos); +const iRecentUrl *constRecentUrl_History(const iHistory *d, size_t pos) { + if (isEmpty_Array(&d->recent)) return NULL; + return &constValue_Array(&d->recent, size_Array(&d->recent) - 1 - pos, iRecentUrl); } -const iString *url_History(iHistory *d, size_t pos) { - const iHistoryItem *item = itemAtPos_History(d, pos); +iRecentUrl *mostRecentUrl_History(iHistory *d) { + return recentUrl_History(d, d->recentPos); +} + +const iRecentUrl *constMostRecentUrl_History(const iHistory *d) { + return constRecentUrl_History(d, d->recentPos); +} + +const iString *url_History(const iHistory *d, size_t pos) { + const iRecentUrl *item = constRecentUrl_History(d, pos); if (item) { return &item->url; } @@ -145,24 +174,24 @@ const iString *url_History(iHistory *d, size_t pos) { } static void addVisited_History_(iHistory *d, const iString *url) { - iHistoryItem visit; - init_HistoryItem(&visit); + iVisitedUrl visit; + init_VisitedUrl(&visit); set_String(&visit.url, url); size_t pos; - if (locate_SortedArray(&d->visitedUrls, &visit, &pos)) { - iHistoryItem *old = at_SortedArray(&d->visitedUrls, pos); - if (cmpNewer_HistoryItem_(&visit, old)) { + if (locate_SortedArray(&d->visited, &visit, &pos)) { + iVisitedUrl *old = at_SortedArray(&d->visited, pos); + if (cmpNewer_VisitedUrl_(&visit, old)) { old->when = visit.when; - deinit_HistoryItem(&visit); + deinit_VisitedUrl(&visit); return; } } - insert_SortedArray(&d->visitedUrls, &visit); + insert_SortedArray(&d->visited, &visit); } void replace_History(iHistory *d, const iString *url) { /* Update in the history. */ - iHistoryItem *item = item_History(d); + iRecentUrl *item = mostRecentUrl_History(d); if (item) { set_String(&item->url, url); } @@ -171,24 +200,24 @@ void replace_History(iHistory *d, const iString *url) { void addUrl_History(iHistory *d, const iString *url ){ /* Cut the trailing history items. */ - if (d->stackPos > 0) { - for (size_t i = 0; i < d->stackPos - 1; i++) { - deinit_HistoryItem(itemAtPos_History(d, i)); + if (d->recentPos > 0) { + for (size_t i = 0; i < d->recentPos - 1; i++) { + deinit_RecentUrl(recentUrl_History(d, i)); } - removeN_Array(&d->stack, size_Array(&d->stack) - d->stackPos, iInvalidSize); - d->stackPos = 0; + removeN_Array(&d->recent, size_Array(&d->recent) - d->recentPos, iInvalidSize); + d->recentPos = 0; } /* Insert new item. */ - const iHistoryItem *lastItem = itemAtPos_History(d, 0); + const iRecentUrl *lastItem = recentUrl_History(d, 0); if (!lastItem || cmpString_String(&lastItem->url, url) != 0) { - iHistoryItem item; - init_HistoryItem(&item); + iRecentUrl item; + init_RecentUrl(&item); set_String(&item.url, url); - pushBack_Array(&d->stack, &item); + pushBack_Array(&d->recent, &item); /* Limit the number of items. */ - if (size_Array(&d->stack) > maxStack_History_) { - deinit_HistoryItem(front_Array(&d->stack)); - remove_Array(&d->stack, 0); + if (size_Array(&d->recent) > maxStack_History_) { + deinit_RecentUrl(front_Array(&d->recent)); + remove_Array(&d->recent, 0); } } addVisited_History_(d, url); @@ -199,48 +228,49 @@ void visitUrl_History(iHistory *d, const iString *url) { } iBool goBack_History(iHistory *d) { - if (d->stackPos < size_Array(&d->stack) - 1) { - d->stackPos++; + if (d->recentPos < size_Array(&d->recent) - 1) { + d->recentPos++; postCommandf_App("open history:1 scroll:%d url:%s", - item_History(d)->scrollY, - cstr_String(url_History(d, d->stackPos))); + mostRecentUrl_History(d)->scrollY, + cstr_String(url_History(d, d->recentPos))); return iTrue; } return iFalse; } iBool goForward_History(iHistory *d) { - if (d->stackPos > 0) { - d->stackPos--; - postCommandf_App("open history:1 url:%s", cstr_String(url_History(d, d->stackPos))); + if (d->recentPos > 0) { + d->recentPos--; + postCommandf_App("open history:1 url:%s", cstr_String(url_History(d, d->recentPos))); return iTrue; } return iFalse; } iTime urlVisitTime_History(const iHistory *d, const iString *url) { - iHistoryItem item; + iVisitedUrl item; size_t pos; iZap(item); initCopy_String(&item.url, url); - if (locate_SortedArray(&d->visitedUrls, &item, &pos)) { - item.when = ((const iHistoryItem *) constAt_SortedArray(&d->visitedUrls, pos))->when; + if (locate_SortedArray(&d->visited, &item, &pos)) { + item.when = ((const iVisitedUrl *) constAt_SortedArray(&d->visited, pos))->when; } deinit_String(&item.url); return item.when; } -void print_History(const iHistory *d) { - iUnused(d); -#if 0 - iConstForEach(Array, i, &d->history) { - const size_t idx = index_ArrayConstIterator(&i); - printf("%s[%zu]: %s\n", - d->historyPos == size_Array(&d->history) - idx - 1 ? "->" : " ", - idx, - cstr_String(&((const iHistoryItem *) i.value)->url)); - } - fflush(stdout); -#endif +const iGmResponse *cachedResponse_History(const iHistory *d) { + const iRecentUrl *item = constMostRecentUrl_History(d); + return item ? item->cachedResponse : NULL; } +void setCachedResponse_History(iHistory *d, const iGmResponse *response) { + iRecentUrl *item = mostRecentUrl_History(d); + if (item) { + delete_GmResponse(item->cachedResponse); + item->cachedResponse = NULL; + if (category_GmStatusCode(response->statusCode) == categorySuccess_GmStatusCode) { + item->cachedResponse = copy_GmResponse(response); + } + } +} -- cgit v1.2.3