/*
**  $Id: host_list.c,v 1.1 1999/04/04 16:22:15 jochen Exp $
**  GXSNMP -- An SNMP management application
**
**  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, Cambridge, MA 02139, USA.
**
**  Host list UI specific functions
*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gnome.h>
#include "gnome-property-dialog.h"
#include "host_list.h"
#include "main.h"
#include "tables.h"
#include "host_dialog.h"
#include "gxsnmp_map.h"
#include "gxsnmp_window.h"

#include "gui.h"
#include "structs.h"
#include "protos.h"

extern gxsnmp *app_info;

/****************************************************************************
 * OBSOLETE CODE FROM THIS POINT ON
 ***************************************************************************/

static void           reload_interface_table       (hosts        *host);
static void           ok_button_cb                 (GtkWidget      *widget,
						    gpointer       data);
static void           list_signal_cb               (GtkWidget      *widget,
						    GdkEvent       *event,
						    gpointer       data);
static void           sys_info_cb                  (GtkWidget      *widget,
						    gpointer       data);
static void           sys_intf_cb                  (GtkWidget      *widget,
						    gpointer       data);
static void           ping_node_cb                 (GtkWidget      *widget,
						    gpointer       data);
static void           del_node_cb                  (GtkWidget      *widget,
						    gpointer       data);
static void           inf_close_cb                 (GtkWidget      *widget,
						    gpointer       data);
static void           refresh_button_cb            (GtkWidget      *widget,
						    gpointer       data);
static void           set_button_cb                (GtkWidget      *widget,
						    gpointer       data);
static gint           panel_delete_cb              (GtkWidget      *widget,
						    GdkEvent       *e,
						    gpointer       data);
static gint           spanel_delete_cb             (GtkWidget      *widget,
						    GdkEvent       *e,
						    gpointer       data);
extern gxsnmp    *app_info;
extern GdkPixmap *book_open;
extern GdkPixmap *book_closed;
extern GdkBitmap *book_open_mask;
extern GdkBitmap *book_closed_mask;
static detail_panel  *int_detail_panel = NULL;

static char *list_labels[] = {
  N_("System Name"),
  N_("System Description"),
  N_("System Contact"),
  N_("System Location"),
  N_("System Uptime"),
  N_("System Services")
};

static char *sql_page_labels[] = {
  N_("Host Name"),
  N_("SQL Database"),
  N_("SQL Table"),
  N_("Last Update"),
  N_("Contact"),
  N_("Location")
};

void 
list_add (void *key, void *val, void *data)
{
  hosts     *host;
  char      *item;

  host = (hosts *)val;
  if (host)
    {
      item = g_strdup (host->hl_snmp.name);
      
      host->listwidget = gtk_list_item_new_with_label (item);
      gtk_container_add (GTK_CONTAINER (app_info->hlist_pane->list), 
			 host->listwidget);
      gtk_object_set_data (GTK_OBJECT (host->listwidget),"list_data", item);
      gtk_object_set_data (GTK_OBJECT (host->listwidget), "host_data", host);
      gtk_widget_show (host->listwidget);
    }
}

void
intf_list_add (char *item)
{
  GtkWidget  *listitem;

  listitem = gtk_list_item_new_with_label (item);
  gtk_container_add (GTK_CONTAINER (app_info->inter_panel->list),
		     listitem);
  gtk_widget_show (listitem);
}

void 
populate_list ()
{

}

void
create_hlist_panel ()
{
    GtkWidget   *button;
    GtkWidget   *w_frame;
    GtkWidget   *scrolled_window;
    GtkWidget   *vbox;
    GtkWidget   *hbox;
    GtkWidget   *right_box;
    GtkWidget   *left_box;
    GtkWidget   *label;
    GtkWidget   *button_box;
    GtkWidget   *bar;

    app_info->hlist_pane = (hlist_panel *) g_malloc (sizeof (hlist_panel));
    app_info->hlist_pane->window = gnome_app_new ("GXSNMP", _("Host List")); 
    gtk_signal_connect (GTK_OBJECT (app_info->hlist_pane->window), 
			"delete_event",
			GTK_SIGNAL_FUNC (panel_delete_cb),
			NULL);
    w_frame = gtk_frame_new (NULL);
    gtk_container_border_width (GTK_CONTAINER (w_frame), 4);
    gnome_app_set_contents (GNOME_APP (app_info->hlist_pane->window), w_frame);

    vbox = gtk_vbox_new (FALSE, 4);
    gtk_container_border_width (GTK_CONTAINER (vbox), 3);
    gtk_container_add (GTK_CONTAINER (w_frame), vbox);

    label = gtk_label_new (_("Known hosts"));
    gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.0);
    gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 1);

    bar = gtk_hseparator_new ();
    gtk_box_pack_start (GTK_BOX (vbox), bar, FALSE, FALSE, 0);

    hbox = gtk_hbox_new (FALSE, 2);
    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);

    left_box = gtk_vbox_new (FALSE, 2);
    gtk_box_pack_start (GTK_BOX (hbox), left_box, FALSE, FALSE, 0);

    right_box = gtk_vbutton_box_new ();
    gtk_button_box_set_layout (GTK_BUTTON_BOX (right_box), 
			       GTK_BUTTONBOX_START);
    gtk_button_box_set_child_size (GTK_BUTTON_BOX (right_box), 50, 20);
    gtk_box_pack_start (GTK_BOX (hbox), right_box, FALSE, FALSE, 0);

    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
    gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10);
    gtk_widget_set_usize (GTK_WIDGET (scrolled_window), 250, 200);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
				    GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
    gtk_box_pack_start (GTK_BOX (left_box), scrolled_window, TRUE, TRUE, 0);

    app_info->hlist_pane->list = gtk_list_new ();
    gtk_widget_set_name (app_info->hlist_pane->list, "host_list");
    gtk_object_set_data (GTK_OBJECT (app_info->hlist_pane->window), 
			 "host_list", app_info->hlist_pane->list);
    gtk_list_set_selection_mode (GTK_LIST (app_info->hlist_pane->list),
				 GTK_SELECTION_MULTIPLE);
    gtk_list_set_selection_mode (GTK_LIST (app_info->hlist_pane->list),
				 GTK_SELECTION_BROWSE);
    gtk_container_add (GTK_CONTAINER (scrolled_window), 
		       app_info->hlist_pane->list);
    gtk_signal_connect (GTK_OBJECT (app_info->hlist_pane->list), 
			"button_press_event",
			GTK_SIGNAL_FUNC (list_signal_cb),
			NULL);

    button = gtk_button_new_with_label (_("System Info"));
    gtk_box_pack_start (GTK_BOX (right_box), button, FALSE, FALSE, 0);
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
			GTK_SIGNAL_FUNC (sys_info_cb),
			NULL);

    button = gtk_button_new_with_label (_("Interface list"));
    gtk_box_pack_start (GTK_BOX (right_box), button, FALSE, FALSE, 0);
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
			GTK_SIGNAL_FUNC (sys_intf_cb),
			NULL);

    /*
      This button _should_ pull up a panel that has the information
      that is stored in the sql database... Thoughts?
    */
    button = gtk_button_new_with_label (_("SQL Info"));
    gtk_box_pack_start (GTK_BOX (right_box), button, FALSE, FALSE, 0);
    gtk_widget_set_sensitive (button, FALSE);

    button = gtk_button_new_with_label (_("Ping"));
    gtk_box_pack_start (GTK_BOX (right_box), button, FALSE, FALSE, 0);
    if (getuid())
      gtk_widget_set_sensitive (button, FALSE);
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
			GTK_SIGNAL_FUNC (ping_node_cb),
			NULL);

    button = gtk_button_new_with_label (_("Traceroute"));
    gtk_box_pack_start (GTK_BOX (right_box), button, FALSE, FALSE, 0);
    if (getuid())
      gtk_widget_set_sensitive (button, FALSE);

    bar = gtk_hseparator_new ();
    gtk_box_pack_start (GTK_BOX (right_box), bar, FALSE, FALSE, 0);
    gtk_widget_show (bar);

    button = gtk_button_new_with_label (_("Delete"));
    gtk_box_pack_end (GTK_BOX (right_box), button, FALSE, FALSE, 0);
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
			GTK_SIGNAL_FUNC (del_node_cb),
			NULL);

    bar = gtk_hseparator_new ();
    gtk_box_pack_start (GTK_BOX (vbox), bar, FALSE, FALSE, 0);

    w_frame = gtk_frame_new (NULL);
    gtk_container_border_width (GTK_CONTAINER (w_frame), 2);
    gtk_box_pack_start (GTK_BOX (vbox), w_frame, FALSE, FALSE, 0);

    button_box = gtk_hbutton_box_new ();
    gtk_container_border_width (GTK_CONTAINER (button_box), 2);
    gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box),
			       GTK_BUTTONBOX_SPREAD);
    gtk_button_box_set_spacing (GTK_BUTTON_BOX (button_box), 2);
    gtk_button_box_set_child_size (GTK_BUTTON_BOX (button_box), 85, 20);
    gtk_container_add (GTK_CONTAINER (w_frame), button_box);

    button = gnome_stock_button (GNOME_STOCK_BUTTON_CLOSE);
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
			GTK_SIGNAL_FUNC (ok_button_cb),
			NULL);
    gtk_container_add (GTK_CONTAINER (button_box), button);
    button = gtk_button_new_with_label (_("Clear"));
    gtk_container_add (GTK_CONTAINER (button_box), button);
    gtk_widget_show_all (app_info->hlist_pane->window);
}

void 
hlist_panel_open ()
{
  if (app_info->hlist_pane == NULL)
    {
      create_hlist_panel();          /* Make the panel */
      populate_list ();              /* fill it out */
      return ;
    }
  else 
    if (!GTK_WIDGET_VISIBLE (app_info->hlist_pane->window))
      {
	gtk_widget_show (app_info->hlist_pane->window);
	/* Need to refresh the list here */
      }
}

