// file: $isip/util/demo/isip_comm_server_dialog_manager/isip_comm_dialog_manager_functions.cc
// version: $Id: isip_comm_dialog_navigation_mgr_func.cc 10019 2005-04-22 15:15:22Z elliott $
//

#include "isip_comm_dialog_navigation_mgr.h"

// transform functions

// "null() is CU's function but could not be used in C++ so that's why
// null_1char and null_3char were created
// These functions are private to this file so that's why they are not in
// the header file
//
void null() {
  //do nothing
  //
}
void null_1char(char*a) {
  //do nothing
  //
}
void null_3char(char *a, char *b, char *c) {
  //do nothing
  //
}

void x_number(char *p) {
  int number = -1;
  char line[LINE_LEN];
  char *c = p;
  char *lp = line;
  
  // Clear the line so no garbage is left over
  // 
  memset(line,0,sizeof(line));
  
  // extract to date-time structure 
  if( parse_int(p, &number) < 0 ) {
    // empty
  }
  
  if (number >= 0) {
    
    // copy [Number] portion 
    if ((c = strchr(c, '.'))) {
      c++;
      *c = '\0';
    }
    sprintf(lp, "%s%d", p, number);
    printf("lp = %s\n", lp);
    
    // copy the remaining portion 
    c++;
    if ((c = strchr(c, '[')) ) {
      strcat(lp, " ");
      strcat(lp, c);
    }
    strcpy(p, line);
  } // end if
} // end x_number()

void x_date_time(char *p) {
  char line[LINE_LEN];
  char tmp[LINE_LEN];
  char mon[50];
  char dd[50];
  char *lp;
  
  // Memset clear all buffers so nothing
  // will be left over
  memset(line,0,sizeof(line));
  memset(tmp,0,sizeof(tmp));
  memset(dd,0,sizeof(dd));
  memset(mon,0,sizeof(mon));
  
  clear_dt(&dt);
  set_today(&today);
  
  // extract to date-time structure 
  if( parse_date_time(p, &dt) < 0 ) {
    // This is a stupid call. This is how CU had it      
  }
  ref_date = dt;
  set_ref_date(&ref_date);
  
  line[0] = '\0';
  lp = line;
  
  if( dt.month >= 0 ) {
    sprintf(lp, "[Date].[Month].%d\n", dt.month);
    endl(lp);
  }
  if( dt.day >= 0 ) {
    sprintf(lp, "[Date].[Day].%d\n", dt.day);
    endl(lp);
  }
  
  // set tolerance if at time 
  if( (dt.start_time >= 0) && (dt.start_time == dt.end_time) ) {
    dt.start_time -= 100;
    if( dt.start_time < 0 )
      dt.start_time = 0;
    dt.end_time += 100;
    if( dt.end_time > 2400 )
      dt.end_time = 2400;
  }
  if( dt.start_time >= 0 ) {
    sprintf(lp, "[Start_Time].%d\n", dt.start_time);
    endl(lp);
  }
  if( dt.end_time >= 0 ) {
    sprintf(lp, "[End_Time].%d\n", dt.end_time);
    endl(lp);
  }
  
  // if anytime 
  if( strstr(p, "[Time_Range]" )) { // If "[Time_Range]" found in p
    
    if( (dt.start_time < 0) && (dt.end_time <0) ) {
      sprintf(lp, "[Start_Time].* [End_Time].*\n");
      endl(lp);
    }
  }
  
  // print and save date string for use in prompts 
  if( (dt.month >= 0) && (dt.day >= 0) ) {
    sprintf(mon, "%d", dt.month);
    sprintf(dd, "%d", dt.day);
    print_date(tmp, mon, dd);
    sprintf(lp, "[date_str].%s\n", tmp); endl(lp);
  }
  // clear confirmed flag 
  setConfirm(prompted.frame, "[date_str]", 0);
  
  // If line has something in it, put it to p to be returned
  //
  if( line[0] )
    strcpy(p,line);
}

