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

color.c

/*
 * xconvers - GTK+ convers client for amateur radio
 * Copyright (C) 2000-2003 Joop Stakenborg <pg4i@amsat.org>
 *
 * 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
 * color.c - private functions for looking up and displaying colors.
 */
 
#include <gtk/gtk.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "support.h"
#include "color.h"
#include "net.h"
#include "types.h"

extern GtkWidget *mainwindow, *preferencesdialog;
extern GdkFont *textfont;
extern preferencestype preferences;
extern gint buttonnumber, mousebutton;
gchar *savedline;
gint previousmessage = 0, usercolor = 0, colorindex = 0;
GHashTable *callsigns = NULL;

/*
 * Different messages are displayed in different colors here. This all depends
 * on the first couple of characters on a line. An incoming message, which can
 * have multiple lines, is first split into lines with g_strsplit, so the lines
 * can be checked for a color. When a line starts with '<', it definitely is a
 * user message. We try to extract the user's callsign with g_strdelimit and 
 * g_strsplit. Finally we call getcolor, to get the color associated with the 
 * user.
 */

void maintext_add(gchar *msg, gint messagetype)
{
  GtkWidget *maintext;
  gchar **rxsplit = NULL, **linesplit = NULL;
  gchar *delimitedline = NULL, *insert = NULL, *callsign = NULL;
  gint i, crs = 0, numbytes = 0;
  gint rxtype = DEFAULT_MESSAGE;

  if (msg[0] == '\0') return;
  numbytes = strlen(msg);
  maintext = lookup_widget(mainwindow, "maintext");
  switch (messagetype)
  {
    case MESSAGE_RX:
      /* count carriage returns */
      for (i = 0; i < numbytes; i++) if (msg[i] == '\n') crs++;

      /* split up the incoming message into lines */
      if (crs > 0) rxsplit = g_strsplit(msg, "\n", crs);

      /* add a saved line which was incomplete in the previous message to the first line */
      /* only attach to the first line if a carriage return was received */
      if (savedline)
      {
        if (crs > 0)
        { 
          rxsplit[0] = g_strconcat(savedline, rxsplit[0], NULL);
          savedline = g_strdup("");
        }
        else
        {
          savedline = g_strconcat(savedline, msg, NULL);
        }
      }

      /* now check for status, private and user messages in every line */
      for (i = 0; i < crs; i++)
      {
        insert = g_strdup_printf("%s\n", rxsplit[i]);

        if (insert[0] == '*'){
          /* string received:'**' --> status message */
          if (insert[1] == '*') rxtype = STATUS_MESSAGE; else rxtype = DEFAULT_MESSAGE;
        }
        else if (insert[0] == '<') {
          /* string received:'<*' --> private message */
          if (insert[1] == '*') rxtype = PRIVATE_MESSAGE; else rxtype = USER_MESSAGE;
        }
        else if (insert[0] == ' ') rxtype = previousmessage;
        /* character other than '<* ' on the first line */
        else rxtype = DEFAULT_MESSAGE;

        switch (rxtype)
        {
          case STATUS_MESSAGE:
            gtk_text_insert(GTK_TEXT(maintext), textfont, &preferences.statusfgcolor, NULL, insert, -1);
            previousmessage = STATUS_MESSAGE;
          break;
          case USER_MESSAGE:
            /* extract callsign from received string, call is in between '<' and '>' */
            if (insert[0] == '<') {
              delimitedline = g_strdelimit(rxsplit[i], "<>", '#');
              linesplit = g_strsplit(delimitedline, "#", 3);
              callsign = g_strstrip(linesplit[1]);
              /* check if it really is a callsign */
              if (strlen(callsign) > 2) { /* only check for now: callsign should be at least 3 letters */
                colorindex = getcolor(callsign); /* get new or existing color for this callsign */
                gtk_text_insert(GTK_TEXT(maintext), textfont, &preferences.userfgcolor[colorindex], NULL, insert, -1);
                previousmessage = USER_MESSAGE;
              } 
              else {
                gtk_text_insert(GTK_TEXT(maintext), textfont, &preferences.rxfgcolor, NULL, insert, -1);
                previousmessage = DEFAULT_MESSAGE;
              }
              g_strfreev(linesplit);
            }
            else {
              gtk_text_insert(GTK_TEXT(maintext), textfont, &preferences.userfgcolor[colorindex], NULL, insert, -1);
              previousmessage = USER_MESSAGE;
            }
          break;
          case PRIVATE_MESSAGE:
            gtk_text_insert(GTK_TEXT(maintext), textfont, &preferences.privatefgcolor, &preferences.privatebgcolor, insert, -1);
            previousmessage = PRIVATE_MESSAGE;
          break;
          case UNKNOWN_MESSAGE:
          break;
          case DEFAULT_MESSAGE:
            gtk_text_insert(GTK_TEXT(maintext), textfont, &preferences.rxfgcolor, NULL, insert, -1);
            previousmessage = DEFAULT_MESSAGE;
          break;
          default:
          break;
        }
      }
      free(insert);
      /* save incomplete line */
      if (crs > 0 && rxsplit[crs]) savedline = g_strdup(rxsplit[crs]);
      g_strfreev(rxsplit);
    break;
    case MESSAGE_TX:
      gtk_text_insert(GTK_TEXT(maintext), textfont, &preferences.txfgcolor, NULL, msg, -1);
    break;
    default:
    break;
  }
}

/*
 * Here the color associated with a callsign is looked up. Information is 
 * stored in a hash table. This will ensure fast lookups. Items are added using
 * a key, which is calculated from the callsign. When a call is not found, the
 * color counter is incremented.
 */

