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

PromptPlugin.cpp

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

#include "PromptPlugin.h"
#include "Win32PluginAPI.cpp"


#define MAJOR "2"
#define MINOR "0"

extern "C" G_MODULE_EXPORT char * plugin_query_name() {
  return "PromptPlugin";
}

extern "C" G_MODULE_EXPORT char * plugin_query_description() {
  return _("Displays fractional bars in the plugin tray.  These can be used to display the amount of hp you have left, etc.");
}

extern "C" G_MODULE_EXPORT char * plugin_query_major() {
  return MAJOR;
}

extern "C" G_MODULE_EXPORT char * plugin_query_minor() {
  return MINOR;
}

#define PREFS_MIN_RGB "PromptPlugin_min_rgb"
#define PREFS_MID_RGB "PromptPlugin_mid_rgb"
#define PREFS_MAX_RGB "PromptPlugin_max_rgb"
#define PREFS_TRIPLET "PromptPlugin_triplet"

static bool isNumber(char * pc) {

  while (1) {
    if (*pc == '\0')
      return true;

    if (!isdigit(*pc))
      return false;

    pc++;
  }

  return true;
}

void pplugin_expose(GtkWidget * widget, GdkEventExpose * event, gpointer data) {

  struct vtPrompt * tmp = (struct vtPrompt *)data;

  if (!widget->window)
    return;

  gdk_window_clear_area (widget->window, 0, 0, widget->allocation.width, widget->allocation.height);
  
  // Drawing here...

  GdkColor * color;

  GdkGC * gc = gdk_gc_new(widget->window);
  if (!gc)
    return;

  gdk_gc_copy(gc,widget->style->white_gc);

  // Need to figure out how many shaded bars we need to display.
  //@@

  for (int i = 0; i < tmp->bars; i++) {
    int width;

    if (tmp->max[i] == 0)
      width = 0;
    else
      width = tmp->curr[i] * 100 / tmp->max[i];

    color = fade_get_shade(tmp->fade, tmp->curr[i], tmp->max[i]);
    gdk_color_alloc (gdk_colormap_get_system () , color);
    gdk_gc_set_foreground(gc,color);
    gdk_gc_set_background(gc,color);

    int bar_height = (widget->allocation.height - (tmp->bars * 2) - 2) / tmp->bars;
    int bar_position = 1 + i * (bar_height + 2);

    if (bar_height < 4) {
      bar_height = (widget->allocation.height - (tmp->bars * 1) - 2) / tmp->bars;
      bar_position = 1 + i * (bar_height + 1);
    }

    gdk_draw_rectangle(widget->window, gc, 1, 1, bar_position, width, bar_height);

    if (bar_height > 3)
      gdk_draw_rectangle(widget->window, widget->style->fg_gc[widget->state],
                   0, 1, bar_position, width, bar_height);
  }

#ifdef USE_GTK
  gdk_gc_destroy(gc);
#else
  gdk_gc_unref(gc);
#endif
}

static PromptPlugin * promptplugin;

extern "C" G_MODULE_EXPORT void plugin_init(plugin_address_table_t * pat) {
      plugin_address_table_init(pat);

      promptplugin = new PromptPlugin();
}

extern "C" G_MODULE_EXPORT void plugin_cleanup(void) {
  delete promptplugin;
}

PromptPlugin::PromptPlugin() {
  version = 1.2;
  name = strdup("Pretty Prompt");

  memset(&prefs_scratch, 0, sizeof(prefs_scratch));

  register_plugin(this, VERSION);

  plugin_handler_add_prompt_filter(get_plugin_handler(), this);
}


PromptPlugin::~PromptPlugin() {
  free(name);
  name = NULL;


  PromptDataList::iterator i_next;
  for (PromptDataList::iterator i = promptList.begin(); i != promptList.end(); 
i = i_next) {
    i_next = i;
    i_next++;

    vt_remove_from_tray(connection_get_vt((*i)->connection), (*i)->event_box, (*i)->frame);
    remove_data((*i));
    free((*i));
  }

  unregister_plugin(this);

}