void x_time_range(char *p) {
  char line[LINE_LEN];
  char *lp;
  
  // Memset clear all buffers so nothing
  // will be left over
  memset(line,0,sizeof(line));
  
  dt.start_time = -1;
  dt.end_time = -1;
  line[0] = (char)0;
  lp = line;
  
  parse_time_range(p, &dt.start_time, &dt.end_time);
  
  if( (dt.start_time < 0) && (dt.end_time <0) ) {
    strcpy(p, "[Start_Time].* ");
    strcat(p, "[End_Time].*\n");
    return;
  }
  
  // set tolerance if at time 
  if( (dt.start_time >= 0) && (dt.start_time == dt.end_time) ) {
    dt.start_time -= 100;
    if( dt.start_time < 0 )
      dt.start_time = 0;
    dt.end_time += 100;
    if( dt.end_time > 2400 )
      dt.end_time = 2400;
  }
  
  line[0] = (char)0;
  lp = line;
  
  if( dt.start_time >= 0 ) {
    sprintf(lp, "[Start_Time].%d ", dt.start_time);
    endl(lp);
  }
  if( dt.end_time >= 0 ) {
    sprintf(lp, "[End_Time].%d ", dt.end_time);
    endl(lp);
  }
  if( ( dt.start_time >= 0 ) || ( dt.end_time >= 0 ) ) {
    strcat(lp, "\n");
    endl(lp);
  }
  
  if( line[0] )
    strcpy(p,line);
}

void decline_form(char *p) {
  strcpy(p, "[Active].no");
}

//  state manipulation functions 

void set_confirmed(char *frame_name, char *key, char *val) {
  aFrame	*frame;
  char	*vv;
  
  // if no prompted frame 
  if( !prompted.frame )
    return;
  
  frame = prompted.frame;
  
  if( (vv = getVal(frame, "[Depart_Loc].[City_Name]")) ) {
    setConfirm(frame, "[Depart_Loc].[City_Name]", 1);
  }
  if( (vv = getVal(frame, "[Arrive_Loc].[City_Name]")) ) {
    setConfirm(frame, "[Arrive_Loc].[City_Name]", 1);
  }
  if( (vv = getVal(frame, "[Depart_Loc].[Address]")) ) {
    setConfirm(frame, "[Depart_Loc].[Address]", 1);
  }
  if( (vv = getVal(frame, "[Arrive_Loc].[Address]")) ) {
    setConfirm(frame, "[Arrive_Loc].[Address]", 1);
  }
  if( (vv = getVal(frame, "[date_str]")) ) {
    setConfirm(prompted.frame, "[date_str]", 1);
  }
}

#if 0
/*
  void help(char *frame_name, char *key, char *val)  {
  // Unneeded airplane stuff
  // Removed code
  //
  static int i = 0;
  if ( prompted.frame ) return;
  
  switch (i%2) {
  case 0:
  prompt = "you may query about driving direction, airline ticket "
  "reservation, hotel and rental car";
  break;
  case 1:
  prompt = "you may say things like, I want to drive or fly from "
  "one place to another place, or I need a direction from one "
  "city to another city. ";
  break;
  }
  i++;
  }
*/
#endif


void repeat(char *frame_name, char *key, char *val) {
  action = "repeat";
}


void accept_response(char *frame_name, char *key, char *val) {
  int i;
  
  // if no prompt, accept not valid 
  if( !prompted.frame ) return;
  if( !prompted.key ) return;
  
  // set row in focus 
  if( !val || !*val ) {
  }
  else {
    if( !parse_int(val, &i) ) return;
    if( --i < 0 ) i=0;
    printf("set row_in_focus= %d\n", i);
    row_in_focus= i;
  }
  
  // if Accept prompted for 
  if( !scmp("[accept]", prompted.key) ){
    
    // save accepted record in frame 
    one_row = set_selection(prompted.frame, row_in_focus);
    
    //mwe-I dont know if we will ever use "accept_response"
    //but this part is useless
    /*
    // mark frame as accepted
    if( !scmp("optimize_price", airmode) &&
    !scmp("Air", prompted.frame->name) ) {
    
    // if nine_best scenario
    for(af= getFrame(context, "Air", "first", &xx); af;
    af= getFrame(context, "Air", "next", &xx)){
    
    setKey(af, "[accept]", "yes");
    }
    }
    else
    setKey(prompted.frame, "[accept]", "yes");
    */
    
    data_current= (aFrame *)0;
  }
  
  /* if in verify mode */
  else if( !scmp("[Correct]", prompted.key) ){
    setKey(prompted.frame, "[Correct]", "yes");
  }
}

