/* e4calc_2.c (c)Copyright Sequiter Software Inc., 1991-1994. All rights reserved. */

#include "d4all.h"
#ifndef S4UNIX
#ifdef ___TURBOC__
#pragma hdrstop
#endif
#endif

int S4FUNCTION expr4calc_remove( EXPR4CALC *calc, int remove_all )
{
  LIST4 save_calc_list, temp_calc_list ;
  EXPR4CALC *calc_on ;
  CODE4 *c4base = calc->expr->code_base ;
  int transfered_one ;
  EXPR4 *expr ;

  memcpy( &save_calc_list, &c4base->calc_list, sizeof( save_calc_list ) ) ;
  memcpy( &temp_calc_list, &c4base->calc_list, sizeof( save_calc_list ) ) ;
  memset( &c4base->calc_list, 0, sizeof( c4base->calc_list ) ) ;

  l4remove( &temp_calc_list, calc ) ;

  /* Check other calculations */
  for( transfered_one = 1; transfered_one; )
  {
    transfered_one = 0 ;
    for( calc_on = (EXPR4CALC *) l4first(&temp_calc_list); calc_on; )
    {
      EXPR4CALC *calc_next = (EXPR4CALC *)l4next( &temp_calc_list, calc_on ) ;

      c4base->expr_error = 0 ;
      expr = expr4parse( calc_on->expr->data, expr4source( calc_on->expr ) ) ;
      c4base->expr_error = 1 ;
      if( expr )
      {
        expr4free( expr ) ;
        l4remove( &temp_calc_list, calc_on ) ;
        l4add( &c4base->calc_list, calc_on ) ;
        transfered_one = 1 ;
      }

      calc_on = calc_next ;
    }
  }

  if( remove_all == 0 )
  {
    if( temp_calc_list.n_link > 0 )
    {
      l4add( &temp_calc_list, calc ) ;
      for( ;; )
      {
        calc_on = (EXPR4CALC *)l4pop( &temp_calc_list ) ;
        if ( calc_on == 0 )
          break ;
        l4add( &c4base->calc_list, calc_on ) ;
      }
      return 1 ;
    }
    l4add( &c4base->calc_list, calc ) ;
    return 0 ;
  }

  /* Remove calculations */
  l4add( &temp_calc_list, calc ) ;

  for( ;; )
  {
    calc_on = (EXPR4CALC *)l4pop( &temp_calc_list ) ;
    if ( calc_on == 0 )
      break ;
    l4add( &c4base->calc_list, calc_on ) ;
    expr4calc_delete( calc_on ) ;
  }

  return 0 ;
}

int S4FUNCTION expr4calc_modify( EXPR4CALC *calc, char *expr_source )
{
  EXPR4 *expr ;
  EXPR4CALC *next_calc, *calc_next ;
  CODE4 *code_base ;
  LIST4 save_calc_list, temp_calc_list ;
  EXPR4CALC *calc_on ;
  CODE4 *c4base = calc->expr->code_base ;
  int transfered_one ;

  memcpy( &save_calc_list, &c4base->calc_list, sizeof( save_calc_list ) ) ;
  memcpy( &temp_calc_list, &c4base->calc_list, sizeof( save_calc_list ) ) ;
  memset( &c4base->calc_list, 0, sizeof( c4base->calc_list ) ) ;

  l4remove( &temp_calc_list, calc ) ;

  /* Check other calculations */
  for( transfered_one = 1; transfered_one; )
  {
    transfered_one = 0 ;
    for( calc_on = (EXPR4CALC *)l4first(&temp_calc_list); calc_on ; )
    {
      calc_next = (EXPR4CALC *)l4next( &temp_calc_list, calc_on ) ;

      c4base->expr_error = 0 ;
      expr = expr4parse( calc_on->expr->data, expr4source( calc_on->expr ) ) ;
      c4base->expr_error = 1 ;
      if( expr )
      {
        expr4free( expr ) ;
        l4remove( &temp_calc_list, calc_on ) ;
        l4add( &c4base->calc_list, calc_on ) ;
        transfered_one = 1 ;
      }

      calc_on = calc_next ;
    }
  }

  expr = expr4parse( calc->expr->data, expr_source ) ;

  l4add( &c4base->calc_list, calc ) ;
  if( temp_calc_list.n_link > 0 )
    for( ;; )
    {
      calc_on = (EXPR4CALC *)l4pop( &temp_calc_list ) ;
      if ( calc_on == 0 )
        break ;
      l4add( &c4base->calc_list, calc_on ) ;
    }

  if( expr == 0 )
    return -1 ;

  expr4free( calc->expr ) ;
  calc->expr = expr ;
  expr4calc_massage( calc ) ;

  next_calc = (EXPR4CALC *)l4first( &c4base->calc_list ) ;
  while( next_calc )
  {
    expr = expr4parse( next_calc->expr->data, expr4source( next_calc->expr ) ) ;
    if( expr == 0 )
      return -1 ;

    expr4free( next_calc->expr ) ;
    next_calc->expr = expr ;
    expr4calc_massage( next_calc ) ;
    next_calc = (EXPR4CALC *)l4next( &c4base->calc_list, next_calc ) ;
  }

  return 0 ;
}