/* This is -*- C -*- */
/* $Id: guppi-stream-preview.c,v 1.13 2001/10/10 06:48:10 trow Exp $ */

/*
 * guppi-stream-preview.c
 *
 * Copyright (C) 1999, 2000 EMC Capital Management, Inc.
 *
 * Developed by Jon Trowbridge <trow@gnu.org> and
 * Havoc Pennington <hp@pobox.com>.
 *
 * 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 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
 */

#include <config.h>
#include "guppi-stream-preview.h"

/* #include <gnome.h> */
#include <glib.h>

#include <gtk/gtkframe.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkvbox.h>
#include <gtk/gtkscrolledwindow.h>
#include <gtk/gtklabel.h>

#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-config.h>
#include <libgnome/gnome-i18n.h>

#include "guppi-convenient.h"


/* First, some style info */

GdkColor *
style_active_line_color (void)
{
  static GdkColor *c = NULL;

  if (c == NULL) {
    c = guppi_new (GdkColor, 1);
    guppi_permanent_alloc (c);
    c->red = 0;
    c->green = 0;
    c->blue = 0;
    gdk_color_alloc (gdk_colormap_get_system (), c);
  }

  return c;
}

GdkColor *
style_inactive_line_color (void)
{
  static GdkColor *c = NULL;

  if (c == NULL) {
    c = guppi_new (GdkColor, 1);
    guppi_permanent_alloc (c);
    c->red = 0x8000;
    c->green = 0x8000;
    c->blue = 0x8000;
    gdk_color_alloc (gdk_colormap_get_system (), c);
  }

  return c;
}

GdkColor *
style_active_line_number_color (void)
{
  static GdkColor *c = NULL;

  if (c == NULL) {
    c = guppi_new (GdkColor, 1);
    guppi_permanent_alloc (c);
    c->red = 0;
    c->green = 0;
    c->blue = 0xffff;
    gdk_color_alloc (gdk_colormap_get_system (), c);
  }

  return c;
}

GdkColor *
style_inactive_line_number_color (void)
{
  static GdkColor *c = NULL;

  if (c == NULL) {
    c = guppi_new (GdkColor, 1);
    guppi_permanent_alloc (c);
    c->red = 0x8000;
    c->green = 0x8000;
    c->blue = 0x6fff;
    gdk_color_alloc (gdk_colormap_get_system (), c);
  }

  return c;
}

GdkColor *
style_title_line_color (void)
{
  static GdkColor *c = NULL;

  if (c == NULL) {
    c = guppi_new (GdkColor, 1);
    guppi_permanent_alloc (c);
    c->red = 0xc000;
    c->green = 0;
    c->blue = 0;
    gdk_color_alloc (gdk_colormap_get_system (), c);
  }

  return c;
}

GdkColor *
style_invalid_line_color (void)
{
  static GdkColor *c = NULL;

  if (c == NULL) {
    c = guppi_new (GdkColor, 1);
    guppi_permanent_alloc (c);
    c->red = 0xffff;
    c->green = 0;
    c->blue = 0;
    gdk_color_alloc (gdk_colormap_get_system (), c);
  }

  return c;
}

GdkFont *
style_line_font (void)
{
  static GdkFont *f = NULL;

  if (f == NULL) {
    const gchar *s = "-misc-fixed-medium-r-*-*-*-120-*-*-*-*-iso8859-1";
    f = gdk_font_load (s);
    if (!f) {
      g_warning ("Can't find font %s", s);
      f = gdk_font_load ("fixed");
      g_assert (f);
    }
  }

  return f;
}

GdkFont *
style_line_number_font (void)
{
  static GdkFont *f = NULL;
  if (f == NULL) {
    const gchar *s = "-misc-fixed-medium-r-*-*-*-50-*-*-*-*-iso8859-1";
    f = gdk_font_load (s);
    if (!f) {
      g_warning ("Can't find font %s", s);
      f = gdk_font_load ("fixed");
      g_assert (f);
    }
  }

  return f;
}

/********************************************************************/

static GtkObjectClass *parent_class = NULL;

