/* dBoxTools:loadDef.c */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "kernel.h"

#include "clibExtra.h"
#include "error.h"

#include "dboxtools.h"
#include "loadDef.h"
#include "find.h"
#include "main.h"
#include "debug.h"
#include "er.h"

static struct event
{ char *n;
  int  e;
} events[] =
{ {"action",0x82881},
  {"hidden",0x82890},
  {"",-1}
}; /* change this and use GSTrans instead *********/          

static int event( char *t, BOOL *message );

#define BUFF_SIZE 1000

static char *nextToken( char **to, char *string )
{ static char *pointer = 0;

  if( string )
    pointer = string; /* starting a new line    */
  else
    string = pointer; /* continuing with a line */

  if( *pointer == 0 ) return NULL; /* end of line */
  
  while( *pointer != '\t' && *pointer != 0 ) pointer++;

  if( *pointer == '\t' ) *pointer++ = 0;

  if( to ) *to = *string ? strdup( string ): NULL;
  return string;
}

void readDefinition( char *resources )
{ FILE *file;
  char buffer[BUFF_SIZE], *t, *b;
  Action *a, *last = NULL;
  Action *lastMapping = NULL, *lastFadedMapping = NULL, *lastMessage = NULL;
  int i;
  BOOL message;

  sprintf( buffer, "%s.def", resources ); 
  file = fopen( buffer, "r" );
  if( file == NULL ) defError( ERROR_DEF_WONT_OPEN, 0, -1 );
    
  /* object:component\tevent\tvalue\taction\t[additional parameters] */
  while( fgets( buffer, BUFF_SIZE, file ) )
  { line += 1;
    for( b = buffer; *b == ' '; b++ );      /* skip leading spaces     */
    if( *b == ';' || *b == '\n' ) continue; /* comment or empty line   */

    t = &buffer[ strlen( buffer ) - 1];     /* find the last character */
    if( *t == '\n' ) *t = 0;                /* remove \n if present    */

    /* object and component */
    t = nextToken( NULL, b );

    a = myMalloc( sizeof( Action ));
    *a = emptyAction;
    a->line = line;
    find_objectAndComponent( t, &a->object, &a->component);
  
    /* event code */
    t = nextToken( NULL, NULL );
    if( *t != 0 )
      a->event = event( t, &message );
    else
      message = FALSE;  
  
    /* value */
    t = nextToken( &a->value, NULL );

    /* action */
    t = nextToken( NULL, NULL );
    if( t == NULL ) defError( ERROR_ACTION_NOT_KNOWN, a->line, -1 );
    
    if( *t != 0 ) a->action = *t;
  
    /* load the parameters */
    for( i = 0; i < MAX_ARG; i++ )
      nextToken( &a->arg[i], NULL );

    /* add to the list */
    if( message )
    { if( firstMessage )
        lastMessage->next = a;
      else
        firstMessage = a;
      lastMessage = a;
    }
    else
    { switch( a->action )
      { case 'M':
          if( firstMapping )
            lastMapping->next = a;
          else
            firstMapping = a;
          lastMapping = a;
          break;

        case 'm':
          if( firstFadedMapping )
            lastFadedMapping->next = a;
          else
            firstFadedMapping = a;
          lastFadedMapping = a;
          break;
  
        default:
          if( firstAction )
            last->next = a;
          else
            firstAction = a;
          last = a;
      }
    }  
  }
  fclose( file );
  if( debug )
  { fputs( "\nToolbox events\n", debug);
    debug_actionList( firstAction );
    fputs( "\nMappings\n", debug);
    debug_actionList( firstMapping );
    fputs( "\nMessages\n", debug);
    debug_actionList( firstMessage );
  }  
}

static int event( char *t, BOOL *message )
{ struct event *p;

  while( *t == ' ' ) t++;
  if( *t == 0 ) return -1;
  if( *message = *t == 'M', *message ) t++;
  for( p = events; *p->n; p++ ) if( strcmp( p->n, t ) == 0 ) break;
  return p->e != -1 ? p->e : (int) strtol( t, &t, 16 );
}

/* end of dBoxTools:loadDef.c */
