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

c_undo.c

/*
 * Calcoo: c_undo.c
 *
 * Copyright (C) 2001, 2002 Alexei Kaminski
 *
 * all about undo
 */

#include <stdlib.h>

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

int us_curr, us_last, us_first;
t_calcoo_cpu *cpu_undo_stack[UNDO_STACK_SIZE];

void pop_undo_stack(void);
void push_undo_stack(void);
void copy_operation_stack(t_stack_element *, t_stack_element **);
void copy_cpu(t_calcoo_cpu *, t_calcoo_cpu *);
void copy_display(t_cpu_display *, t_cpu_display *);

void init_undo_stack(void)
{
      int i, j;

      for (i = 0; i < UNDO_STACK_SIZE; i++) {
            cpu_undo_stack[i] = 
                  (t_calcoo_cpu*) malloc(sizeof(t_calcoo_cpu));
            verify_malloc(cpu_undo_stack[i]);

            for(j = 0; j < NUMBER_OF_MEMS; j++){
                  (cpu_undo_stack[i])->mem_d[j] = 
                         (t_cpu_display*) malloc (sizeof(t_cpu_display));
                  verify_malloc((cpu_undo_stack[i])->mem_d[j]);
            }

            for(j = 0; j < NUMBER_OF_REG_DISPLAYS; j++) {
                  (cpu_undo_stack[i])->reg_d[j] = 
                         (t_cpu_display*) malloc (sizeof(t_cpu_display));
                  verify_malloc(cpu_undo_stack[i]->reg_d[j]);
                  (cpu_undo_stack[i])->op_d[j] = 
                        (t_cpu_operation_display*)
                        malloc (sizeof(t_cpu_operation_display));
                  verify_malloc((cpu_undo_stack[i])->op_d[j]);
            }

            (cpu_undo_stack[i])->d = 
                  (t_cpu_display*) malloc (sizeof(t_cpu_display));
            verify_malloc((cpu_undo_stack[i])->d);

            (cpu_undo_stack[i])->stack_head = NULL;
      }

      us_curr = 0;
      for (i = 0; i < UNDO_STACK_SIZE; i++){
            save_for_undo();
      }
      us_first = 0;
      us_curr = 0;
      us_last = 0;
      disable_undo_button();
      disable_redo_button();
}

void reset_undo_stack(void)
{
      us_first = 0;
      us_curr = 0;
      us_last = 0;
      disable_undo_button();
      disable_redo_button();
}

void call_undo(void)
{
      if ( us_curr != us_first ) {
            us_curr = (us_curr - 1 + UNDO_STACK_SIZE) % UNDO_STACK_SIZE;
            pop_undo_stack();

            /* this is needed because the rounding mode may have changed */
            cpu_to_output();
            if (cpu->last_action == ACTION_INPUT){
                  copy_display(cpu_undo_stack[us_curr]->d, cpu->d);
            }

            enable_redo_button();
      }

      if ( us_curr == us_first )
            disable_undo_button();

      refresh_body();
}

void call_redo(void)
{
      if ( us_curr != us_last) {
            us_curr = (us_curr + 1) % UNDO_STACK_SIZE;
            pop_undo_stack();

            /* this is needed because the rounding mode may have changed */
            cpu_to_output();
            if (cpu->last_action == ACTION_INPUT){
                  copy_display(cpu_undo_stack[us_curr]->d, cpu->d);
            }

            enable_undo_button();
      }
      if ( us_curr == us_last ) 
            disable_redo_button();
      refresh_body();
}

void save_for_undo(void)
{
      us_curr = (us_curr + 1) % UNDO_STACK_SIZE;
      push_undo_stack();
      enable_undo_button();
      disable_redo_button();
      us_last = us_curr;
      if ( us_last == us_first )
            us_first++;
}

void pop_undo_stack(void)
{
      copy_cpu(cpu_undo_stack[us_curr], cpu);
}

void push_undo_stack(void)
{
      copy_cpu(cpu, cpu_undo_stack[us_curr]);
}

void copy_operation_stack(t_stack_element *from, t_stack_element **to)
{
      t_stack_element *from_curr, *to_curr, *to_remove, *to_prev;
      t_stack_element pre_head;

      if (*to == NULL ) {
            *to = (t_stack_element*) malloc (sizeof(t_stack_element));
            verify_malloc(*to);
            (*to)->next = NULL;
      }

      from_curr = from;
      to_curr = *to;

      /* pre_head is introduced to have a stack element whose next is
       * the stack head; it is not needed; it is introduced ONLY
       * to prevent compiler warnings and for uniformity. */
      pre_head.next = to_curr;
      to_prev = &pre_head;

      while (from_curr != NULL) {
            if (to_curr == NULL) {
                  to_curr = (t_stack_element*) 
                        malloc (sizeof(t_stack_element));
                  verify_malloc(to_curr);
                  to_curr->next = NULL;
                  to_prev->next = to_curr;
            }
            to_curr->z = from_curr->z;
            to_curr->op = from_curr->op;
            to_curr->number_of_parens = from_curr->number_of_parens;

            to_prev = to_curr;
            to_curr = to_curr->next;
            from_curr = from_curr->next;        
      }

      to_prev->next = NULL;
      
      while (to_curr != NULL) {
            to_remove = to_curr;
            to_curr = to_curr->next;
            free(to_remove);
      }
      
      if (from == NULL) 
            *to = NULL; /* the memory is already freed */
}

void copy_cpu(t_calcoo_cpu *from, t_calcoo_cpu *to)
{
      int i, j;

      to->x = from->x;
      to->y = from->y;
      to->z = from->z;
      to->t = from->t;

      for(i = 0; i < NUMBER_OF_MEMS; i++)
            to->mem[i] = from->mem[i];

      to->op = from->op;
      to->number_of_parens = from->number_of_parens;

      copy_operation_stack(from->stack_head, &(to->stack_head));

      copy_display(from->d, to->d);

      to->curr_mem = from->curr_mem;

      for(j = 0; j < NUMBER_OF_MEMS; j++)
            copy_display(from->mem_d[j], to->mem_d[j]);

      for(j = 0; j < NUMBER_OF_REG_DISPLAYS; j++) {
            copy_display(from->reg_d[j], to->reg_d[j]);
            to->op_d[j]->op_code = from->op_d[j]->op_code;
            to->op_d[j]->show_brace = from->op_d[j]->show_brace;
      }

      to->last_action = from->last_action;
      to->x_overflow = from->x_overflow;
      to->prescribed_format = from->prescribed_format;
      to->enter_mode = from->enter_mode;
      to->error = from->error;
}

void copy_display(t_cpu_display *from, t_cpu_display *to)
{
      int i;

      to->input_field = from->input_field; 
      to->sign = from->sign;
      to->exp_sign = from->exp_sign;
      for (i = 0; i < INPUT_LENGTH; i++)
            to->int_field[i] = from->int_field[i];
      for (i = 0; i < INPUT_LENGTH; i++)
            to->frac_field[i] = from->frac_field[i];
      for (i = 0; i < EXP_INPUT_LENGTH; i++)
            to->exp_field[i] = from->exp_field[i];
      to->n_int = from->n_int;
      to->n_frac = from->n_frac;
      to->display_overflow = from->display_overflow;
      to->format = from->format;
}

Generated by  Doxygen 1.6.0   Back to index