/* silcerchatview.cc Author: Pekka Riikonen Copyright (C) 2001 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Code is mostly ripped from Gabber, thus code also copyrighted by: Copyright (C) 1999-2001 Dave Smith & Julian Missig */ #include "silcerchatview.hh" #include #include #include extern "C" { #include "xtext.h" } GdkColor colors[] = { {0, 0, 0, 0}, /* 0 black */ {0, 0xcccc, 0xcccc, 0xcccc}, /* 1 white */ {0, 0, 0, 0xcccc}, /* 2 blue */ {0, 0, 0xcccc, 0}, /* 3 green */ {0, 0xcccc, 0, 0}, /* 4 red */ {0, 0xbbbb, 0xbbbb, 0}, /* 5 yellow/brown */ {0, 0xbbbb, 0, 0xbbbb}, /* 6 purple */ {0, 0xffff, 0xaaaa, 0}, /* 7 orange */ {0, 0xffff, 0xffff, 0}, /* 8 yellow */ {0, 0, 0xffff, 0}, /* 9 green */ {0, 0, 0xcccc, 0xcccc}, /* 10 aqua */ {0, 0, 0xffff, 0xffff}, /* 11 light aqua */ {0, 0, 0, 0xffff}, /* 12 blue */ {0, 0xffff, 0, 0xffff}, /* 13 pink */ {0, 0x7777, 0x7777, 0x7777}, /* 14 grey */ {0, 0x9999, 0x9999, 0x9999}, /* 15 light grey */ {0, 0, 0, 0xcccc}, /* 16 blue markBack */ {0, 0xeeee, 0xeeee, 0xeeee}, /* 17 white markFore */ {0, 0xcccc, 0xcccc, 0xcccc}, /* 18 foreground (white) */ {0, 0, 0, 0}, /* 19 background (black) */ }; typedef const int CONSTANT; const int WORD_URL = 1; const int WORD_HOST = 2; void palette_load(GtkWidget* w) { int i; if (!colors[0].pixel) /* don't do it again */ for (i = 0; i < 20; i++) { colors[i].pixel = (gulong) ((colors[i].red & 0xff00) * 256 + (colors[i].green & 0xff00) + (colors[i].blue & 0xff00) / 256); if (!gdk_colormap_alloc_color (gtk_widget_get_colormap (w), &colors[i], 0, 1)) cerr << "Error allocating color " << i << endl; } } int word_check(GtkXText* t, char* word) { if (!word) return 0; int len = strlen (word); if (!strncasecmp (word, "irc://", 6)) return WORD_URL; if (!strncasecmp (word, "irc.", 4)) return WORD_URL; if (!strncasecmp (word, "ftp.", 4)) return WORD_URL; if (!strncasecmp (word, "ftp:", 4)) return WORD_URL; if (!strncasecmp (word, "www.", 4)) return WORD_URL; if (!strncasecmp (word, "http:", 5)) return WORD_URL; if (!strncasecmp (word, "https:", 6)) return WORD_URL; if (!strncasecmp (word, "silc:", 7)) return WORD_URL; if (!strncasecmp (word, "sftp:", 7)) return WORD_URL; if (!strncasecmp (word + len - 4, ".org", 4)) return WORD_HOST; if (!strncasecmp (word + len - 4, ".net", 4)) return WORD_HOST; if (!strncasecmp (word + len - 4, ".com", 4)) return WORD_HOST; if (!strncasecmp (word + len - 4, ".edu", 4)) return WORD_HOST; return 0; } SilcerChatView::SilcerChatView(Gtk::Widget *owner, Gtk::Container *parent, gboolean indent) { // Create a Gtk::Text so we can grab the colors, then destroy it Gtk::Text textwidget; parent->add(textwidget); textwidget.realize(); // Copy the style of the Gtk::Text widget GtkStyle* gs = gtk_widget_get_style(GTK_WIDGET(textwidget.gtkobj())); colors[16] = gs->bg[GTK_STATE_SELECTED]; colors[17] = gs->fg[GTK_STATE_SELECTED]; colors[18] = gs->fg[GTK_STATE_NORMAL]; colors[19] = gs->base[GTK_STATE_NORMAL]; parent->remove(textwidget); textwidget.destroy(); // Initialize the palette palette_load(owner->gtkobj()); // Create the GtkXText object _xtext = GTK_XTEXT(gtk_xtext_new(75, 0)); // Internal init _xtext->max_lines = 1024; _xtext->urlcheck_function = word_check; _xtext->auto_indent = !indent; _xtext->wordwrap = true; // Display the widget gtk_xtext_set_palette(_xtext, colors); gtk_xtext_set_font(_xtext, gs->font, ""); // Create a frame around it _frmChat = GTK_FRAME(gtk_frame_new(NULL)); gtk_frame_set_shadow_type(GTK_FRAME(_frmChat), GTK_SHADOW_IN); // Add the widget to a container, which happens to be a frame gtk_container_add(parent->gtkobj(), GTK_WIDGET(_frmChat)); gtk_container_add(GTK_CONTAINER(_frmChat), GTK_WIDGET(_xtext)); gtk_widget_show(GTK_WIDGET(_frmChat)); gtk_widget_show(GTK_WIDGET(_xtext)); // Create a scrollbar _vsChat = GTK_VSCROLLBAR(gtk_vscrollbar_new(_xtext->adj)); gtk_box_pack_start (GTK_BOX (parent->gtkobj()), GTK_WIDGET(_vsChat), FALSE, FALSE, 1); GTK_WIDGET_UNSET_FLAGS (_vsChat, GTK_CAN_FOCUS); gtk_widget_show (GTK_WIDGET(_vsChat)); // Hookup stub callback gtk_signal_connect(GTK_OBJECT(_xtext), "word_click", GTK_SIGNAL_FUNC(&SilcerChatView::_on_word_clicked_stub), this); } SilcerChatView::~SilcerChatView() { gtk_widget_destroy(GTK_WIDGET(_xtext)); gtk_widget_destroy(GTK_WIDGET(_frmChat)); gtk_widget_destroy(GTK_WIDGET(_vsChat)); } void SilcerChatView::render(const string &message, const string &username, const string ×tamp, COLOR_T &c) { if (username == "") print(timestamp + c + "***\017", message); else print(timestamp + c + "<\017" + username + c + ">\017" , message); } void SilcerChatView::render_error(const string &message, const string &error, const string ×tamp, COLOR_T &c) { // Process error messages print(timestamp + c + error + "\017:", message); } void SilcerChatView::clearbuffer() { // Flush the buffer gtk_xtext_remove_lines(_xtext, -1, true); } string SilcerChatView::get_chars() { return string(gtk_xtext_get_chars(_xtext)); } void SilcerChatView::on_word_clicked(char *word, GdkEventButton *evt) { string s_word = word; if (evt->button == 3) { switch(word_check(_xtext, word)) { case WORD_URL: gnome_url_show(word); break; case WORD_HOST: s_word = "http://" + s_word; gnome_url_show(s_word.c_str()); break; } } } void SilcerChatView::_on_word_clicked_stub(GtkXText *xtext, char *word, GdkEventButton *evt, SilcerChatView *_this) { _this->on_word_clicked(word, evt); } inline void SilcerChatView::print(const string &s) { char* astr = (char*)s.c_str(); char* anewline = strchr(astr, '\n'); if (anewline) { while(1) { gtk_xtext_append(_xtext, astr, (unsigned long)anewline - (unsigned long)astr); astr = anewline + 1; if (*astr == 0) break; anewline = strchr(astr, '\n'); if (!anewline) { gtk_xtext_append(_xtext, astr, -1); break; } } } else { gtk_xtext_append(_xtext, astr, s.length()); } } inline void SilcerChatView::print(const string& left, const string& right) { char* s = (char*)right.c_str(); char* newline = strchr(s, '\n'); if (newline) { // Display the first line w/ the user who said it gtk_xtext_append_indent(_xtext, (char*)left.c_str(), left.length(), s, (unsigned long)newline - (unsigned long)s); // Now loop through the rest of the string, displaying it while (1) { s = newline + 1; if (*s == 0) break; newline = strchr(s, '\n'); // If another newline is found, append it to the display and loop again if (newline) { gtk_xtext_append_indent(_xtext, "", 0, s, (unsigned long)newline - (unsigned long)s); } else { // Otherwise append the rest of the string and break out of the loop gtk_xtext_append_indent(_xtext, "", 0, s, -1); break; } } } else { gtk_xtext_append_indent(_xtext, (char*)left.c_str(), left.length(), (char*)right.c_str(), right.length()); } }