void yes(char *frame_name, char *key, char *val) {
  //aFrame *next; //unused variable mwe
  
  if( !prompted.key ) return;
  
  /* yes confirms a value */
  if( !scmp("confirm", prompted.type) ){
    setConfirm(prompted.frame, prompted.key, 1);
    return;
  }
  
  //mwe-useless airplane code
  /*
  // if confirming air frame, update next leg if exist
  if( prompted.frame && !scmp("Air", prompted.frame->name) &&
  !scmp("[confirmed]", prompted.key) ){
  if( (next= get_next_leg(prompted.frame)) ) {
  set_next_leg(prompted.frame, next);
  }
  setKey(prompted.frame, prompted.key, "yes");
  return;
  }
  */
  
  /* yes  to retry */
  if( !scmp("[retry]", prompted.key) ){
    retry= 1;
    return;
  }
  
  /* yes  to alternates list */
  /*
    if( !scmp("_alternates", prompted.key) ){
    row_in_focus= 1;
    row_abs= 2;
    prompt="Option one is your current schedule.";
    nl_request("prompt_user",prompt,NULL,1,main_server_data, (char *)0);
    prompt= (char *)0;
    //nl_task= "summarize_alt";
    return;
    }
  */
  
  /* yes  to new depart date */
  /*if( !scmp("[date_str]", prompted.key) ){
    setKey(prompted.frame, prompted.key, (char *)0);
    backoff_cnt= 0;
    return;
    }
  */
  /*
    if( !scmp("[Hotel_Name]", prompted.key) ){
    // clear old hotel name
    setKey(prompted.frame, prompted.key, (char *)0);
    return;
    }
    if( !scmp("[Rental_Company]", prompted.key) ){
    setKey(prompted.frame, prompted.key, (char *)0);
    return;
    }
  */
  
  /* if yes to start over */
  if( !scmp("startover", prompted.key) ){
    Reset_dm(frame_name, key, val);
    return;
  }
  
  if( !scmp("[Active]", prompted.key) ){
  }
  //else if( !scmp("[Correct]", prompted.key) ){
  //}
  //else if( !scmp("[accept]", prompted.key) ){
  //    data_current= (aFrame *)0;
  //	val= (char *)0;
  //}
  //else if( !scmp("[Summarize]", prompted.key) ){
  //}
  //else if( !scmp("[Email]", prompted.key) ){
  //}
  //else if( !scmp("[Success]", prompted.key) ){
  //}
  //else if( !scmp("[Real]", prompted.key) ){
  //}
  //else if( !scmp("[airline_pref]", prompted.key) ){
  //}
  
  
  else if( !scmp("yes", prompted.type) ){
  }
  else if( !scmp("[Arrive_Loc]", prompted.key) ) {
    prompt="Okay go ahead.";
    check_function(prompted.frame->name, prompted.key, val);
    return;
  }      
  else if( !scmp("[Depart_Loc]", prompted.key) ) {
    prompt="Okay go ahead.";
    check_function(prompted.frame->name, prompted.key, val);
    return;
  }      
  else return;
  
  // execute function associted with prompted slot 
  check_function(prompted.frame->name, prompted.key, val);
  
  setKey(prompted.frame, prompted.key, "yes");
}

