Initial import of the ircii-pana-1.1-final source tree.
git-svn-id: svn://svn.code.sf.net/p/bitchx/code/tags/ircii-pana-1.1-final@1 13b04d17-f746-0410-82c6-800466cd88b0
This commit is contained in:
378
source/history.c
Normal file
378
source/history.c
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* history.c: stuff to handle command line history
|
||||
*
|
||||
*
|
||||
* Written By Michael Sandrof
|
||||
*
|
||||
* Copyright(c) 1990
|
||||
*
|
||||
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
|
||||
*/
|
||||
|
||||
|
||||
#include "irc.h"
|
||||
static char cvsrevision[] = "$Id: history.c,v 1.1.1.1 2003/04/11 01:09:07 dan Exp $";
|
||||
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;
|
||||
|
||||
/* command_history: pointer to head of command_history list */
|
||||
static History *command_history_head = NULL;
|
||||
static History *command_history_tail = NULL;
|
||||
static History *command_history_pos = NULL;
|
||||
|
||||
/* hist_size: the current size of the command_history array */
|
||||
static int hist_size = 0;
|
||||
|
||||
/* hist_count: the absolute counter for the history list */
|
||||
static int hist_count = 0;
|
||||
|
||||
/*
|
||||
* last_dir: the direction (next or previous) of the last get_from_history()
|
||||
* call.... reset by add to history
|
||||
*/
|
||||
static int last_dir = -1;
|
||||
|
||||
/*
|
||||
* history pointer
|
||||
*/
|
||||
static History *tmp = NULL;
|
||||
|
||||
/*
|
||||
* history_match: using wild_match(), this finds the latest match in the
|
||||
* history file and returns it as the function result. Returns null if there
|
||||
* is no match. Note that this sticks a '*' at the end if one is not already
|
||||
* there.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/* shove_to_history: a key binding that saves the current line into
|
||||
* the history and then deletes the whole line. Useful for when you
|
||||
* are in the middle of a big line and need to "get out" to do something
|
||||
* else quick for just a second, and you dont want to have to retype
|
||||
* everything all over again
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* set_history_size: adjusts the size of the command_history to be size. If
|
||||
* the array is not yet allocated, it is set to size and all the entries
|
||||
* nulled. If it exists, it is resized to the new size with a realloc. Any
|
||||
* new entries are nulled.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* add_to_history: adds the given line to the history array. The history
|
||||
* array is a circular buffer, and add_to_history handles all that stuff. It
|
||||
* automagically allocted and deallocated memory as needed
|
||||
*/
|
||||
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 (last_dir != which) { last_dir = which; get_from_history(which); }
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_history: gets the next history entry, either the PREV entry or the
|
||||
* NEXT entry, and sets it to the current input string
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
/* history: the /HISTORY command, shows the command history buffer. */
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* do_history: This finds the given history entry in either the history file,
|
||||
* or the in memory history buffer (if no history file is given). It then
|
||||
* returns the found entry as its function value, or null if the entry is not
|
||||
* found for some reason. Note that this routine mallocs the string returned
|
||||
*/
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user