void 
create_sysinfo_panel ()
{
  GtkWidget     *frame;
  GtkWidget     *dframe;
  GtkWidget     *vbox;
  GtkWidget     *hbox;
  GtkWidget     *label;
  GtkWidget     *table;
  GtkWidget     *button;
  GtkWidget     *button_box;
  GtkWidget     *notebook;
  GtkWidget     *pixwid;
  GtkWidget     *scrolled;
  GtkWidget     *dial;
  GtkWidget     *dial_label;
  GtkAdjustment *adj;
  int           i;

  app_info->sinf_panel = (sinfo_panel *)g_malloc(sizeof(sinfo_panel));
  app_info->sinf_panel->window = new_window ("Node System Information",
					     GTK_WINDOW_TOPLEVEL,
					     GTK_WIN_POS_MOUSE, 1);
  gtk_signal_connect (GTK_OBJECT (app_info->sinf_panel->window),
		      "delete_event",
		      GTK_SIGNAL_FUNC (spanel_delete_cb),
		      NULL);
  frame = gtk_frame_new (NULL);
  gtk_container_border_width (GTK_CONTAINER (frame), 2);
  gtk_container_add (GTK_CONTAINER (app_info->sinf_panel->window), frame);
  gtk_widget_show (frame);
  vbox = gtk_vbox_new (FALSE, 4);
  gtk_container_border_width (GTK_CONTAINER (vbox), 2);
  gtk_container_add (GTK_CONTAINER (frame), vbox);
  gtk_widget_show (vbox);
  label = gtk_label_new (_("Node Information"));
  gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.0);
  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);
  /*
   * Notebook
   */
  notebook = gtk_notebook_new();
  gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
  gtk_signal_connect (GTK_OBJECT (notebook), "switch_page",
		      GTK_SIGNAL_FUNC (page_switch_cb), NULL);
  gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);

  frame = gtk_frame_new (NULL);
  gtk_container_border_width (GTK_CONTAINER (frame), 2);
  gtk_widget_show (frame);

  table = gtk_table_new (ELEMENTS (list_labels), 2, TRUE);
  gtk_container_border_width (GTK_CONTAINER (table), 2);
  gtk_container_add (GTK_CONTAINER (frame), table);
  for (i = 0; i < ELEMENTS(list_labels); i++)
    {
      label = gtk_label_new (gettext(list_labels[i]));
      gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
      gtk_table_attach (GTK_TABLE (table), label, 0, 1, i, (i+1),
		    GTK_FILL | GTK_SHRINK, GTK_SHRINK, 2, 1);
      gtk_widget_show (label);
    }

  app_info->sinf_panel->sys_name = gtk_entry_new ();
  gtk_table_attach (GTK_TABLE (table), app_info->sinf_panel->sys_name,
		    1, 3, 0, 1,
		    GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 1);
  gtk_widget_show (app_info->sinf_panel->sys_name);

  app_info->sinf_panel->sys_desc = gtk_entry_new ();
  gtk_entry_set_editable (GTK_ENTRY (app_info->sinf_panel->sys_desc), FALSE);
  gtk_table_attach (GTK_TABLE (table), app_info->sinf_panel->sys_desc,
		    1, 3, 1, 2,
		    GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 1);
  gtk_widget_show (app_info->sinf_panel->sys_desc);

  app_info->sinf_panel->sys_contact = gtk_entry_new ();
  gtk_table_attach (GTK_TABLE (table), app_info->sinf_panel->sys_contact,
		    1, 3, 2, 3,
		    GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 1);
  gtk_widget_show (app_info->sinf_panel->sys_contact);

  app_info->sinf_panel->sys_location = gtk_entry_new ();
  gtk_table_attach (GTK_TABLE (table), app_info->sinf_panel->sys_location,
		    1, 3, 3, 4,
		    GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 1);
  gtk_widget_show (app_info->sinf_panel->sys_location);

  app_info->sinf_panel->sys_uptime = gtk_entry_new ();
  gtk_entry_set_editable (GTK_ENTRY (app_info->sinf_panel->sys_uptime), FALSE);
  gtk_table_attach (GTK_TABLE (table), app_info->sinf_panel->sys_uptime,
		    1, 3, 4, 5,
		    GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 1);
  gtk_widget_show (app_info->sinf_panel->sys_uptime);

  app_info->sinf_panel->sys_services = gtk_entry_new ();
  gtk_entry_set_editable (GTK_ENTRY (app_info->sinf_panel->sys_services), 
			  FALSE);
  gtk_table_attach (GTK_TABLE (table), app_info->sinf_panel->sys_services,
		    1, 2, 5, 6,
		    GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 1);
  gtk_widget_show (app_info->sinf_panel->sys_services);

  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, 
			    notebook_tab (_("SNMP Information")));
  /*
   * Load info
   */
  frame = gtk_frame_new (NULL);
  table = gtk_table_new (4, 5, FALSE);
  gtk_container_border_width (GTK_CONTAINER (table), 4);
  gtk_container_add (GTK_CONTAINER (frame), table);

  /* dials */
  for (i = 0; i < 3; i++)
    {

      adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 0.01, 
						0.1, 0));
      dial = gtk_dial_new (adj);
      gtk_dial_set_update_policy (GTK_DIAL (dial), 
				  GTK_UPDATE_CONTINUOUS);
      gtk_table_attach (GTK_TABLE (table), 
			dial,
			1, 2, (i + 1), (i + 2),
			GTK_FILL, GTK_FILL, 1, 2);
      dframe = gtk_frame_new (NULL);
      gtk_table_attach (GTK_TABLE (table),
			dframe,
			2, 3, (i + 1), (i + 2),
			GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 2);
      dframe = gtk_frame_new (NULL);
      gtk_table_attach (GTK_TABLE (table),
			dframe,
			3, 4, (i + 1), (i + 2),
			GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 2);
      switch (i)
	{
	case 0:
	  dial_label = gtk_label_new ("Inbound");
	  gtk_table_attach (GTK_TABLE (table), 
			    dial_label,
			    0, 1, (i + 1), (i + 2),
			    GTK_FILL, GTK_FILL, 2, 2);
	  gtk_object_set_data (GTK_OBJECT (app_info->sinf_panel->window),
			       "inbound_guage", dial);
	  break;
	case 1:
	  dial_label = gtk_label_new ("Outbound");
	  gtk_table_attach (GTK_TABLE (table),
			    dial_label,
			    0, 1, i + 1, (i + 2),
			    GTK_FILL, GTK_FILL, 2, 2);
	  gtk_object_set_data (GTK_OBJECT (app_info->sinf_panel->window),
			       "outbound_guage", dial);
	  break;
	case 2:
	  dial_label = gtk_label_new ("Combined");
	  gtk_table_attach (GTK_TABLE (table),
			    dial_label,
			    0, 1, i + 1, (i + 2),
			    GTK_FILL, GTK_FILL, 2, 2);
	  gtk_object_set_data (GTK_OBJECT (app_info->sinf_panel->window),
			       "combined_guage", dial);
	  break;
	}

    }
		    
  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame,
			    notebook_tab (_("Server Load")));

  /*
   * Sql info
   */
  frame = gtk_frame_new (NULL);
  table = gtk_table_new (ELEMENTS (sql_page_labels), 2, FALSE);
  gtk_container_add (GTK_CONTAINER (frame), table);
  for (i = 0; i < ELEMENTS(sql_page_labels); i++)
    {
      label = gtk_label_new (gettext(sql_page_labels[i]));
      gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
      gtk_table_attach (GTK_TABLE (table),label,  0, 1, i, (i + 1),
			GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 1);
      gtk_widget_show (label);
      app_info->sinf_panel->sql_widgets[i] = gtk_entry_new ();
      gtk_table_attach (GTK_TABLE (table), 
			app_info->sinf_panel->sql_widgets[i],
			1, 2, i, (i + 1), 
			GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_SHRINK, 2, 1);
      gtk_widget_show (app_info->sinf_panel->sql_widgets[i]);
    }

  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, 
			    notebook_tab (_("Database Information")));
  /*
   * Services for this host
   */
  frame = gtk_frame_new (NULL);
  gtk_widget_show (frame);
  hbox = gtk_vbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (frame), hbox);
  scrolled = gtk_scrolled_window_new (NULL, NULL);
  gtk_container_border_width (GTK_CONTAINER (scrolled), 10);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
				  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
  gtk_box_pack_start (GTK_BOX (hbox), scrolled, TRUE, TRUE, 0);
  gtk_widget_show_all (hbox);

  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, 
			    notebook_tab (_("Node Services")));


  /* 
   * Bottom of the window 
   */
  label = gtk_hseparator_new ();
  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

  button_box = gtk_hbutton_box_new ();
  gtk_container_border_width (GTK_CONTAINER (button_box), 4);
  gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box),
			     GTK_BUTTONBOX_SPREAD);
  gtk_button_box_set_spacing (GTK_BUTTON_BOX (button_box), 2);
  gtk_button_box_set_child_size (GTK_BUTTON_BOX (button_box), 85, 20);
  gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 1);

  button = gnome_stock_button (GNOME_STOCK_BUTTON_CLOSE);
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (inf_close_cb),
		      NULL);
  gtk_container_add (GTK_CONTAINER (button_box), button);

  pixwid = gnome_stock_pixmap_widget (button_box, GNOME_STOCK_PIXMAP_REFRESH);

  button = gnome_pixmap_button (pixwid, _("Reload"));
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (refresh_button_cb),
		      NULL);
  gtk_container_add (GTK_CONTAINER (button_box), button);
 
  button = gtk_button_new_with_label (_("Set"));
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
		      GTK_SIGNAL_FUNC (set_button_cb),
		      NULL);
  gtk_container_add (GTK_CONTAINER (button_box), button);
 
  gtk_widget_show_all (app_info->sinf_panel->window);
  app_info->sinf_panel->irequest = NULL;
}
/*
 * Relocate this to the snmp_lib.c file maybe?
 * And make it return something useful? 
 */
void
add_null_var (GSList **objs, GSList **entry, char *what, GtkWidget *name)
{
  struct _SNMP_OBJECT *obj;
  oidentry            *var;

  obj = g_malloc(sizeof(struct _SNMP_OBJECT));

  obj->type       = SNMP_NULL;
  obj->syntax_len = 0;
  obj->id_len     = SNMP_SIZE_OBJECTID;
  obj->id         = g_malloc(SNMP_SIZE_OBJECTID);

  if (!read_objid (what, obj->id, &obj->id_len))
    {
/*      map_update_stat ("Invaild snmp variable \"%s\"!", what); */
      g_free(obj);
      return;
    }
  var = g_malloc(sizeof(oidentry));
  var->id_len  = obj->id_len;
  g_memmove(var->id, obj->id, obj->id_len * sizeof(gulong));
  var->name = name;
  var->oid_name = g_strdup (what);
  *objs  = g_slist_append(*objs, obj);
  *entry = g_slist_append(*entry, var);
}

