/*
* historyManager.c
* Wcalc
*
* Created by Kyle Wheeler on Mon Jan 21 2002.
* Copyright (c) 2001 Kyle Wheeler. All rights reserved.
*
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h> /* might make readline happy */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "number.h"
#include "historyManager.h"
#include "calculator.h"
#ifdef HAVE_READLINE_HISTORY
# if defined(HAVE_READLINE_HISTORY_H)
# include <readline/history.h>
# elif defined(HAVE_HISTORY_H)
# include <history.h>
# else /* ! defined(HAVE_HISTORY_H) */
extern void add_history();
extern int write_history();
extern int read_history();
# endif /* defined(HAVE_READLINE_HISTORY_H) */
/* no history */
#endif /* HAVE_READLINE_HISTORY */
#ifdef MEMWATCH
#include "memwatch.h"
#endif
/* Configuration Variables */
short allow_duplicates = 0;
short recalculate = 0;
/* Data Types */
struct entry
{
char *exp;
Number ans;
unsigned int calc:1;
};
/* Private Variables */
static struct entry *history = NULL;
static size_t histlen = 0;
/* Private Functions */
static int all_calculated(void);
static void clear_calculated(void);
void clearHistory()
{
unsigned int i;
for (i = 0; i < histlen; i++) {
free(history[i].exp);
num_free(history[i].ans);
}
if (histlen) {
free(history);
histlen = 0;
}
}
void addToHistory(char *expression, Number answer)
{
#ifdef HAVE_READLINE_HISTORY
add_history(expression);
#endif
if (!histlen) {
/* this is the beginning of a new history record */
if (!conf.history_limit || conf.history_limit_len > 0) {
history = malloc(sizeof(struct entry));
if (!history)
return;
history->exp = strdup(expression);
if (!history->exp) {
free(history);
return;
}
num_init_set(history->ans, answer);
histlen = 1;
}
} else { /* a history exists */
// eliminate duplicates
if (allow_duplicates || strcmp(history[histlen - 1].exp, expression)) {
if (!conf.history_limit || histlen < conf.history_limit_len) {
/* history not too long, just add a new entry */
struct entry *temp =
realloc(history, sizeof(struct entry) * (histlen + 1));
if (!temp) {
// if it couldn't be realloced, try malloc and memcpy
temp = malloc(sizeof(struct entry) * (histlen + 1));
if (!temp)
return;
memcpy(temp, history, sizeof(struct entry) * histlen);
free(history);
}
history = temp;
if (expression)
history[histlen].exp = strdup(expression);
else
history[histlen].exp = NULL;
num_init_set(history[histlen].ans, answer);
/* why is this if statement here? */
if (!temp[histlen].exp)
return;
++histlen;
} else {
/* history too long */
unsigned long i;
if (history[0].exp)
free(history[0].exp);
for (i = 0; i < histlen - 1; ++i) {
history[i].exp = history[i + 1].exp;
num_set(history[i].ans, history[i + 1].ans);
history[i].calc = history[i + 1].calc;
}
if (expression)
history[histlen - 1].exp = strdup(expression);
else
history[histlen - 1].exp = NULL;
num_set(history[histlen - 1].ans, answer);
return;
}
}
}
}
char *historynum(int step, int col)
{
if (col == 1)
return history[step].exp;
else {
static char *temp;
if (recalculate) {
parseme(history[step].exp);
num_set(history[step].ans, last_answer);
history[step].calc = 1;
if (all_calculated()) {
recalculate = 0;
clear_calculated();
}
}
temp = print_this_result(history[step].ans);
return (temp ? temp : "Not Enough Memory");
}
}
static int all_calculated(void)
{
unsigned long i, ret = 0;
for (i = 0; i < histlen; ++i) {
if (history[i].calc)
++ret;
}
return (ret == histlen);
}
static void clear_calculated(void)
{
unsigned long i;
for (i = 0; i < histlen; ++i) {
history[i].calc = 0;
}
}
size_t historyLength(void)
{
return histlen;
}
syntax highlighted by Code2HTML, v. 0.9.1