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

TriggerEntity.cpp

#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef WIN32
extern "C" {
#endif
#include <regex.h>
#ifdef WIN32
}
#endif
#include <ctype.h>

#include "EntityHandler.h"
#include "TriggerEntity.h"
#include "PluginHandler.h"
#include "mudclient.h"

extern EntityHandler * entities;
extern PluginHandler * phandler;

TriggerEntity::TriggerEntity() : Entity() {

  body = NULL;
  text = NULL;
  trigger_type = TriggerSimple;
  mud = NULL;
  setType(EntityTrigger);
  stripColour = true;

  widget = NULL;

}

TriggerEntity::~TriggerEntity() {

  if (body)
    free(body);
  if (text)
    free(text);
  if (mud)
    free(mud);

}

void TriggerEntity::setStripColour(bool strip) {
  stripColour = strip;
}

bool TriggerEntity::getStripColour() {
  return stripColour;
}

static void replaceString(char * str, char c, char * rep) {
  char * curr = str;
  char * pc;

  while ((pc = strchr(curr, c))) {
    memmove(pc + strlen(rep),pc + 1, strlen(pc+1) + 1);
    memcpy(pc, rep, strlen(rep));
    curr = pc + strlen(rep);
  }
}

static void convert(char * buf) {
  replaceString(buf, '.', "\\.");
  replaceString(buf, '(', "\\(");
  replaceString(buf, ')', "\\)");
  replaceString(buf, '[', "\\[");
  replaceString(buf, ']', "\\]");
  replaceString(buf, '?', "(.)");
  replaceString(buf, '*', "(.+)");
}

void TriggerEntity::compile() {

  char buf[16384];

  //  regfree(&regexp);

  strcpy(buf, getText());
  if (getTriggerType() == TriggerSimple)
    convert(buf);

  regcomp(&regexp, buf, REG_ICASE|REG_EXTENDED);
}

void TriggerEntity::setMudName(char * n) {
  if (mud)
    free(mud);
  mud = strdup(n);
}

void TriggerEntity::setBody(char * b) {
  if (body)
    free(body);
  body = strdup(b);
}

void TriggerEntity::setText(char * t) {
  if (text)
    free(text);
  text = strdup(t);

  compile();
}

void TriggerEntity::setTriggerType(TriggerType t) {
  trigger_type = t;
}

char * TriggerEntity::getMudName() {
  return mud;
}

char * TriggerEntity::getBody() {
  if (body)
    return body;
  return "";
}

char * TriggerEntity::getText() {
  if (text)
    return text;
  return "";
}

TriggerType TriggerEntity::getTriggerType() {
  return trigger_type;
}

static int getReplacementString(char * output, int len, int pos, regex_t * regex, char i, char * input) {

  regmatch_t match[10];
  int nmatch = 10;

  int index;
  char index_str[2];

  index_str[0] = i;
  index_str[1] = '\0';
  index = atoi(index_str);

  if (index >= 10 || index < 0)
    return 0;

  if (regexec(regex, input, nmatch, match, 0) != REG_NOMATCH) {
    int length = match[index].rm_eo - match[index].rm_so;
    memcpy(output + pos, input + match[index].rm_so, length);
    return length;
  } else { // No match
    return 0;
  }

}

static int append_char(char * output, int len, int pos, char c) {
  if (pos >= len) {
    output[len-1] = '\0';
    return 0;
  }

  output[pos] = c;
  return 1;
}