void
update_host_load ()
{
  hosts     *entry;
  GtkWidget *tmp;

  if (app_info->sinf_panel)
    {
      if (GTK_WIDGET_VISIBLE (app_info->sinf_panel->window))
	{
	  entry = gtk_object_get_data (GTK_OBJECT 
				       (app_info->sinf_panel->window),
				       "selected_host");
	  if (entry)
	    {
	      tmp = get_widget (app_info->sinf_panel->window, "inbound_guage");
	      if (tmp)
		{
		  gtk_dial_set_percentage (GTK_DIAL (tmp), entry->hl_in_load);
		}
	      tmp = get_widget (app_info->sinf_panel->window, 
				"outbound_guage");
	      if (tmp)
		{
		  gtk_dial_set_percentage (GTK_DIAL (tmp), entry->hl_out_load);
		}
	      tmp = get_widget (app_info->sinf_panel->window,
				"combined_guage");
	      if (tmp)
		{
		  g_print ("Setting combined guage....\n");
		  gtk_dial_set_percentage (GTK_DIAL (tmp), 
					   (entry->hl_in_load + 
					    entry->hl_out_load));
		}
	      else 
		g_print ("No combined_guage?\n");
	    }
	}
    }
}

void
refresh_info (hosts *entry)
{
  hosts    *host;
  GSList   *objs;
  GSList   *magic;

  g_return_if_fail (entry != NULL);

  host = (hosts *)entry;
  host->hl_state = host->hl_state ^ INFO_PANEL_OPEN;
  /* Cancel any running request */

  if(app_info->sinf_panel->irequest)
    g_remove_request(app_info->sinf_panel->irequest);

  /* Clearing panel */

  gtk_entry_set_text(GTK_ENTRY (app_info->sinf_panel->sys_name), "");
  gtk_entry_set_text(GTK_ENTRY (app_info->sinf_panel->sys_desc), "");
  gtk_entry_set_text(GTK_ENTRY (app_info->sinf_panel->sys_location), "");
  gtk_entry_set_text(GTK_ENTRY (app_info->sinf_panel->sys_contact), "");
  gtk_entry_set_text(GTK_ENTRY (app_info->sinf_panel->sys_uptime), "");
  gtk_entry_set_text(GTK_ENTRY (app_info->sinf_panel->sys_services), "");


  if(host)
    {
      objs  = NULL;
      magic = NULL;
      magic = g_slist_append(magic, host);
/*      map_update_stat (_("Refreshing system info from node \"%s\""), 
			 host->hl_disp); */
      add_null_var (&objs, &magic, "system.sysName.0", 
                    app_info->sinf_panel->sys_name);
      add_null_var (&objs, &magic, "system.sysDescr.0", 
                    app_info->sinf_panel->sys_desc);
      add_null_var (&objs, &magic, "system.sysLocation.0", 
                    app_info->sinf_panel->sys_location);
      add_null_var (&objs, &magic, "system.sysContact.0", 
                    app_info->sinf_panel->sys_contact);
      add_null_var (&objs, &magic, "system.sysUpTime.0", 
                    app_info->sinf_panel->sys_uptime);
      add_null_var (&objs, &magic, "system.sysServices.0", 
                    app_info->sinf_panel->sys_services);
      host->hl_snmp.magic = magic;
      host->hl_snmp.done_callback = update_widget;
      host->hl_snmp.time_callback = destroy_widget;
      app_info->sinf_panel->irequest = g_async_get(&host->hl_snmp, objs);
      if (!app_info->sinf_panel->irequest)
	{
	  g_print ("Snmp error!!\n");
	}
    } else {
      g_print ("Null pointer??\n");
    }
}

void
sysinfo_set_selected_host (hosts *entry)
{
  hosts     *old_entry;
  
  old_entry = gtk_object_get_data (GTK_OBJECT (app_info->sinf_panel->window),
				   "selected_host");
  if (old_entry)
    old_entry->hl_state = entry->hl_state ^ INFO_PANEL_OPEN;
  gtk_object_set_data (GTK_OBJECT (app_info->sinf_panel->window), 
		       "selected_host", entry);
  
}

hosts *
sysinfo_get_selected_host ()
{
  if (app_info->sinf_panel->window)
    {
      return (hosts *)gtk_object_get_data (GTK_OBJECT
                                          (app_info->sinf_panel->window),
                                          "selected_host");
    }
  else 
    return (hosts *)NULL;
}

void
set_info (hosts *entry)
{
  hosts    *host;
  char     *value;
  GSList   *objs;

  host = (hosts *)entry;
  if(host)
    {
/*      map_update_stat ("Writing system info to node \"%s\"", host->hl_disp); */
      host->hl_snmp.magic = host;
      host->hl_snmp.done_callback = NULL;
      host->hl_snmp.time_callback = NULL;

      objs = NULL;
      value = gtk_entry_get_text (GTK_ENTRY (app_info->sinf_panel->sys_name));
      g_pdu_add_name(&objs, "system.sysName.0", SNMP_OCTETSTR, value);
      g_async_set(&host->hl_snmp, objs);

      objs = NULL;
      value = gtk_entry_get_text (GTK_ENTRY (app_info->sinf_panel->sys_contact));
      g_pdu_add_name(&objs, "system.sysContact.0", SNMP_OCTETSTR, value);
      g_async_set(&host->hl_snmp, objs);

      objs = NULL;
      value = gtk_entry_get_text (GTK_ENTRY (app_info->sinf_panel->sys_location));
      g_pdu_add_name(&objs, "system.sysLocation.0", SNMP_OCTETSTR, value);
      g_async_set(&host->hl_snmp, objs);

    } else {
      g_print ("Null pointer??\n");
    }
}

gboolean
update_widget (host_snmp *host, void *magic, SNMP_PDU *spdu, GSList *objs)
{
  char                 buf[1024];              /* Should be big enough? */
  GSList              *entry;
  GSList              *myentry;
  GSList              *myobj;
  oidentry            *var;
  struct _SNMP_OBJECT *obj;
  hosts               *ahost;
#ifdef HAVE_SQL
  char                *value;
  int                 changed;
#endif                         

#ifdef MEM_DEBUG
  DMC ();
#endif

  app_info->sinf_panel->irequest = NULL;

  entry = (GSList *)magic;

  if (spdu->request.error_status)
    {
      g_slist_free(entry);
      return TRUE;
    }

  ahost = (hosts *) entry->data;

  myobj = objs;
  while(myobj)
    {
      obj = (struct _SNMP_OBJECT *) myobj->data;
      g_snmp_printf(buf, sizeof(buf), obj);
      
      myentry = entry->next; /* First entry in magic list is host struct */
      while (myentry)
        {
          var = (oidentry *) myentry->data;
          if (!memcmp(obj->id, var->id, var->id_len * sizeof(gulong)))
            gtk_entry_set_text (GTK_ENTRY (var->name), buf);
          myentry = myentry->next;
        }
      myobj = myobj->next;
    }
  g_slist_free(entry);
/*  map_update_stat (_("Refresh of system info complete.")); */

#ifdef HAVE_SQL

/* Update location and contact if changed */

  changed = 0;
  if (app_info->sinf_panel)
    {
      value = gtk_entry_get_text (GTK_ENTRY (app_info->sinf_panel->sys_location));
      if (ahost->hl_sysloc && strcmp(value, ahost->hl_sysloc))
        {
          g_free(ahost->hl_sysloc);
          ahost->hl_sysloc = g_strdup(value);
          changed = 1;
        }
      value = gtk_entry_get_text (GTK_ENTRY (app_info->sinf_panel->sys_contact));
      if (ahost->hl_syscon && strcmp(value, ahost->hl_syscon))
        {
          g_free(ahost->hl_syscon);
          ahost->hl_syscon = g_strdup(value);
          changed = 1;
        }
    }
  if (changed)
    {
      /* should send SNMP trap / notify here? - Gnome MIB still needs work */
/*      host_db_update_entry (ahost);  */
    }
#endif        

  return TRUE;
}

void
destroy_widget (host_snmp *host, void *magic)
{
  GSList              *entry;

  app_info->sinf_panel->irequest = NULL;

  entry = (GSList *)magic;
  g_slist_free(entry);
}

void
open_sysinfo_panel ()
{
  if (app_info->sinf_panel == NULL)
      create_sysinfo_panel ();
  else if (!GTK_WIDGET_VISIBLE (app_info->sinf_panel->window))
      gtk_widget_show (app_info->sinf_panel->window);
}

void
fill_table (hosts *host)
{
#if 0
  int   i;
  for (i = 0; i < INTF_NUM_LABELS; i++)
    {
      switch (i)
	{
	case INTF_NA_IDX:
	  gtk_label_set_text (GTK_LABEL (app_info->inter_panel->widget[INTF_NA_IDX]),
			 host->hl_snmp.name);
	  break;
	case INTF_IP_IDX:                /* Fix to do the proper thing */
	  gtk_label_set (GTK_LABEL (app_info->inter_panel->widget[INTF_IP_IDX]),
			 host->hl_snmp.name);
	  break;
	case INTF_CN_IDX:
	  gtk_label_set (GTK_LABEL (app_info->inter_panel->widget[INTF_CN_IDX]),
			 "0");
	  break;
	}
    }
#endif
}

/*
 * The callback functions
 */
static void 
ok_button_cb (GtkWidget *widget, gpointer  data)
{
  gtk_widget_hide (app_info->hlist_pane->window);
}

static void
inf_close_cb (GtkWidget *widget, gpointer  data)
{
  gtk_widget_hide (app_info->sinf_panel->window);
}

static void
refresh_button_cb (GtkWidget *widget, gpointer  data)
{
  hosts *host;
  if (app_info->sinf_panel->window)
    {
      host = gtk_object_get_data (GTK_OBJECT (app_info->sinf_panel->window), 
				  "selected_host");
      if (host)
	refresh_info (host);
    }
}
static void
set_button_cb (GtkWidget *widget, gpointer  data)
{
  hosts *host;

  host = sysinfo_get_selected_host ();
  if (host)
    set_info (host);

}

static void
list_signal_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
{
  GList     *dlist;
  GtkObject *list_item;
  hosts     *host;

  dlist = GTK_LIST(widget)->selection;
  switch (event->type)
    {
    case GDK_BUTTON_PRESS:
      switch (event->button.button)
	{
	case 1:
	  break;
	case 2:
	  break;
	case 3:
g_print ("host_menu_right_popup ((int)&event->button, event->button.time);\n");
	  break;
	default:
	  break;
	}
      break;
    case GDK_2BUTTON_PRESS:
      list_item = GTK_OBJECT (dlist->data);
      host = gtk_object_get_data (GTK_OBJECT (list_item), "host_data");
      open_sysinfo_panel ();
      refresh_info (host);
      break;
    default:
      break;
    }
}

static void
sys_info_cb (GtkWidget *widget,
	     gpointer  data)
{
  GList       *dlist;
  GtkObject   *list_item;
  hosts       *host;

  dlist = GTK_LIST (app_info->hlist_pane->list)->selection;
  list_item = GTK_OBJECT (dlist->data);
/*  host = find_host_by_name (gtk_object_get_data 
			    (GTK_OBJECT (list_item), 
			     "list_data")); */
  open_sysinfo_panel ();
  refresh_info (host);
  sysinfo_set_selected_host (host);
}

