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

MUDConnectorList.cpp

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

#include <gmodule.h>

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <sys/types.h>
#include <sys/stat.h>

#ifndef WIN32
#include <unistd.h>
#else
#define strncasecmp strnicmp
#endif

#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>

#include "callbacks.h"
#include "support.h"
#include "Message.h"
#include "mudclient.h"
#include "MUDConnectorList.h"

char * stristr(char * haystack, char * needle) {
  
  char * pc = haystack;
  int len = strlen(needle);

  while (*pc != '\0') {
    if (!strncasecmp(pc, needle, len))
      return pc;
    
    pc++;
  }

  return NULL;
}

/**
 * Reads the MUD Connector text MUD list.
 *
 * Saves offset into file and name of MUD.  When MUD is queried the data can be
 * read from the data file.
 */
extern MUDConnectorList * mcl;

extern "C" G_MODULE_EXPORT gint on_close_button_clicked(GtkButton * button, gpointer data) {
  mcl->destroyInterface();
  return 1;
}

extern "C" G_MODULE_EXPORT gint on_mcw_delete_event(GtkWidget * widget, GdkEvent * event, gpointer data) {
      return on_close_button_clicked(NULL, data);
}

extern "C" G_MODULE_EXPORT gint on_treeview_selection_changed(GtkTreeSelection * selection, gpointer data) {
  GtkTreeModel * model;
  GtkTreeIter iter;

  if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
    gchar * name;
    
    gtk_tree_model_get(model, &iter, 0, &name, -1);
    mcl->setCurrentMUD(name);
    g_free(name);
    return 1;
  }

  // Nothing currently selected - blank the display area.
  mcl->setCurrentMUD(NULL);
  return 1;
}

#include "MUDSelector.h"
extern MUDSelector * mud_selector;
void on_mcw_new_clicked(GtkButton * button, gpointer data);

extern "C" G_MODULE_EXPORT gint on_connection_wizard_button_clicked(GtkButton * button, gpointer data) {

  // Jump to the connection wizard with the currently selected MUD from the
  // TreeView.
  // Determine the currently selected MUD.
  GtkTreeModel * model;
  GtkTreeIter iter;
  char buf[1024];

  if (gtk_tree_selection_get_selected(mcl->selection, &model, &iter)) {
    gchar * name;
    
    gtk_tree_model_get(model, &iter, 0, &name, -1);

    // Connect to this MUD.
    MUDConnectorMUD * mud = mcl->getEntry(name);
    g_free(name);

    if (!mud) {
      // Display an error message
      new Message("Error", _("Please select a MUD to export to the MUD connection wizard and try again."), true);
      return 1;
    }

    on_mcw_new_clicked(button, (gpointer)NULL);        
    snprintf(buf, 1024, "%d", mud->getPort());     
    gtk_entry_set_text(GTK_ENTRY(mud_selector->mcw_port), buf);
    gtk_entry_set_text(GTK_ENTRY(mud_selector->mcw_host), mud->getHost());
    gtk_entry_set_text(GTK_ENTRY(mud_selector->mcw_name), mud->getName());

    mcl->destroyInterface();
    delete mud;
    return 1;
  }

  new Message("Error", _("Please select a MUD to export to the MUD connection wizard and try again."), true);
  return 1;
}

extern "C" G_MODULE_EXPORT gint on_connect_button_clicked(GtkButton * button, gpointer data) {

  // Determine the currently selected MUD.
  GtkTreeModel * model;
  GtkTreeIter iter;

  if (gtk_tree_selection_get_selected(mcl->selection, &model, &iter)) {
    gchar * name;
    
    gtk_tree_model_get(model, &iter, 0, &name, -1);

    // Connect to this MUD.
    MUDConnectorMUD * mud = mcl->getEntry(name);
    g_free(name);

    if (!mud) {
      // Display an error message
      new Message("Error", _("Please select a MUD to connect to and try again."), true);
      return 1;
    }

    initialise_network(mud->getHost(), mud->getPort());
    mcl->destroyInterface();
    delete mud;
    return 1;
  }
  
  new Message("Error", _("Please select a MUD to connect to and try again."), true);
  return 1;
}

extern "C" G_MODULE_EXPORT gint on_search_mud_button_clicked(GtkButton * button, gpointer data) {
  mcl->search();

  return 1;

}

extern "C" G_MODULE_EXPORT gint on_search_name_entry_activate(GtkWidget * widget, gpointer data) {
  mcl->search();
  return 1;

}

extern "C" G_MODULE_EXPORT gint on_search_codebase_entry_activate(GtkWidget * widget, gpointer data) {
  mcl->search();
  return 1;

}

