#ifndef NEWSRAFT_H
#define NEWSRAFT_H
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <inttypes.h>
#include <time.h>
#include <wchar.h>
#include <pthread.h>
#include <sqlite3.h>
#include <expat.h>
#include <curl/curl.h>
#include "termbox2.h"

#ifndef NEWSRAFT_VERSION
#define NEWSRAFT_VERSION "0.37"
#endif

#define ISWHITESPACE(A) (((A)==' ')||((A)=='\n')||((A)=='\t')||((A)=='\v')||((A)=='\f')||((A)=='\r'))
#define ISWHITESPACEEXCEPTNEWLINE(A) (((A)==' ')||((A)=='\t')||((A)=='\v')||((A)=='\f')||((A)=='\r'))
#define ISWIDEWHITESPACE(A) (((A)==L' ')||((A)==L'\n')||((A)==L'\t')||((A)==L'\v')||((A)==L'\f')||((A)==L'\r'))
#define ISDIGIT(A) (((A)=='0')||((A)=='1')||((A)=='2')||((A)=='3')||((A)=='4')||((A)=='5')||((A)=='6')||((A)=='7')||((A)=='8')||((A)=='9'))
#define INFO(...) log_print("INFO", __VA_ARGS__)
#define WARN(...) log_print("WARN", __VA_ARGS__)
#define FAIL(...) log_print("FAIL", __VA_ARGS__)
#define info_status(...) status_write(CFG_COLOR_STATUS_INFO, __VA_ARGS__)
#define fail_status(...) status_write(CFG_COLOR_STATUS_FAIL, __VA_ARGS__)
#define LENGTH(A) ((sizeof(A))/(sizeof(*A)))
#define NEWSRAFT_MIN(A, B) (((A) < (B)) ? (A) : (B)) // Need prefix because some platforms have their own MIN definition
#define NEWSRAFT_UI(CALL) do { if (ui_is_running()) { CALL; } } while (0) // Make CALL only if UI is running
#define STRING_IS_EMPTY(A) (((A) == NULL) || ((A)->ptr == NULL) || ((A)->len == 0))
#define NEWSRAFT_ALL_BITS_SET(x, type) ((x) == (type)~(type)0)

typedef uint8_t config_entry_id;
typedef uint8_t input_id;
typedef int newsraft_video_t;
typedef struct WINDOW WINDOW;

enum {
	FEED_COLUMN_FEED_URL,
	FEED_COLUMN_TITLE,
	FEED_COLUMN_LINK,
	FEED_COLUMN_CONTENT,
	FEED_COLUMN_ATTACHMENTS,
	FEED_COLUMN_PERSONS,
	FEED_COLUMN_EXTRAS,
	FEED_COLUMN_DOWNLOAD_DATE,
	FEED_COLUMN_UPDATE_DATE,
	FEED_COLUMN_TIME_TO_LIVE,
	FEED_COLUMN_HTTP_HEADER_ETAG,
	FEED_COLUMN_HTTP_HEADER_LAST_MODIFIED,
	FEED_COLUMN_HTTP_HEADER_EXPIRES,
	FEED_COLUMN_NONE,
};

enum {
	ITEM_COLUMN_FEED_URL,
	ITEM_COLUMN_GUID,
	ITEM_COLUMN_TITLE,
	ITEM_COLUMN_LINK,
	ITEM_COLUMN_CONTENT,
	ITEM_COLUMN_ATTACHMENTS,
	ITEM_COLUMN_PERSONS,
	ITEM_COLUMN_EXTRAS,
	ITEM_COLUMN_DOWNLOAD_DATE,
	ITEM_COLUMN_PUBLICATION_DATE,
	ITEM_COLUMN_UPDATE_DATE,
	ITEM_COLUMN_UNREAD,
	ITEM_COLUMN_IMPORTANT,
	ITEM_COLUMN_NONE,
};

enum {
	SECTIONS_MENU = 0,
	FEEDS_MENU,
	ITEMS_MENU,
	PAGER_MENU,
	MENUS_COUNT,
};

enum {
	MENU_NORMAL           = 0,
	MENU_IS_EXPLORE       = 1, // Tell items menu to use explore mode
	MENU_IS_SEARCH        = 2, // Identifies items search menu
	MENU_SWALLOW          = 4, // Replace current menu with this menu
	MENU_DISABLE_SETTINGS = 8,
};