void PromptPlugin::onEvent(Event * e, Connection * c) {

  if (event_get_type(e) == EvConnect) {
    /* Ensure that we have data structures when we make a connection. */
    findPrompt(c);
    return;
  }

  if (event_get_type(e) == EvDisconnect) {
    struct vtPrompt * data = find_data(c);
    if (!data)
      return;

    // Delete the Fade object
    if (data->fade)
      fade_delete(data->fade);

    vt_remove_from_tray(connection_get_vt(c), data->event_box, data->frame);
    g_free(data->tooltips);

    // remove this entry from the list.
    remove_data(data);
    free(data);
    return;
  }


}

void PromptPlugin::prompt(Connection * c, char * in) {

  if (!c)
    return;

  struct vtPrompt * tmp = findPrompt(c);
  if (!tmp)
    return;

  // Duplicate the input string since we want to stick NULs everywhere.
  char * pc2 = in;
  char * pc = pc2;

  int i = 0;
  while (pc && i < MAX_BARS) {
    pc = findBar(pc, &(tmp->curr[i]), &(tmp->max[i]));
    tmp->bars = i;
    i++;
  }

  pplugin_expose(tmp->widget, NULL, (gpointer)tmp);

}

char * PromptPlugin::findBar(char * pc, int * first, int * second) {

  char * dollar;
  char * slash;
  char * end;
  char * orig_dollar;

  dollar = strchr(pc, '$');
  if (!dollar)
    return NULL;
  orig_dollar = dollar;
  dollar++;

  if (*dollar == '\033') {
    while (!isalpha(*dollar))
      dollar++;
    dollar++;
  }
  
  slash = strchr(dollar, ':');
  if (!slash)
    return NULL;
  *slash = '\0';
  slash++;
  
  if (*slash == '\033') {
    while (!isalpha(*slash))
      slash++;
    slash++;
  }
  
  end = strchr(slash, '$');
  char * end2 = strchr(slash, '\033');
  if (!end)
    return NULL;
  if (end2)
    *end2 = '\0';

  *end = '\0';

  // First string pointed at by dollar.
  // Second string pointer at by slash.
  // Both NUL terminated.

  if (isNumber(dollar))
    *first = atoi(dollar);
  else {
    if (*dollar == '=')
      *first = calculate(dollar);
    else
      *first = convert(dollar);
  }

  if (isNumber(slash))
    *second = atoi(slash);
  else {
    if (*dollar == '=')
      *second = calculate(slash);
    else
      *second = convert(slash);
  }

  if (end2) {
    *end2 = '\033';
  }

  end++;
  memmove(orig_dollar, end, strlen(end) + 1);
  return orig_dollar;
}

#ifdef WIN32
//#ifdef _DEBUG
//int evaluate(char *, double *);
//#  else
extern "C" int evaluate(char *, double *);
//#  endif
#else
extern "C" int evaluate(char *, double *);
#endif

int PromptPlugin::calculate(char * pc) {
  double val = 0;
  int res;

  res = evaluate(pc+1, &val);

  return (int)val;
}

struct word_entry {
  char * word;
  int value;
};

struct word_entry word_table[] = {

      { "perfect", 100 },
      { "unharmed", 100 },
      { "scratched", 90 },
      { "bruised", 80 },
        { "battered", 80 },
      { "good", 80 },
      { "cut", 70 },
      { "fair", 70 },
        { "heavily battered", 70 },
      { "wounded", 60 },
      { "fine", 60 },
        { "slightly damaged", 60 },
      { "badly wounded", 50 },
      { "hurt", 50 },
        { "damaged", 50 },
      { "bleeding freely", 40 },
      { "injured", 40 },
        { "badly damaged", 40 },
      { "covered in blood", 30 },
      { "wounded", 30 },
        { "losing bits", 30 },
      { "leaking guts", 20 },
      { "bleeding", 20 },
        { "falling apart", 20 },
      { "almost dead", 10 },
      { "dying", 10 },
        { "in pieces", 10 },
      { "finished", 5 },
      //    { "dying", 5 },
      { NULL, 0 }
};


int PromptPlugin::convert(char * str) {

      int i = 0;

      while (word_table[i].word) {
            if (!strcmp(word_table[i].word, str))
                  return word_table[i].value;
        i++;
      }
      return 100;
}

// find prompt now uses connection rather than vt

struct vtPrompt * PromptPlugin::findPrompt(Connection * c) {