extern "C" G_MODULE_EXPORT gint on_display_all_button_clicked(GtkButton * button, gpointer data) {
  mcl->displayAll();
  return 1;

}

gboolean select_by_mud(GtkTreeModel * tree_model, GtkTreePath * path, GtkTreeIter * iter, gpointer data) {
  mcl->selectByMUD(iter, data);
  return false;

}

MUDConnectorList::MUDConnectorList() {
  firstEntry = NULL;
  fp = NULL;
  xml = NULL;
  currentMUD = NULL;
  readMudlist();
}

MUDConnectorList::~MUDConnectorList() {
  struct mce * tmp = firstEntry;
  struct mce * tmp_next;

  for (; tmp; tmp = tmp_next) {
    tmp_next = tmp->next;
    if (tmp->name)
      free(tmp->name);
    free(tmp);
  }
  
  if (currentMUD) {
    delete currentMUD;
    currentMUD = NULL;
  }

  if (fp)
    fclose(fp);
}

void MUDConnectorList::appendList(struct mce * entry) {

  struct mce * curr;

  if (!firstEntry) {
    firstEntry = entry;
    firstEntry->next = NULL;
    firstEntry->prev = NULL;
    return;
  }

  for (curr = firstEntry; curr; curr = curr->next) {
    if (!curr->next) {
      curr->next = entry;
      entry->next = NULL;
      entry->prev = curr;
      return;
    }
  }

}

void MUDConnectorList::readMudlist() {

  char line[1024];

  fp = openFile("mudlist.txt", NULL, "rb");
  if (!fp) {
    new Message("Information", _("You do not have the MUD Connector MUD List installed.  To install please select the MUD List option from the Connection menu and follow the instructions there."), true);
    return;
  }

  // Attempt to read a line from the file.
  while (fgets(line, 1024, fp)) {
    // Is this a 'Mud        :' line?
    if (!strncmp(line, "Mud         :", 13)) {
      struct mce * entry = (struct mce *)malloc(sizeof(struct mce));
      memset(entry, 0, sizeof(struct mce));
      entry->offset = ftell(fp);
      entry->name = strdup(line+14);

      char * pc = strchr(entry->name, '\n');
      if (pc)
      *pc = '\0';

      appendList(entry);
    }
  }
}

MUDConnectorMUD * MUDConnectorList::getEntry(char * name) {

  struct mce * tmp;

  for (tmp = firstEntry; tmp; tmp = tmp->next) {
    if (!strcmp(tmp->name, name)) {
      return readEntry(tmp);
    }
  }
  
  return NULL;
}

MUDConnectorMUD * MUDConnectorList::readEntry(struct mce * entry) {

  char line[1024];

  if (!fp)
    return NULL;

  // Set the pointer to offset bytes from the start of the file.
  if (fseek(fp, entry->offset, SEEK_SET) == -1) {
    perror("fseek");
    return NULL;
  }

  MUDConnectorMUD * mud = new MUDConnectorMUD();
  mud->setName(entry->name);

  while (fgets(line, 1024, fp)) {

    if (!strncmp(line, "Code Base", 9)) {
      mud->setCodeBase(line);
    } else if (!strncmp(line, "Telnet", 6)) {
      mud->setTelnet(line);
    } else if (!strncmp(line, "WWW", 3)) {
      mud->setWWW(line);
    } else if (!strncmp(line, "Description", 11)) {
      // Read until we hit 'Mud' or other garbage.

      while (1) {
      char * pc = fgets(line, 1024, fp);
      
      if (!pc)
        return mud;

      if (!strncmp(line, "Mud         :", 13))
        return mud;
      mud->appendDescription(line);
      }
      return mud;
    }
  }

  return mud;
}

MUDConnectorMUD::MUDConnectorMUD() {

  name = NULL;
  description = NULL;
  host = NULL;
  port = 0;
  www = NULL;
  codebase = NULL;

}

MUDConnectorMUD::~MUDConnectorMUD() {
  if (name)
    free(name);

  if (description)
    free(description);

  if (host)
    free(host);

  if (www)
    free(www);

  if (codebase)
    free(codebase);
}

void MUDConnectorMUD::setName(char * n) {
  if (name)
    free(name);
  name = strdup(n);

  while (strlen(name) >  0) {
    char * pc = &(name[strlen(name) - 1]);
    if (*pc == '\r')
      *pc = '\0';
    else if (*pc == '\n')
      *pc = '\0';
    else
      break;
  }
}

char * MUDConnectorMUD::getName() {
  return name;
}