typedef enum {
	// Even is ascending, odd is descending
	SORT_BY_INITIAL_ASC = 0,
	SORT_BY_INITIAL_DESC,
	SORT_BY_TIME_ASC,
	SORT_BY_TIME_DESC,
	SORT_BY_TIME_DOWNLOAD_ASC,
	SORT_BY_TIME_DOWNLOAD_DESC,
	SORT_BY_TIME_PUBLICATION_ASC,
	SORT_BY_TIME_PUBLICATION_DESC,
	SORT_BY_TIME_UPDATE_ASC,
	SORT_BY_TIME_UPDATE_DESC,
	SORT_BY_ROWID_ASC,
	SORT_BY_ROWID_DESC,
	SORT_BY_UNREAD_ASC,
	SORT_BY_UNREAD_DESC,
	SORT_BY_ALPHABET_ASC,
	SORT_BY_ALPHABET_DESC,
	SORT_BY_IMPORTANT_ASC,
	SORT_BY_IMPORTANT_DESC,
	SORT_METHODS_COUNT,
} sorting_method_t;

typedef uint8_t render_block_format;
enum {
	TEXT_PLAIN,
	TEXT_RAW,   // Same thing as TEXT_PLAIN, but without link marks
	TEXT_HTML,
	TEXT_LINKS, // Special block type which has to be populated with links
};

enum {
	NEWSRAFT_THREAD_DOWNLOAD = 0, // Downloads the feed from the web
	NEWSRAFT_THREAD_SHRUNNER = 1, // Reads the feed from the command
	NEWSRAFT_THREAD_DBWRITER = 2, // Writes the feed to the database
};

enum {
	NEWSRAFT_HTTP_NOT_MODIFIED      = 304,
	NEWSRAFT_HTTP_TOO_MANY_REQUESTS = 429,
};

struct config_context;
struct deserialize_stream;

struct string {
	char *ptr;
	size_t len;
	size_t lim;
};

struct wstring {
	wchar_t *ptr;
	size_t len;
	size_t lim;
};

struct binding_action {
	input_id cmd;
	struct wstring *arg;
};

struct input_binding {
	struct string *key;
	struct binding_action *actions;
	size_t actions_count;
	struct input_binding *next;
};

struct feed_entry {
	struct string *url;  // feed URL specified by the user
	struct string *name;
	struct string *link; // link to webpage related to this feed
	int64_t unread_count;
	int64_t items_count;
	int64_t update_date; // date of last feed update attempt
	int64_t section_index;
	struct config_context *cfg;
	struct input_binding *binds;
	struct string *errors;
};

struct item_entry {
	struct string *guid;
	struct string *title;
	struct string *url;
	struct feed_entry **feed;
	int64_t rowid;
	bool is_unread;
	bool is_important;
	int64_t pub_date;
	int64_t upd_date;
	struct string *date_str;
	struct string *pub_date_str;
};

struct items_list {
	sqlite3_stmt *res;
	struct string *query;
	struct string *find_filter;
	struct item_entry *ptr;
	size_t len;
	bool finished;
	sorting_method_t sorting;
	struct feed_entry **feeds; // Just a pointer to parent feeds
	size_t feeds_count;
};

struct format_arg {
	wchar_t specifier;
	wchar_t type_specifier;
	union {
		int i;
		const char *s;
	} value;
};

struct menu_state {
	struct string *name;
	struct menu_state *(*run)(struct menu_state *); // Function used to start menu
	struct feed_entry **feeds_full;     // Original feeds unchanged/ordered per file
	struct feed_entry **feeds_view;     // Virtual feeds with user filtering applied
	size_t feeds_full_size;
	size_t feeds_view_size;
	struct items_list *items;
	uint64_t age;                       // Must refresh if it doesn't match global age
	uint32_t flags;
	size_t view_sel;                    // Index of the selected entry
	size_t view_min;                    // Index of the first visible entry
	size_t view_max;                    // Index of the last visible entry
	bool is_initialized;
	bool is_deleted;
	struct string *search_token;
	const struct wstring *entry_format;
	const struct wstring *find_filter;
	bool (*enumerator)(struct menu_state *ctx, size_t index); // Checks if index is valid
	void (*printer)(size_t index, WINDOW *w);                 // Prints to list entry
	struct format_arg *(*get_args)(struct menu_state *ctx, size_t index, struct format_arg *args, size_t args_size);
	struct config_color (*paint_action)(struct menu_state *ctx, size_t index, bool is_selected);
	bool (*unread_state)(struct menu_state *ctx, size_t index);
	bool (*failed_state)(struct menu_state *ctx, size_t index);
	struct menu_state *prev;
};

