Logo Search packages:      
Sourcecode: calcoo version File versions

c_input.c

/*
 * Calcoo: c_input.c
 *
 * Copyright (C) 2001, 2002 Alexei Kaminski
 *
 * handles input operations
 *
 */

#include <math.h>

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

void call_digit(int received_code)
{
      int digit_entered;
      int i;

/* first we determine whether we start a new input or just 
 * continue input started before */
      if (cpu->rpn_mode)
      {
            switch (cpu->last_action) {
            case ACTION_CLEAR:
                  /* no need to call cpu_to_output, because input 
                   * routine works directly with the main display,
                   * and the other displays must have been taken
                   * care of before */
                  reset_input();
                  break;
            case ACTION_ENTER:
                  /* this action type is set by the <Enter> button
                   * in the traditional enter mode, and by any
                   * operation that puts something into X,
                   * like Pi, M->x */
                  push_stack(); 
                  cpu->op = CODE_ENTER; 
                  cpu->y = cpu->x;
                  cpu_to_output();
                  reset_input();
                  break;
            case ACTION_ENTER_PUSH:
                  /* this action type is set by the <Enter> button
                   * in the traditional enter mode */
                  reset_input();
                  break;
            case ACTION_INPUT:
                  break;
            default:
                  error_occured("call_digit() RPN, unknown last_action",
                              FALSE);
            }
      } else {
            switch (cpu->last_action) {
            case ACTION_CLEAR:
            case ACTION_ENTER:
                  /* no need to call cpu_to_output, because input 
                   * routine works directly with the main display,
                   * and the other displays must have been taken
                   * care of before */
                  reset_input();
                  break;
                  /* ACTION_ENTER_PUSH does not occur in the 
                   * algebraic mode */
            case ACTION_INPUT:
                  break;
            case ACTION_BINOP:
                  reset_input();
                  break;
            default:
                  error_occured("call_digit() alg, unknown last_action",
                              FALSE);
            }
      }

/* now we process the input itself */
      digit_entered = code_to_digit(received_code);
      
      switch (cpu->d->input_field) {
      case INPUT_FIELD_INT:
            if (cpu->d->n_int < INPUT_LENGTH) 
            {
                  if ((digit_entered != CODE_0)
                       || (cpu->d->n_int != 0) ) 
                  {
                        cpu->d->int_field[cpu->d->n_int] = 
                              digit_entered;
                        cpu->d->n_int++;
                  }
            }
            break;
      case INPUT_FIELD_FRAC:
            if (cpu->d->n_int + cpu->d->n_frac < INPUT_LENGTH) 
            {
                  cpu->d->frac_field[cpu->d->n_frac] = digit_entered;
                  cpu->d->n_frac++;
            }
            break;
      case INPUT_FIELD_EXP:
            for (i = 0; i < EXP_INPUT_LENGTH - 1; i++) 
            {
                  cpu->d->exp_field[i] = cpu->d->exp_field[i + 1];
            }
            cpu->d->exp_field[EXP_INPUT_LENGTH - 1] = digit_entered;
            break;
      }

/* final actions */
      cpu->last_action = ACTION_INPUT;
/* we do not call aftermath() here, because we want to skip
 * cpu_to_output() (since it has already been done above)
 * and output-error-checking, since no output errors may occur in the course
 * of input. Even if we input 9999e99, the error should pop up later, when we
 * try to do something with this number */
      save_for_undo();
      refresh_body();
}

void call_dot(void)
{
      if (cpu->last_action != ACTION_INPUT) 
      {
            if ((cpu->rpn_mode)
                && (cpu->last_action == ACTION_ENTER)) 
            {
                  push_stack();
                  cpu->y = cpu->x;
            }
            reset_input();
            cpu->last_action = ACTION_INPUT;
            cpu_to_output();
      }

      if (cpu->d->input_field == INPUT_FIELD_INT) 
      {
            if (cpu->d->n_int == 0)
            {
                  cpu->d->int_field[0] = CODE_0;
                  cpu->d->n_int++;
            }
            cpu->d->input_field = INPUT_FIELD_FRAC;
      }

      save_for_undo();
      refresh_body();
}

void call_exp(void)
/* this is the "e" button, not exp(x) */
{
      int i;
      
      if (cpu->last_action != ACTION_INPUT) 
      {
            if ((cpu->rpn_mode)
                && (cpu->last_action == ACTION_ENTER)) 
            {
                  push_stack();
                  cpu->y = cpu->x;
            }
            reset_input();
            cpu->d->int_field[0] = CODE_1;
            cpu->d->n_int = 1;
            cpu->last_action = ACTION_INPUT;
      }

      cpu->d->input_field = INPUT_FIELD_EXP;
      cpu->d->format = FORMAT_SCI;
      cpu->d->exp_sign = SIGN_PLUS;
      for (i = 0; i < EXP_INPUT_LENGTH; i++) 
            cpu->d->exp_field[i] = 0;

      save_for_undo();
      refresh_body();
}

