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

AliasEntity.cpp

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

#include <glade/glade.h>

#include "AliasEntity.h"
#include "EntityHandler.h"

extern EntityHandler * entities;

#define ALIAS_FAIL 0
#define ALIAS_OK 1

extern "C" gint on_alias_entity_keypress_event(GtkWidget * widget, GdkEventKey * event, gpointer data) {

  AliasEntity * aliasEntity = (AliasEntity *) data;

  aliasEntity->keypressed(event);
  return 0;
}

AliasEntity::AliasEntity() : Entity() {
  body = NULL;
  command = NULL;
  macro_key = 0;

  body_buffer = NULL;

  xml = NULL;
  setType(EntityAlias);
}

AliasEntity::~AliasEntity() {
  if (body) {
    free(body);
    body = NULL;
  }

  if (command) {
    free(command);
    command = NULL;
  }

  if (xml) {
    GtkWidget * frame = glade_xml_get_widget(xml, "vbox1");
    gtk_widget_unref(frame);
    g_object_unref(xml);
    xml = NULL;
  }
}

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

void AliasEntity::setCommand(char * c) {
  if (command)
    free(command);
  command = strdup(c);
}

char * AliasEntity::getCommand() {
  if (command)
    return command;
  else
    return "";
}

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

void AliasEntity::setMacroKey(int k) {
  macro_key = k;
}

int AliasEntity::getMacroKey() {
  return macro_key;
}

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

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

  if (disabled)
    return false;

  if (!strcasecmp(field, "key")) {
    int key = *((int *)value);

    if (!getMacroKey() || getMacroKey() != key)
      return false;

    execute(value, (char *)data);
    return true;
  }

  if (!strcasecmp(field, "command")) {
    char * command = value;
    char * end = strchr(command, ' ');
    if (!end)
      end = command + strlen(command);
    
    int len = end-command > strlen(getCommand()) ? end-command : strlen(getCommand());

    if (memcmp(command, getCommand(), len))
      return false;

    //    if (strncmp(value, getCommand(), strlen(getCommand()))) // no match
    //      return false;

    execute(value, (char *)data);
    return true;
  }

  return false;
}

static char * findArgument(char * text, int index) {

  int count = 1;
  char * arg = text;

  while (count < index) {
    while (isspace(*arg))
      arg++;
     arg = strchr(arg, ' ');
     if (!arg) {
       return NULL;
     }
     count++;
  }

  while (isspace(*arg))
    arg++;
  return arg;
}


static int append_argument(char * output, int len, int pos, char * input, char i) {
  
  int index;
  char index_str[2];
  int count = 0;

  if (!input)
    return 0;

  index_str[0] = i;
  index_str[1] = '\0';
  index = atoi(index_str);
  
  if (index == 0) {
    if (pos + strlen(input) >= (unsigned int)len)
      return 0;

    memcpy(output + pos, input, strlen(input));
    return strlen(input);
  }

  char * arg = findArgument(input, index);
  if (!arg)
    return 0;

  while (*arg != '\0' && !isspace(*arg)) {
    output[pos + count] = *arg;
    arg++;
    count++;
  }

  return count;
}

static int append_char(char * output, int len, int pos, char c) {

  if (pos >= len) {
    output[len-1] = '\0';
    return ALIAS_FAIL;
  }

  output[pos] = c;
  return ALIAS_OK;
}

void AliasEntity::execute(char * input, char * output) {

  char * pc = getBody();
  int out_pos = 0;
  int output_len = 16384;

  output[0] = '\0';

  if (output_len == 0)
    return;

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

void AliasEntity::save(FILE * fp) {
  fprintf(fp, "Alias %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, "Command %s\n", getCommand());
  fprintf(fp, "MacroKey %d\n", getMacroKey());
  fprintf(fp, "Body\n");
  fprintf(fp, "%s", getBody());
  if (strlen(getBody()) > 0)
    if (getBody()[strlen(getBody()) - 1] != '\n')
      fprintf(fp, "\n");

  fprintf(fp, "EndBody\n");
  fprintf(fp, "EndAlias\n");
}

bool AliasEntity::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, "Command", 7)) {
      char comm[16384];
      if (sscanf(buf, "Command %[^\n]\n", comm) == 1)
      setCommand(comm);
      else {
      perror("sscanf");
      return false;
      }
      continue;
    }

    if (!strncasecmp(buf, "MacroKey", 8)) {
      int tmp;
      if (sscanf(buf, "MacroKey %d\n", &tmp) == 1)
      setMacroKey(tmp);
      else {
      perror("sscanf");
      return false;
      }
      continue;
    }

    if (!strncasecmp(buf, "EndAlias", 8)) {
      return true;
    }

  }
}

void AliasEntity::apply() {

  // If there is a widget read the data into temp from it.
  if (xml)
    getWidgetData();

}