void MUDConnectorMUD::setCodeBase(char * n) {
  if (codebase)
    free(codebase);
  codebase = strdup(n+13);
}

char * MUDConnectorMUD::getCodeBase() {
  return codebase;
}

void MUDConnectorMUD::setTelnet(char * h) {

  char ho[1024];
  int p;

  sscanf(h, "Telnet      : %s %d%*[^\n]", ho, &p);

  host = strdup(ho);
  port = p;
}

char * MUDConnectorMUD::getHost() {
  return host;
}

int MUDConnectorMUD::getPort() {
  return port;
}

void MUDConnectorMUD::appendDescription(char * d) {
  if (!description) {
    description = (char *)malloc(16384);
    description[0] = '\0';
  }

  strcat(description, d);
}

char * MUDConnectorMUD::getDescription() {
  return description;
}

void MUDConnectorMUD::setWWW(char * w) {
  if (www)
    free(www);
  www = strdup(w + 13);

  char * pc = strchr(www, '\n');
  if (pc)
    *pc = '\0';
}

char * MUDConnectorMUD::getWWW() {
  return www;
}

void MUDConnectorList::createInterface() {
  char buf[1024];

  if (xml) { // present it
    gtk_window_present((GtkWindow *)glade_xml_get_widget(xml, "mud_connector_dialog"));
    return;
  }

  snprintf(buf, 1024, "%s/share/papaya/mudlist.glade", getPrefix());
  xml = glade_xml_new(buf, NULL, NULL);
  if (!xml) {
    printf (_("Critical Error: Could not load '%s'.\n"), buf);
    abort();
  }
  
  // Connect the signals
  glade_xml_signal_autoconnect(xml);

  // Configure the treeview widget and its associated tree store.
  mud_list_store = gtk_list_store_new(1, G_TYPE_STRING);
  GtkTreeViewColumn * column;
  GtkCellRenderer * renderer = gtk_cell_renderer_text_new();

  GtkWidget * tree_view = glade_xml_get_widget(xml, "display_mud_treeview");
  if (!tree_view) {
    printf (_("Critical Error: Widget display_mud_treeview not found in mudlist.glade.\n"));
    abort();
  }

  gtk_tree_view_set_model(GTK_TREE_VIEW(tree_view), GTK_TREE_MODEL(mud_list_store));

  column = gtk_tree_view_column_new_with_attributes( _("MUD Name"),
                                         renderer,
                                         "text", 0,
                                         NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);


  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));

  g_signal_connect_data(G_OBJECT(selection), "changed",
                  GTK_SIGNAL_FUNC(on_treeview_selection_changed),
                  this, NULL, (GConnectFlags) 0);

  displayAll();
}

void MUDConnectorList::displayAll() {
  GtkTreeIter iter;

  // By default we enter _all_ entries into the TreeView widget.
  gtk_list_store_clear(mud_list_store);
  gchar * first_mud = NULL;
  for (struct mce * tmp = firstEntry; tmp; tmp = tmp->next) {
    gtk_list_store_append(mud_list_store, &iter);
    gtk_list_store_set(mud_list_store, &iter,
                   0, tmp->name,
                   -1);

    if (!first_mud)
      first_mud = tmp->name;
  }

  if (first_mud)
    gtk_tree_model_foreach(GTK_TREE_MODEL(mud_list_store), select_by_mud, (gpointer)first_mud);
  else
    setCurrentMUD(first_mud); // Event won't trigger, want no text displayed.

}

void MUDConnectorList::selectByMUD(GtkTreeIter * iter, gpointer data) {

  gchar * row_name;
  gchar * name = (gchar *)data;

  gtk_tree_model_get(GTK_TREE_MODEL(mud_list_store), iter, 0, &row_name, -1);
  if (!strcmp(name, row_name)) {
    gtk_tree_selection_select_iter(selection, iter);
  }

  g_free(row_name);
}

void MUDConnectorList::destroyInterface() {
  GtkWidget * window = glade_xml_get_widget(xml, "mud_connector_dialog");
  if (window) {
    gtk_widget_hide(window);
    gtk_widget_destroy(window);
  }

  if (currentMUD) {
    delete currentMUD;
    currentMUD = NULL;
  }

  g_object_unref(xml);
  xml = NULL;
}

