Logo Search packages:      
Sourcecode: wcalc version File versions  Download package

historyManager.c

/*
 *  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 */

#include <gmp.h>
#include <mpfr.h>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#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;
    mpfr_t ans;
    unsigned int calc:1;
};

/* Private Variables */
static struct entry *history = NULL;
static unsigned long 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);
      mpfr_clear(history[i].ans);
    }
    if (histlen) {
      free(history);
      histlen = 0;
    }
}

void addToHistory(char *expression, mpfr_t 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;
          }
          mpfr_init_set(history->ans, answer, GMP_RNDN);
          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;
            mpfr_init_set(history[histlen].ans, answer, GMP_RNDN);
            /* 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;
                mpfr_set(history[i].ans, history[i + 1].ans, GMP_RNDN);
                history[i].calc = history[i + 1].calc;
            }
            if (expression)
                history[histlen - 1].exp = strdup(expression);
            else
                history[histlen - 1].exp = NULL;
            mpfr_set(history[histlen - 1].ans, answer, GMP_RNDN);
            return;
          }
      }
    }
}

char *historynum(int step, int col)
{
    if (col == 1)
      return history[step].exp;
    else {
      static char *temp;

      if (recalculate) {
          parseme(history[step].exp);
          mpfr_set(history[step].ans, last_answer, GMP_RNDN);
          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;
    }
}

int historyLength(void)
{
    return histlen;
}

Generated by  Doxygen 1.6.0   Back to index