static void
guppi_stream_preview_destroy (GtkObject * obj)
{
  GuppiStreamPreview *gsp = GUPPI_STREAM_PREVIEW (obj);

  gtk_signal_disconnect_by_data (GTK_OBJECT (gsp->stream), gsp);

  guppi_unref0 (gsp->stream);

  if (parent_class->destroy)
    parent_class->destroy (obj);
}

static void
guppi_stream_preview_finalize (GtkObject * obj)
{
  guppi_finalized (obj);

  if (parent_class->finalize)
    parent_class->finalize (obj);
}

static void
guppi_stream_preview_class_init (GuppiStreamPreviewClass * klass)
{
  GtkObjectClass *object_class = (GtkObjectClass *) klass;

  parent_class = gtk_type_class (GTK_TYPE_FRAME);

  object_class->destroy = guppi_stream_preview_destroy;
  object_class->finalize = guppi_stream_preview_finalize;
}

static void
guppi_stream_preview_init (GuppiStreamPreview * obj)
{
  obj->line_skip = NULL;
  obj->line_skip_user_data = NULL;
  obj->extra_info = NULL;
  obj->extra_info_user_data = NULL;
  obj->line_color = NULL;
  obj->line_color_user_data = NULL;
}

GtkType
guppi_stream_preview_get_type (void)
{
  static GtkType guppi_stream_preview_type = 0;
  if (!guppi_stream_preview_type) {
    static const GtkTypeInfo guppi_stream_preview_info = {
      "GuppiStreamPreview",
      sizeof (GuppiStreamPreview),
      sizeof (GuppiStreamPreviewClass),
      (GtkClassInitFunc) guppi_stream_preview_class_init,
      (GtkObjectInitFunc) guppi_stream_preview_init,
      NULL, NULL, (GtkClassInitFunc) NULL
    };
    guppi_stream_preview_type =
      gtk_type_unique (GTK_TYPE_FRAME, &guppi_stream_preview_info);
  }
  return guppi_stream_preview_type;
}

static void
guppi_stream_preview_set_info (GuppiStreamPreview * gsp)
{
  GuppiStream *gs;
  gchar total_bytes[128];
  gchar total_lines[128];
  gint lines, lines_est;
  gchar all[256];

  g_return_if_fail (gsp != NULL);

  gs = gsp->stream;

  if (gs->total_size >= 0)
    g_snprintf (total_bytes, 128, "%d", gs->total_size);
  else
    g_snprintf (total_bytes, 128, _("?"));

  lines = guppi_stream_number_of_lines (gs);
  lines_est = guppi_stream_estimated_number_of_lines (gs);

  if (lines >= 0)
    g_snprintf (total_lines, 128, "%d", lines);
  else if (lines_est >= 0)
    g_snprintf (total_lines, 128, _("approx %d"), lines_est);
  else
    g_snprintf (total_lines, 128, _("?"));

  g_snprintf (all, 256, _("Size: %s bytes / Length: %s lines"),
	      total_bytes, total_lines);

  gtk_label_set (gsp->info_label, all);
}

static void
render_marked_line (GtkText * text,
		    const gchar * line,
		    gchar escape,
		    gboolean skip,
		    GdkFont * font,
		    GdkColor * active_color, GdkColor * inactive_color)
{
  const gchar *prev;
  const gchar *p;
  gboolean pending, in_comment;

  g_return_if_fail (text != NULL);
  g_return_if_fail (line != NULL);

  p = line;
  prev = p;
  pending = FALSE;
  in_comment = FALSE;
  while (p && *p) {

    if (pending) {

      if (*p == 'L') {
	gtk_text_insert (text, font, inactive_color, NULL, p + 1, -1);
	p = NULL;
      } else if (*p == 'C') {
	in_comment = TRUE;
	prev = p + 1;
      } else if (*p == 'c') {
	in_comment = FALSE;
	prev = p + 1;
      } else if (*p != escape) {
	g_message ("Unknown line marking: <escape>-%c", *p);
      }

      pending = FALSE;

    } else {

      if (*p == escape) {
	pending = TRUE;
	if (p > prev)
	  gtk_text_insert (text, font,
			   in_comment || skip ? inactive_color : active_color,
			   NULL, prev, p - prev);
	prev = p;
      }

    }

    if (p)
      ++p;
  }

  if (p > prev)
    gtk_text_insert (text, font,
		     in_comment || skip ? inactive_color : active_color,
		     NULL, prev, p - prev);

}