void no(char *frame_name, char *key, char *val) {
  
  if( !prompted.key ) return;
  
  if (is_debug)
    printf("entered 'no()' with prompted.key = %s\n", prompted.key);
  
  // if no in response to confirm 
  if( !scmp("confirm", prompted.type) ){
    setConfirm(prompted.frame, prompted.key, 0);
    // clear incorrect info 
    setKey(prompted.frame, prompted.key, (char *)0);
    return;
  }
  
  // no to alternates list 
  //if( !scmp("_alternates", prompted.key) ){
  //  data_current= (aFrame *)0;
  //  return;
  //}
  
  // if no to start over 
  if( !scmp("startover", prompted.key) ){
    hangup= 1;
    return;
  }
  
  if( !scmp("[Active]", prompted.key) ){
  }
  //else if( !scmp("[Summarize]", prompted.key) ){
  //}
  /*
    else if( !scmp("[accept]", prompted.key) ){
    if( !scmp("summarize_alt", nl_task) ) {
    prompt="Ok we'll keep your original schedule.";
    nl_request("prompt_user",prompt,NULL,1,main_server_data, (char *)0);
    prompt= (char *)0;
    data_current= (aFrame *)0;
    nl_task= (char *)0;
    return;
    }
    select_row(frame_name, "[Select_Row]", "next");
    return;
    }
  */
  //else if( !scmp("[Email]", prompted.key) ){
  //}
  //else if( !scmp("[Success]", prompted.key) ){
  //}
  //else if( !scmp("[Real]", prompted.key) ){
  //}
  else if( !scmp("yes", prompted.type) ){
  }
  
  // if user don't want to specify locations 
  else if( !scmp("[Arrive_Loc].[Place_Type]", prompted.key)) {
    setKey(prompted.frame, "[Arrive_Loc].[Place_Type]", "*");
    setKey(prompted.frame, "[Arrive_Loc].[Place_Name]", "*");
    return;
  }      
  else if( !scmp("[Arrive_Loc].[Place_Name]", prompted.key)) {
    setKey(prompted.frame, "[Arrive_Loc].[Place_Name]", "*");
    return;
  }      
  else if( !scmp("[Depart_Loc].[Place_Name]", prompted.key)) {
    setKey(prompted.frame, "[Depart_Loc].[Place_Name]", "*");
    return;
  }
  else if( !scmp("[Arrive_Loc].[Address]", prompted.key) || 
	   !scmp("[Arrive_Loc].[address]", prompted.key)) {
    setKey(prompted.frame, "[Arrive_Loc].[Address]", "*");
    // clear the text version 
    setKey(prompted.frame, "[Arrive_Loc].[address]", (char *)0);
    return;
  }      
  else if( !scmp("[Depart_Loc].[Address]", prompted.key) ||
	   !scmp("[Depart_Loc].[Address]", prompted.key)) {
    printf("set %s\n", prompted.key);
    setKey(prompted.frame, "[Depart_Loc].[Address]", "*");
    // clear the text version 
    setKey(prompted.frame, "[Depart_Loc].[address]", (char *)0);
    return;
  }
  else return;
  
  setKey(prompted.frame, prompted.key, "no");
}