void TriggerEntity::execute(Connection * c, char * input, char *) {
  /*
  char * input = strdup(in);
  char * ptr = input;
  */
  char * last;

#if 0
  if (getStripColour()) {
    // Strip all colour codes.
    while (*ptr != '\0') {
      
      // If we have hit ESCAPE, look for the next alpha character.
      if (*ptr == '\033') {
      last = ptr;
      
      while (!isalpha(*ptr))
        ptr++;
      
      ptr++;
      
      memmove(last, ptr, strlen(ptr) + 1);
      ptr = last;
      
      continue;
      }
      
      ptr++;
    }
  }
#endif

  char output[32768];
  int output_len = 32768;

  char * pc = getBody();

  if (!strncasecmp(pc, "#python", 7)) {
    void * handle = phandler->findPlugin("PythonPlugin");

    dl_call_func_int_ret(handle, "python_alias_exec", pc, (void *)c, input);
    free(input);
    return;
  }

  char out_pos = 0;

  output[0] = '\0';

  if (output_len == 0) {
    free(input);
    return;
  }

  while (*pc != '\0') {
    // Normal character.
    if (*pc != '$') {
      append_char(output, output_len, out_pos, *pc);
      pc++;
      out_pos++;
      continue;
    } else { // $ character.
      if (*(pc+1) == '\0')
      break;
      else if (*(pc+1) == '$') { // $$
      append_char(output, output_len, out_pos, '$');
      pc += 2;
      out_pos++;
      continue;
      } else { // $[0-9]
      out_pos += getReplacementString(output, output_len, out_pos, &regexp, *(pc + 1), input);
      pc += 2;
      continue;
      }
    }
  }
  
  append_char(output, output_len, out_pos, '\0');

  c->getSocket()->write(output, strlen(output));
  free(input);
  return;
}

bool TriggerEntity::findExecute(EntityType t, char * field, char * value, void * data, bool multiple) {

  if (t != getType())
    return false;

  if (disabled)
    return false;

  regmatch_t pmatch[10];
  int nmatch = 10;

  Connection * conn = (Connection *)data;
  char * mud_name = conn->getMUD()->getName();

  // Is this trigger valid for this particular connection?
  if (getMudName() && strlen(getMudName()) > 0)
    if (strcmp(getMudName(), mud_name))
      return false;

  // Only do the copy operation if we actually need to regexp on this.
  if (!strcmp(field, "text")) {

    char * input = strdup(value);
    char * ptr = input;
    char * last;
    if (getStripColour()) {
      // Strip all colour codes.
      while (*ptr != '\0') {
      
      // If we have hit ESCAPE, look for the next alpha character.
      if (*ptr == '\033') {
        last = ptr;
      
        while (!isalpha(*ptr))
          ptr++;
      
        ptr++;
      
        memmove(last, ptr, strlen(ptr) + 1);
        ptr = last;
      
        continue;
      }
      
      ptr++;
      }
    }    

    if (regexec(&regexp, input, nmatch, pmatch, 0) == 0) {
      execute((Connection *)data, input, NULL);
      return true;
    }

    return false;
  }

  return false;
}

void TriggerEntity::save(FILE * fp) {
  fprintf(fp, "Trigger %s\n", getName());
  fprintf(fp, "Description\n");
  fprintf(fp, "%s", getDescription());
  if (strlen(getDescription()) > 0)
    if (getDescription()[strlen(getDescription()) - 1] != '\n')
      fprintf(fp, "\n");
  fprintf(fp, "EndDescription\n");
  fprintf(fp, "TriggerType %d\n", getTriggerType());
  fprintf(fp, "Text %s\n", getText());
  fprintf(fp, "Body\n");
  fprintf(fp, "%s", getBody());
  if (getBody()[strlen(getBody()) - 1] != '\n')
    fprintf(fp, "\n");
  fprintf(fp, "EndBody\n");
  fprintf(fp, "StripColour %d\n", getStripColour());
  fprintf(fp, "EndTrigger\n");
}