static void
guppi_stream_preview_render_into_text (GuppiStreamPreview * gsp)
{
  gint i;
  const gchar *line;
  const gchar *sani;
  const gint buffer_len = 32;
  gchar buffer[32];
  gboolean skip_line;
  GdkFont *l_f;
  GdkFont *ln_f;
  GdkColor *ln_c;
  GdkColor *info_c;
  GdkColor *this_c;
  gchar escape;

  g_return_if_fail (gsp != NULL);

  l_f = style_line_font ();
  ln_f = style_line_number_font ();

  escape = guppi_stream_escape (gsp->stream);

  gtk_text_freeze (gsp->text);

  gtk_text_set_point (gsp->text, 0);
  gtk_text_forward_delete (gsp->text, gtk_text_get_length (gsp->text));

  gtk_text_thaw (gsp->text);

  /* 
     If I don't thaw and re-freeze here (i.e. if I try to make all of my
     changes between one freeze/thaw pair) I get a segfault if the scrolling
     window my GtkText is sitting inside of isn't up at the very top.

     I don't know if this is a gtk bug or if I'm doing something wrong
     somewhere.  This workaround makes things flicker a bit more, but
     otherwise seems pretty painless.
   */

  gtk_text_freeze (gsp->text);

  for (i = 0; i <= gsp->stream->current_line_no; ++i) {

    if (i != 0)
      gtk_text_insert (gsp->text, NULL, NULL, NULL, "\n", 1);

    line = guppi_stream_get_marked_line (gsp->stream, i);
    sani = guppi_stream_get_sanitized_line (gsp->stream, i);

    skip_line = FALSE;
    if (gsp->line_skip)
      skip_line = (gsp->line_skip) (gsp, sani, i + 1,
				    gsp->line_skip_user_data);

    if (skip_line) {
      ln_c = style_inactive_line_number_color ();
    } else {
      ln_c = style_active_line_number_color ();
    }

    g_snprintf (buffer, buffer_len, "%4d", i + 1);
    gtk_text_insert (gsp->text, ln_f, ln_c, NULL, buffer, -1);

    gtk_text_insert (gsp->text, l_f, NULL, NULL, " ", 1);

    if (gsp->extra_info) {

      info_c = (gsp->extra_info) (gsp, sani, i + 1,
				  buffer, buffer_len,
				  gsp->extra_info_user_data);
      if (info_c == NULL)
	info_c = ln_c;
      gtk_text_insert (gsp->text, ln_f, info_c, NULL, buffer, -1);
      gtk_text_insert (gsp->text, l_f, NULL, NULL, " ", 1);
    }

    this_c = style_active_line_color ();
    if (gsp->line_color) {
      GdkColor *alt_c = (gsp->line_color) (gsp, sani, i + 1,
					   gsp->line_color_user_data);
      if (alt_c != NULL)
	this_c = alt_c;
    }

    render_marked_line (gsp->text, line,
			escape, skip_line, l_f,
			this_c, style_inactive_line_color ());

  }

  gtk_text_thaw (gsp->text);
}

#ifdef EXTRA_CONTROLS
static void
guppi_stream_preview_reset_codes (GuppiStreamPreview * gsp)
{
  gchar *p;

  g_return_if_fail (gsp != NULL);

  p = gtk_entry_get_text (gsp->eol_combo_entry);
  guppi_stream_set_eol_comment (gsp->stream,
				strcmp (p, _("<none>")) == 0 ? NULL : p);

  p = gtk_entry_get_text (gsp->begin_ml_combo_entry);
  guppi_stream_set_ml_comment_start (gsp->stream,
				     strcmp (p, _("<none>")) == 0 ? NULL : p);

  p = gtk_entry_get_text (gsp->end_ml_combo_entry);
  guppi_stream_set_ml_comment_end (gsp->stream,
				   strcmp (p, _("<none>")) == 0 ? NULL : p);
}
#endif