struct render_block {
	struct wstring *content;
	render_block_format content_type;
	bool needs_trimming;
};

struct link {
	struct string *url;      // URL link to data.
	struct string *type;     // Standard MIME type of data.
	struct string *size;     // Size of data in bytes.
	struct string *duration; // Duration of data in seconds.
};

struct links_list {
	struct link *ptr;
	size_t len;
};

struct render_blocks_list {
	struct render_block *ptr;
	size_t len;
	struct links_list links;
};

struct render_line {
	struct wstring *ws;
	newsraft_video_t *hints;
	size_t hints_len;
	size_t indent;
};

struct render_result {
	struct render_line *lines;
	size_t lines_len;
};

struct getfeed_item {
	struct string *guid;
	struct string *title;
	struct string *link;
	struct string *content;
	struct string *attachments;
	struct string *persons;
	struct string *extras;
	int64_t publication_date; // Publication date in seconds since the Epoch (0 means unset).
	int64_t update_date; // Update date in seconds since the Epoch (0 means unset).
	bool guid_is_link;
	struct getfeed_item *next;
};

struct getfeed_feed {
	struct string *title;
	struct string *link;
	struct string *content;
	struct string *attachments;
	struct string *persons;
	struct string *extras;
	int64_t time_to_live;
	struct string *http_header_etag;
	int64_t http_header_last_modified;
	int64_t http_header_expires;
	struct getfeed_item *item;
};

struct feed_update_state {
	struct feed_entry *feed_entry;
	struct string *new_errors;

	CURL *curl;
	char curl_error[CURL_ERROR_SIZE];
	struct curl_slist *download_headers;
	long http_response_code;

	// This function processes pieces of feed coming to us during the download.
	bool (*process_fn)(struct feed_update_state *, const char *, size_t, bool);

	XML_Parser xml_parser;
	struct getfeed_feed feed;
	bool in_item;
	struct string *text;
	uint8_t path[256];
	uint8_t depth;
	struct string decoy;
	struct string *emptying_target;

	size_t new_items_count;

	bool curl_handle_added_to_multi;

	bool is_in_progress;
	bool is_downloaded;
	bool is_failed;
	bool is_canceled;
	bool is_finished;

	struct feed_update_state *next;
};

// See "sections.c" file for implementation.
int64_t make_sure_section_exists(const struct string *section_name);
struct feed_entry *copy_feed_to_section(const struct feed_entry *feed_data, int64_t section_index);
void refresh_sections_statistics_about_underlying_feeds(void);
bool purge_abandoned_feeds(void);
struct menu_state *sections_menu_loop(struct menu_state *m);
void free_sections(void);
bool start_updating_all_feeds_and_wait_finish(void);
bool print_unread_items_count(void);
void process_auto_updating_feeds(void);
void mark_feeds_read(struct feed_entry **feeds, size_t feeds_count, bool status);
struct feed_entry **get_all_feeds(size_t *feeds_count);
char *get_section_name(size_t section_index);

// See "feeds-parse.c" file for implementation.
bool parse_feeds_file(void);

// See "feeds.c" file for implementation.
struct menu_state *feeds_menu_loop(struct menu_state *m);

// See "interface-list.c" file for implementation.
bool is_current_menu_a_pager(void);
bool adjust_list_menu(void);
void free_list_menu(void);
void list_menu_writer(size_t index, WINDOW *w);
void expose_entry_of_the_list_menu(size_t index);
void expose_all_visible_entries_of_the_list_menu_unprotected(void);
void expose_all_visible_entries_of_the_list_menu(void);
void redraw_list_menu_unprotected(void);
void reset_list_menu_unprotected(void);
bool handle_list_menu_control(struct menu_state *m, input_id cmd, const struct wstring *arg);
bool handle_pager_menu_control(input_id cmd);
void free_menus(void);
size_t get_menu_depth(void);
struct menu_state *setup_menu(struct menu_state *(*run)(struct menu_state *), const struct string *name, struct feed_entry **feeds, size_t feeds_count, uint32_t flags, const void *ctx);
struct menu_state *close_menu(void);
void start_menu(void);
void write_menu_path_string(struct string *names, struct menu_state *m);
void raise_menu_age(void);
uint64_t fetch_menu_age(void);