static void
sys_intf_cb (GtkWidget *widget, gpointer data)
{
  GList     *dlist;
  GtkObject *list_item;
  hosts     *host;

  dlist = GTK_LIST (app_info->hlist_pane->list)->selection;
  list_item = GTK_OBJECT (dlist->data);
/*  host = find_host_by_name (gtk_object_get_data 
			    (GTK_OBJECT (list_item), 
			     "list_data"));
*/
  open_interface_panel ();
  reload_interface_table (host);
  interface_set_selected_host (host);
}

static void
ping_node_cb (GtkWidget *widget, gpointer data)
{
  GList          *dlist;
  GtkObject      *list_item;
  hosts          *host;
  struct hostent *hp;

  dlist = GTK_LIST (app_info->hlist_pane->list)->selection;
  list_item = GTK_OBJECT (dlist->data);
/*  host = find_host_by_name (gtk_object_get_data (GTK_OBJECT (list_item),
					 "list_data"));
*/
/*  hp = lookuphost (host->hl_snmp.name); */
  if (hp)
    sendping (*(gulong *)hp->h_addr);

}
static void 
del_node_cb (GtkWidget *widget, gpointer data)
{
  GList     *dlist;
  GtkObject *list_item;
  hosts     *host;

  dlist = GTK_LIST (app_info->hlist_pane->list)->selection;
  list_item = GTK_OBJECT (dlist->data);
/*  host = find_host_by_name (gtk_object_get_data 
			    (GTK_OBJECT (list_item), "list_data"));
*/
  if (host)
    {
/*      hl_del_host (host);   */
    }
}

static gint
panel_delete_cb (GtkWidget *widget, GdkEvent  *e, gpointer  data)
{
  gtk_widget_destroy (app_info->hlist_pane->window);
  g_free (app_info->hlist_pane);
  app_info->hlist_pane = NULL;
  return TRUE;
}

static gint
spanel_delete_cb (GtkWidget *widget, GdkEvent  *e, gpointer  data)
{
  gtk_widget_destroy (app_info->sinf_panel->window);
  g_free (app_info->sinf_panel);
  app_info->sinf_panel = NULL;
  return TRUE;
}


/*
 * The route panel code
 */
/* 
 * Local functions to the route panel
 */
static void     create_route_panel              (void);
static gint     route_panel_delete_cb           (GtkWidget    *widget,
						 GdkEvent     *e,
						 gpointer     data);

static void     route_close_button_cb           (GtkWidget    *widget,
						 gpointer     data);
static void     route_reload_button_cb          (GtkWidget    *widget,
						 gpointer     data);
static void     route_abort_button_cb           (GtkWidget    *widget,
						 gpointer     data);
static void     route_print_menu_cb             (GtkWidget    *widget,
						 gpointer     data);
static void     route_exit_menu_cb              (GtkWidget    *widget,
						 gpointer     data);

/*
 * Local variables
 */
static char *iproute_labels[] = {
  N_("Protocol"),
  N_("Destination"),
  N_("Netmask"),
  N_("Gateway"),
  N_("Interface"),
  N_("Metric"),
  N_("Route Age"),
  N_("Type")
};

static route_panel   *rt_panel = NULL;

/* 
 * Menus!
 */
static GnomeUIInfo file_menu[] = {
  { GNOME_APP_UI_ITEM, N_("Save"), NULL,
    NULL, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_SAVE, 0, 0, NULL },
  { GNOME_APP_UI_ITEM, N_("Save As..."), NULL,
    NULL, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_SAVE, 0, 0, NULL },
  { GNOME_APP_UI_ITEM, N_("Print"), NULL, 
    route_print_menu_cb, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_PRINT, 0, 0, NULL },
  { GNOME_APP_UI_SEPARATOR },  
  { GNOME_APP_UI_ITEM, N_("Close"), NULL, route_close_button_cb, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_CLOSE, 0, 0, NULL },
  { GNOME_APP_UI_ITEM, N_("Exit"), NULL, route_exit_menu_cb, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_EXIT, 'X', GDK_CONTROL_MASK,
    NULL },
  { GNOME_APP_UI_ENDOFINFO }
};

static GnomeUIInfo edit_menu[] = {
  { GNOME_APP_UI_ITEM, N_("Find"), NULL, 
    NULL, NULL, NULL, 
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_SEARCH, 0, 0, NULL },
  { GNOME_APP_UI_ENDOFINFO }
};

static GnomeUIInfo route_panel_menu[] = {
  { GNOME_APP_UI_SUBTREE, N_("File"), NULL, file_menu, NULL, NULL,
    GNOME_APP_PIXMAP_NONE, NULL, 0, 0, NULL },
  { GNOME_APP_UI_SUBTREE, N_("Edit"), NULL, edit_menu, NULL, NULL, 
    GNOME_APP_PIXMAP_NONE, NULL, 0, 0, NULL },
  { GNOME_APP_UI_ENDOFINFO }
};

/* 
 * Local functions
 */

static void
create_route_panel ()
{
  GtkWidget    *w_box;
  GtkWidget    *rt_frame;
  GtkWidget    *bb_frame;
  GtkWidget    *b_box;
  GtkWidget    *h_bar;
  GtkWidget    *pixmap;
  GtkWidget    *scrolled_window;
  int           i;
  int           col_sizes[ELEMENTS (iproute_labels)];

  rt_panel = (route_panel *)g_malloc (sizeof (route_panel));

  rt_panel->window = gnome_app_new ("GXSNMP", _("Route Table"));
  gtk_window_set_wmclass (GTK_WINDOW (rt_panel->window), "route_panel",
			  "GXSNMP");
  gtk_signal_connect (GTK_OBJECT (rt_panel->window), "delete_event",
		      GTK_SIGNAL_FUNC (route_panel_delete_cb),
		      NULL);

  /*
   * There _HAS_ to be a better way to do this so that the entire
   * clist is _visible_.
   */
  gtk_widget_set_usize (rt_panel->window, 600, 400);

  w_box = gtk_vbox_new (FALSE, 4);
  rt_frame = gtk_frame_new (NULL);
  rt_panel->flt_entry = gtk_entry_new ();
  gtk_box_pack_start (GTK_BOX (w_box), rt_panel->flt_entry, FALSE, TRUE, 2);
  gtk_box_pack_start (GTK_BOX (w_box), rt_frame, TRUE, TRUE, 2);
  /* --- ROUTE LIST --- */
  for (i=0; i< ELEMENTS (iproute_labels); i++)
    {
      iproute_labels[i] = strdup(gettext(iproute_labels[i]));
      col_sizes[i] = gdk_string_width (w_box->style->font,
				       iproute_labels[i]) + 10;
    }
  rt_panel->rtt_clist = gtk_clist_new_with_titles (ELEMENTS (iproute_labels),
					       iproute_labels);
  for (i = 0; i < ELEMENTS (iproute_labels); i++)
    {
      gtk_clist_set_column_width (GTK_CLIST (rt_panel->rtt_clist), i, 
				  (col_sizes[i] + (col_sizes[i] / 2)));
    }
  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
				  GTK_POLICY_AUTOMATIC,
				  GTK_POLICY_ALWAYS);
  gtk_container_add (GTK_CONTAINER (rt_frame), scrolled_window);
  gtk_container_add (GTK_CONTAINER (scrolled_window), rt_panel->rtt_clist);
  h_bar = gtk_hseparator_new ();
  gtk_box_pack_start (GTK_BOX (w_box), h_bar, FALSE, TRUE, 0);
  bb_frame = gtk_frame_new (NULL);
  gtk_box_pack_start (GTK_BOX (w_box), bb_frame, FALSE, FALSE, 2);
  b_box = gtk_hbutton_box_new ();
  gtk_container_border_width (GTK_CONTAINER (b_box), 4);
  gtk_button_box_set_layout (GTK_BUTTON_BOX (b_box), GTK_BUTTONBOX_END);
  gtk_button_box_set_spacing (GTK_BUTTON_BOX (b_box), 2);
  gtk_button_box_set_child_size (GTK_BUTTON_BOX (b_box), 85, 20);
  gtk_container_add (GTK_CONTAINER (bb_frame), b_box);
  rt_panel->buttons[ROUTE_CLOS_BUTTON] = gnome_stock_button 
    (GNOME_STOCK_BUTTON_CLOSE);
  gtk_signal_connect (GTK_OBJECT (rt_panel->buttons[ROUTE_CLOS_BUTTON]),
		      "clicked", 
		      GTK_SIGNAL_FUNC (route_close_button_cb),
		      rt_panel->window);
  gtk_container_add (GTK_CONTAINER (b_box), 
		     rt_panel->buttons[ROUTE_CLOS_BUTTON]);
  pixmap = gnome_stock_pixmap_widget (rt_panel->window, 
				      GNOME_STOCK_PIXMAP_REFRESH);
  rt_panel->buttons[ROUTE_REFR_BUTTON] = gnome_pixmap_button (pixmap, 
							      _("Reload"));
  gtk_widget_set_sensitive (rt_panel->buttons[ROUTE_REFR_BUTTON], FALSE);
  gtk_signal_connect (GTK_OBJECT (rt_panel->buttons[ROUTE_REFR_BUTTON]),
		      "clicked",
		      GTK_SIGNAL_FUNC (route_reload_button_cb),
		      rt_panel->window);
  gtk_container_add (GTK_CONTAINER (b_box), 
		     rt_panel->buttons[ROUTE_REFR_BUTTON]);
  pixmap = gnome_stock_pixmap_widget (rt_panel->window,
				      GNOME_STOCK_PIXMAP_STOP);
  rt_panel->buttons[ROUTE_ABRT_BUTTON] = gnome_pixmap_button (pixmap,
							      _("Abort"));
  gtk_signal_connect (GTK_OBJECT (rt_panel->buttons[ROUTE_ABRT_BUTTON]),
		      "clicked",
		      GTK_SIGNAL_FUNC (route_abort_button_cb),
		      rt_panel->window);
  gtk_container_add (GTK_CONTAINER (b_box),
		     rt_panel->buttons[ROUTE_ABRT_BUTTON]);

  gnome_app_set_contents (GNOME_APP (rt_panel->window), w_box);
  gnome_app_create_menus (GNOME_APP (rt_panel->window), route_panel_menu);
  gtk_widget_show_all (rt_panel->window);
  rt_panel->rrequest = NULL;
}

static gint 
route_panel_delete_cb (GtkWidget *widget, GdkEvent *e, gpointer data)
{
  if (rt_panel)
    {
      if (rt_panel->rrequest)
	g_remove_request (rt_panel->rrequest);
      rt_panel->rrequest = NULL;
      gtk_widget_destroy (rt_panel->window);
      g_free (rt_panel);
      rt_panel = NULL;
    }
  return TRUE;
}