#ifdef EXTRA_CONTROLS
static void
guppi_stream_preview_sync_codes (GuppiStreamPreview * gsp)
{
  const gchar *p;

  g_return_if_fail (gsp != NULL);
  g_return_if_fail (gsp->stream != NULL);

  p = guppi_stream_eol_comment (gsp->stream);
  gtk_entry_set_text (gsp->eol_combo_entry, p ? p : "<none>");

  p = guppi_stream_ml_comment_start (gsp->stream);
  gtk_entry_set_text (gsp->begin_ml_combo_entry, p ? p : "<none>");

  p = guppi_stream_ml_comment_end (gsp->stream);
  gtk_entry_set_text (gsp->end_ml_combo_entry, p ? p : "<none>");
}
#endif

/**********************************************************************/

static void
on_stream_preload (GuppiStream * gs, gpointer user_data)
{
  GuppiStreamPreview *gsp = GUPPI_STREAM_PREVIEW (user_data);
  g_return_if_fail (gsp != NULL);

  g_message ("preloading");
  guppi_stream_preview_render_into_text (gsp);
  guppi_stream_preview_set_info (gsp);
}

#ifdef EXTRA_CONTROLS
static void
on_stream_fully_preloaded (GuppiStream * gs, gpointer user_data)
{
  GuppiStreamPreview *gsp = GUPPI_STREAM_PREVIEW (user_data);
  g_return_if_fail (gsp != NULL);

  gtk_widget_set_sensitive (GTK_WIDGET (gsp->preload_button), FALSE);
}
#endif

static void
on_stream_changed_codes (GuppiStream * gs, gpointer user_data)
{
  GuppiStreamPreview *gsp = GUPPI_STREAM_PREVIEW (user_data);
  g_return_if_fail (gsp != NULL);

  //  guppi_stream_preview_render_into_text(gsp);
  guppi_stream_preview_refresh (gsp);
#ifdef EXTRA_CONTROLS
  guppi_stream_preview_sync_codes (gsp);
#endif
}


#ifdef EXTRA_CONTROLS
static void
on_preload_button_clicked (GtkButton * button, gpointer user_data)
{
  GuppiStreamPreview *gsp = GUPPI_STREAM_PREVIEW (user_data);
  g_return_if_fail (gsp != NULL);

  guppi_stream_load_more_lines (gsp->stream);
}

static void
on_combo_entry_focus_out (GtkWidget * w, GdkEventFocus * foo,
			  gpointer user_data)
{
  GuppiStreamPreview *gsp = GUPPI_STREAM_PREVIEW (user_data);
  g_return_if_fail (gsp != NULL);

  guppi_stream_preview_reset_codes (gsp);
}
#endif

void
guppi_stream_preview_construct (GuppiStreamPreview * gsp)
{
  GtkWidget *preview_frame;
  GtkWidget *vbox1;
  GtkWidget *scrolledwindow1;
  GtkWidget *text;
  GtkWidget *info_label;
#ifdef EXTRA_CONTROLS
  GtkWidget *hseparator1;
  GtkWidget *table1;
  GtkWidget *label4;
  GtkWidget *label5;
  GtkWidget *label6;
  GtkWidget *eol_combo;
  GList *eol_combo_items = NULL;
  GtkWidget *combo_entry6;
  GtkWidget *begin_ml_combo;
  GList *begin_ml_combo_items = NULL;
  GtkWidget *combo_entry7;
  GtkWidget *end_ml_combo;
  GList *end_ml_combo_items = NULL;
  GtkWidget *combo_entry8;
  GtkWidget *preload_button;
#endif

  g_return_if_fail (gsp != NULL);

  preview_frame = GTK_WIDGET (gsp);
  gsp->preview_frame = GTK_FRAME (preview_frame);
  gtk_frame_set_label (gsp->preview_frame, _("No stream selected."));

  gtk_container_set_border_width (GTK_CONTAINER (preview_frame), 3);

  vbox1 = gtk_vbox_new (FALSE, 0);
  gtk_widget_show (vbox1);
  gtk_container_add (GTK_CONTAINER (preview_frame), vbox1);
  gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);

  scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
  gtk_widget_show (scrolledwindow1);
  gtk_box_pack_start (GTK_BOX (vbox1), scrolledwindow1, TRUE, TRUE, 0);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1),
				  GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);

  gsp->vadj =
    gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW
					 (scrolledwindow1));

  text = gtk_text_new (NULL, gsp->vadj);
  gtk_text_set_line_wrap (GTK_TEXT (text), FALSE);
  gtk_widget_show (text);
  gtk_container_add (GTK_CONTAINER (scrolledwindow1), text);
  gsp->text = GTK_TEXT (text);

  info_label = gtk_label_new (_("No stream selected."));
  gtk_widget_show (info_label);
  gtk_box_pack_start (GTK_BOX (vbox1), info_label, FALSE, FALSE, 1);
  gsp->info_label = GTK_LABEL (info_label);