void call_sign(void)
{
      cpu->d->sign = inverse_sign(cpu->d->sign);

      /* since the sign change does not toggle INPUT_IN_PROGRESS ... */
      cpu->x = -cpu->x;

      save_for_undo();
      refresh_body();
}

void call_exp_sign(void)
{
      if ( (cpu->d->input_field != INPUT_FIELD_EXP)
           || (cpu->last_action != ACTION_INPUT) ) 
            return;

      cpu->d->exp_sign = inverse_sign(cpu->d->exp_sign);

      save_for_undo(); 
      refresh_body();
}

void call_pi(void)
{
      if (cpu->rpn_mode) {
            if (cpu->last_action == ACTION_INPUT) 
                  input_to_x();
            push_stack(); 
            cpu->op = CODE_ENTER; 
            cpu->y = cpu->x;
      } else {
      }
      cpu->x = PI;
      cpu_to_output();
      cpu->last_action = ACTION_ENTER;
      save_for_undo();
      refresh_body();
}

void call_clear_all(void)
{
      int i;

      reset_registers();
      
      if (cpu->error) {
            for (i=0; i<NUMBER_OF_MEMS; i++) {
                  if (cpu->mem_d[i]->display_overflow) {
                        /* not quite consistent but otherwise
                         * we would have to disable clear_all in the
                         * state of error at all, in contrast to 
                         * the behavior of real calculators */
                        cpu->mem[i] = 0.0;
                  }
            }
      }

      aftermath();
}

void call_clear_x(void)
{
      reset_input();

      aftermath();
}


void call_import_paste(double a)
{
      if (cpu->rpn_mode) {
            if (cpu->last_action == ACTION_INPUT) 
                  input_to_x();
            push_stack(); 
            cpu->op = CODE_ENTER; 
            cpu->y = cpu->x;
      }
      cpu->x = a;
      cpu->last_action = ACTION_ENTER;
      aftermath();
}

void call_change_display_format(void)
{
      if (cpu->last_action == ACTION_INPUT) 
            input_to_x();

      switch (cpu->prescribed_format) {
      case FORMAT_FIX:        
            cpu->prescribed_format = FORMAT_SCI;
            break;
      case FORMAT_SCI:        
            cpu->prescribed_format = FORMAT_ENG;
            break;
      case FORMAT_ENG:
            cpu->prescribed_format = FORMAT_FIX;
            break;
      }

      cpu->last_action = ACTION_ENTER;

      aftermath();
}

void reset_input(void)
/* is the function called by call_clear_x() (Cx button) */
/* also called by some other operations in cpu */
{
      cpu->x = 0.0;
      cpu->x_overflow = FALSE;

      cpu->last_action = ACTION_CLEAR;
      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 input_to_x(void)
{
      double tmp, tmp10, tmp_exp;
      int i;
      tmp = 0.0;

      /* if there is nothing in input, there will be 0 in x 
       * like in real-world calculators */

      /* processing int part */
      for (i = 0; i < cpu->d->n_int; i++) 
            tmp = tmp * 10 
                  + code_to_digit(cpu->d->int_field[i]);
      

      /* processing frac part (if there is any) */
      if (cpu->d->n_frac > 0) {
            tmp10 = 1.0;
            for (i = 0; i < cpu->d->n_frac; i++) {
                  tmp10 *= 0.1;
                  tmp += code_to_digit (
                        cpu->d->frac_field[i]
                        ) * tmp10;
            }
      }

      /* sign */
      if(cpu->d->sign == SIGN_MINUS)
            tmp = -tmp;

      /* processing exp part (if there is any) */
      if (cpu->d->format == FORMAT_SCI) {
            tmp_exp = 0.0;
            for (i = 0; i < EXP_INPUT_LENGTH; i++) 
                  tmp_exp = tmp_exp * 10.0 
                          + code_to_digit(
                                cpu->d->exp_field[i]
                                );
            if (cpu->d->exp_sign == SIGN_MINUS) 
                  tmp_exp = -tmp_exp;
            tmp *= pow(10.0, tmp_exp);
      }

      cpu->x = tmp;
      cpu->x_overflow = FALSE;
}

Generated by  Doxygen 1.6.0   Back to index