#include "irc.h"
static char cvsrevision[] = "$Id: history.c 3 2008-02-25 09:49:14Z keaston $";
CVS_REVISION(history_c)
#include "struct.h"
#include "ircaux.h"
#include "vars.h"
#include "history.h"
#include "output.h"
#include "input.h"
#define MAIN_SOURCE
#include "modval.h"
static char *history_match (char *);
static void add_to_history_list (int, char *);
static char *get_from_history_buffer (int);
typedef struct HistoryStru
{
int number;
char *stuff;
struct HistoryStru *next;
struct HistoryStru *prev;
} History;
static History *command_history_head = NULL;
static History *command_history_tail = NULL;
static History *command_history_pos = NULL;
static int hist_size = 0;
static int hist_count = 0;
static int last_dir = -1;
static History *tmp = NULL;
static char *history_match (char *match)
{
char *ptr;
char *match_str = NULL;
if (*(match + strlen(match) - 1) == '*')
match_str = LOCAL_COPY(match);
else
{
match_str = alloca(strlen(match) + 3);
strcpy(match_str, match);
strcat(match_str, "*");
}
if (get_int_var(HISTORY_VAR))
{
if ((last_dir == -1) || (tmp == NULL))
tmp = command_history_head;
else
tmp = tmp->next;
if (tmp)
{
for (; tmp; tmp = tmp->next)
{
ptr = tmp->stuff;
while (ptr && strchr(get_string_var(CMDCHARS_VAR), *ptr))
ptr++;
if (wild_match(match_str, ptr))
{
last_dir = PREV;
return (tmp->stuff);
}
}
}
}
last_dir = -1;
return NULL;
}
extern void shove_to_history (char unused, char *not_used)
{
add_to_history(get_input());
input_clear_line(unused, not_used);
}
static void add_to_history_list(int cnt, char *stuff)
{
History *new;
if (get_int_var(HISTORY_VAR) == 0)
return;
if ((hist_size == get_int_var(HISTORY_VAR)) && command_history_tail)
{
if (hist_size == 1)
{
malloc_strcpy(&command_history_tail->stuff, stuff);
return;
}
new = command_history_tail;
command_history_tail = command_history_tail->prev;
command_history_tail->next = NULL;
new_free(&new->stuff);
new_free((char **)&new);
if (command_history_tail == NULL)
command_history_head = NULL;
}
else
hist_size++;
new = (History *) new_malloc(sizeof(History));
new->stuff = NULL;
new->number = cnt;
new->next = command_history_head;
new->prev = NULL;
malloc_strcpy(&(new->stuff), stuff);
if (command_history_head)
command_history_head->prev = new;
command_history_head = new;
if (command_history_tail == NULL)
command_history_tail = new;
command_history_pos = NULL;
}
void set_history_size(Window *win, char *unused, int size)
{
int i,
cnt;
History *ptr;
if (size < hist_size)
{
cnt = hist_size - size;
for (i = 0; i < cnt; i++)
{
ptr = command_history_tail;
command_history_tail = ptr->prev;
new_free(&(ptr->stuff));
new_free((char **)&ptr);
}
if (command_history_tail == NULL)
command_history_head = NULL;
else
command_history_tail->next = NULL;
hist_size = size;
}
}
void add_to_history(char *line)
{
char *ptr;
if (line && *line)
{
while (line && *line)
{
if ((ptr = sindex(line, "\n\r")) != NULL)
*(ptr++) = '\0';
add_to_history_list(hist_count, line);
last_dir = PREV;
hist_count++;
line = ptr;
}
}
}
static char *get_from_history_buffer(int which)
{
if ((get_int_var(HISTORY_VAR) == 0) || (hist_size == 0))
return NULL;
if (which == NEXT)
{
if (command_history_pos)
{
if (command_history_pos->prev)
command_history_pos = command_history_pos->prev;
else
command_history_pos = command_history_tail;
}
else
{
add_to_history(get_input());
command_history_pos = command_history_tail;
}
return (command_history_pos->stuff);
}
else
{
if (command_history_pos)
{
if (command_history_pos->next)
command_history_pos = command_history_pos->next;
else
command_history_pos = command_history_head;
}
else
{
add_to_history(get_input());
command_history_pos = command_history_head;
}
return (command_history_pos->stuff);
}
}
extern void get_history (int which)
{
char *ptr;
if ((ptr = get_from_history(which)) != NULL)
{
set_input(ptr);
update_input(UPDATE_ALL);
}
}
char *get_from_history(int which)
{
return(get_from_history_buffer(which));
}
BUILT_IN_COMMAND(history)
{
int cnt,
max = 0;
char *value;
char *match = NULL;
if (get_int_var(HISTORY_VAR))
{
say("Command History:");
if ((value = next_arg(args, &args)) != NULL)
{
if (my_strnicmp(value, "-CLEAR", 3))
{
for (tmp = command_history_head; command_history_head; tmp = command_history_head)
{
new_free(&tmp->stuff);
command_history_head = tmp->next;
new_free(&tmp);
}
hist_size = hist_count = 0;
command_history_pos = NULL;
command_history_tail = NULL;
command_history_head = NULL;
return;
}
if (isdigit((unsigned char)*value))
{
max = my_atol(value);
if (max > get_int_var(HISTORY_VAR))
max = get_int_var(HISTORY_VAR);
}
else
match = value;
}
else
max = get_int_var(HISTORY_VAR);
for (tmp = command_history_tail, cnt = 0; tmp && (match || (cnt < max));
tmp = tmp->prev, cnt++)
{
if (!match || (match && wild_match(match, tmp->stuff)))
put_it("%d: %s", tmp->number, tmp->stuff);
}
}
}
char *do_history (char *com, char *rest)
{
int hist_num;
char *ptr, *ret = NULL;
static char *last_com = NULL;
if (!com || !*com)
{
if (last_com)
com = last_com;
else
com = empty_string;
}
else
malloc_strcpy(&last_com, com);
if (!is_number(com))
{
if ((ptr = history_match(com)))
{
ret = m_strdup(ptr);
m_s3cat_s(&ret, space, rest);
return ret;
}
say("No Match");
}
else
{
hist_num = my_atol(com);
if (hist_num > 0)
{
for (tmp = command_history_head; tmp; tmp = tmp->next)
{
if (tmp->number == hist_num)
{
ret = m_strdup(tmp->stuff);
m_s3cat_s(&ret, space, rest);
return ret;
}
}
}
else
{
hist_num++;
for (tmp = command_history_head; tmp && hist_num < 0; )
tmp = tmp->next, hist_num++;
if (tmp)
{
ret = m_strdup(tmp->stuff);
m_s3cat_s(&ret, space, rest);
return (ret);
}
}
say("No such history entry: %d", hist_num);
}
return NULL;
}