void AliasEntity::getWidgetData() {

  if (!xml)
    return;

  // Get details from widgets and copy into temporary data.

  GtkWidget * name_entry;
  GtkWidget * command_entry;
  GtkWidget * macro_entry;
  GtkWidget * option_menu;

  name_entry = glade_xml_get_widget(xml, "name_entry");
  command_entry = glade_xml_get_widget(xml, "command_entry");
  macro_entry = glade_xml_get_widget(xml, "macro_entry");
  option_menu = glade_xml_get_widget(xml, "option_menu");

  // Read the alias name
  const gchar * text = gtk_entry_get_text(GTK_ENTRY(name_entry));
  setName((gchar *)text);
  
  // Read the alias description
  GtkTextIter start, end;
  gtk_text_buffer_get_bounds(description_buffer, &start, &end);
  text = gtk_text_buffer_get_text(description_buffer, &start, &end, -1);
  setDescription((gchar *)text);

  // Read the alias command
  text = gtk_entry_get_text(GTK_ENTRY(command_entry));
  setCommand((gchar *)text);

  // Read the alias body
  gtk_text_buffer_get_bounds(body_buffer, &start, &end);
  text = gtk_text_buffer_get_text(body_buffer, &start, &end, -1);
  setBody((gchar *)text);

  // Read the macro key
  text = gtk_entry_get_text(GTK_ENTRY(macro_entry));
  if (strlen(text) == 0) {
    setMacroKey(-1);
  } else { 
    setMacroKey(gdk_keyval_from_name(text));
  }

  // Figure out which group this allegedly belongs to.
  gint index = gtk_option_menu_get_history(GTK_OPTION_MENU(option_menu));

  if (index == -1) { // Invalid selection - not currently selected?
    
    return;
  }

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

  entities->moveGroup(this, label);
}

int alias_shortcut_pressed(GtkWidget * widget, GdkEventKey * event, gpointer data) {

  // @@ For the best way to do this see the keybindings control-center applet.
  // It's long, complex, but fortunately GPLd.
  // /tmp/control-center-2.0.3/capplets/keybindings


  AliasEntity * alias = (AliasEntity *)data;

  int keyval = event->keyval;
  int state = event->state;

  alias->setMacroKey(keyval);

  // We've handled this event.
  return 1;

}

GtkWidget * AliasEntity::getWidgets() {
  char buf[1024];

  if (xml) {
    GtkWidget * frame = glade_xml_get_widget(xml, "vbox1");
    gtk_widget_ref(frame);

    // Update the option menu.
    GtkWidget * option_menu = glade_xml_get_widget(xml, "option_menu");
    GList * option_menu_list = entities->getGroupOptionMenuList();
    GtkWidget * menu = gtk_menu_new();
    EntityGroup * eg = entities->getEntityGroupForEntity(this);
    int index = -1;
    
    for (int i = 0; i < g_list_length(option_menu_list); i++) {
      char * item = (char *)g_list_nth_data(option_menu_list, i);
      GtkWidget * menu_item = gtk_menu_item_new_with_label(item);
      gtk_widget_show(menu_item);
      gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
      if (!strcmp(eg->getName(), item))
      index = i;
    }
    
    gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
    gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), index);

    return frame;
  }
  
  snprintf(buf, 1024, "%s/share/papaya/alias_entity.glade", getPrefix());

  xml = glade_xml_new(buf, NULL, NULL);
  if (!xml) {
    printf (_("Critical Error: File '%s' not found.\n"), buf);
    return NULL;
  }


  glade_xml_signal_connect_data(xml, "on_alias_entity_keypress_event",
                        GTK_SIGNAL_FUNC(on_alias_entity_keypress_event), this);

  // Need to set values in the widgets.

  GtkWidget * name_entry, * description_entry;
  GtkWidget * body_entry, * command_entry;
  GtkWidget * option_menu, * macro_entry;

  name_entry = glade_xml_get_widget(xml, "name_entry");
  description_entry = glade_xml_get_widget(xml, "description_entry");

  command_entry = glade_xml_get_widget(xml, "command_entry");
  body_entry = glade_xml_get_widget(xml, "body_entry");
  macro_entry = glade_xml_get_widget(xml, "macro_entry");

  option_menu = glade_xml_get_widget(xml, "option_menu");

  description_buffer = gtk_text_buffer_new(NULL);
  gtk_text_view_set_buffer(GTK_TEXT_VIEW(description_entry), description_buffer);
  GtkTextIter start, end;

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

  body_buffer = gtk_text_buffer_new(NULL);
  gtk_text_view_set_buffer(GTK_TEXT_VIEW(body_entry), body_buffer);

  gtk_text_buffer_get_bounds(body_buffer, &start, &end);
  gtk_text_buffer_insert(body_buffer, &end, getBody(), -1);
  

  gtk_entry_set_text(GTK_ENTRY(name_entry), getName());
  gtk_entry_set_text(GTK_ENTRY(command_entry), getCommand());

  if (getMacroKey() != -1)
    gtk_entry_set_text(GTK_ENTRY(macro_entry), gdk_keyval_name(getMacroKey()));
  
  GList * option_menu_list = entities->getGroupOptionMenuList();
  GtkWidget * menu = gtk_menu_new();
  EntityGroup * eg = entities->getEntityGroupForEntity(this);
  int index = -1;

  for (int i = 0; i < g_list_length(option_menu_list); i++) {
    char * item = (char *)g_list_nth_data(option_menu_list, i);
    GtkWidget * menu_item = gtk_menu_item_new_with_label(item);
    gtk_widget_show(menu_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    if (!strcmp(eg->getName(), item))
      index = i;
  }

  gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
  gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), index);

  GtkWidget * frame = glade_xml_get_widget(xml, "vbox1");
  gtk_widget_ref(frame);
  return frame;
}

void AliasEntity::destroyWidgets() {
  if (xml) {
    g_object_unref(xml);
    xml = NULL;
  }
}

void AliasEntity::keypressed(GdkEventKey * key) {
  GtkWidget * macro_entry = glade_xml_get_widget(xml, "macro_entry");

  if (key->keyval == 65307) { // ESCAPE
    gtk_entry_set_text(GTK_ENTRY(macro_entry), "");
    return; // Clear
  }

  gtk_entry_set_text(GTK_ENTRY(macro_entry), gdk_keyval_name(key->keyval));
}


Generated by  Doxygen 1.6.0   Back to index