// See "interface-list-pager.c" file for implementation.
bool is_pager_pos_valid(struct menu_state *ctx, size_t index);
void pager_menu_writer(size_t index, WINDOW *w);
bool start_pager_menu(struct config_context **new_ctx, struct render_blocks_list *new_blocks);
bool refresh_pager_menu(void);

// See "wstring-format.c" file for implementation.
void do_format(struct wstring *dest, const wchar_t *fmt, const struct format_arg *args);

// See "sorting.c" file for implementation.
sorting_method_t get_sorting_id(const char *sorting_name);
const char *get_sorting_message(int sorting_id);

// See "items.c" file for implementation.
struct string *generate_items_search_condition(struct feed_entry **feeds, size_t feeds_count);
bool important_item_condition(struct menu_state *ctx, size_t index);
struct menu_state *items_menu_loop(struct menu_state *dest);

// See "items-list.c" file for implementation.
bool update_menu_item_list(struct menu_state *ctx, int64_t selected_rowid);
void obtain_items_at_least_up_to_the_given_index(struct items_list *items, size_t index);
void change_items_list_sorting(struct menu_state *ctx, input_id cmd, int64_t selected_rowid);
void free_items_list(struct items_list *items);
extern bool hide_read_feeds;
extern bool hide_read_items;

// See "items-pager.c" file for implementation.
struct menu_state *item_pager_loop(struct menu_state *m);

// Functions responsible for managing render blocks.
// Render block is a piece of text in a single format. A list of render blocks
// is passed to render_data function which processes them based on their types
// and generates a single plain text buffer for a pager to display.
// See "render-block.c" file for implementation.
bool add_render_block(struct render_blocks_list *blocks, const char *content, size_t content_len, render_block_format content_type, bool needs_trimming);
void apply_links_render_blocks(struct render_blocks_list *blocks, const struct wstring *data);
void free_render_blocks(struct render_blocks_list *blocks);
void free_render_result(struct render_result *render);

// See "render_data" directory for implementation.
bool render_data(struct config_context **ctx, struct render_result *result, struct render_blocks_list *blocks, size_t content_width);

// See "items-metadata.c" file for implementation.
bool generate_render_blocks_based_on_item_data(struct render_blocks_list *blocks, const struct item_entry *item, sqlite3_stmt *res);

// See "items-metadata-content.c" file for implementation.
bool get_largest_piece_from_item_content(const char *content, struct string **text, render_block_format *type);
bool get_largest_piece_from_item_attachments(const char *attachments, struct string **text, render_block_format *type);

// See "items-metadata-links.c" file for implementation.
char *complete_url(const char *base, const char *rel);
int64_t add_url_to_links_list(struct links_list *links, const char *url, size_t url_len);
struct wstring *generate_link_list_wstring_for_pager(struct config_context **ctx, const struct links_list *links);
bool add_item_attachments_to_links_list(struct links_list *links, sqlite3_stmt *res);

// See "items-metadata-persons.c" file for implementation.
struct string *deserialize_persons_string(const char *src);

// See "path.c" file for implementation.
bool set_feeds_path(const char *path);
bool set_config_path(const char *path);
bool set_db_path(const char *path);
const char *get_feeds_path(void);
const char *get_config_path(void);
const char *get_db_path(void);

// See "dates.c" file for implementation.
int64_t parse_date(const char *str, bool rfc3339_first);
struct string *get_cfg_date(struct config_context **ctx, config_entry_id format_id, int64_t date);
struct timespec newsraft_get_monotonic_time(void);
struct string *newsraft_get_pretty_time_diff(struct timespec *start, struct timespec *stop);

// See "db.c" file for implementation.
bool db_init(void);
bool db_vacuum(void);
bool exec_database_file_optimization(void);
void db_stop(void);
sqlite3_stmt *db_prepare(const char *statement, int size, const char **p_error);
bool db_transaction_begin(void);
bool db_transaction_commit(void);
bool db_rollback_transaction(void);
const char *db_error_string(void);
int db_bind_string(sqlite3_stmt *stmt, int pos, const struct string *str);
int db_bind_feed_url(sqlite3_stmt *stmt, int pos, const struct string *str);
int64_t db_get_date_from_feeds_table(const struct string *url, const char *column, size_t column_len);
struct string *db_get_string_from_feed_table(const struct string *url, const char *column, size_t column_len);
void db_update_feed_int64(const struct string *url, const char *column_name, int64_t value, bool only_positive);
void db_update_feed_string(const struct string *url, const char *column_name, const struct string *value, bool only_nonempty);
void db_perform_user_edit(const struct wstring *fmt, struct feed_entry **feeds, size_t feeds_count, const struct item_entry *item);