static void
route_close_button_cb (GtkWidget *widget, gpointer data)
{
  hide_route_panel ();
}

static void
route_reload_button_cb (GtkWidget *widget, gpointer data)
{
  reset_route_panel ();
}

static void
route_abort_button_cb (GtkWidget *widget, gpointer data)
{
  if (rt_panel->rrequest)
    g_remove_request (rt_panel->rrequest);
  rt_panel->rrequest = NULL;
  
  gtk_widget_set_sensitive (GTK_WIDGET (rt_panel->buttons[ROUTE_ABRT_BUTTON]), 
			    FALSE);
  gtk_widget_set_sensitive (GTK_WIDGET (rt_panel->buttons[ROUTE_REFR_BUTTON]),
			    TRUE);
/*  map_update_stat (_("Route loading from node aborted.")); */
}

static void
route_print_menu_cb (GtkWidget *widget, gpointer data)
{
}

static void
route_exit_menu_cb (GtkWidget *widget, gpointer data)
{
}

static void
reload_route_table (hosts *host)
{
  hosts     *this_host;
  GSList    *objs;
  GSList    *magic;

  this_host = (hosts *)host;

  if (rt_panel->rrequest)
    g_remove_request (rt_panel->rrequest);
  rt_panel->rrequest = NULL;

  if (this_host)
    {
      objs  = NULL;
      magic = NULL;
      /*map_update_stat (_("Reloading route table from host '%s'..."),
			 this_host->hl_disp); */
      add_null_var (&objs, &magic, "ip.ipRouteTable.ipRouteEntry.ipRouteProto",
		    rt_panel->rtt_clist);
      add_null_var (&objs, &magic, "ip.ipRouteTable.ipRouteEntry.ipRouteDest",
		    rt_panel->rtt_clist);      
      add_null_var (&objs, &magic, "ip.ipRouteTable.ipRouteEntry.ipRouteMask",
		    rt_panel->rtt_clist);
      add_null_var (&objs, &magic, 
		    "ip.ipRouteTable.ipRouteEntry.ipRouteNextHop",
		    rt_panel->rtt_clist);
      add_null_var (&objs, &magic, 
		    "ip.ipRouteTable.ipRouteEntry.ipRouteIfIndex",
		    rt_panel->rtt_clist);
      add_null_var (&objs, &magic, 
		    "ip.ipRouteTable.ipRouteEntry.ipRouteMetric1",
		    rt_panel->rtt_clist);
      add_null_var (&objs, &magic, 
		    "ip.ipRouteTable.ipRouteEntry.ipRouteAge",
		    rt_panel->rtt_clist);
      add_null_var (&objs, &magic,
		    "ip.ipRouteTable.ipRouteEntry.ipRouteType",
		    rt_panel->rtt_clist);
      host->hl_snmp.magic = magic;
      host->hl_snmp.done_callback = update_ctable;
      host->hl_snmp.time_callback = destroy_ctable;
      rt_panel->rrequest = g_async_getnext (&host->hl_snmp, objs);
    } else {
      g_warning ("Null pointer alert!\n");
    }
}
static void 
free_hash_element (void *key, void *val, void *data)
{
  g_free (val);
  g_free (key);
}

gboolean
update_ctable (host_snmp *host, void *magic, SNMP_PDU *spdu, GSList *objs)
{
  char                buf[1024];              /* Should be big enough? */
  char                sync_buf[1024];
  GSList              *entry;
  GSList              *myentry;
  GSList              *myobj;
  GSList              *nobjs;
  GSList              *sync_objs;
  GSList              *sync_vars;  
  oidentry            *var;
  struct _SNMP_OBJECT *obj;
  struct _SNMP_OBJECT *nobj;
  char                *kludge[ELEMENTS (iproute_labels)];  /* FIXME */
  int                  i, j;
  int                  if_index;
  static GHashTable   *if_desc = NULL;
  struct tree         *snmptree;
  char                *descr;
  gint                *ptr;

#ifdef MEM_DEBUG
  DMC ();
#endif
  if (rt_panel->rrequest)
    rt_panel->rrequest = NULL;
  else
    return TRUE;
  entry = (GSList *)magic;
  if (!if_desc)
      if_desc = g_hash_table_new (g_int_hash, g_int_equal);

  if (spdu->request.error_status)
    {
      g_slist_free(entry);
      return TRUE;
    }

  nobjs = NULL;
  myobj = objs;
  i     = 0;
  j     = 0;
  while(myobj)
    {
      obj = (struct _SNMP_OBJECT *) myobj->data;
      g_snmp_printf(buf, sizeof(buf), obj);
      myentry = entry;
      i = 0;
      while (myentry)
        {
          var = (oidentry *) myentry->data;
          if (!memcmp(obj->id, var->id, var->id_len * sizeof(gulong)))
            {
	      snmptree = get_mib_tree (var->id, var->id_len);
	      if (strcasecmp (var->oid_name,
		  "ip.ipRouteTable.ipRouteEntry.ipRouteIfIndex")  == 0)
		{
		  if_index = atoi (buf);
		  if ( (descr = (char *)g_hash_table_lookup (if_desc, 
							   &if_index)))
		      kludge[i] = g_strdup (descr);
		  else
		    {
		      sync_vars = NULL;
		      sync_objs = NULL;
		      snprintf (sync_buf, sizeof(sync_buf),
				"interfaces.ifTable.ifEntry.ifDescr.%s",buf);
		      g_pdu_add_name (&sync_vars, sync_buf, SNMP_NULL, NULL);
		      sync_objs = g_sync_get (host, sync_vars);
		      if (!sync_objs)
			{
			  g_warning(" Aieeeeee sync get failed!\n");
			  g_slist_free (sync_vars);
			  sync_vars = NULL;
			}
		      else
			{
			  g_snmp_printf (buf, sizeof (buf), sync_objs->data);
			  kludge[i] = g_strdup (buf);
			  ptr = g_malloc (sizeof(int));
			  *ptr = if_index;
			  g_hash_table_insert (if_desc, ptr, g_strdup (buf));
			}
		      
		    }
		  
		}
	      else
		{
		  if (snmptree->enums)
		    {
		      struct enum_list *list;
		      list = snmptree->enums;
		      while (list)
			{
			  if (list->value == atoi (buf))
			    {
			      kludge[i] = g_strdup (list->label);
			      break;
			    }
			  list = list->next;
			}
		    }
		  else
		    kludge[i] = g_strdup(buf);
		}
              nobj = g_malloc(sizeof(struct _SNMP_OBJECT));
              nobj->type       = SNMP_NULL;
	      nobj->syntax_len = 0;
              nobj->id_len     = obj->id_len;
              nobj->id         = g_malloc(obj->id_len * sizeof(gulong));
              g_memmove(nobj->id, obj->id, obj->id_len * sizeof(gulong));
              nobjs            = g_slist_append(nobjs, nobj);
              j++;
            }
          i++;
          myentry = g_slist_next (myentry);
        }
      myobj = myobj->next;
    }
  if (i != j)
    {
      g_slist_free(nobjs);
      nobjs = NULL;
    }
  if (nobjs)
    {
      var = (oidentry *) entry->data;
      if (GTK_WIDGET (var->name))
	gtk_clist_append (GTK_CLIST (var->name), kludge);
      host->magic = magic;
      host->done_callback = update_ctable;
      host->time_callback = destroy_ctable;
      rt_panel->rrequest = g_async_getnext(host, nobjs);
    }
  else 
    {
      g_slist_free(entry);
/*      map_update_stat (_("Route reload from host '%s' complete."),
		       host->name); */
      rt_panel->rrequest = NULL;
      g_hash_table_foreach (if_desc, free_hash_element, NULL);
      g_hash_table_destroy (if_desc);
      if_desc = NULL;
      gtk_widget_set_sensitive (GTK_WIDGET 
				(rt_panel->buttons[ROUTE_REFR_BUTTON]),
				TRUE);
      gtk_widget_set_sensitive (GTK_WIDGET
				(rt_panel->buttons[ROUTE_ABRT_BUTTON]),
				FALSE);
    }
  return TRUE;
}

void
destroy_ctable (host_snmp *host, void *magic)
{
  GSList              *entry;

  rt_panel->rrequest = NULL;

  entry = (GSList *)magic;
  g_slist_free(entry);
}

void 
route_panel_set_selected_host (hosts *host)
{
  if (rt_panel->window)
    gtk_object_set_data (GTK_OBJECT (rt_panel->window), "selected_host", host);
}


hosts *
route_panel_get_selected_host ()
{
  if (rt_panel->window)
    return (hosts *)gtk_object_get_data (GTK_OBJECT (rt_panel->window), 
					 "selected_host");
  else
    return NULL;
}
/*
 * Global panel functions (route panel)
 */
void
open_route_panel ()
{
  if (rt_panel == NULL)
      create_route_panel ();
  else
    if (!GTK_WIDGET_VISIBLE (rt_panel->window))
      gtk_widget_show (rt_panel->window);
}

void 
destroy_route_panel ()
{
  if (rt_panel != NULL)
    {
      if (rt_panel->rrequest)
	g_remove_request (rt_panel->rrequest);
      rt_panel->rrequest = NULL;
    route_panel_delete_cb (NULL, NULL, rt_panel);
    }
}

void
hide_route_panel ()
{
  if (rt_panel->window)
    {
      if (GTK_WIDGET_VISIBLE (rt_panel->window))
	gtk_widget_hide (rt_panel->window);
    }
}

void
reset_route_panel ()
{
  gtk_widget_set_sensitive (GTK_WIDGET (rt_panel->buttons[ROUTE_REFR_BUTTON]), 
			    FALSE);
  gtk_widget_set_sensitive (GTK_WIDGET (rt_panel->buttons[ROUTE_ABRT_BUTTON]),
			    TRUE);
  gtk_clist_clear (GTK_CLIST (rt_panel->rtt_clist));
  reload_route_table (route_panel_get_selected_host());
}

/*
 * The interface list panel
 */

/*
 * Local functions to the interface list panel
 */
static void          create_interface_panel       (void);
static gint          interface_panel_delete_cb    (GtkWidget    *widget,
						   GdkEvent     *e,
						   gpointer     data);
static void          interface_close_button_cb    (GtkWidget    *widget,
						   gpointer     data);
static void          interface_reload_button_cb   (GtkWidget    *widget,
						   gpointer     data);
static void          interface_abort_button_cb    (GtkWidget    *widget,
						   gpointer     data);
static void          interface_select_row         (GtkWidget    *widget,
						   gint         row,
						   gint         column,
						   GdkEventButton *e);
static void          interface_detail_cb          (GtkWidget    *widget,
						   gpointer     data);