  struct vtPrompt * data = find_data(c);
  if (!data) {
    data = (struct vtPrompt *)malloc(sizeof(struct vtPrompt));
    memset(data, 0, sizeof(struct vtPrompt));
    data->connection = c;
    add_data(data);

    // Setup global/local preference-based drawing colours
    loadColours(data, connection_get_mud(c));


    //    data->connection = c;
    data->widget = gtk_drawing_area_new();

    gtk_widget_set_size_request(GTK_WIDGET(data->widget), 105, 16);

    g_signal_connect_data(data->widget, "configure_event",
                    GTK_SIGNAL_FUNC(pplugin_expose), 
                    data,
                    NULL,
                    (GConnectFlags)0);
    g_signal_connect_data(data->widget, "expose_event",
                    GTK_SIGNAL_FUNC(pplugin_expose), 
                    data,
                    NULL,
                    (GConnectFlags)0);


    data->event_box = gtk_event_box_new();
    gtk_container_add(GTK_CONTAINER(data->event_box), data->widget);
    gtk_widget_show(data->widget);


    vt_add_to_tray(connection_get_vt(c), data->event_box, &data->frame);

    
    data->tooltips = gtk_tooltips_new();
    gtk_tooltips_set_tip(data->tooltips, data->event_box, _("PromptPlugin: displays information from the prompt as coloured bars."), NULL);

    // Create widgets.
  } // end if (!data)

  return data;
}

#if 0
// Re-enabling this will break the colour prefs mod
//struct vtPrompt * PromptPlugin::newPrompt(VT * c) {
//  
//  struct vtPrompt * tmp = (struct vtPrompt *)malloc(sizeof(struct vtPrompt));
//
//  memset(tmp, 0, sizeof(struct vtPrompt));
//  tmp->vt = c;
//
//  tmp->widget = gtk_drawing_area_new();
//  gtk_drawing_area_size(GTK_DRAWING_AREA(tmp->widget), 105, 16);
//
//  gtk_signal_connect(GTK_OBJECT(tmp->widget), "configure_event", GTK_SIGNAL_FUNC(pplugin_expose), tmp);
//  gtk_signal_connect(GTK_OBJECT(tmp->widget), "expose_event", GTK_SIGNAL_FUNC(pplugin_expose), tmp);
//  
//  // Add the widget to the tray
//  c->addToTray(tmp->widget, &tmp->frame);
//
//  tmp->next = firstPrompt;
//  firstPrompt = tmp;
//  return tmp;
//}

//char * PromptPlugin::getDescription() {
//  return "Displays two bars in the plugin tray.  Shading of the bars is dependent on prompt data.";
//}

#endif

#if 0

GtkWidget * PromptPlugin::getPrefsWidget(MUD * m) {
  GtkWidget * panel;
  GtkWidget * table;
  GtkWidget * widget;

  // Load a vtPrompt with the appropriate colour information
  loadColours(&prefs_scratch, m);

  panel = gtk_frame_new (NULL);
  gtk_widget_ref(panel);

#ifdef USE_GTK_2
  g_object_set_data(G_OBJECT(panel), "panel", panel);
#else
  gtk_object_set_data(GTK_OBJECT(panel), "panel", panel);
#endif

  table = gtk_table_new (1, 1, TRUE);
  gtk_widget_show (table);
  gtk_container_add (GTK_CONTAINER (panel), table);

#ifdef USE_GTK_2
  g_object_set_data_full(G_OBJECT(panel), "table", table,
                   (GtkDestroyNotify) gtk_widget_unref);
#else
  gtk_object_set_data_full(GTK_OBJECT(panel), "table", table,
                     (GtkDestroyNotify) gtk_widget_unref);
#endif

  widget = fade_get_editor(prefs_scratch.fade);
  gtk_widget_show(widget);
  gtk_table_attach (GTK_TABLE (table), widget, 0, 1, 0, 1,
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                    (GtkAttachOptions) (GTK_FILL), 0, 0);

#ifdef USE_GTK_2
  g_object_set_data_full(G_OBJECT(panel), "widget", widget,
                   (GtkDestroyNotify) gtk_widget_unref);
#else
  gtk_object_set_data_full(GTK_OBJECT(panel), "widget", widget,
                     (GtkDestroyNotify) gtk_widget_unref);
#endif

  return panel;
}

