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

ColouredLabel.cpp

#include "papaya/system.h"

#include <ctype.h>

#include "SystemColour.h"
#include "ColouredLabel.h"

#define ESCAPE '\033'

ColouredLabel::ColouredLabel(Connection * c) {
  conn = c;

  widget = NULL;
  widget_text = strdup("");
}

ColouredLabel::ColouredLabel(Connection * c, char * text) {
  conn = c;

  widget = NULL;
  widget_text = strdup("");
}

ColouredLabel::~ColouredLabel() {
  free(widget_text);
}

void ColouredLabel::init() {

  papaya_colour = false;
  bold = false;
  background_color_default = true;
  foreground_color_default = true;
  flashing = false;
  span = false;

  // Initialise color and background_color
  fg = conn->queryPreferences()->getPreferenceInteger("DefaultForegroundColour");
  bg = conn->queryPreferences()->getPreferenceInteger("DefaultBackgroundColour");

  if (fg == 8)
    fg = 0;
  if (bg == 8)
    bg = 7;

  struct colour_table * table = conn->getVT()->getColourTable();

  color_map = gdk_colormap_get_system();

  color.red = table[fg].red;
  color.green = table[fg].green;
  color.blue = table[fg].blue;

  background_color.red = table[bg].red;
  background_color.green = table[bg].green;
  background_color.blue = table[bg].blue;

  gdk_color_alloc(color_map, &color);
  gdk_color_alloc(color_map, &background_color);
}

void ColouredLabel::createWidget() {
  init();

  widget = gtk_label_new("");
}

// Text string includes ANSI colour codes.

void ColouredLabel::setText(char * text) {

  char inter[16384];
  char output[16384];
  char * inter_ptr;
  char * output_ptr;
  char * pc = text;
  char * last_marker = text;

  inter_ptr = inter;
  inter[0] = '\0';

  output_ptr = output;
  output[0] = '\0';

  while (*pc != '\0') {
        if (*pc == '>' || *pc == '<' || *pc == '&') {
              *inter_ptr++ = '&';
              if (*pc == '>') {
                    *inter_ptr++ = 'g';
                    *inter_ptr++ = 't';
              }
              else if (*pc == '<') {
                    *inter_ptr++ = 'l';
                    *inter_ptr++ = 't';
              }
              else {
                    *inter_ptr++ = 'a';
                    *inter_ptr++ = 'm';
                    *inter_ptr++ = 'p';
              }
              *inter_ptr++ = ';';
        } else {
              *inter_ptr++ = *pc;
        }
        pc++;
  }

  *inter_ptr = '\0';

  pc = inter;
  last_marker = pc;

  while ((pc = strchr(pc, ESCAPE))) {
    *pc = '\0';
    
    if (last_marker != '\0') {
      printPrompt(last_marker, output_ptr);
      output_ptr = output + strlen(output);
    }

    pc = parseVTCode(pc);
    last_marker = pc;
  }

  if (last_marker != '\0')
    printPrompt(last_marker, output_ptr);

  if (span)
    strcat(output_ptr, "</span>");

  gtk_label_set_markup(GTK_LABEL(widget), output);

  span = false;

}

GtkWidget * ColouredLabel::getWidget() {
  return widget;
}

void ColouredLabel::printPrompt(char * text, char * output) {

  if (!text) {
    printf ("FIXME: ColouredLabel::printPrompt given NULL string.\n");
    return;
  }

  if (span) {
    strcat(output, "</span>");
    output += strlen("</span>");
  }

  char foreground[16384];
  char background[16384];

  foreground[0] = '\0';
  background[0] = '\0';

  if (!foreground_color_default || papaya_colour)
    snprintf(foreground, 16384, " foreground=\"#%02x%02x%02x\"",
           color.red * 255 / 65535 , color.green * 255 / 65535 , color.blue * 255 / 65535);
  
  if (!background_color_default)
    snprintf(background, 16384, " background=\"#%02x%02x%02x\"",
           background_color.red * 255 / 65535 , background_color.green * 255 / 65535 , background_color.blue * 255 / 65535);

  snprintf(output, 16384, "<span font_desc=\"%s\"%s%s>%s",
         conn->queryPreferences()->getPreference("PromptFont"),
         foreground, background, text);
  
  span = true;
}

void ColouredLabel::printPrompt(char * string, int y_offset) {

  // Create a graphics context and set the colours in it.

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

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

  gdk_gc_set_foreground(gc, &color);
  gdk_gc_set_background(gc, &background_color);

  gdk_draw_string(widget->window,
              NULL, // Used to retrieve Prefs::getPrompt()
              gc,
              x_offset,
              y_offset,
              string);

  x_offset += gdk_string_width(NULL, string);

  gdk_gc_destroy(gc);
}

char * ColouredLabel::parseVTCode(char * code) {
  char *pc = code+1;

  switch (*pc) {
  case '[':
    pc = parseBracketVTCode(pc);
    break;

  default:
    pc = parsePlainVTCode(pc);
    break;
  }

  pc++;
  return pc;
}