bool TriggerEntity::load(FILE * fp, char * name) {
  char buf[16384];
  char * ptr;

  setName(name);

  while (true) {
    if (!fgets(buf, 16384, fp)) {
      perror("fgets");
      return false;
    }

    if (!strncasecmp(buf, "Description", 11)) {
      ptr = loadBlock(fp, "EndDescription");
      if (!ptr)
      return false;
      setDescription(ptr);
      continue;
    }

    if (!strncasecmp(buf, "Body", 4)) {
      ptr = loadBlock(fp, "EndBody");
      if (!ptr)
      return false;
      setBody(ptr);
      continue;
    }

    if (!strncasecmp(buf, "Text", 4)) {
      char text[16384];
      if (sscanf(buf, "Text %[^\n]\n", text) == 1)
      setText(text);
      else {
      perror("fscanf");
      return false;
      }
      continue;
    }

    if (!strncasecmp(buf, "StripColour", 11)) {
      int tmp;
      if (sscanf(buf, "StripColour %d\n", &tmp) == 1)
      setStripColour((bool) tmp);
      else {
      perror("fscanf");
      return false;
      }
      continue;
    }

    if (!strncasecmp(buf, "TriggerType", 11)) {
      int tmp;
      if (sscanf(buf, "TriggerType %d\n", &tmp) == 1)
      setTriggerType((TriggerType)tmp);
      else {
      perror("fscanf");
      return false;
      }
      continue;
    }

    if (!strncasecmp(buf, "EndTrigger", 10)) {
      return true;
    }
      
  }
}

