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

c_main.c

/*
 * Calcoo: c_main.c
 *
 * Copyright (C) 2001, 2002, 2003 Alexei Kaminski
 *
 * creates and initializes cpu
 *
 * also handles "clear all" and RPN toggles
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>

#include "codes.h"
#include "const.h"
#include "defaults.h"
#include "cpu.h"
#include "c_headers.h"
#include "io_headers.h"
#include "aux_headers.h"

t_calcoo_cpu *cpu;

void reset_stack(void);

void init_cpu(void)
/* mallocs and initializes cpu variables;
 * runs once, after calcoo is started */
{
      int i;
      
      cpu = (t_calcoo_cpu*) malloc (sizeof(t_calcoo_cpu));
      if(cpu == NULL)
            error_occured("malloc in init_cpu() failed", TRUE);
      cpu->d = (t_cpu_display*) malloc (sizeof(t_cpu_display));
      if(cpu->d == NULL)
            error_occured("malloc in init_cpu() failed", TRUE);

      cpu->stack_head = NULL;

      for(i = 0; i < NUMBER_OF_MEMS; i++)
      {
            cpu->mem[i] = 0.0;
            cpu->mem_d[i] = 
                  (t_cpu_display*) malloc (sizeof(t_cpu_display));
      }
      for(i = 0; i < NUMBER_OF_REG_DISPLAYS; i++)
      {
            cpu->reg_d[i] = 
                  (t_cpu_display*) malloc (sizeof(t_cpu_display));
            if(cpu->reg_d[i] == NULL)
                  error_occured("malloc in init_cpu() failed", TRUE);

            cpu->op_d[i] = (t_cpu_operation_display*)
                  malloc (sizeof(t_cpu_operation_display));
            if(cpu->op_d[i] == NULL)
                  error_occured("malloc in init_cpu() failed", TRUE);
      }

      reset_registers();
      cpu->prescribed_format = DEFAULT_DISPLAY_FORMAT;
      cpu->curr_mem = 0;
      cpu->rpn_mode = FALSE ; /* It is a kluge. We need it to have proper
            * (to display nothing) initialization of the operation 
            * displays. The reason is that cpu->rpn_mode is used in
            * cpu_to_output(), and if it turns out to be set to TRUE
            * after having been malloc'ed, cpu_to_output() does not
            * reset operation displays. If these displays contain
            * some garbage after having been malloc'ed, it will lead to
            * weird stuff displayed in the operation displays in the 
            * algebraic mode from after initialization until the next
            * call to cpu_to_output */

      if (MAXIMIZE_PRECISION)
            cpu->precision = pow(10, -floor(fabs(log10(DBL_EPSILON))) + 1);
              /* "+1" is just in case, to underestimate precision;
             * as for -floor(fabs()), it is just me being paranoid, 
             * since I am not sure wether the behavior of floor()
             * of a negative number is universal */
      else
            cpu->precision = pow(10, -INPUT_LENGTH - 1); 
        /* it is going to be used in evaluation of
       * trigonometric functions to get sin PI == 0 
       * rather than 10^-17 and also in subtraction/addition 
       * to have 100.1 - 100 - 0.1 == 0 rather than 1e-15 */

      cpu_to_output();
      init_undo_stack();
      refresh_body(); 
}

void aftermath(void)
{
      cpu_to_output();
      save_for_undo();
      refresh_body();
}

void reset_registers(void)
/* the function called by the "C" button" */
{
      cpu->x = 0.0;
      cpu->y = 0.0; 
      cpu->z = 0.0; 
      cpu->t = 0.0; 

      cpu->op = CODE_NO_OPERATION;
      cpu->number_of_parens = 0;

      reset_stack();
      cpu->last_action = ACTION_CLEAR;
      cpu->x_overflow = FALSE;

      cpu->d->input_field = INPUT_FIELD_INT;
      cpu->d->sign = SIGN_PLUS; 
      cpu->d->exp_sign = SIGN_PLUS;
      cpu->d->format = FORMAT_FIX;
      cpu->d->display_overflow = FALSE;
      cpu->d->n_int = 0;
      cpu->d->n_frac = 0;
}

void reset_stack(void)
{
      t_stack_element *to_remove;

      while (cpu->stack_head != NULL) 
      {
            to_remove = cpu->stack_head;
            cpu->stack_head = cpu->stack_head->next;
            free(to_remove);
      }
}

void call_set_rpn_mode(int a)
{
      double tmp;

      if (a != cpu->rpn_mode) 
      {
            if (cpu->last_action == ACTION_INPUT) 
                  input_to_x();
            tmp = cpu->x;
            reset_undo_stack();
            reset_registers();
            cpu->x = tmp;

            if (a) 
            {
                  cpu->rpn_mode = TRUE;
            } else {
                  cpu->rpn_mode = FALSE;
            } /* why not just "cpu->rpn_mode = a;"? I don't remember why */

            cpu_to_output();
            save_for_undo();
            refresh_body();
      }
}

int call_get_rpn_mode(void)
{
      return cpu->rpn_mode;
}

void call_set_enter_mode(int new_mode)
{
      cpu->enter_mode = new_mode;
}

int call_get_enter_mode(void)
{
      return cpu->enter_mode;
}

void call_set_rounding_mode(int a)
{
      if (cpu->last_action == ACTION_INPUT) {
            input_to_x();
            cpu->last_action = ACTION_ENTER;
      }

      if (a > 0 ) 
      {
            cpu->rounding = TRUE;
            cpu->digits_to_keep = a;
      } else {
            cpu->rounding = FALSE;
            cpu->digits_to_keep = -a;
      }
      cpu_to_output();
      refresh_body();
}

int call_get_rounding_mode(void)
{
      if (cpu->rounding)
            return cpu->digits_to_keep;
      else
            return -cpu->digits_to_keep;
}

void call_set_trunc_zeros_mode(int a)
{
      if(cpu->rounding){
            if (cpu->last_action == ACTION_INPUT) {
                  input_to_x();
                  cpu->last_action = ACTION_ENTER;
            }

            cpu->trunc_zeros = a;
            cpu_to_output();
            refresh_body();
      } else {
            /* to ensure proper loading of options */
            cpu->trunc_zeros = a;
      }
}

int call_get_trunc_zeros_mode(void)
{
      return cpu->trunc_zeros;
}


void call_set_stack_mode(int new_mode)
{
      cpu->stack_mode = new_mode;
      if (new_mode == STACK_MODE_XYZT)
            reset_stack(); /* resets stack only beyond T */
}

int call_get_stack_mode(void)
{
      return cpu->stack_mode;
}

int call_get_angle_units(void)
{
      return cpu->angle_units;
}

void call_change_angle_units(void)
{
      if (cpu->angle_units == CODE_DEG)
            cpu->angle_units = CODE_RAD;
      else
            cpu->angle_units = CODE_DEG;

      save_for_undo();
      refresh_body();
}

void call_set_angle_units(int a)
{
      cpu->angle_units = a;
      refresh_body();
}


Generated by  Doxygen 1.6.0   Back to index