gint                 interface_sort_func          (GtkCList     *clist, 
						   gconstpointer     row1, 
						   gconstpointer     row2);
/*
 * Local variables
 */
static char *interface_labels[] = {
  N_("Interface"),                    /* Descr    */
  N_("Index"),                        /* ifIndex  */
  N_("Type"),
  N_("Speed"),
  N_("Admin Status"),
  N_("Operational Status"),
  N_("Last Change")
};

static int icol_sizes[ELEMENTS(interface_labels)];
static interface_panel *int_panel = NULL;
static hosts *interface_host = NULL;

/*
 * Menus
 */

static GnomeUIInfo i_file_menu[] = {
  { GNOME_APP_UI_ITEM, N_("Close"), NULL, interface_close_button_cb,
    NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_CLOSE, 0, 0, NULL },
  { GNOME_APP_UI_ITEM, N_("Exit"), NULL, NULL,
    NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_EXIT, 0, 0, NULL },
  { GNOME_APP_UI_ENDOFINFO },
};

static GnomeUIInfo interface_panel_menu[] = {
  { GNOME_APP_UI_SUBTREE, N_("File"), NULL, i_file_menu, NULL, NULL,
    GNOME_APP_PIXMAP_NONE, NULL, 0, 0, NULL },
  { GNOME_APP_UI_ENDOFINFO },
};

/* 
 * Local functions
 */
static void 
create_interface_panel ()
{
  GtkWidget   *w_box;
  GtkWidget   *i_frame;
  GtkWidget   *scrolled_window;
  GtkWidget   *b_box;
  GtkWidget   *button;
  GtkWidget   *table;
  GtkWidget   *bar;
  GtkWidget   *pixmap;
  int         i, w_size, w_height;

  int_panel = (interface_panel *)g_malloc (sizeof (interface_panel));

  int_panel->window = gnome_app_new ("GXSNMP", _("Interface Table"));
  gtk_window_set_wmclass (GTK_WINDOW (int_panel->window), "interface_panel",
			  "GXSNMP");
  gtk_signal_connect (GTK_OBJECT (int_panel->window), "delete_event",
		      GTK_SIGNAL_FUNC (interface_panel_delete_cb),
		      int_panel);
  w_box = gtk_vbox_new (FALSE, 4);
  i_frame = gtk_frame_new (NULL);
  gtk_box_pack_start (GTK_BOX (w_box), i_frame, TRUE, TRUE, 2);
  table = gtk_table_new (3, 3, FALSE);
  gtk_container_add (GTK_CONTAINER (i_frame), table);

  for (i = 0; i <ELEMENTS (interface_labels); i++)
    {
      interface_labels[i] = g_strdup (gettext(interface_labels[i]));
      icol_sizes[i] = gdk_string_width (w_box->style->font, 
					 interface_labels[i]) + 5;
    }
  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
  w_height = (scrolled_window->style->font->ascent + 
	      scrolled_window->style->font->descent) * 24;
  int_panel->list = gtk_clist_new_with_titles (ELEMENTS (interface_labels),
						interface_labels);
  w_size = 0;
  for (i = 0; i <ELEMENTS (interface_labels); i++)
    {
      gtk_clist_set_column_width (GTK_CLIST (int_panel->list), i, 
				  (icol_sizes[i] + (icol_sizes[i] / 2)));
      w_size += (icol_sizes[i] + (icol_sizes[i] / 2));
    }

  gtk_widget_set_usize (GTK_WIDGET (scrolled_window), w_size, w_height);
  gtk_clist_set_selection_mode (GTK_CLIST (int_panel->list),
				 GTK_SELECTION_BROWSE);
  gtk_clist_set_compare_func (GTK_CLIST (int_panel->list), 
			      interface_sort_func);
  gtk_clist_column_titles_passive (GTK_CLIST (int_panel->list));
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
			GTK_POLICY_AUTOMATIC,
			GTK_POLICY_ALWAYS);
  gtk_clist_set_sort_column (GTK_CLIST (int_panel->list), 1);
  gtk_clist_set_auto_sort (GTK_CLIST (int_panel->list), TRUE);
  gtk_signal_connect (GTK_OBJECT (int_panel->list), 
		      "select_row",
		      (GtkSignalFunc) interface_select_row,
		      NULL);
  gtk_table_attach (GTK_TABLE (table), scrolled_window, 0, 1, 0, 4,
		    GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 1);
  gtk_container_add (GTK_CONTAINER (scrolled_window), int_panel->list);
  bar = gtk_vseparator_new ();
  gtk_table_attach (GTK_TABLE (table), bar, 1, 2, 0, 4,
		    GTK_FILL, GTK_FILL | GTK_EXPAND, 2, 1);
  /* --- ACTION BUTTONS ---*/
  b_box = gtk_vbutton_box_new ();
  gtk_button_box_set_layout (GTK_BUTTON_BOX (b_box), GTK_BUTTONBOX_START);
  gtk_button_box_set_spacing (GTK_BUTTON_BOX (b_box), 4);
  gtk_container_border_width (GTK_CONTAINER (b_box), 4);
  gtk_table_attach (GTK_TABLE (table), b_box, 2, 3, 0, 1,
		    GTK_FILL | GTK_EXPAND, 0, 1, 2);
  /* -- Interface Detail -- */
  button = gtk_button_new_with_label (_("Details..."));
  gtk_object_set_data (GTK_OBJECT (int_panel->window), 
		       "detail_button", button);
  gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
  gtk_signal_connect (GTK_OBJECT (button),
		      "clicked",
		      (GtkSignalFunc) interface_detail_cb,
		      int_panel->list);
  gtk_container_add (GTK_CONTAINER (b_box), button);
  /* -- Down an Interface -- */
  button = gtk_button_new_with_label (_("Down"));
  gtk_object_set_data (GTK_OBJECT (int_panel->window),
		       "down_button", button);
  gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
  gtk_container_add (GTK_CONTAINER (b_box), button);

  /* -- Bring an interface back up -- */
  button = gtk_button_new_with_label (_("Up"));
  gtk_object_set_data (GTK_OBJECT (int_panel->window),
		       "up_button", button);
  gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
  gtk_container_add (GTK_CONTAINER (b_box), button);

  bar = gtk_hseparator_new ();
  gtk_box_pack_start (GTK_BOX (w_box), bar, FALSE, FALSE, 2);
  /*
   * Requsite button box on the bottom
   */
  i_frame = gtk_frame_new (NULL);
  gtk_box_pack_start (GTK_BOX (w_box), i_frame, FALSE, FALSE, 1);
  b_box = gtk_hbutton_box_new ();
  gtk_container_add (GTK_CONTAINER (i_frame), b_box);
  gtk_button_box_set_layout (GTK_BUTTON_BOX (b_box), GTK_BUTTONBOX_END);
  gtk_button_box_set_spacing (GTK_BUTTON_BOX (b_box), 2);
  gtk_container_border_width (GTK_CONTAINER (b_box), 4);

  int_panel->buttons[INTER_CLOS_BUT]= gnome_stock_button 
    (GNOME_STOCK_BUTTON_CLOSE);
  gtk_signal_connect (GTK_OBJECT (int_panel->buttons[INTER_CLOS_BUT]), 
		      "clicked",
		      GTK_SIGNAL_FUNC (interface_close_button_cb),
		      int_panel);
  gtk_container_add (GTK_CONTAINER (b_box), 
		     int_panel->buttons[INTER_CLOS_BUT]);
  pixmap = gnome_stock_pixmap_widget (int_panel->window, 
				      GNOME_STOCK_PIXMAP_REFRESH);
  int_panel->buttons[INTER_REFR_BUT] = gnome_pixmap_button (pixmap, 
							    _("Reload"));
  gtk_signal_connect (GTK_OBJECT (int_panel->buttons[INTER_REFR_BUT]), 
		      "clicked",
		      GTK_SIGNAL_FUNC (interface_reload_button_cb),
		      int_panel);
  gtk_container_add (GTK_CONTAINER (b_box), 
		     int_panel->buttons[INTER_REFR_BUT]);
  pixmap = gnome_stock_pixmap_widget (int_panel->window,
				      GNOME_STOCK_PIXMAP_STOP);
  int_panel->buttons[INTER_ABRT_BUT] = gnome_pixmap_button (pixmap, 
							    _("Abort"));
  gtk_signal_connect (GTK_OBJECT (int_panel->buttons[INTER_ABRT_BUT]), 
		      "clicked",
		      GTK_SIGNAL_FUNC (interface_abort_button_cb),
		      int_panel);
  gtk_container_add (GTK_CONTAINER (b_box), 
		     int_panel->buttons[INTER_ABRT_BUT]);
  gnome_app_set_contents (GNOME_APP (int_panel->window), w_box);
  gnome_app_create_menus (GNOME_APP (int_panel->window), interface_panel_menu);
  w_size += (90 * 3);
  int_panel->request = NULL;
  /*  gtk_widget_set_usize (int_panel->window, w_size, 200); */
  gtk_widget_show_all (int_panel->window);
}

/*
 * This is kooky.. Looks like we may have to do a two stage loading here.
 * get the stuff from the ip table, extract the ipAdEntIfIndex.<ip address>
 * index, then get the info from the interfaces table.
 * Bleh! Otherwise this stuff is not gonna match.
 */
static void
reload_interface_table (hosts *host)
{
  hosts     *this_host;
  GSList    *objs;
  GSList    *magic;
  GtkWidget *button;

  this_host = (hosts *)host;

  if (int_panel->request)
    g_remove_request (int_panel->request);
  int_panel->request = NULL;
  if (this_host)
    {
      button = get_widget (int_panel->window, "detail_button");
      if (button)
	gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
      objs  = NULL;
      magic = NULL;
/*      map_update_stat (_("Reloading interface table from node \"%s\"..."),
		       this_host->hl_disp); */
      gtk_widget_set_sensitive (int_panel->buttons[INTER_REFR_BUT], FALSE);
      gtk_widget_set_sensitive (int_panel->buttons[INTER_ABRT_BUT], TRUE);
      add_null_var (&objs, &magic, 
		    "interfaces.ifTable.ifEntry.ifDescr",
		    int_panel->list);
      add_null_var (&objs, &magic, 
		    "interfaces.ifTable.ifEntry.ifIndex",
		    int_panel->list);
      add_null_var (&objs, &magic, 
		    "interfaces.ifTable.ifEntry.ifType",
		    int_panel->list);
      add_null_var (&objs, &magic,
		    "interfaces.ifTable.ifEntry.ifSpeed",
		    int_panel->list);
      add_null_var (&objs, &magic,
		    "interfaces.ifTable.ifEntry.ifAdminStatus",
		    int_panel->list);
      add_null_var (&objs, &magic,
		    "interfaces.ifTable.ifEntry.ifOperStatus",
		    int_panel->list);
      add_null_var (&objs, &magic,
		    "interfaces.ifTable.ifEntry.ifLastChange",
		    int_panel->list);

      host->hl_snmp.magic = magic;
      host->hl_snmp.done_callback = update_interface_table;
      host->hl_snmp.time_callback = destroy_interface_table;
      g_print ("Starting chain running...\n");
      int_panel->request = g_async_getnext (&host->hl_snmp, objs);
      return;
    }
  else
    {
      notice_dlg ("No host was selected to get the interface table from.");
    }
}