GtkWidget * TriggerEntity::getWidgets() {

  if (widget)
    return widget;

  GtkWidget *vbox7;
  GtkWidget *frame4;
  GtkWidget *table3;
  GtkWidget *label13;
  GtkWidget *scrolledwindow5;

  GtkWidget * trigger_body_view;
  GtkWidget * trigger_description_view;
  GtkWidget *label14;
  GtkWidget *frame5;
  GtkWidget *table4;
  GtkWidget *label15;
  GtkWidget *label16;
  GtkWidget *label17, *label7;
  GtkWidget *scrolledwindow6;
  GtkWidget *trigger_options_menu;
  GtkWidget *glade_menuitem;

  vbox7 = gtk_vbox_new (FALSE, 0);
  gtk_widget_ref (vbox7);
  gtk_widget_show (vbox7);

  frame4 = gtk_frame_new (_("General"));
  gtk_widget_ref (frame4);
  gtk_widget_show (frame4);
  gtk_box_pack_start (GTK_BOX (vbox7), frame4, TRUE, TRUE, 0);
  gtk_container_set_border_width (GTK_CONTAINER (frame4), 2);

  table3 = gtk_table_new (2, 2, FALSE);
  gtk_widget_ref (table3);
  gtk_widget_show (table3);
  gtk_container_add (GTK_CONTAINER (frame4), table3);
  gtk_container_set_border_width (GTK_CONTAINER (table3), 2);
  gtk_table_set_row_spacings (GTK_TABLE (table3), 2);
  gtk_table_set_col_spacings (GTK_TABLE (table3), 2);

  label13 = gtk_label_new (_("Name:"));
  gtk_widget_ref (label13);
  gtk_widget_show (label13);
  gtk_table_attach (GTK_TABLE (table3), label13, 0, 1, 0, 1,
                    (GtkAttachOptions) (GTK_FILL),
                    (GtkAttachOptions) (0), 0, 0);
  gtk_misc_set_alignment (GTK_MISC (label13), 0, 0.5);

  trigger_name = gtk_entry_new ();
  gtk_widget_ref (trigger_name);
  gtk_widget_show (trigger_name);
  gtk_table_attach (GTK_TABLE (table3), trigger_name, 1, 2, 0, 1,
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                    (GtkAttachOptions) (0), 0, 0);

  label7 = gtk_label_new(_("Group:"));
  gtk_widget_ref(label7);
  gtk_widget_show(label7);
  gtk_table_attach (GTK_TABLE (table3), label7, 0, 1, 1, 2,
                    (GtkAttachOptions) (GTK_FILL),
                    (GtkAttachOptions) (0), 0, 0);
  gtk_misc_set_alignment (GTK_MISC (label7), 0, 0.5);

  option_menu = entities->getGroupOptionMenu(this);
  gtk_widget_show(option_menu);
  gtk_table_attach(GTK_TABLE(table3), option_menu, 1, 2, 1, 2,
               (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
               (GtkAttachOptions) (0), 0, 0);

  scrolledwindow5 = gtk_scrolled_window_new (NULL, NULL);
  gtk_widget_ref (scrolledwindow5);
  gtk_widget_show (scrolledwindow5);
  gtk_table_attach (GTK_TABLE (table3), scrolledwindow5, 1, 2, 2, 3,
                    (GtkAttachOptions) (GTK_FILL),
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow5), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);

  trigger_description_buffer = gtk_text_buffer_new(NULL);
  trigger_description_view = gtk_text_view_new_with_buffer(trigger_description_buffer);
  
  gtk_widget_show(trigger_description_view);
  gtk_container_add(GTK_CONTAINER(scrolledwindow5), trigger_description_view);

  label14 = gtk_label_new (_("Description:"));
  gtk_widget_ref (label14);
  gtk_widget_show (label14);
  gtk_table_attach (GTK_TABLE (table3), label14, 0, 1, 2, 3,
                    (GtkAttachOptions) (GTK_FILL),
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
  gtk_misc_set_alignment (GTK_MISC (label14), 0, 7.45058e-09);

  frame5 = gtk_frame_new (_("Trigger"));
  gtk_widget_ref (frame5);
  gtk_widget_show (frame5);
  gtk_box_pack_start (GTK_BOX (vbox7), frame5, TRUE, TRUE, 0);
  gtk_container_set_border_width (GTK_CONTAINER (frame5), 2);

  table4 = gtk_table_new (3, 2, FALSE);
  gtk_widget_ref (table4);
  gtk_widget_show (table4);
  gtk_container_add (GTK_CONTAINER (frame5), table4);
  gtk_container_set_border_width (GTK_CONTAINER (table4), 2);
  gtk_table_set_row_spacings (GTK_TABLE (table4), 2);
  gtk_table_set_col_spacings (GTK_TABLE (table4), 2);

  label15 = gtk_label_new (_("Trigger String:"));
  gtk_widget_ref (label15);
  gtk_widget_show (label15);
  gtk_table_attach (GTK_TABLE (table4), label15, 0, 1, 0, 1,
                    (GtkAttachOptions) (GTK_FILL),
                    (GtkAttachOptions) (0), 0, 0);
  gtk_misc_set_alignment (GTK_MISC (label15), 0, 0.5);

  label16 = gtk_label_new (_("Trigger Type:"));
  gtk_widget_ref (label16);
  gtk_widget_show (label16);
  gtk_table_attach (GTK_TABLE (table4), label16, 0, 1, 1, 2,
                    (GtkAttachOptions) (GTK_FILL),
                    (GtkAttachOptions) (0), 0, 0);

  gtk_misc_set_alignment (GTK_MISC (label16), 0, 0.5);

  label17 = gtk_label_new (_("Trigger Body:"));
  gtk_widget_ref (label17);
  gtk_widget_show (label17);
  gtk_table_attach (GTK_TABLE (table4), label17, 0, 1, 2, 3,
                    (GtkAttachOptions) (GTK_FILL),
                    (GtkAttachOptions) (0), 0, 0);
  //  gtk_misc_set_alignment (GTK_MISC (label17), 0, 0.5);

  scrolledwindow6 = gtk_scrolled_window_new (NULL, NULL);
  gtk_widget_ref (scrolledwindow6);
  gtk_widget_show (scrolledwindow6);
  gtk_table_attach (GTK_TABLE (table4), scrolledwindow6, 1, 3, 2, 3,
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 0, 0);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow6), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);

  trigger_body_buffer = gtk_text_buffer_new(NULL);
  trigger_body_view = gtk_text_view_new_with_buffer(trigger_body_buffer);
  
  gtk_widget_show(trigger_body_view);
  gtk_container_add(GTK_CONTAINER(scrolledwindow6), trigger_body_view);

  trigger_text = gtk_entry_new ();
  gtk_widget_ref (trigger_text);
  gtk_widget_show (trigger_text);
  gtk_table_attach (GTK_TABLE (table4), trigger_text, 1, 2, 0, 1,
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                    (GtkAttachOptions) (0), 0, 0);

  colour_checkbutton = gtk_check_button_new_with_label(_("Strip colour codes"));
  gtk_widget_ref(colour_checkbutton);
  gtk_widget_show(colour_checkbutton);
  gtk_table_attach(GTK_TABLE(table4), colour_checkbutton, 2, 3, 0, 1,
               (GtkAttachOptions) (GTK_FILL),
               (GtkAttachOptions) (0), 0, 0);
  

  trigger_options = gtk_option_menu_new ();
  gtk_widget_ref (trigger_options);
  gtk_widget_show (trigger_options);
  gtk_table_attach (GTK_TABLE (table4), trigger_options, 1, 3, 1, 2,
                    (GtkAttachOptions) (GTK_FILL),
                    (GtkAttachOptions) (0), 0, 0);
  trigger_options_menu = gtk_menu_new ();
  glade_menuitem = gtk_menu_item_new_with_label (_("Simple Pattern Matching"));
  gtk_widget_show (glade_menuitem);
  gtk_menu_shell_append (GTK_MENU_SHELL (trigger_options_menu), glade_menuitem);
  glade_menuitem = gtk_menu_item_new_with_label (_("Regular Expression (experts only)"));
  gtk_widget_show (glade_menuitem);
  gtk_menu_shell_append (GTK_MENU_SHELL (trigger_options_menu), glade_menuitem);
  gtk_option_menu_set_menu (GTK_OPTION_MENU (trigger_options), trigger_options_menu);

  if (getName())
    gtk_entry_set_text(GTK_ENTRY(trigger_name), getName());

  if (getDescription()) {
    GtkTextIter start, end;

    gtk_text_buffer_get_bounds(trigger_description_buffer, &start, &end);
    gtk_text_buffer_insert(trigger_description_buffer, &end, getDescription(), -1);
  }

  if (getText())
    gtk_entry_set_text(GTK_ENTRY(trigger_text), getText());
  
  gtk_option_menu_set_history(GTK_OPTION_MENU(trigger_options), getTriggerType());

  if (getBody()) {
    GtkTextIter start, end;
    gtk_text_buffer_get_bounds(trigger_body_buffer, &start, &end);
    gtk_text_buffer_insert(trigger_body_buffer, &end, getBody(), -1);
  }

  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(colour_checkbutton), getStripColour());

  widget = vbox7;
  gtk_widget_ref(widget);
  return widget;
}