void anything(char *frame_name, char *key, char *val) {
  //  aFrame* prompt_frame;
  //  char** key_ptr;
  
  if( !prompted.key ) return;
  /*
    prompt_frame = prompted.frame;
    if( !scmp("Drive", prompt_frame->name) ) {
    if ( !scmp("[Depart_Loc]", prompted.key) ){
    key_ptr = getKeyPtr(prompt_frame, "[Depart_Loc].[Address]");
    if (*key_ptr != NULL) {
    prompt="Okay";
    return;
    }
    }     
    else if ( !scmp("[Arrive_Loc]", prompted.key) ){
    key_ptr = getKeyPtr(prompt_frame, "[Arrive_Loc].[Address]");
    if (*key_ptr != NULL) {
    prompt="Okay";
    return;
    }
    }
    }
  */
  
  printf("entered 'anything()' with prompted.key = %s\n", prompted.key);
  
  // if use don't want to specify the location 
  if( !scmp("[Arrive_Loc].[Place_Type]", prompted.key)) {
    setKey(prompted.frame, "[Arrive_Loc].[Place_Type]", "*");
    setKey(prompted.frame, "[Arrive_Loc].[Place_Name]", "*");
    return;
  }
  else if( !scmp("[Arrive_Loc].[Place_Name]", prompted.key)) {
    setKey(prompted.frame, "[Arrive_Loc].[Place_Name]", "*");
    return;
  }
  else if( !scmp("[Depart_Loc].[Place_Name]", prompted.key) ){
    setKey(prompted.frame, "[Depart_Loc].[Place_Name]", "*");
    return;
  }
  else if( !scmp("[Arrive_Loc].[Address]", prompted.key) || 
	   !scmp("[Arrive_Loc].[address]", prompted.key)) {
    setKey(prompted.frame, "[Arrive_Loc].[Address]", "*");
    // clear the text version 
    setKey(prompted.frame, "[Arrive_Loc].[address]", (char *)0);
    return;
  }      
  else if( !scmp("[Depart_Loc].[Address]", prompted.key) ||
	   !scmp("[Depart_Loc].[Address]", prompted.key)) {
    setKey(prompted.frame, "[Depart_Loc].[Address]", "*");
    // clear the text version 
    setKey(prompted.frame, "[Depart_Loc].[address]", (char *)0);
    return;
  }
  
  else if( !scmp("[Arrive_Place].[Place_Name]", prompted.key) ) {
    if (!scmp("Cityguide", prompted.frame->name) ) {
      setKey(prompted.frame, "[Arrive_Place].[Place_Spec]", "*");
      setKey(prompted.frame, "[Arrive_Place].[Place_Name]", "*");
      return;
    }
  }
  else if( !scmp("[arrive_address]", prompted.key) ) {
    setKey(prompted.frame, "[Arrive_Loc].[Address]", "*");
    setKey(prompted.frame, prompted.key, "no");
    return;
  }      
  else if( !scmp("[depart_address]", prompted.key) ) {
    setKey(prompted.frame, "[Depart_Loc].[Address]", "*");
    setKey(prompted.frame, prompted.key, "no");
    return;
  }      
  
  // fill prompted slot and associated form field with "*" 
  fill_prompted("*");
  
}
void Reset_dm(char *frame_name, char *key, char *val) {
  task = "reset";
}

// Support Functions

// Cityguide domain special 

// 1. transform functions 

void x_query(char *p) {
  char line[LINE_LEN];
  char *c = p;
  
  // Clear line
  memset(line,0,sizeof(line));
  
  if ((c = strchr(c, ']'))) {
    //    *c = '\0';
    sprintf(line, "[question_type].%s", c+2);
    strcpy(p, line);    
  }
}