#ifdef EXTRA_CONTROLS
  hseparator1 = gtk_hseparator_new ();
  gtk_widget_show (hseparator1);
  gtk_box_pack_start (GTK_BOX (vbox1), hseparator1, FALSE, TRUE, 2);

  table1 = gtk_table_new (2, 4, FALSE);
  gtk_widget_show (table1);
  gtk_box_pack_start (GTK_BOX (vbox1), table1, FALSE, FALSE, 2);

  label4 = gtk_label_new (_("Ignore To\nEnd of Line"));
  gtk_widget_show (label4);
  gtk_table_attach (GTK_TABLE (table1), label4, 1, 2, 0, 1,
		    (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);

  label5 = gtk_label_new (_("Begin Multiline\nComment"));
  gtk_widget_show (label5);
  gtk_table_attach (GTK_TABLE (table1), label5, 2, 3, 0, 1,
		    (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);

  label6 = gtk_label_new (_("End Multiline\nComment"));
  gtk_widget_show (label6);
  gtk_table_attach (GTK_TABLE (table1), label6, 3, 4, 0, 1,
		    (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);

  eol_combo = gtk_combo_new ();
  gtk_widget_show (eol_combo);
  gtk_table_attach (GTK_TABLE (table1), eol_combo, 1, 2, 1, 2,
		    (GtkAttachOptions) (GTK_EXPAND),
		    (GtkAttachOptions) (0), 0, 0);
  gtk_widget_set_usize (eol_combo, 75, -2);
  eol_combo_items = g_list_append (eol_combo_items, "#");
  eol_combo_items = g_list_append (eol_combo_items, "//");
  eol_combo_items = g_list_append (eol_combo_items, ";");
  eol_combo_items = g_list_append (eol_combo_items, _("<none>"));
  gtk_combo_set_popdown_strings (GTK_COMBO (eol_combo), eol_combo_items);
  g_list_free (eol_combo_items);

  gtk_combo_disable_activate (GTK_COMBO (eol_combo));
  gsp->eol_combo_entry = GTK_ENTRY (GTK_COMBO (eol_combo)->entry);

  combo_entry6 = GTK_COMBO (eol_combo)->entry;
  gtk_widget_show (combo_entry6);
  gtk_entry_set_text (GTK_ENTRY (combo_entry6), "#");

  begin_ml_combo = gtk_combo_new ();
  gtk_widget_show (begin_ml_combo);
  gtk_table_attach (GTK_TABLE (table1), begin_ml_combo, 2, 3, 1, 2,
		    (GtkAttachOptions) (GTK_EXPAND),
		    (GtkAttachOptions) (0), 0, 0);
  gtk_widget_set_usize (begin_ml_combo, 75, -2);
  begin_ml_combo_items = g_list_append (begin_ml_combo_items, _("<none>"));
  begin_ml_combo_items = g_list_append (begin_ml_combo_items, "/*");
  begin_ml_combo_items = g_list_append (begin_ml_combo_items, "<");
  begin_ml_combo_items = g_list_append (begin_ml_combo_items, "(*");
  gtk_combo_set_popdown_strings (GTK_COMBO (begin_ml_combo),
				 begin_ml_combo_items);
  g_list_free (begin_ml_combo_items);

  gtk_combo_disable_activate (GTK_COMBO (begin_ml_combo));
  gsp->begin_ml_combo_entry = GTK_ENTRY (GTK_COMBO (begin_ml_combo)->entry);

  combo_entry7 = GTK_COMBO (begin_ml_combo)->entry;
  gtk_widget_show (combo_entry7);
  gtk_entry_set_text (GTK_ENTRY (combo_entry7), _("<none>"));

  end_ml_combo = gtk_combo_new ();
  gtk_widget_show (end_ml_combo);
  gtk_table_attach (GTK_TABLE (table1), end_ml_combo, 3, 4, 1, 2,
		    (GtkAttachOptions) (GTK_EXPAND),
		    (GtkAttachOptions) (0), 0, 0);
  gtk_widget_set_usize (end_ml_combo, 75, -2);
  end_ml_combo_items = g_list_append (end_ml_combo_items, _("<none>"));
  end_ml_combo_items = g_list_append (end_ml_combo_items, "*/");
  end_ml_combo_items = g_list_append (end_ml_combo_items, ">");
  end_ml_combo_items = g_list_append (end_ml_combo_items, "*)");
  gtk_combo_set_popdown_strings (GTK_COMBO (end_ml_combo),
				 end_ml_combo_items);
  g_list_free (end_ml_combo_items);

  gtk_combo_disable_activate (GTK_COMBO (end_ml_combo));
  gsp->end_ml_combo_entry = GTK_ENTRY (GTK_COMBO (end_ml_combo)->entry);

  combo_entry8 = GTK_COMBO (end_ml_combo)->entry;
  gtk_widget_show (combo_entry8);
  gtk_entry_set_text (GTK_ENTRY (combo_entry8), _("<none>"));

  preload_button = gtk_button_new_with_label (_("Preload"));
  gtk_widget_show (preload_button);
  gtk_table_attach (GTK_TABLE (table1), preload_button, 0, 1, 0, 2,
		    (GtkAttachOptions) (GTK_EXPAND),
		    (GtkAttachOptions) (0), 0, 0);
  gsp->preload_button = GTK_BUTTON (preload_button);
#endif

#ifdef EXTRA_CONTROLS
  /* This means we are fully preloaded. */
  if (guppi_stream_number_of_lines (gsp->stream) >= 0)
    gtk_widget_set_sensitive (GTK_WIDGET (gsp->preload_button), FALSE);


  /* Get the comment codes in the GuppiStream to match up with the ones
     in our combo boxes. */
  guppi_stream_preview_sync_codes (gsp);
#endif

#ifdef EXTRA_CONTROLS
  s = gtk_signal_connect (GTK_OBJECT (gsp->stream),
			  "fully_preloaded",
			  GTK_SIGNAL_FUNC (on_stream_fully_preloaded), gsp);

  gtk_signal_connect (GTK_OBJECT (gsp->preload_button),
		      "clicked",
		      GTK_SIGNAL_FUNC (on_preload_button_clicked), gsp);

  gtk_signal_connect_object (GTK_OBJECT (gsp->eol_combo_entry),
			     "activate",
			     GTK_SIGNAL_FUNC
			     (guppi_stream_preview_reset_codes),
			     GTK_OBJECT (gsp));
  gtk_signal_connect_object (GTK_OBJECT (gsp->begin_ml_combo_entry),
			     "activate",
			     GTK_SIGNAL_FUNC
			     (guppi_stream_preview_reset_codes),
			     GTK_OBJECT (gsp));
  gtk_signal_connect_object (GTK_OBJECT (gsp->end_ml_combo_entry), "activate",
			     GTK_SIGNAL_FUNC
			     (guppi_stream_preview_reset_codes),
			     GTK_OBJECT (gsp));

  gtk_signal_connect (GTK_OBJECT (gsp->eol_combo_entry),
		      "focus_out_event",
		      GTK_SIGNAL_FUNC (on_combo_entry_focus_out),
		      GTK_OBJECT (gsp));
  gtk_signal_connect (GTK_OBJECT (gsp->begin_ml_combo_entry),
		      "focus_out_event",
		      GTK_SIGNAL_FUNC (on_combo_entry_focus_out),
		      GTK_OBJECT (gsp));
  gtk_signal_connect (GTK_OBJECT (gsp->end_ml_combo_entry),
		      "focus_out_event",
		      GTK_SIGNAL_FUNC (on_combo_entry_focus_out),
		      GTK_OBJECT (gsp));
#endif
}

GtkWidget *
guppi_stream_preview_new (GuppiStream * stream)
{
  GuppiStreamPreview *gsp;

  g_return_val_if_fail (stream != NULL, NULL);

  gsp =
    GUPPI_STREAM_PREVIEW (guppi_type_new (guppi_stream_preview_get_type ()));
  guppi_stream_preview_construct (gsp);
  guppi_stream_preview_set_stream (gsp, stream);

  return GTK_WIDGET (gsp);
}

void
guppi_stream_preview_set_stream (GuppiStreamPreview * gsp, GuppiStream * gs)
{
  g_return_if_fail (gsp != NULL);
  g_return_if_fail (gs != NULL);
  g_return_if_fail (gsp->stream == NULL);	/* can't set stream twice */

  gsp->stream = gs;
  guppi_ref (gs);

  gtk_frame_set_label (gsp->preview_frame, guppi_stream_source (gsp->stream));

  /* We touch the stream to force the initial preloading, if necessary. */
  guppi_stream_load_some_lines (gsp->stream);

  guppi_stream_preview_render_into_text (gsp);
  guppi_stream_preview_set_info (gsp);

  gtk_signal_connect (GTK_OBJECT (gsp->stream),
		      "preload", GTK_SIGNAL_FUNC (on_stream_preload), gsp);

  gtk_signal_connect (GTK_OBJECT (gsp->stream),
		      "changed_codes",
		      GTK_SIGNAL_FUNC (on_stream_changed_codes), gsp);
}

void
guppi_stream_preview_refresh (GuppiStreamPreview * gsp)
{
  gfloat x;

  x = gsp->vadj->value;
  guppi_stream_preview_render_into_text (gsp);
  gtk_adjustment_set_value (gsp->vadj, x);
}

void
guppi_stream_preview_set_line_skip_cb (GuppiStreamPreview * gsp,
				       gboolean (*cb) (GuppiStreamPreview *,
						       const gchar *, gint,
						       gpointer),
				       gpointer user_data)
{
  g_return_if_fail (gsp != NULL);
  g_return_if_fail (cb != NULL);

  gsp->line_skip = cb;
  gsp->line_skip_user_data = user_data;
  guppi_stream_preview_render_into_text (gsp);
}

void
guppi_stream_preview_set_extra_info_cb (GuppiStreamPreview * gsp,
					GdkColor *
					(*cb) (GuppiStreamPreview *,
					       const gchar *, gint, gchar *,
					       gint, gpointer),
					gpointer user_data)
{
  g_return_if_fail (gsp != NULL);
  g_return_if_fail (cb != NULL);

  gsp->extra_info = cb;
  gsp->extra_info_user_data = user_data;
  guppi_stream_preview_render_into_text (gsp);
}

void
guppi_stream_preview_set_line_color_cb (GuppiStreamPreview * gsp,
					GdkColor *
					(*cb) (GuppiStreamPreview *,
					       const gchar *, gint, gpointer),
					gpointer user_data)
{
  g_return_if_fail (gsp != NULL);
  g_return_if_fail (cb != NULL);

  gsp->line_color = cb;
  gsp->line_color_user_data = user_data;
  guppi_stream_preview_render_into_text (gsp);
}

GtkWidget *
guppi_stream_preview_glade_custom_func (gchar * name,
					gchar * dum1, gchar * dum2,
					gint dum3, gint dum4)
{
  GtkWidget *w;
  w = GTK_WIDGET (guppi_type_new (GUPPI_TYPE_STREAM_PREVIEW));
  guppi_stream_preview_construct (GUPPI_STREAM_PREVIEW (w));
  return w;
}



/* $Id: guppi-stream-preview.c,v 1.13 2001/10/10 06:48:10 trow Exp $ */


syntax highlighted by Code2HTML, v. 0.9.1