2005-09-15 09:58:31 -04:00
|
|
|
/* Visited URL history managment - NOT goto_url_dialog history! */
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "elinks.h"
|
|
|
|
|
|
|
|
#include "cache/cache.h"
|
|
|
|
#include "config/options.h"
|
|
|
|
#include "dialogs/status.h"
|
|
|
|
#include "network/connection.h"
|
|
|
|
#include "protocol/uri.h"
|
|
|
|
#include "session/history.h"
|
|
|
|
#include "session/location.h"
|
|
|
|
#include "session/session.h"
|
|
|
|
#include "session/task.h"
|
|
|
|
#include "util/memory.h"
|
|
|
|
#include "util/string.h"
|
|
|
|
#include "viewer/text/view.h"
|
|
|
|
#include "viewer/text/vs.h"
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
2007-07-26 15:39:08 -04:00
|
|
|
free_history(LIST_OF(struct location) *history)
|
2005-09-15 09:58:31 -04:00
|
|
|
{
|
|
|
|
while (!list_empty(*history)) {
|
|
|
|
struct location *loc = history->next;
|
|
|
|
|
|
|
|
del_from_list(loc);
|
|
|
|
destroy_location(loc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
create_history(struct ses_history *history)
|
|
|
|
{
|
|
|
|
init_list(history->history);
|
|
|
|
history->current = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
destroy_history(struct ses_history *history)
|
|
|
|
{
|
|
|
|
free_history(&history->history);
|
|
|
|
history->current = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
clean_unhistory(struct ses_history *history)
|
|
|
|
{
|
|
|
|
if (!history->current) return;
|
|
|
|
|
|
|
|
while (list_has_next(history->history, history->current)) {
|
|
|
|
struct location *loc = history->current->next;
|
|
|
|
|
|
|
|
del_from_list(loc);
|
|
|
|
destroy_location(loc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
add_to_history(struct ses_history *history, struct location *loc)
|
|
|
|
{
|
|
|
|
if (!history->current) {
|
|
|
|
add_to_list(history->history, loc);
|
|
|
|
} else {
|
|
|
|
add_at_pos(history->current, loc);
|
|
|
|
}
|
|
|
|
|
|
|
|
history->current = loc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
del_from_history(struct ses_history *history, struct location *loc)
|
|
|
|
{
|
|
|
|
if (history->current == loc)
|
|
|
|
history->current = loc->prev;
|
|
|
|
|
|
|
|
if (history->current == (struct location *) &history->history)
|
|
|
|
history->current = loc->next;
|
|
|
|
|
|
|
|
if (history->current == (struct location *) &history->history)
|
|
|
|
history->current = NULL;
|
|
|
|
del_from_list(loc);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ses_history_move(struct session *ses)
|
|
|
|
{
|
|
|
|
struct location *loc;
|
|
|
|
|
|
|
|
/* Prepare. */
|
|
|
|
|
|
|
|
free_files(ses);
|
|
|
|
mem_free_set(&ses->search_word, NULL);
|
|
|
|
|
|
|
|
/* Does it make sense? */
|
|
|
|
|
|
|
|
if (!have_location(ses) || !ses->task.target.location)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (ses->task.target.location
|
|
|
|
== (struct location *) &ses->history.history)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Move. */
|
|
|
|
|
|
|
|
ses->history.current = ses->task.target.location;
|
|
|
|
|
|
|
|
loc = cur_loc(ses);
|
|
|
|
|
|
|
|
/* There can be only one ... */
|
|
|
|
if (compare_uri(loc->vs.uri, ses->loading_uri, 0))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Remake that location. */
|
|
|
|
|
|
|
|
del_from_history(&ses->history, loc);
|
|
|
|
destroy_location(loc);
|
|
|
|
ses_forward(ses, 0);
|
|
|
|
|
|
|
|
/* Maybe trash the unhistory. */
|
|
|
|
|
|
|
|
if (get_opt_bool("document.history.keep_unhistory"))
|
|
|
|
clean_unhistory(&ses->history);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
go_history(struct session *ses, struct location *loc)
|
|
|
|
{
|
|
|
|
ses->reloadlevel = CACHE_MODE_NORMAL;
|
|
|
|
|
|
|
|
if (ses->task.type) {
|
|
|
|
abort_loading(ses, 0);
|
|
|
|
print_screen_status(ses);
|
|
|
|
reload(ses, CACHE_MODE_NORMAL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!have_location(ses)
|
|
|
|
|| loc == (struct location *) &ses->history.history) {
|
|
|
|
/* There's no history, at most only the current location. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
abort_loading(ses, 0);
|
|
|
|
|
|
|
|
set_session_referrer(ses, NULL);
|
|
|
|
|
|
|
|
ses_goto(ses, loc->vs.uri, NULL, loc,
|
|
|
|
CACHE_MODE_ALWAYS, TASK_HISTORY, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
go_history_by_n(struct session *ses, int n)
|
|
|
|
{
|
|
|
|
struct location *loc = cur_loc(ses);
|
|
|
|
|
|
|
|
if (!loc) return;
|
|
|
|
|
|
|
|
if (n > 0) {
|
|
|
|
while (n-- && list_has_next(ses->history.history, loc))
|
|
|
|
loc = loc->next;
|
|
|
|
} else {
|
|
|
|
while (n++ && list_has_prev(ses->history.history, loc))
|
|
|
|
loc = loc->prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
go_history(ses, loc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See go_history() description regarding unpredictable effects on cur_loc()
|
|
|
|
* by this function. */
|
|
|
|
void
|
|
|
|
go_back(struct session *ses)
|
|
|
|
{
|
|
|
|
go_history_by_n(ses, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* See go_history() description regarding unpredictable effects on cur_loc()
|
|
|
|
* by this function. */
|
|
|
|
void
|
|
|
|
go_unback(struct session *ses)
|
|
|
|
{
|
|
|
|
go_history_by_n(ses, 1);
|
|
|
|
}
|