void x_address(char *p) {
  char line[LINE_LEN];
  char adr[LINE_LEN];
  char *c = p;
  char *cur = p;
  char *lp = line;
  char *lp_adr = adr;
  int count;
  int number = -1;
  
  // Clear buffers
  memset(line,0,sizeof(line));
  memset(adr,0,sizeof(adr));
  
  // copy "[Address]." string 
  if ((c = strchr(c, '.'))) {
    *c = 0;
    count = sprintf(lp, "%s.", cur);
    lp += count;
    count = sprintf(lp_adr, "[address].");
    lp_adr += count;
  }
  
  // copy [Street_Name] portion and converted [Number] 
  cur = c + 1;
  while ((c = strchr(cur, '.'))) {
    *c = 0;
    
    // if it's [Number] portion 
    if (!strcmp(cur, "[Number]")) {
      
      // get number converted 
      *c = '.';
      if( parse_int(cur, &number) < 0 ) {
	// Not sure why CU left this empty
      }
      
      if (number >= 0) {
	
	// copy [Number] portion 
	count = sprintf(lp, "%d ", number);
	lp += count;
      }
      
      // copy number string to [address] 
      cur = c + 1;
      if ((c = strchr(cur, '['))) {
	c--;
	*c = '\0';
	count = sprintf(lp_adr, "%s ", cur);
	lp_adr += count;
	cur = c + 1;
      }
      else {
	sprintf(lp_adr, "%s", cur);
	break;
      }
      
    } // if [Number]
    
    // if [Street_Name] portion 
    else if (!strcmp(cur, "[Street_Name]")) {
      
      cur = c + 1;
      
      // copy [Street_Name] portion 
      if ((c = strchr(cur, '['))) {
	c--;
	*c = '\0';
	count = sprintf(lp, "%s ", cur);
	lp += count;
	count = sprintf(lp_adr, "%s ", cur);
	lp_adr += count;
	cur = c + 1;
      }
      else {
	sprintf(lp, "%s", cur);
	sprintf(lp_adr, "%s", cur);
	break;
      }
    }
    
    // if not [Address] portion, simply copy the rest 
    else {
      *c = '.';
      sprintf(lp_adr, "%s", cur);
      break;
    }
  }
  
  // output [Address].110 LEE BLVD [address].ONE ONE ZERO LEE BLVD [rest] 
  strcpy(p, line);
  strcat(p, adr);
}

void x_place_name(char *p) {
  char line[LINE_LEN];
  char *c = p;
  char *lp = line;
  int count;
  
  // Clear out line
  memset(line,0,sizeof(line));
  
  printf("pre_address = %s\n", p);
  
  //This is the problem area
  //  pre_address =
  //    [Place_Name].WAL-MART
  //    [Arrive_Loc].[Place_Spec].NEW
  //    [Place_Name].[Supermarket_Name].WAL-MART 
  //  x_address =
  //    [Place_Name].[Place_Spec].NEW
  //    [Place_Name].[Supermarket_Name].WAL-MART 
  //  !!!END!!!Value =
  //    [[Place_Name].[Place_Spec].NEW
  //    [Place_Name].[Supermarket_Name].WAL-MART ]
  //  Ending key-val:
  //    ^^[question_type].query_map
  //    [Depart_Loc].[Place_Spec].OLD
  //    [Place_Name].[Place_Spec].NEW
  //    [Place_Name].[Supermarket_Name].WAL-MART ^^
  
  // copy [Place_Name] portion 
  
  // mwe - Below is my code to fix the problem of not expanding correctly
  if ((c = strchr(c, '.'))) {
    c++;
    
    //char *pNextBracket = strchr(c,']'); //mwe
    //printf("***cursor is at [%s]\n",c);
    
    if ((c = strchr(c, '.'))) {
      //if the ']' is farther than the '.', do not move it over //mwe
      //example is [Place_Name].Walmart [Arrive_Loc].[Place_Spec].bob
      //DOES NOT WANT [Place_Name].[Place_Spec].bob
      //but if [Place_Name].[SuperMarket].Walmart
      //DO WANT [Place_Name].Walmart
      //if (pNextBracket == NULL || c > pNextBracket) { //mwe
      count = sprintf(lp, "[Place_Name]%s", c);
      lp += count;
    }
  }
  
  // copy [Place_Type] portion 
  //
  /*  c = p + 1;
      count = sprintf(lp, "[Place_Type].");
      lp += count;
      if ((c = strchr(c, '['))) {
      while (*(++c) != '_') {
      *lp = toupper(*c);
      lp++;
      }
      *lp = '\0';
      }
  */
  
  
  strcpy(p, line);
  printf("x_address = %s\n", p);
}

void x_place_spec(char *p) {
  char *c = p;
  
  printf("pre_place_spec = %s\n", p);
  
  // replace [Place_Spec].optimize distance with
  // [optimize_mode].optimize_distance
  //
  if ((c = strstr(c, "optimize distance"))) {
    // 18 is length of 'optimize distance'
    //
    c += 18;
    strcpy(p, c);
    strcat(p, "[optimize_mode].optimize_distance");
  }
  
  if ((c = strstr(p, "[Place_Name]"))) {
    x_place_name(c);
  }
  
  printf("post_place_spec = %s\n", p);
}