void TriggerEntity::apply() {

  if (!widget)
    return;

  if (!trigger_name)
    return;

  const gchar * new_name = gtk_entry_get_text(GTK_ENTRY(trigger_name));
  const gchar * new_text = gtk_entry_get_text(GTK_ENTRY(trigger_text));

  GtkTextIter start, end;
  gtk_text_buffer_get_bounds(trigger_description_buffer, &start, &end);
  gchar * new_desc = gtk_text_buffer_get_text(trigger_description_buffer, &start, &end, -1);

  gtk_text_buffer_get_bounds(trigger_body_buffer, &start, &end);
  gchar * new_body = gtk_text_buffer_get_text(trigger_body_buffer, &start, &end, -1);

  setName((gchar *)new_name);
  setDescription(new_desc);
  setText((gchar *)new_text);
  setBody(new_body);
  setStripColour(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(colour_checkbutton)));

  setTriggerType((TriggerType)gtk_option_menu_get_history(GTK_OPTION_MENU(trigger_options)));

  gint index = gtk_option_menu_get_history(GTK_OPTION_MENU(option_menu));
  GList * items = entities->getGroupOptionMenuList();
  gchar * label = (gchar *)g_list_nth_data(items, index);

  entities->moveGroup(this, label);
  compile();

}



Generated by  Doxygen 1.6.0   Back to index