// See "db-items.c" file for implementation.
sqlite3_stmt *db_find_item_by_rowid(int64_t rowid);
bool db_mark_item_read(int64_t rowid, bool status);
bool db_mark_item_important(int64_t rowid, bool status);
int64_t db_count_items(struct feed_entry **feeds, size_t feeds_count, bool count_only_unread);
bool db_change_unread_status_of_all_items_in_feeds(struct feed_entry **feeds, size_t feeds_count, bool unread);

// See "interface.c" file for implementation.
bool ui_init(void);
void ui_term(void);
bool ui_is_running(void);
bool ui_set_window_title(void);
bool run_menu_loop(void);
input_id resize_handler(void);
bool call_resize_handler_if_current_list_menu_size_is_different_from_actual(void);
bool arent_we_colorful(void);

// Functions related to window which displays status messages.
// See "interface-status.c" file for implementation.
void update_status_window_content_unprotected(void);
bool status_recreate_unprotected(void);
void status_clean_unprotected(void);
void status_clean(void);
void prevent_status_cleaning(void);
void allow_status_cleaning(void);
void status_write(config_entry_id color, const char *format, ...);
void status_delete(void);
input_id get_input(struct input_binding *ctx, uint32_t *count, const struct wstring **p_arg);
struct string *pop_search_filter(void);

// Forces get_input() function to quit waiting for user input and return an empty command.
// This lets menu routines redraw the screen immediately after a state change,
// rather than waiting for user to submit a valid action for menu routine to process.
// Think of it as redraw alarm.
void yield_control_to_menu(void);

// See "interface-errors-pager.c" file for implementation.
struct menu_state *errors_pager_loop(struct menu_state *m);

// Functions responsible for managing of key bindings.
// See "binds.c" file for implementation.
input_id get_action_of_bind(struct input_binding *ctx, const char *key, size_t action_index, const struct wstring **p_arg);
struct input_binding *create_or_clean_bind(struct input_binding **target, const char *key);
bool attach_action_to_bind(struct input_binding *bind, input_id cmd, const char *arg, size_t arg_len);
bool assign_default_binds(void);
input_id get_input_id_by_name(const char *name);
bool is_escape_key_used(void);
void free_binds(struct input_binding *target);
void free_default_binds(void);

// Functions related to executing system commands.
// See "commands.c" file for implementation.
void copy_string_to_clipboard(const struct string *src);
void run_formatted_command(const struct wstring *wcmd_fmt, const struct format_arg *args, bool quiet);

// See "string.c" file for implementation.
struct string *crtes(size_t desired_capacity);
struct string *crtas(const char *src_ptr, size_t src_len);
struct string *crtss(const struct string *src);
void cpyas(struct string **dest, const char *src_ptr, size_t src_len);
void cpyss(struct string **dest, const struct string *src);
void catas(struct string *dest, const char *src_ptr, size_t src_len);
void catss(struct string *dest, const struct string *src);
void catcs(struct string *dest, char c);
void make_string_fit_more(struct string **dest, size_t n);
void str_vappendf(struct string *dest, const char *fmt, va_list args);
void str_appendf(struct string *dest, const char *fmt, ...);
void empty_string(struct string *dest);
void free_string(struct string *str);
void trim_whitespace_from_string(struct string *str);
struct wstring *convert_string_to_wstring(const struct string *src);
struct wstring *convert_array_to_wstring(const char *src_ptr, size_t src_len);
void remove_start_of_string(struct string *str, size_t size);
void inlinefy_string(struct string *title);
void newsraft_simple_hash(struct string **dest, const char *src);
struct string *newsraft_base64_encode(const uint8_t *data, size_t size);

// See "string-serialize.c" file for implementation.
void serialize_caret(struct string **target);
void serialize_array(register struct string **target, register const char *key, register size_t key_len, register const char *value, register size_t value_len);
void serialize_string(struct string **target, const char *key, size_t key_len, const struct string *value);
struct deserialize_stream *open_deserialize_stream(const char *serialized_data);
const struct string *get_next_entry_from_deserialize_stream(struct deserialize_stream *stream);
void close_deserialize_stream(struct deserialize_stream *stream);