/*
 * Callbacks
 */
static gint 
interface_panel_delete_cb (GtkWidget *widget, GdkEvent *e, gpointer data)
{
  destroy_interface_panel ();
  return TRUE;
}

static void
interface_close_button_cb (GtkWidget *widget, gpointer data)
{
  hide_interface_panel ();
  if (int_panel->request)
    g_remove_request (int_panel->request);
  int_panel->request = NULL;
}

static void
interface_reload_button_cb (GtkWidget *widget, gpointer data)
{
  reset_interface_panel ();
}

static void
interface_abort_button_cb (GtkWidget *widget, gpointer data)
{
  if (int_panel->request)
    g_remove_request (int_panel->request);
  int_panel->request = NULL;
  gtk_widget_set_sensitive (int_panel->buttons[INTER_REFR_BUT], TRUE);
  gtk_widget_set_sensitive (int_panel->buttons[INTER_ABRT_BUT], FALSE);
/*  map_update_stat (_("Interface loading aborted.")); */
}

static void
interface_select_row (GtkWidget *widget, gint row, gint column, 
		      GdkEventButton *e)
{
  GtkWidget    *button;
  GtkWidget    *parent;

  if (widget->parent)
    parent = gtk_widget_get_toplevel (widget);
  else
    parent = widget;
  button = get_widget (parent, "detail_button");
  if (button)
    gtk_widget_set_sensitive (GTK_WIDGET (button), TRUE);

  g_print ("GtkClist Selection: row %d column %d button %d\n",
	   row, column, e ? e->button : 0);
}

static void
interface_detail_cb (GtkWidget *widget, gpointer data)
{
  hosts            *host;
  GList            *list;
  gchar            *text;
  gint             row;

  open_int_detail_panel ();
  host = interface_get_selected_host ();
  list = GTK_CLIST (int_panel->list)->selection;
  if (list)
    {
      row = GPOINTER_TO_INT (list->data);
      gtk_entry_set_text (GTK_ENTRY (int_detail_panel->entry[D_NODE_NAME]),
			  host->hl_disp);
      gtk_entry_set_text (GTK_ENTRY (int_detail_panel->entry[D_NODE_ADDR]),
			  host->hl_snmp.name);
      gtk_clist_get_text (GTK_CLIST (int_panel->list), row, 0, &text);
      gtk_entry_set_text (GTK_ENTRY (int_detail_panel->entry[D_IFNAME]),
			   text);
      gtk_clist_get_text (GTK_CLIST (int_panel->list), row, 1, &text);
      gtk_entry_set_text (GTK_ENTRY (int_detail_panel->entry[D_IFIDX]),
			  text);
      gtk_object_set_data (GTK_OBJECT (int_detail_panel->window), 
			   "oid_text", g_strdup(text));
      gtk_clist_get_text (GTK_CLIST (int_panel->list), row, 2, &text);
      gtk_entry_set_text (GTK_ENTRY (int_detail_panel->entry[D_IFADDR]),
			  text);
      int_detail_set_selected_host (host);
      reset_int_detail_panel ();
    }
}

/*
 * Global standard panel functions
 */
void
interface_set_selected_host (hosts *host)
{

  if (int_panel->window)
    gtk_object_set_data (GTK_OBJECT (int_panel->window), "selected_host",
                        host);
}

hosts *
interface_get_selected_host ()
{
  if (int_panel->window)
    return (hosts *)gtk_object_get_data (GTK_OBJECT (int_panel->window),
                                        "selected_host");
  else
    return NULL;
}

void
interface_panel_reload (hosts *host)
{
  if (int_panel->list)
    gtk_clist_clear (GTK_CLIST (int_panel->list));
  if (host)
    reload_interface_table (host);
  
}

void
open_interface_panel (void)
{
  if (!int_panel)
    create_interface_panel ();
  else
    if (!GTK_WIDGET_VISIBLE (int_panel->window))
      gtk_widget_show (int_panel->window);
}

void
destroy_interface_panel (void)
{
  if (int_panel)
    {
      if (int_panel->request)
	g_remove_request (int_panel->request);
      gtk_widget_destroy (int_panel->window);
      g_free (int_panel);
      int_panel = NULL;
    }
}

void
reset_interface_panel (void)
{
  if (int_panel->list) 
    {
      gtk_clist_clear (GTK_CLIST (int_panel->list));
      interface_host = interface_get_selected_host ();
      reload_interface_table (interface_host);
    }
}

void
hide_interface_panel (void)
{
  if (int_panel)
    {
      if (GTK_WIDGET_VISIBLE (int_panel->window))
	gtk_widget_hide (int_panel->window);
    }
}