void MUDConnectorList::setCurrentMUD(gchar * name) {

  char buf[1024];

  GtkWidget * mudname;
  GtkWidget * mudwww;
  GtkWidget * mudcodebase;

  GtkWidget * text_view;
  GtkTextBuffer * text_buffer;
  GtkTextIter start, end;

  if (currentMUD) {
    delete currentMUD;
    currentMUD = NULL;
  }

  mudname = glade_xml_get_widget(xml, "mudname_label");
  mudwww = glade_xml_get_widget(xml, "mudwww_label");
  mudcodebase = glade_xml_get_widget(xml, "mudcodebase_label");

  // Clear the labels
  gtk_label_set_text(GTK_LABEL(mudname), "");
  gtk_label_set_text(GTK_LABEL(mudwww), "");
  gtk_label_set_text(GTK_LABEL(mudcodebase), "");

  // Clear the text view
  text_view = glade_xml_get_widget(xml, "muddescription_textview");
  text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
  gtk_text_buffer_get_bounds(text_buffer, &start, &end);
  gtk_text_buffer_delete(text_buffer, &start, &end);

  if (!name) {
    gtk_text_buffer_insert(text_buffer, &start, _("No MUD currently selected."), -1);
    return;
  }

  currentMUD = getEntry(name);
  if (!currentMUD) {
    gtk_text_buffer_insert(text_buffer, &start, _("Sorry, the selected MUD does not appear to have a description."), -1);
    return;
  }

  // Sort out the MUD Name Labels etc.
  snprintf(buf, 1024, "<b>%s</b> (%s:%d)", currentMUD->getName(), currentMUD->getHost(), currentMUD->getPort());
  gtk_label_set_markup(GTK_LABEL(mudname), buf);

  snprintf(buf, 1024, "<i>%s</i>", currentMUD->getWWW());
  gtk_label_set_markup(GTK_LABEL(mudwww), buf);

  snprintf(buf, 1024, "%s", currentMUD->getCodeBase());
  gtk_label_set_markup(GTK_LABEL(mudcodebase), buf);

  // Insert the MUD's description
  gtk_text_buffer_insert(text_buffer, &start, currentMUD->getDescription(), -1);
}

// Search for the MUD according to the criteria specified
void MUDConnectorList::search() {

  GtkWidget * name_entry;
  GtkWidget * codebase_entry;
  GtkWidget * name_regexp_toggle;

  name_entry = glade_xml_get_widget(xml, "search_name_entry");
  codebase_entry = glade_xml_get_widget(xml, "search_codebase_entry");
  name_regexp_toggle = glade_xml_get_widget(xml, "search_name_checkbox");

  gchar * name;
  gchar * codebase;
  bool regexp;

  name = (gchar *)gtk_entry_get_text(GTK_ENTRY(name_entry));
  codebase = (gchar *)gtk_entry_get_text(GTK_ENTRY(codebase_entry));
  regexp = GTK_TOGGLE_BUTTON(name_regexp_toggle)->active;
  
  // Clear the list store.
  gtk_list_store_clear(mud_list_store);

  gchar * first_mud = NULL;
  GtkTreeIter iter;
  for (struct mce * tmp = firstEntry; tmp; tmp = tmp->next) {
    bool name_found = false;
    bool codebase_found = false;

    MUDConnectorMUD * mud = getEntry(tmp->name);
    if (!mud)
      continue;

    // If (name matches && codebase matches)
    if (strlen(name) > 0) { // Check name
      if (!regexp) {
      if (stristr(mud->getName(), name))
        name_found = true;
      } else {
      // Perform a regexp match
      regex_t regex;
      regcomp(&regex, name, REG_ICASE|REG_EXTENDED);
      if (regexec(&regex, mud->getName(), 0, NULL, 0) == 0)
        name_found = true;
      regfree(&regex);
      }
    }

    if (strlen(codebase) > 0) {
      if (stristr(mud->getCodeBase(), codebase))
      codebase_found = true;
    }

    if ((strlen(codebase) == 0 || codebase_found)
      && ((strlen(name) == 0) || name_found)
      ) {
      if (!(strlen(name) == 0 && strlen(codebase) == 0)) {
      gtk_list_store_append(mud_list_store, &iter);
      gtk_list_store_set(mud_list_store, &iter,
                     0, tmp->name,
                     -1);
      if (!first_mud)
        first_mud = tmp->name;
      //mud->getName();
      }
    }

    // Else we get a giant memory leak!
    delete mud;
  }

  if (first_mud)
    gtk_tree_model_foreach(GTK_TREE_MODEL(mud_list_store), select_by_mud, (gpointer)first_mud);
  else
    setCurrentMUD(first_mud); // Event won't trigger, want no text displayed.


}

void on_mud_list_clicked(GtkButton * button, gpointer data) {
  mcl->createInterface();
}


Generated by  Doxygen 1.6.0   Back to index