char * ColouredLabel::parseBracketVTCode(char * pc) {

  char * orig = pc;
  
  while (!isalpha(*pc))
    pc++;
  
  switch (*pc) {
    
  case 'm': // Colour code
    setColour(orig);
    break;
    
  case 'p': // Internal Papaya colour code.
    setPapayaColour(orig);
    break;
    
  case 'q': // Reset Papaya colour.
    resetPapayaColour();
    
  }
  
  return pc;
}

char * ColouredLabel::parsePlainVTCode(char * pc) {
  while (!isalpha(*pc))
    pc++;

  return pc;
}
void ColouredLabel::setPapayaColour(char * buf) {

  int red;
  int green;
  int blue;

  // allocate color

  char * pc;

  pc = strchr(buf, 'p');
  if (!pc)
    return;

  if (pc - buf != 12) { // [rrr;ggg;bbb
    printf(_("Invalid Papaya colour code.\n"));
    return;
  }

  *pc = '\0';
  if (sscanf(buf, "[%d;%d;%d", &red, &green, &blue) != 3) {
    printf(_("Invalid Papaya colour code.\n"));
    return;
  }

  papaya_colour = TRUE;

  color.red = red * 0xffff / 255;
  color.green = green * 0xffff / 255;
  color.blue = blue * 0xffff / 255;

  gdk_color_alloc(color_map, &color);
}


void ColouredLabel::resetPapayaColour() {
  papaya_colour = FALSE;

  if (bold) {
    struct colour_table * table = conn->getVT()->getColourTable();

    color.red = table[fg+8].red;
    color.green = table[fg+8].green;
    color.blue = table[fg+8].blue;

    background_color.red = table[bg + 8].red;
    background_color.green = table[bg + 8].green;
    background_color.blue = table[bg + 8].blue;

    gdk_color_alloc(color_map, &color);
    gdk_color_alloc(color_map, &background_color);
  } else {
    struct colour_table * table = conn->getVT()->getColourTable();

    color.red = table[fg].red;
    color.green = table[fg].green;
    color.blue = table[fg].blue;

    background_color.red = table[bg].red;
    background_color.green = table[bg].green;
    background_color.blue = table[bg].blue;

    gdk_color_alloc(color_map, &color);
    gdk_color_alloc(color_map, &background_color);
  }
}

void ColouredLabel::setColour(char * buf) {
  char * pc = buf;
  char buf2[10];
  int pos = 0;

  buf2[0] = '\0';
  
  papaya_colour = FALSE;

  while (1) {

    // If we haven't got a [ or ; indicating more codes, leave the loop.
    if (!(*pc == ';' || *pc == '['))
      break;

    // Rip out the bit until the next non-alphanumeric character.
    pos = 0;

    buf2[pos] = *pc++;

    while (1) {
      if (isalpha(*pc) || *pc == ';')
        break;

      buf2[pos++] = *pc++;
    }
    
    buf2[pos] = '\0';
    setActualColour(buf2);
  }
}

void ColouredLabel::setActualColour(char * buf) {

  if (!conn->queryPreferences()->getPreferenceBoolean("EnableColour"))
    return;

  if (buf[0] == '0') {

    // Set everything to defaults.
    background_color_default = TRUE;
    foreground_color_default = TRUE;

    bold = FALSE;
    flashing = FALSE;
    return;
  }

  if (buf[0] == '1') {
    bold = TRUE;

    struct colour_table * table = conn->getVT()->getColourTable();

    color.red = table[fg+8].red;
    color.green = table[fg+8].green;
    color.blue = table[fg+8].blue;

    background_color.red = table[bg + 8].red;
    background_color.green = table[bg + 8].green;
    background_color.blue = table[bg + 8].blue;

    gdk_color_alloc(color_map, &color);
    gdk_color_alloc(color_map, &background_color);

    return;
  }

  if (buf[0] == '5') {
    flashing = TRUE;
    return;
  }

  /* Look up which colour we're to use. */

  /* buf[2] should contain the colour. */

  if (strlen(buf) >= 2) {
    for (int i = 0; i < 8; i++) {

      struct colour_table * table = conn->getVT()->getColourTable();

      if (table[i].colour_character == buf[1]) {

        if (buf[0] == '3') {
          foreground_color_default = FALSE;

          if (bold) {
            color.red = table[i+8].red;
            color.green = table[i+8].green;
            color.blue = table[i+8].blue;
          } else {
            color.red = table[i].red;
            color.green = table[i].green;
            color.blue = table[i].blue;
          }
          gdk_color_alloc(color_map, &color);
          fg = i;
          return;
        }
        
        if (buf[0] == '4') {
          background_color_default = FALSE;

          if (bold) {
            background_color.red = table[i+8].red;
            background_color.green = table[i+8].green;
            background_color.blue = table[i+8].blue;
          } else {
            background_color.red = table[i].red;
            background_color.green = table[i].green;
            background_color.blue = table[i].blue;
          }
          gdk_color_alloc(color_map, &background_color);
          bg = i;
          return;
        }
        
        return;

      }
    }
  }
}

Generated by  Doxygen 1.6.0   Back to index