gint getcolor(gchar *color)
{
  gchar *call = g_strdup(color);
  gint i;

  if (g_hash_table_lookup(callsigns, call) == NULL)
  {
    usercolor++;
    g_hash_table_insert(callsigns, g_strdup(call), GINT_TO_POINTER(usercolor));
    i = usercolor;
  }
  else
    i = GPOINTER_TO_INT(g_hash_table_lookup(callsigns, call));
  return((i-1) % 10);
}

/*
 * The color which is looked up in the xconvers preferences file is put in the
 * right format for XParseColor, so it can be processed by gdk_color_parse.
 */

gchar *color_parse(gchar value[100])
{
  gchar **valuesplit = NULL;
  gchar *rgbsyntax;
  
  valuesplit = g_strsplit(value, ",", 3);
  rgbsyntax = g_strconcat("rgb:", valuesplit[0], "/", valuesplit[1], "/", valuesplit[2], NULL);
  g_strfreev(valuesplit);
  return (rgbsyntax);
}

/*
 * Look up the button name and set the color.
 */

void setbuttoncolor(gchar *buttonname, GdkColor buttoncolor)
{
  GtkWidget *colorbutton;
  GtkStyle *buttonstyle;
  
  colorbutton = lookup_widget(preferencesdialog, buttonname);
  buttonstyle = gtk_style_new();
  buttonstyle->bg[GTK_STATE_NORMAL] = buttoncolor;
  buttonstyle->bg[GTK_STATE_ACTIVE] = buttoncolor;
  buttonstyle->bg[GTK_STATE_PRELIGHT] = buttoncolor;
  buttonstyle->bg[GTK_STATE_SELECTED] = buttoncolor;
  gtk_widget_set_style(colorbutton, buttonstyle);
}

/*
 * Update the little window in the preferences dialog where all the session
 * colors can be seen.
 */

void updatepreview(GdkColor selectedcolor)
{
  GtkWidget *colorstext;
  GtkStyle *textstyle;

  colorstext = lookup_widget(preferencesdialog, "colorstext");
  gtk_text_freeze(GTK_TEXT(colorstext));
  gtk_editable_delete_text(GTK_EDITABLE(colorstext), 0, gtk_text_get_length(GTK_TEXT(colorstext)));

  switch (buttonnumber)
  {
    case 0:
      preferences.backgroundcolor = selectedcolor;
      setbuttoncolor("backgroundcolorbutton", selectedcolor);
    break;
    case 1:
      preferences.txfgcolor = selectedcolor;
      setbuttoncolor("txmessagebutton", selectedcolor);
    break;
    case 2:
      preferences.rxfgcolor = selectedcolor;
      setbuttoncolor("rxmessagebutton", selectedcolor);
    break;
    case 3:
      preferences.statusfgcolor = selectedcolor;
      setbuttoncolor("statusmessagebutton", selectedcolor);
    break;
    case 4:
      if (mousebutton == 1) 
      {
        preferences.privatefgcolor = selectedcolor;
        setbuttoncolor("privatemessagebutton", selectedcolor);
      }
      else preferences.privatebgcolor = selectedcolor;
    break;
    case 5:
      preferences.userfgcolor[0] = selectedcolor;
      setbuttoncolor("user1button", selectedcolor);
    break;
    case 6:
      preferences.userfgcolor[1] = selectedcolor;
      setbuttoncolor("user2button", selectedcolor);
    break;
    case 7:
      preferences.userfgcolor[2] = selectedcolor;
      setbuttoncolor("user3button", selectedcolor);
    break;
    case 8:
      preferences.userfgcolor[3] = selectedcolor;
      setbuttoncolor("user4button", selectedcolor);
    break;
    case 9:
      preferences.userfgcolor[4] = selectedcolor;
      setbuttoncolor("user5button", selectedcolor);
    break;
    case 10:
      preferences.userfgcolor[5] = selectedcolor;
      setbuttoncolor("user6button", selectedcolor);
    break;
    case 11:
      preferences.userfgcolor[6] = selectedcolor;
      setbuttoncolor("user7button", selectedcolor);
    break;
    case 12:
      preferences.userfgcolor[7] = selectedcolor;
      setbuttoncolor("user8button", selectedcolor);
    break;
    case 13:
      preferences.userfgcolor[8] = selectedcolor;
      setbuttoncolor("user9button", selectedcolor);
    break;
    case 14:
      preferences.userfgcolor[9] = selectedcolor;
      setbuttoncolor("user10button", selectedcolor);
    break;
    default:
    break;
  }
  
  buttonnumber = -1;

  textstyle = gtk_style_new();
  textstyle->base[GTK_STATE_NORMAL] = preferences.backgroundcolor;
  textstyle->base[GTK_STATE_INSENSITIVE] = preferences.backgroundcolor;
  gtk_widget_set_style(colorstext, textstyle);

  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.txfgcolor, NULL, _("\ntransmitted text\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.rxfgcolor, NULL, _("received text\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.statusfgcolor, NULL, _("*** status text\n\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.privatefgcolor, &preferences.privatebgcolor, _("<*private*>\n\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.userfgcolor[0], NULL, _("<user1>\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.userfgcolor[1], NULL, _("<user2>\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.userfgcolor[2], NULL, _("<user3>\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.userfgcolor[3], NULL, _("<user4>\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.userfgcolor[4], NULL, _("<user5>\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.userfgcolor[5], NULL, _("<user6>\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.userfgcolor[6], NULL, _("<user7>\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.userfgcolor[7], NULL, _("<user8>\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.userfgcolor[8], NULL, _("<user9>\n"), -1);
  gtk_text_insert(GTK_TEXT(colorstext), textfont, &preferences.userfgcolor[9], NULL, _("<user10>\n"), -1);

  gtk_text_thaw(GTK_TEXT(colorstext));
}

Generated by  Doxygen 1.6.0   Back to index