#include #include #include #include #include "stack.h" #include "card.h" #include "common.h" void stack_malloc(struct stack **stack) { if (!(*stack = malloc(sizeof(**stack)))) { tty_solitaire_generic_error(errno, __FILE__, __LINE__); } card_malloc(&((*stack)->card)); } void stack_init(struct stack *stack) { card_init(stack->card); stack->next = NULL; } void stack_free(struct stack *stack) { struct stack *tmp; for (; stack; stack = tmp) { tmp = stack->next; card_free(stack->card); free(stack); } } struct stack *stack_dup(struct stack *stack) { struct stack *iterator = stack; struct stack *tmp_stack, *new_stack; stack_malloc(&new_stack); stack_malloc(&tmp_stack); stack_init(new_stack); stack_init(tmp_stack); for (iterator = stack; iterator; iterator = iterator->next) { stack_push(&tmp_stack, card_dup(iterator->card)); } while (!stack_empty(tmp_stack)) { stack_push(&new_stack, (stack_pop(&tmp_stack))); } stack_free(tmp_stack); return(new_stack); } bool stack_empty(struct stack *stack) { return(stack->card->value == NO_VALUE && stack->card->suit == NO_SUIT && stack->card->face == NO_FACE && !stack->next); } int stack_length(struct stack *stack) { int stack_length = 0; if (!stack_empty(stack)) { for (stack_length = 1; stack->next; stack = stack->next, stack_length++) ; } return(stack_length); } void stack_push(struct stack **stack, struct card *card) { if (card) { if (stack_empty(*stack)) { card_free((*stack)->card); (*stack)->card = card; } else { /* Allocating by hand because stack_malloc() would * have allocated an unwanted card object. */ struct stack *new_stack = malloc(sizeof(*new_stack)); new_stack->card = card; new_stack->next = (*stack); *stack = new_stack; } } } struct card *stack_pop(struct stack **stack) { if(stack_empty(*stack)) { return(NULL); } else { struct card *popped_card = (*stack)->card; if (stack_length(*stack) == 1) { /* Remembering the stack position before clearing it. */ int begin_y = (*stack)->card->frame->begin_y; int begin_x = (*stack)->card->frame->begin_x; card_malloc(&((*stack)->card)); /* A stack_empty stack is a stack with a blank top card * and with stack->next == NULL. */ card_set((*stack)->card, NO_VALUE, NO_SUIT, NO_FACE, begin_y, begin_x); (*stack)->next = NULL; } else { struct stack *tmp = *stack; *stack = (*stack)->next; free(tmp); } return(popped_card); } } struct stack *stack_reverse(struct stack *stack) { struct stack *tmp_stack, *iterator; stack_malloc(&tmp_stack); stack_init(tmp_stack); if (stack_length(stack) > 1) { for (iterator = stack; iterator; iterator = iterator->next) { stack_push(&tmp_stack, card_dup(iterator->card)); } } else { card_set(tmp_stack->card, stack->card->value, stack->card->suit, stack->card->face, stack->card->frame->begin_y, stack->card->frame->begin_x); } return(tmp_stack); }