1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-11-04 08:17:17 -05:00
elinks/src/session/history.c
2007-07-27 09:55:40 +03:00

194 lines
3.7 KiB
C

/** Visited URL history managment - NOT dialog_goto_url() history!
* @file */
#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
free_history(LIST_OF(struct location) *history)
{
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);
}
/** Go backward in the history. 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);
}
/** Go forward in the history. 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);
}