/*
* Playground+ - historee.c
* History lib for creating, maintaining and cleaning dynamic
* history buffers... an excersise in pointer play (c) phypor 1998
* ---------------------------------------------------------------------------
*
* Modifications to original release:
* Include paths
* commented out su history stufs, to be used as an example in creating others
* removed strcasestr func, as its found in xstring.c for pg+
* changed malloc to MALLOC and free to FREE
*
* Notes:
* to add a history to anything else, just give it
* a history * pointer, either in the struct for it
* or as a global var (depending on how you will need it),
* init_history to give it some memory,
* add items to it with the add_to_hist,
* use stack_hist as a possible method to retrieve the history,
* and free_hist when you are finished.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "include/config.h"
#include "include/player.h"
#include "include/proto.h"
history *init_hist(int max)
{
history *nh;
nh = (history *) MALLOC(sizeof(history));
if (!nh)
{
log("error", "Failed to malloc history.");
return (history *) NULL;
}
memset(nh, 0, sizeof(history));
nh->hist = (char **) MALLOC((max + 1) * sizeof(char *));
if (!nh->hist)
{
FREE(nh);
log("error", "Failed to malloc history.");
return (history *) NULL;
}
memset(nh->hist, 0, max * sizeof(char *));
nh->max = max;
return nh;
}
void add_to_hist(history * h, char *str)
{
int i;
if (!h) /* malloc failed at some point... */
return;
for (i = 0; i < h->max; i++) /* find the first free one */
if (!h->hist[i])
break;
if (i == h->max) /* if the handles are full */
{
FREE(h->hist[i - 1]); /* get rid of the last one */
h->hist[i - 1] = (char *) NULL;
}
for (i = h->max; i > 0; i--) /* shift the handles down */
h->hist[i] = h->hist[i - 1];
/* malloc something to point to */
h->hist[0] = (char *) MALLOC(strlen(str) + 1);
if (!h->hist[0]) /* make sure we got it */
{
log("error", "Failed to malloc history");
return;
}
/* clean it and put it in */
memset(h->hist[0], 0, strlen(str) + 1);
strcpy(h->hist[0], str);
}
int stack_hist(history * h, int lines, char *needle)
{
int i;
if (!h || !h->hist[0])
return -1;
for (i = 0; h->hist[i + 1]; i++); /* get to the end to put the oldest top */
if (lines > 0)
i = i < lines ? i : lines - 1; /* use the smallest */
if (!needle || !*needle)
for (; i >= 0; i--)
stack += sprintf(stack, "%s", h->hist[i]);
else
for (; i >= 0; i--)
if (strcasestr(h->hist[i], needle))
stack += sprintf(stack, "%s", h->hist[i]);
return 0;
}
void clean_hist(history * h)
{
int i;
if (!h || !h->hist) /* make sure its got memory */
return;
for (i = 0; i < h->max; i++)
if (h->hist[i])
{
FREE(h->hist[i]);
h->hist[i] = (char *) NULL;
}
}
void free_hist(history * h)
{
clean_hist(h);
FREE(h->hist);
FREE(h);
}
void init_global_histories(void)
{
/* init any global histories here...such as
SuHistory = init_hist (HIST_SU);
*/
}
#ifdef EXAMPLES
/* su history */
#define HIST_SU 50
history *SuHistory;
void zap_suhist(player * p, char *str)
{
clean_hist(SuHistory);
tell_player(p, " SuperUsers History zapped!\n");
}
void view_su_history(player * p, char *str)
{
char *oldstack = stack, *needle = "";
int lines = -1;
if (*str && !strcmp(str, "?")) /* use strcmp so ? can be first char of
pattern to be matched */
{
tell_player(p,
" Format : suhist to view the entire suhist, unabriged\n"
" suhist # to view the mot recent # of lines\n"
" suhist <str> to view all lines strcasestr'ing <str>\n"
" suhist ? to view the format\n");
return;
}
if (*str && isdigit(*str))
{
lines = atoi(str);
if (lines < 2)
lines = 2;
stack += sprintf(stack, "--- SuperUsers History (last %d lines) ---\n",
lines);
}
else if (*str)
{
stack += sprintf(stack, "--- SuperUsers History (searching %s) ---\n",
str);
needle = str;
}
else
stack += sprintf(stack, "--- SuperUsers History --------------------\n")
;
if (stack_hist(SuHistory, lines, needle) < 0)
{
tell_player(p, " SuperUsers History is empty.\n");
stack = oldstack;
return;
}
stack += sprintf(stack, "-------------------------------------------\n");
stack = end_string(stack);
tell_player(p, oldstack);
stack = oldstack;
}
#endif /* EXAMPLES */