/* $Id: session.h,v 1.89 2004/01/08 09:53:07 zas Exp $ */

#ifndef EL__SCHED_SESSION_H
#define EL__SCHED_SESSION_H

#include "bfu/leds.h"
#include "cache/cache.h"
#include "sched/connection.h"
#include "sched/history.h"
#include "util/lists.h"
#include "viewer/text/vs.h"

struct document_view;
struct link;
struct location;
struct session_status;
struct term_event;
struct terminal;
struct window;


/* This is used to pass along the initial session parameters. */
struct initial_session_info {
	/* The session whose state to copy, -1 is none. */
	int base_session;
	/* The URL we should load immediatelly (or NULL). */
	unsigned char *url;
};

/* This is generic frame descriptor, meaningful mainly for ses_*_frame*(). */
struct frame {
	LIST_HEAD(struct frame);

	unsigned char *name;
	int redirect_cnt;

	struct view_state vs; /* Must be last. */
};

/* This is the repeat count being inserted by user so far. It is stored
 * intermediately per-session. */
struct kbdprefix {
	int rep;
	int rep_num;

	/* If the previous key was a mark prefix, this describes what kind of
	 * action are we supposed to do when we receive the next key. */
	enum { KP_MARK_NOTHING, KP_MARK_SET, KP_MARK_GOTO } mark;

	/* If non NULL we are in typeahead mode and the @typeahead buffer
	 * has size MAX_STR_LEN. */
	unsigned char *typeahead;
};

struct session;

struct tq {
	LIST_HEAD(struct tq);
	struct download download;
	struct cache_entry *ce;
	struct session *ses;
	unsigned char *url;
	unsigned char *target_frame;
	unsigned char *goto_position;
	unsigned char *prog;
	int prog_flags;
	int frame;
};

/* This describes, what are we trying to do right now. We pass this around so
 * that we can use generic scheduler routines and when the control will get
 * back to our subsystem, we will know what are we up to. */
enum task_type {
	TASK_NONE,
	TASK_FORWARD,
	TASK_IMGMAP,
	TASK_RELOAD,
	TASK_HISTORY,
};

struct session_task {
	enum task_type type;
	/* TODO: union --pasky */
	unsigned char *target_frame;
	struct location *target_location;
};

struct session_status {
	unsigned int show_tabs_bar:1;
	unsigned int show_status_bar:1;
	unsigned int show_title_bar:1;

	unsigned int set_window_title:1;
	unsigned char *last_title;

#ifdef CONFIG_LEDS
	unsigned int show_leds:1;
	struct led_panel leds;
	struct led *ssl_led;
#endif
	/* Has the tab been visited yet. */
	unsigned int visited:1;
};

/* This is one of the building stones of ELinks architecture --- this structure
 * carries information about the specific ELinks session. Each tab (thus, at
 * least one per terminal, in the normal case) has own session. Session
 * describes mainly the current browsing and control state, from the currently
 * viewed document through the browsing history of this session to the status
 * bar information. */
struct session {
	LIST_HEAD(struct session);


	/* The vital session data */

	int id;

	struct window *tab;


	/* Browsing history */

	struct ses_history history;


	/* The current document */

	struct list_head more_files; /* -> struct file_to_load */

	struct download loading;
	unsigned char *loading_url;

	enum cache_mode reloadlevel;
	int redirect_cnt;

	struct document_view *doc_view;
	struct list_head scrn_frames; /* -> struct document_view */

	unsigned char *dn_url;

	unsigned char *ref_url;

	unsigned char *goto_position;

	unsigned char *imgmap_href_base;
	unsigned char *imgmap_target_base;


	/* The current action-in-progress selector */

	struct session_task task;


	/* The current browsing state */

	int search_direction;
	struct kbdprefix kbdprefix;
	int exit_query;
	int display_timer;

	unsigned char *search_word;
	unsigned char *last_search_word;


	/* The possibly running type query (what-to-do-with-that-file?) */
	struct list_head tq; /* -> struct tq */

	/* The info for status displaying */
	struct session_status status;
};

extern struct list_head sessions; /* -> struct session */

/* This returns a pointer to the current location inside of the given session.
 * That's nice for encapsulation and alrady paid out once ;-). */
#define cur_loc(x) ((x)->history.current)

/* Return if we have anything being loaded in this session already. */
static inline int
have_location(struct session *ses) {
	return !!ses->history.current;
}

/* See go_history() description regarding unpredictable effects on cur_loc()
 * by this function. */
static inline void
go_back(struct session *ses)
{
	if (!cur_loc(ses)) return;
	go_history(ses, cur_loc(ses)->prev);
}

/* See go_history() description regarding unpredictable effects on cur_loc()
 * by this function. */
static inline void
go_unback(struct session *ses)
{
	if (!cur_loc(ses)) return;
	go_history(ses, cur_loc(ses)->next);
}

#include <string.h>
#include "util/memory.h"
#include "util/string.h"

static inline void
set_referrer(struct session *ses, unsigned char *referrer)
{
	if (ses->ref_url) mem_free(ses->ref_url);

	if (referrer) {
		/* Don't set referrer for file protocol */
		referrer = strncasecmp("file:", referrer, 5)
			 ? stracpy(referrer) : NULL;
	}

	ses->ref_url = referrer;
}

void print_error_dialog(struct session *, struct download *);
void print_unknown_protocol_dialog(struct session *);

void process_file_requests(struct session *);

void *create_session_info(int, unsigned char *, int *);
struct initial_session_info *decode_session_info(const void *);
struct session *create_basic_session(struct window *);

void tabwin_func(struct window *, struct term_event *, int);

void doc_end_load(struct download *, struct session *);

void abort_loading(struct session *, int);
void reload(struct session *, enum cache_mode);
void load_frames(struct session *, struct document_view *);

struct frame *ses_find_frame(struct session *, unsigned char *);
struct frame *ses_change_frame_url(struct session *, unsigned char *, unsigned char *);

void free_files(struct session *);
void display_timer(struct session *ses);

struct download *get_current_download(struct session *ses);

/* Information about the current document */
unsigned char *get_current_url(struct session *, unsigned char *, size_t);
unsigned char *get_current_title(struct session *, unsigned char *, size_t);

struct link *get_current_link(struct session *ses);
unsigned char *get_current_link_url(struct session *, unsigned char *, size_t);
unsigned char *get_current_link_name(struct session *, unsigned char *, size_t);

extern struct list_head questions_queue;
void add_questions_entry(void *);
void check_questions_queue(struct session *ses);

unsigned char *get_homepage_url(void);

#endif