void x_active(char *p) {
  sprintf(p, "[Active].yes");
}

// 2. state manipulation functions 

// This function is never used although the comment is there in
// check_drive_generic and all the check_drive_XXXX's
void user_query(char *frame_name, char *key, char *val) {
  /*
    int	xx;
    aFrame *frame;
    aFrameDef *fd;
    Slot *s;
    int node;
  */
  if( !val ) return;
  
  // reset some required slot for this query 
  /*
    if( !strcmp("[user_query]", key) ) {
    if( !strcmp("Query_Direction", val) ) {
    if( (frame= getFrame(context, frame_name, "first", &xx)) ) {    
    if ( !(fd = getFrameDef(frame_name)) ) {
    return;
    }
    
    for (node = 0; node < fd->n_slot; node++) {
    s = fd->slot + node;
    if (!scmp("[Depart_Loc].[address]", s->key)) {
    s->required = '+';
    break;
    }
    }
    }
    }
    }
  */
  
  // if no current data 
  /*
    if( !data_current || (db_rows <= 0) ) {
    prompt="Ok, I need more information about your query.";
    nl_request("prompt_user",prompt,NULL,1,main_server_data, (char *)0);
    prompt= (char *)0;
    row_abs= 0;
    }
  */
}

//* Function Table *

// array to associate nets with their mapping function 
const struct x_fun xform[] = {
  {"[Date_Time]", 	x_date_time},
  {"[Time_Range]", 	x_time_range},
  {"[Decline]", 	decline_form},
  {"[Address]",         x_address},
  {"[Place_Name]",      x_place_name},
  {"[Place_Spec]",      x_place_spec},
  {"[Query_Address]",   x_query},
  {"[Query_List]",      x_query},
  {"[Query_Direction]", x_query},
  {"[Query_Distance]",  x_query},
  {"[Query_Building]",  x_query},
  {"[Drive_Active]",    x_active},
  {NULL, null_1char}
};

// array to associate slots with their state change function 
const struct s_fun state_fun[] = {
  {"[Accept]", 		accept_response},
  {"[accept]", 		accept_response},
  //{"[Summarize]", 	summarize},
  //{"[Correction]", 	correction},
  {"[Yes]", 		yes},
  {"[No]", 		no},
  {"[Anything]", 	anything},
  {"[Options]", 	anything},
  {"[Reset]", 		Reset_dm},
  {"[Repeat]", 		repeat},
  {"[confirmed]", 	set_confirmed},
  //{"[Help]",            help},
  {"[user_query]",      user_query},
  {NULL, null_3char}
};

void check_transform( char *tree) {
  int	    i;
  char    key[LABEL_LEN];
  
  get_slot(tree, key);
  
  // see if xform function associated with key 
  for(i = 0; true; i++) {
    if( !xform[i].name || !strcmp(xform[i].name, key)) 
      break;
  }
  
  if( !xform[i].name ) 
    return;
  
  // execute transform function 
  if( xform[i].fun ) { 
    // debug
    // printf("!!!START!!!Value = [%s]\n",tree);
    (*xform[i].fun)(tree); 
    // printf("!!!END!!!Value = [%s]\n",tree);
    // end debug
  }
}

void check_function(char *frame_name, char *key,  char *val) {
  int     i;
  char    slot[LABEL_LEN];
  
  get_slot(key, slot);
  
  if( ( i = find_fun(slot)) < 0 )
    return;
  
  // execute function for slot
  if( state_fun[i].fun )
    (*state_fun[i].fun)(frame_name, key,  val);
}


int find_fun(char *slot) {
  int i;
  
  for(i = 0; true; i++) {
    if (!state_fun[i].name)
      break;
    
    if( !strcmp(state_fun[i].name, slot) )
      break;
  }
  
  // If no function, return error
  //
  if (!state_fun[i].name)
    return(-1);
  
  return(i);
}