void PromptPlugin::onPrefsOk(MUD * m) {

  // We only clean up the widgets here - onPrefsApply is always called
  // before an onPrefsOk()
  fade_on_prefs_cancel(prefs_scratch.fade);
}

void PromptPlugin::onPrefsApply(MUD * m) {

  char * maxc;
  char * midc;
  char * minc;
  char * triplet;

  // Find a vtPrompt with the appropriate colour information

  fade_on_prefs_apply(prefs_scratch.fade);

  maxc = fade_string_max_colour(prefs_scratch.fade);
  midc = fade_string_mid_colour(prefs_scratch.fade);
  minc = fade_string_min_colour(prefs_scratch.fade);
  triplet = fade_string_use_three(prefs_scratch.fade);


  Prefs * currPref;

  if (!m)

        currPref = get_global_preferences();

  else

        currPref = mud_get_preferences(m);



  preferences_set_preference(currPref, PREFS_MIN_RGB, minc);

  preferences_set_preference(currPref, PREFS_MID_RGB, midc);

  preferences_set_preference(currPref, PREFS_MAX_RGB, maxc);

  preferences_set_preference(currPref, PREFS_TRIPLET, triplet);


  free(maxc);
  free(midc);
  free(minc);
  free(triplet);

  // Force all prompts to reset to the configured colours
  for (PromptDataList::iterator i = promptList.begin(); i != promptList.end(); i++)
    loadColours((struct vtPrompt)(*i),
            connection_get_mud((*i)->connection));

}

void PromptPlugin::onPrefsCancel(MUD * m) {
  fade_on_prefs_cancel(prefs_scratch.fade);
}

#endif

void PromptPlugin::loadColours(struct vtPrompt *data, MUD * m) {

  char * triplet = NULL;
  char * cs_min  = NULL;
  char * cs_mid  = NULL;
  char * cs_max  = NULL;

  // Find the correct description strings (if there are any)
  if (m && mud_get_preferences(m)) {

        Prefs * p = mud_get_preferences(m);



        cs_min = preferences_get_preference(p, PREFS_MIN_RGB);

        cs_mid = preferences_get_preference(p, PREFS_MID_RGB);

        cs_max = preferences_get_preference(p, PREFS_MAX_RGB);

        triplet = preferences_get_preference(p, PREFS_TRIPLET);

  }



  Prefs * global = get_global_preferences();


  // Fall back to globals if the prefs are missing
  if (!m || !cs_min)
      cs_min = preferences_get_preference(global, PREFS_MIN_RGB);


  if (!m || !cs_mid)
      cs_mid = preferences_get_preference(global, PREFS_MID_RGB);


  if (!m || !cs_max)
      cs_max = preferences_get_preference(global, PREFS_MAX_RGB);


  if (!m || !triplet)
      triplet = preferences_get_preference(global, PREFS_TRIPLET);


  if (!data->fade) {
    if (triplet)
      data->fade = fade_new(atoi(triplet), cs_min, cs_mid, cs_max);
    else
      data->fade = fade_new(FALSE, cs_min, cs_mid, cs_max);
  } else {
    if (triplet)
      fade_reset(data->fade, atoi(triplet), cs_min, cs_mid, cs_max);
    else
      fade_reset(data->fade, FALSE, cs_min, cs_mid, cs_max);
  }
}


static int PromptCmp(struct vtPrompt * l1, struct vtPrompt *l2) {
  return (l1 < l2);
}

void PromptPlugin::remove_data(struct vtPrompt * data) {
  PromptDataList::iterator i = std::lower_bound(promptList.begin(),
                                               promptList.end(),
                                               data,
                                               PromptCmp);
  if (i == promptList.end() || (*i) != data)
    return;

  promptList.erase(i);
}

struct vtPrompt * PromptPlugin::find_data(Connection * connection) {
  for (PromptDataList::iterator i = promptList.begin(); i != promptList.end(); 
i++)
    if ((*i)->connection == connection)
      return (*i);

  return NULL;
}

void PromptPlugin::add_data(struct vtPrompt * data) {
    PromptDataList::iterator i = std::lower_bound(promptList.begin(),
                                                 promptList.end(),
                                                 data,
                                                 PromptCmp);
    
    promptList.insert(i, data);
}

Generated by  Doxygen 1.6.0   Back to index