gint
interface_sort_func (GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
{
  char *text1 = NULL;
  char *text2 = NULL;
  GtkCListRow *row1 = (GtkCListRow *)ptr1;
  GtkCListRow *row2 = (GtkCListRow *)ptr2;
  gint t1, t2;

  text1 = GTK_CELL_TEXT (row1->cell[1])->text;
  text2 = GTK_CELL_TEXT (row2->cell[1])->text;

  t1 = atoi (text1);
  t2 = atoi (text2);

  return (t1 < t2) ? 0 : 1;
}

/*
 * Misc global functions
 */
gboolean
update_interface_table (host_snmp *host, void *magic, SNMP_PDU *spdu, 
			GSList *objs)
{
     char                 buf[1024];
     GSList               *entry;
     GSList               *myentry;
     GSList               *myobj;
     GSList               *nobjs;
     oidentry             *var;
     struct _SNMP_OBJECT  *obj;
     struct _SNMP_OBJECT  *nobj;
     char                 *tab_data[ELEMENTS (interface_labels)];
     int                  i, j;
     struct tree          *snmptree;

     if (int_panel->request)
       int_panel->request = NULL;
     else
       return TRUE;
     entry = (GSList *)magic;
     
     if (spdu->request.error_status)
     {
	  g_slist_free (entry);
	  return TRUE;
     }
     nobjs = NULL;
     myobj = objs;
     j     = 0;
     i     = 0;
     while (myobj)
       {
       obj = (struct _SNMP_OBJECT *) myobj->data;
       g_snmp_printf (buf, sizeof(buf), obj);
       myentry = entry;
       i = 0;
       while (myentry)
	 {
	   var = (oidentry *) myentry->data;
	   if (!memcmp (obj->id, var->id, var->id_len * sizeof (gulong)))
	     {
	       snmptree = get_mib_tree (var->id, var->id_len);
	       if (snmptree->enums)
		 {
		   struct enum_list *list;
		   list = snmptree->enums;
		   while (list)
		     {
		       if (list->value == atoi (buf))
			 {
			   tab_data[i] = g_strdup (list->label);
			   break;
			 }
		       list = list->next;
		     }
		 } else {
		   tab_data[i] = g_strdup (buf);
		 }
	       nobj = g_malloc (sizeof (struct _SNMP_OBJECT));
	       nobj->type       = SNMP_NULL;
	       nobj->syntax_len = 0;
	       nobj->id_len     = obj->id_len;
	       nobj->id         = g_malloc(obj->id_len * sizeof (gulong));
	       g_memmove (nobj->id, obj->id, obj->id_len * sizeof (gulong));
	       nobjs            = g_slist_append (nobjs, nobj);
	       j++;
	       
	     }
	   i++;
	   myentry = g_slist_next (myentry);
	 }
       myobj = myobj->next;
       }
     if (i != j)
       {
	 g_slist_free (nobjs);
	 nobjs = NULL;
       }
     if (nobjs)
       {
	 var = (oidentry *)entry->data;
	 if (GTK_WIDGET (var->name))
	   gtk_clist_insert (GTK_CLIST (var->name), 0, tab_data);
	 host->magic = magic;
	 host->done_callback = update_interface_table;
	 host->time_callback = destroy_interface_table;
	 int_panel->request = g_async_getnext (host, nobjs);
       }
     else
       {
	 if (entry)
	   g_slist_free (entry); 
/*	 map_update_stat (_("Interface list loading from host \"%s\" "
			    "complete..."),
			  host->name); */
	 gtk_widget_set_sensitive (int_panel->buttons[INTER_REFR_BUT], TRUE);
	 gtk_widget_set_sensitive (int_panel->buttons[INTER_ABRT_BUT], FALSE);
	 int_panel->request = NULL;
       }
     return TRUE;
}

void
destroy_interface_table (host_snmp *host, void *magic)
{
  GSList     *entry;

  int_panel->request = NULL;
  notice_dlg ("Snmp query timed out.");
  entry = (GSList *)magic;
  /*  g_slist_free (entry); */
}

/*
 * Interface detail panel(s)
 */

static char *detail_labels[] = {
  N_("Node Name"),
  N_("Node Address"),
  N_("Interface Name"),
  N_("Interface Address"),
  N_("Interface Speed"),
  N_("Interface MTU"),
  N_("Interface Index"),
  N_("Interface Type"),
  N_("Interface Admin Status"),
  N_("Interface Operational Status"),
  N_("Interface In Octets"),
  N_("Interface Out Octets"),
  N_("Interface In Errors"),
  N_("Interface Out Errors"),
};

/*
 * Local functions to the interface detail panel
 */
static void           create_int_detail_panel      (void);
static gint           int_detail_panel_delete_cb   (GtkWidget   *widget,
						    GdkEvent    *e,
						    gpointer    data);
static void           int_detail_close_button_cb   (GtkWidget   *widget,
						    gpointer    data);
static void           int_detail_reload_button_cb  (GtkWidget   *widget,
						    gpointer    data);
static void           int_detail_abort_button_cb   (GtkWidget   *widget,
						    gpointer    data);
static void           reload_int_detail            (hosts       *host);
/*
 * Local functions
 */
static void
create_int_detail_panel ()
{
  GtkWidget    *w_box;
  GtkWidget    *frame;
  GtkWidget    *b_box;
  GtkWidget    *pixmap;
  GtkWidget    *table;
  GtkWidget    *label;
  int          i;

  int_detail_panel = (detail_panel *)g_malloc (sizeof (detail_panel));
  int_detail_panel->request = NULL;
  int_detail_panel->update_id = 0;
  int_detail_panel->window = gnome_app_new ("GXSNMP", _("Interface Detail"));
  gtk_window_set_wmclass (GTK_WINDOW (int_detail_panel->window), 
			  "int_detail_panel",
			  "GXSNMP");
  gtk_signal_connect (GTK_OBJECT (int_detail_panel->window), "delete_event",
		      GTK_SIGNAL_FUNC (int_detail_panel_delete_cb),
		      int_detail_panel);
  w_box = gtk_vbox_new (FALSE, 4);
  frame = gtk_frame_new (NULL);
  gtk_box_pack_start (GTK_BOX (w_box), frame, TRUE, TRUE, 0);
  table = gtk_table_new (4, ELEMENTS(detail_labels) / 2, FALSE);
  gtk_container_add (GTK_CONTAINER (frame), table);

  /*
   * This may not be the most efficent but it works!
   */
  for (i = 0; i < ELEMENTS (detail_labels); i++)
    {
      label = gtk_label_new (g_strdup (gettext(detail_labels[i])));
      gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
      gtk_table_attach (GTK_TABLE (table), label,
			(i % 2) + (i % 2), (i % 2) + ( i % 2) + 1, 
			(i / 2), (i / 2) + 1,
			GTK_EXPAND | GTK_SHRINK | GTK_FILL, 
			GTK_EXPAND | GTK_SHRINK | GTK_FILL,
		        1, 2);
      int_detail_panel->entry[i] = gtk_entry_new ();
      gtk_table_attach (GTK_TABLE (table), int_detail_panel->entry[i],
			(i % 2) + (i % 2) + 1, (i % 2) + (i % 2) + 2,
			(i / 2), (i / 2) + 1,
			GTK_EXPAND | GTK_SHRINK | GTK_FILL,
			GTK_EXPAND | GTK_SHRINK | GTK_FILL,
			1, 2);
      
    }

  /* 
   * Button box at the bottom of the panel
   */
  frame = gtk_frame_new (NULL);
  gtk_container_border_width (GTK_CONTAINER (frame), 4);
  gtk_box_pack_start (GTK_BOX (w_box), frame, FALSE, FALSE, 1);
  b_box = gtk_hbutton_box_new ();
  gtk_container_border_width (GTK_CONTAINER (b_box), 2);
  gtk_container_add (GTK_CONTAINER (frame), b_box);
  int_detail_panel->buttons[DETAIL_CLOS_BUT] = gnome_stock_button 
    (GNOME_STOCK_BUTTON_CLOSE);
  gtk_signal_connect (GTK_OBJECT (int_detail_panel->buttons[DETAIL_CLOS_BUT]),
		      "clicked",
		      (GtkSignalFunc) int_detail_close_button_cb,
		      int_detail_panel);
  gtk_container_add (GTK_CONTAINER (b_box), int_detail_panel->
		     buttons[DETAIL_CLOS_BUT]);
  pixmap = gnome_stock_pixmap_widget (int_detail_panel->window,
				      GNOME_STOCK_PIXMAP_REFRESH);
  int_detail_panel->buttons[DETAIL_REFR_BUT] = gnome_pixmap_button 
    (pixmap, _("Reload"));
  gtk_signal_connect (GTK_OBJECT (int_detail_panel->buttons[DETAIL_REFR_BUT]),
		      "clicked",
		      (GtkSignalFunc) int_detail_reload_button_cb,
		      int_detail_panel);
  gtk_container_add (GTK_CONTAINER (b_box), int_detail_panel->buttons
		     [DETAIL_REFR_BUT]);
  pixmap = gnome_stock_pixmap_widget (int_detail_panel->window,
				      GNOME_STOCK_PIXMAP_STOP);
  int_detail_panel->buttons[DETAIL_ABRT_BUT] = gnome_pixmap_button 
    (pixmap, _("Abort"));
  gtk_signal_connect (GTK_OBJECT (int_detail_panel->buttons[DETAIL_ABRT_BUT]),
		      "clicked",
		      (GtkSignalFunc) int_detail_abort_button_cb,
		      int_detail_panel);
  gtk_container_add (GTK_CONTAINER (b_box), int_detail_panel->buttons
		     [DETAIL_ABRT_BUT]);

  gnome_app_set_contents (GNOME_APP (int_detail_panel->window), w_box);

  gtk_widget_show_all (int_detail_panel->window);
}

int
int_detail_timed_update (gpointer data)
{

  reload_int_detail (int_detail_get_selected_host ());
  if (GTK_WIDGET_VISIBLE (int_detail_panel->window))
    return TRUE;
  else 
    {
      int_detail_panel->update_id = 0;
      return FALSE;
    }
}

void
reload_int_detail (hosts *host)
{
  GSList  *objs;
  GSList  *magic;
  gchar   *text;
  gchar   buf[2048];

  if (host) 
    {
      text = gtk_object_get_data (GTK_OBJECT (int_detail_panel->window),
				  "oid_text");
      objs  = NULL;
      magic = NULL;
      g_snprintf (buf, sizeof(buf),
		  "interfaces.ifTable.ifEntry.ifSpeed.%s", text);
      add_null_var (&objs, &magic, buf, int_detail_panel->entry[D_IFSPEED]);
      g_snprintf (buf, sizeof(buf), 
		  "interfaces.ifTable.ifEntry.ifMtu.%s", text);
      add_null_var (&objs, &magic, buf, int_detail_panel->entry[D_IFMTU]);
      g_snprintf (buf, sizeof(buf),
		  "interfaces.ifTable.ifEntry.ifType.%s", text);
      add_null_var (&objs, &magic, buf, int_detail_panel->entry[D_IFTYPE]);
      g_snprintf (buf, sizeof(buf),
		  "interfaces.ifTable.ifEntry.ifAdminStatus.%s", text);
      add_null_var (&objs, &magic, buf, int_detail_panel->entry[D_IFADMIN]);
      g_snprintf (buf, sizeof(buf),
		  "interfaces.ifTable.ifEntry.ifOperStatus.%s", text);
      add_null_var (&objs, &magic, buf, int_detail_panel->entry[D_IFOPER]);
      g_snprintf (buf, sizeof(buf),
		  "interfaces.ifTable.ifEntry.ifInOctets.%s", text);
      add_null_var (&objs, &magic, buf, int_detail_panel->entry[D_IFINOCT]);
      g_snprintf (buf, sizeof(buf),
		  "interfaces.ifTable.ifEntry.ifOutOctets.%s", text);
      add_null_var (&objs, &magic, buf, int_detail_panel->entry[D_IFOUTOCT]);
      g_snprintf (buf, sizeof(buf),
		  "interfaces.ifTable.ifEntry.ifInErrors.%s", text);
      add_null_var (&objs, &magic, buf, int_detail_panel->entry[D_IFINERR]);
      g_snprintf (buf, sizeof(buf),
		  "interfaces.ifTable.ifEntry.ifOutErrors.%s", text);
      add_null_var (&objs, &magic, buf, int_detail_panel->entry[D_IFOUTERR]);
      host->hl_snmp.magic = magic;
      host->hl_snmp.done_callback = update_int_detail;
      host->hl_snmp.time_callback = destroy_widget;
      int_detail_panel->request = g_async_get (&host->hl_snmp, objs);
      if (!int_detail_panel->update_id) 
	{
	  int_detail_panel->update_id = gtk_timeout_add 
	    (10000, int_detail_timed_update, NULL);
	}
    }
}

gboolean
update_int_detail (host_snmp *host, void *magic, SNMP_PDU *spdu, GSList *objs)
{
     char                buf[1024];
     GSList              *entry;
     GSList              *myentry;
     GSList              *myobj;
     oidentry            *var;
     struct _SNMP_OBJECT *obj;

     int_detail_panel->request = NULL;
     entry = (GSList *)magic;
     if (spdu->request.error_status) 
       {
	 g_slist_free (entry);
	 return TRUE;
       }
     myobj = objs;
     while (myobj) 
       {
	 obj = (struct _SNMP_OBJECT *)myobj->data;
	 g_snmp_printf (buf, sizeof(buf), obj);
	 myentry = entry;
	 while (myentry) 
	   {
	     var = (oidentry *)myentry->data;
	     if (!memcmp (obj->id, var->id, var->id_len * (sizeof (gulong))))
	       gtk_entry_set_text (GTK_ENTRY (var->name), buf);
	     myentry = myentry->next;
	   }
	 myobj = myobj->next;
       }
     g_slist_free (entry);
     return TRUE; 
}
/*
 * Callback functions
 */
static gint
int_detail_panel_delete_cb (GtkWidget *widget, GdkEvent *e, gpointer data)
{
  destroy_int_detail_panel ();
  return TRUE;
}

static void
int_detail_close_button_cb (GtkWidget *widget, gpointer data)
{
  hide_int_detail_panel ();
}

static void
int_detail_reload_button_cb (GtkWidget *widget, gpointer data)
{
  reset_int_detail_panel ();
}

static void
int_detail_abort_button_cb (GtkWidget *widget, gpointer data)
{
  if (int_detail_panel) 
    {
      if (int_detail_panel->request)
	g_remove_request (int_detail_panel->request);
      int_detail_panel->request = NULL;
    }
}


/*
 * Global standard panel functions
 */

void 
int_detail_set_selected_host (hosts *host)
{
  if (int_detail_panel->window)
    gtk_object_set_data (GTK_OBJECT (int_detail_panel->window), 
			 "selected_host", host);
}

hosts *
int_detail_get_selected_host ()
{
  if (int_detail_panel->window)
    return (hosts *)gtk_object_get_data (GTK_OBJECT (int_detail_panel->window),
					 "selected_host");
  else
    return (hosts *)NULL;
}

void
open_int_detail_panel ()
{
  if (!int_detail_panel)
    create_int_detail_panel ();
  else
    if (!GTK_WIDGET_VISIBLE (int_detail_panel->window))
      gtk_widget_show_all (int_detail_panel->window);

}

void
destroy_int_detail_panel ()
{
  if (int_detail_panel) 
    {
      if (int_detail_panel->request)
	g_remove_request (int_detail_panel->request);
      if (int_detail_panel->update_id)
	gtk_timeout_remove (int_detail_panel->update_id);
      gtk_widget_destroy (int_detail_panel->window);
      g_free (int_detail_panel);
      int_detail_panel = NULL;
    }
}

void 
reset_int_detail_panel ()
{
  hosts    *host;

  host = int_detail_get_selected_host ();
  if (host) 
    {
      reload_int_detail (host);
    }
}

void 
hide_int_detail_panel ()
{
  if (int_detail_panel)
    {
      if (GTK_WIDGET_VISIBLE (int_detail_panel->window))
	gtk_widget_hide (int_detail_panel->window);
    }
}
/* EOF */