// See "wstring.c" file for implementation.
void wstr_set(struct wstring **dest, const wchar_t *src_ptr, size_t src_len, size_t src_lim);
struct wstring *wcrtes(size_t desired_capacity);
struct wstring *wcrtas(const wchar_t *src_ptr, size_t src_len);
void wcatas(struct wstring *dest, const wchar_t *src_ptr, size_t src_len);
void wcatss(struct wstring *dest, const struct wstring *src);
void wcatcs(struct wstring *dest, wchar_t c);
void make_sure_there_is_enough_space_in_wstring(struct wstring *dest, size_t need_space);
void empty_wstring(struct wstring *dest);
void free_wstring(struct wstring *wstr);
struct string *convert_wstring_to_string(const struct wstring *src);
struct string *convert_warray_to_string(const wchar_t *src_ptr, size_t src_len);

// See "signal.c" file for implementation.
bool register_signal_handlers(void);

// Parse config file, fill out config_data structure, bind keys to actions.
// See "load_config" directory for implementation.
bool process_config_line(struct feed_entry *feed, const char *str, size_t len);
bool parse_config_file(void);
bool get_cfg_bool(struct config_context **ctx, config_entry_id id);
size_t get_cfg_uint(struct config_context **ctx, config_entry_id id);
struct config_color get_cfg_color(struct config_context **ctx, config_entry_id id);
bool is_cfg_color_set(struct config_context **ctx, config_entry_id id);
const struct string *get_cfg_string(struct config_context **ctx, config_entry_id id);
const struct wstring *get_cfg_wstring(struct config_context **ctx, config_entry_id id);
void free_config(void);
void free_config_context(struct config_context *cfg);

// Download, process and store new items of feed.
// See "queue.c" file for implementation.
void queue_updates(struct feed_entry **feeds, size_t feeds_count);
void queue_wait_finish(void);
struct feed_update_state *queue_pull(bool (*condition)(struct feed_update_state *));
void queue_destroy(void);
void queue_examine(void);

// Functions for opening and closing the log stream.
// To write to the log stream use macros INFO, WARN or FAIL.
// See "log.c" file for implementation.
bool log_init(const char *path);
int log_vprint(const char *prefix, const char *format, va_list args);
int log_print(const char *prefix, const char *format, ...);
FILE *log_get_stream(void);
void log_stop(int error_code);

// Functions for buffering errors to prevent UI from erasing printed text.
// See "errors.c" file for implementation.
void write_error(const char *format, ...);
void flush_errors(void);

// See "downloader.c" file for implementation.
void *downloader_worker(void *dummy);
bool curl_init(void);
void curl_stop(void);
void downloader_curl_wakeup(void);
void remove_downloader_handle(struct feed_update_state *data);

// See "executor.c" file for implementation.
void *executor_worker(void *dummy);

// See "inserter.c" file for implementation.
void *inserter_worker(void *dummy);

// See "threads.c" file for implementation.
bool threads_start(void);
void threads_wake_up(int thread_id);
void threads_take_a_nap(int thread_id);
void threads_stop(void);

// See "parse_xml" directory for implementation.
bool setup_xml_parser(struct feed_update_state *data);
bool convert_opml_to_feeds(void);
bool convert_feeds_to_opml(void);

// See "parse_json" directory for implementation.
bool newsraft_json_parse(struct feed_update_state *data, const char *content, size_t content_size);

// See "insert_feed" directory for implementation.
bool insert_feed(struct feed_entry *feed, struct getfeed_feed *feed_data);

// See "struct-item.c" file for implementation.
void prepend_item(struct getfeed_item **head_item_ptr);
void free_item(struct getfeed_item *item);

// See "alloc.c" file for implementation.
void *newsraft_malloc(size_t size);
void *newsraft_calloc(size_t n, size_t size);
void *newsraft_realloc(void *ptr, size_t size);
void newsraft_free(void *ptr);

extern volatile bool they_want_us_to_stop;
extern size_t list_menu_height;
extern size_t list_menu_width;
extern pthread_mutex_t interface_lock;

#include "config.h"
#include "input.h"
#endif // NEWSRAFT_H
