Skip to content
Snippets Groups Projects
common.c 58.7 KiB
Newer Older
/*****************************************************************************\
 *  common.c - common functions used by tabs in sview
 *****************************************************************************
 *  Copyright (C) 2004-2007 The Regents of the University of California.
 *  Copyright (C) 2008-2009 Lawrence Livermore National Security.
 *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
 *  Written by Danny Auble <da@llnl.gov>
 *
 *  This file is part of SLURM, a resource management program.
 *  For details, see <http://www.schedmd.com/slurmdocs/>.
 *  Please also read the included file: DISCLAIMER.
 *  SLURM 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.
 *  SLURM 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 SLURM; if not, write to the Free Software Foundation, Inc.,
 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
\*****************************************************************************/

#include "src/sview/sview.h"
#include "src/common/parse_time.h"
#include <gdk/gdkkeysyms.h>

#define TOPO_DEBUG 0
#define _DEBUG 0
static bool menu_right_pressed = false;

	display_data_t *display_data;
	void (*pfunc)(GtkTreeModel*, GtkTreeIter*, int);
	GtkTreeView  *tree_view;
} each_t;

typedef struct {
	GtkTreeIter iter;
static gboolean enter_key_in_effect = FALSE;



static int _find_node_inx (char *name)
{
	int i;

	if ((name == NULL) || (name[0] == '\0')) {
		info("_find_node_inx passed NULL name");
		return -1;
	}


	for (i = 0; i < g_node_info_ptr->record_count; i++) {
		if (!strcmp (name, g_node_info_ptr->node_array[i].name)) {
			return i;
		}
	}

	return -1;
}


static void _display_topology(void)
{
Danny Auble's avatar
Danny Auble committed
	int i, match = 0, match_cnt = 0;
	hostset_t hs;
	int one_liner = 1;

	if (TOPO_DEBUG)
		g_print("_display_topology,  record_count = %d\n",
			g_topo_info_msg_ptr->record_count);
	for (i=0; i<g_topo_info_msg_ptr->record_count; i++) {

		if ((g_topo_info_msg_ptr->topo_array[i].nodes == NULL) ||
		    (g_topo_info_msg_ptr->topo_array[i].nodes[0] == '\0'))
			continue;
		if (g_topo_info_msg_ptr->topo_array[i].level == 0) {
			hs = hostset_create(g_topo_info_msg_ptr->
					    topo_array[i].nodes);
			if (hs == NULL)
				fatal("hostset_create: memory "
				      "allocation failure");
		}

		hostset_destroy(hs);
		if (!match)
			continue;
		match_cnt++;
		slurm_print_topo_record(stdout,
					&g_topo_info_msg_ptr->topo_array[i],
					one_liner);
		if (match_cnt == 0) {
			g_print("Topology information contains no switch or "
				"node named %s",
				g_topo_info_msg_ptr->topo_array[i].nodes);
		}
	}
}



static void _foreach_popup_all(GtkTreeModel  *model,
			       GtkTreePath   *path,
			       GtkTreeIter   *iter,
			       gpointer       userdata)
{

	each_t *each = userdata;
	each->pfunc(model, iter, each->display_data->id);
}

static void _foreach_full_info(GtkTreeModel  *model,
			       GtkTreePath   *path,
			       GtkTreeIter   *iter,
			       gpointer       userdata)
{

	each_t *each = userdata;
	(each->display_data->set_menu)(each->tree_view, NULL, path,
				       FULL_CLICKED);
	popup_pos.x = popup_pos.slider + popup_pos.cntr * 10;
	popup_pos.y = popup_pos.cntr * 22;
	popup_pos.cntr++;
	if (popup_pos.cntr > 10) {
		popup_pos.cntr = 1;
		popup_pos.slider += 100;
	}
/* These next 2 functions are here to make it so we don't magically
 * click on something before we really want to in a menu.
 */
static gboolean _menu_button_pressed(GtkWidget *widget, GdkEventButton *event,
Danny Auble's avatar
Danny Auble committed
	if (event->button == 3) {
		menu_right_pressed = true;
		return true;
	}
	return false;
}

static gboolean _menu_button_released(GtkWidget *widget, GdkEventButton *event,
				      gpointer extra)
{
Danny Auble's avatar
Danny Auble committed
	if (event->button == 3 && !menu_right_pressed)
		return true;
	menu_right_pressed = false;
	return false;
}

static gboolean _frame_callback(GtkWindow *window,
				GdkEvent *event, gpointer data)
{

	if (event->expose.send_event == 0) {
		default_sview_config.fi_popup_width = event->configure.width;
		default_sview_config.fi_popup_height = event->configure.height;
		working_sview_config.fi_popup_width = event->configure.width;
		working_sview_config.fi_popup_height = event->configure.height;

		ListIterator itr = list_iterator_create(popup_list);
		popup_info_t *popup_win = NULL;

Danny Auble's avatar
Danny Auble committed
		while ((popup_win = list_next(itr))) {
			gtk_window_resize(GTK_WINDOW(popup_win->popup),
					  working_sview_config.fi_popup_width,
					  working_sview_config.fi_popup_height);
		}
		list_iterator_destroy(itr);
	}


	return FALSE;
}




static void _handle_response(GtkDialog *dialog, gint response_id,
			     popup_info_t *popup_win)
{
	switch(response_id) {
	case GTK_RESPONSE_OK: //refresh
		(popup_win->display_data->refresh)(NULL, popup_win);
		break;
	case GTK_RESPONSE_DELETE_EVENT: // exit
	case GTK_RESPONSE_CLOSE: // close
		delete_popup(NULL, NULL, popup_win->spec_info->title);
		break;
	case GTK_RESPONSE_CANCEL: // cancel
		delete_popups();
		break;
	default:
		g_print("handle unknown response %d\n", response_id);
		break;
	}
	return;
}

static int _sort_iter_compare_func_char(GtkTreeModel *model,
					GtkTreeIter  *a,
					GtkTreeIter  *b,
					gpointer      userdata)
{
	int sortcol = GPOINTER_TO_INT(userdata);
	int ret = 0;
Danny Auble's avatar
Danny Auble committed
	int len1 = 0, len2 = 0;
	gchar *name1 = NULL, *name2 = NULL;
	gtk_tree_model_get(model, a, sortcol, &name1, -1);
	gtk_tree_model_get(model, b, sortcol, &name2, -1);
	if (!name1 && !name2)
		goto cleanup; /* both equal => ret = 0 */
	else if (!name1 || !name2) {
		ret = (name1 == NULL) ? -1 : 1;
Danny Auble's avatar
Danny Auble committed
		   meaning snowflake2 would be greater than
		   snowflake12 */
		len1 = strlen(name1);
		len2 = strlen(name2);
Danny Auble's avatar
Danny Auble committed
		while ((ret < len1) && (!g_ascii_isdigit(name1[ret])))
Danny Auble's avatar
Danny Auble committed
			ret++;
Danny Auble's avatar
Danny Auble committed
		if (ret < len1) {
			if (!g_ascii_strncasecmp(name1, name2, ret)) {
				if (len1 > len2)
Danny Auble's avatar
Danny Auble committed
					ret = 1;
Danny Auble's avatar
Danny Auble committed
				else if (len1 < len2)
Danny Auble's avatar
Danny Auble committed
					ret = -1;
Danny Auble's avatar
Danny Auble committed
					ret = g_ascii_strcasecmp(name1, name2);
Danny Auble's avatar
Danny Auble committed
				ret = g_ascii_strcasecmp(name1, name2);
Danny Auble's avatar
Danny Auble committed
			ret = g_ascii_strcasecmp(name1, name2);
	return ret;
}

static int _sort_iter_compare_func_int(GtkTreeModel *model,
				       GtkTreeIter  *a,
				       GtkTreeIter  *b,
				       gpointer      userdata)
{
	int sortcol = GPOINTER_TO_INT(userdata);
	int ret = 0;
	gint int1, int2;

	gtk_tree_model_get(model, a, sortcol, &int1, -1);
	gtk_tree_model_get(model, b, sortcol, &int2, -1);
	if (int1 != int2)
		ret = (int1 > int2) ? 1 : -1;
static int _sort_iter_compare_func_nodes(GtkTreeModel *model,
					 GtkTreeIter  *a,
					 GtkTreeIter  *b,
					 gpointer      userdata)
{
	int sortcol = GPOINTER_TO_INT(userdata);
	int ret = 0;
	gchar *name1 = NULL, *name2 = NULL;
	gtk_tree_model_get(model, a, sortcol, &name1, -1);
	gtk_tree_model_get(model, b, sortcol, &name2, -1);
	if (!name1 && !name2)
		goto cleanup; /* both equal => ret = 0 */
	else if (!name1 || !name2)
		uint64_t int1=0, int2=0, tmp_int;
		int spot=0;
		/* If this is in a mixed state we need to get them all */
Danny Auble's avatar
Danny Auble committed
		while (name1[spot]) {
			while (name1[spot]
			       && !g_ascii_isdigit(name1[spot])) {
Danny Auble's avatar
Danny Auble committed
			if (!name1[spot])
				break;
			tmp_int = atoi(name1+spot);
Danny Auble's avatar
Danny Auble committed
			while (name1[spot] && g_ascii_isdigit(name1[spot])) {
Danny Auble's avatar
Danny Auble committed
			if (!name1[spot]) {
			} else if (name1[spot] == 'K')
Danny Auble's avatar
Danny Auble committed
			else if (name1[spot] == 'M')
Danny Auble's avatar
Danny Auble committed
			else if (name1[spot] == 'G')
				tmp_int *= 1073741824;

			int1 += tmp_int;
Danny Auble's avatar
Danny Auble committed
		while (name2[spot]) {
			while (name2[spot]
			       && !g_ascii_isdigit(name2[spot])) {
Danny Auble's avatar
Danny Auble committed
			if (!name2[spot])
				break;
			tmp_int = atoi(name2+spot);
Danny Auble's avatar
Danny Auble committed
			while (name2[spot] && g_ascii_isdigit(name2[spot])) {
Danny Auble's avatar
Danny Auble committed
			if (!name2[spot]) {
			} else if (name2[spot] == 'K')
Danny Auble's avatar
Danny Auble committed
			else if (name2[spot] == 'M')
Danny Auble's avatar
Danny Auble committed
			else if (name2[spot] == 'G')
				tmp_int *= 1073741824;

			int2 += tmp_int;
/* Translate a three-digit alpha-numeric value into it's
 * base 36 equivalent number */
static int _xlate_bp_coord(const char *name)
{
	int i, rc = 0;

	for (i=0; i<cluster_dims; i++) {
		rc += select_char2coord(name[i]);
/* Make a BlueGene node name into a numeric representation of
 * its location.
 * Value is low_node_coordinate * 1,000 + I/O node (999 if none)
 * with use of base 36 for the node coordinate:
 * (e.g. bg123[4]    ->  1,371,004
 *       bg[234x235] ->  2,704,999
 *       bglZZZ      -> 46,655,999
 */
static int _bp_coordinate(const char *name)
{

	for (i=0; name[i]; i++) {
		if (name[i] == '[') {
			i++;
			if (low_val < 0)
				low_val = _xlate_bp_coord(name+i);
			else
				io_val = atoi(name+i);
			break;
		} else if ((low_val < 0) &&
			   ((name[i] >= '0' && (name[i] <= '9')) ||
			    (name[i] >= 'A' && (name[i] <= 'Z')))) {
			low_val = _xlate_bp_coord(name+i);
			i += 2;
		}
	if (low_val < 0)
		return low_val;
	return ((low_val * 1000) + io_val);
static int _sort_iter_compare_func_bp_list(GtkTreeModel *model,
					   GtkTreeIter  *a,
					   GtkTreeIter  *b,
					   gpointer      userdata)
{
	int sortcol = GPOINTER_TO_INT(userdata);
	int ret = 0;
	gchar *name1 = NULL, *name2 = NULL;
	gtk_tree_model_get(model, a, sortcol, &name1, -1);
	gtk_tree_model_get(model, b, sortcol, &name2, -1);
	if (!name1 && !name2)
		goto cleanup; /* both equal => ret = 0 */
	else if (!name1 || !name2)
		/* Sort in numeric order based upon coordinates */
		ret = _bp_coordinate(name1) - _bp_coordinate(name2);
static void _editing_started(GtkCellRenderer *cell,
			     GtkCellEditable *editable,
			     const gchar     *path,
			     gpointer         data)
{
	gdk_threads_leave();
	g_static_mutex_lock(&sview_mutex);
}

static void _editing_canceled(GtkCellRenderer *cell,
{
	g_static_mutex_unlock(&sview_mutex);
}

static void *_editing_thr(gpointer arg)
	int msg_id = 0;
	sleep(5);
	gdk_threads_enter();
	msg_id = GPOINTER_TO_INT(arg);
	gtk_statusbar_remove(GTK_STATUSBAR(main_statusbar),
			     STATUS_ADMIN_EDIT, msg_id);
	gdk_threads_leave();
static void _cell_data_func(GtkTreeViewColumn *col,
			    GtkCellRenderer *renderer,
			    GtkTreeModel *model,
			    GtkTreeIter *iter,
			    gpointer data)
{
	GdkPixbuf *pixbuf = NULL;
Danny Auble's avatar
Danny Auble committed
	char *color_char, *color_char2;
	uint32_t color;

	g_object_get(renderer, "pixbuf", &pixbuf, NULL);
Danny Auble's avatar
Danny Auble committed
	if (!pixbuf)
		return;

	gtk_tree_model_get(model, iter,
			   GPOINTER_TO_INT(g_object_get_data(G_OBJECT(renderer),
							     "column")),
			   &color_char, -1);
Danny Auble's avatar
Danny Auble committed
	if (!color_char)
Danny Auble's avatar
Danny Auble committed
	color_char2 = color_char+1;
	color = strtoul(color_char2, (char **)&color_char2, 16);
Danny Auble's avatar
Danny Auble committed
	g_free(color_char);

	/* we need to shift over 2 spots for the alpha */
	gdk_pixbuf_fill(pixbuf, color << 8);
	/* This only has to be done once, but I can't find any way to
	 * set something to only make it happen once.  It only takes
	 * 3-5 usecs to do it so I didn't worry about it doing it
	 * multiple times.  If you can figure out how to make this
	 * happen only once please fix, but the pointers for the col,
	 * renderer, and pixbuf are all the same.  You could put in
	 * some think in the tree_model, but that seemed a bit more
	 * cumbersome. - da
	 */
}

static void _add_col_to_treeview(GtkTreeView *tree_view,
				 display_data_t *display_data, int color_column)
	GtkTreeViewColumn *col;
	GtkListStore *model;
	GtkCellRenderer *renderer = NULL;
	/* Since some systems have different default columns (some
	 * which aren't displayed on all types of clusters only add a
	 * column if there is a name for it. */
	if (!display_data->name && (display_data->extra != EDIT_COLOR))
		return;

	col = gtk_tree_view_column_new();
	model = (display_data->create_model)(display_data->id);

	if (model && display_data->extra != EDIT_NONE) {
		renderer = gtk_cell_renderer_combo_new();
		g_object_set(renderer,
			     "model", model,
			     "text-column", 0,
	} else if (display_data->extra == EDIT_TEXTBOX) {
		renderer = gtk_cell_renderer_text_new();
		g_object_set(renderer,
			     "editable", TRUE,
			     NULL);
	} else if (display_data->extra == EDIT_COLOR) {
		GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false,
						   8, 10, 20);
		renderer = gtk_cell_renderer_pixbuf_new();
		g_object_set(renderer, "pixbuf", pixbuf, NULL);
		g_object_unref(pixbuf);
	} else
		renderer = gtk_cell_renderer_text_new();
	gtk_tree_view_column_pack_start(col, renderer, TRUE);

	g_object_set_data(G_OBJECT(renderer), "column",
			  GINT_TO_POINTER(display_data->id));
	if (display_data->extra == EDIT_COLOR) {
		gtk_tree_view_column_set_cell_data_func(
			col, renderer, _cell_data_func,
			NULL, NULL);
		g_signal_connect(renderer, "editing-started",
				 G_CALLBACK(_editing_started), NULL);
		g_signal_connect(renderer, "editing-canceled",
				 G_CALLBACK(_editing_canceled), NULL);
		g_signal_connect(renderer, "edited",
				 G_CALLBACK(display_data->admin_edit),
				 gtk_tree_view_get_model(tree_view));

		gtk_tree_view_column_add_attribute(col, renderer,
						   "text", display_data->id);
		gtk_tree_view_column_set_expand(col, true);
		gtk_tree_view_column_set_reorderable(col, true);
		gtk_tree_view_column_set_resizable(col, true);
		gtk_tree_view_column_set_sort_column_id(col, display_data->id);
		gtk_tree_view_column_set_title(col, display_data->name);
	gtk_tree_view_append_column(tree_view, col);
static void _toggle_state_changed(GtkCheckMenuItem *menuitem,
Danny Auble's avatar
Danny Auble committed
	if (display_data->show)
		display_data->show = FALSE;
	else
		display_data->show = TRUE;
	toggled = TRUE;
	refresh_main(NULL, NULL);
}

static void _popup_state_changed(GtkCheckMenuItem *menuitem,
				 display_data_t *display_data)
{
	popup_info_t *popup_win = (popup_info_t *) display_data->user_data;
Danny Auble's avatar
Danny Auble committed
	if (display_data->show)
		display_data->show = FALSE;
	else
		display_data->show = TRUE;
	(display_data->refresh)(NULL, display_data->user_data);
}

static void _selected_page(GtkMenuItem *menuitem, display_data_t *display_data)
{
	treedata_t *treedata = (treedata_t *)display_data->user_data;
	each_t each;
	memset(&each, 0, sizeof(each_t));
	each.tree_view = treedata->treeview;
	each.display_data = display_data;
	global_row_count = gtk_tree_selection_count_selected_rows(
		gtk_tree_view_get_selection(treedata->treeview));
	switch(display_data->extra & EXTRA_BASE) {
		each.pfunc = &popup_all_part;
		each.pfunc = &popup_all_job;
		each.pfunc = &popup_all_node;
		each.pfunc = &popup_all_block;
		each.pfunc = &popup_all_resv;
	case FRONT_END_PAGE:
		each.pfunc = &popup_all_front_end;
		break;
	case ADMIN_PAGE:
		switch(display_data->id) {
		case JOB_PAGE:
			admin_job(treedata->model, &treedata->iter,
			select_admin_partitions(treedata->model,
						&treedata->iter,
						display_data,
						treedata->treeview);
			select_admin_block(treedata->model, &treedata->iter,
					   display_data, treedata->treeview);
		case FRONT_END_PAGE:
			select_admin_front_end(treedata->model,
					       &treedata->iter,
					       display_data,
					       treedata->treeview);
			break;
		case RESV_PAGE:
			select_admin_resv(treedata->model, &treedata->iter,
					  display_data, treedata->treeview);
			select_admin_nodes(treedata->model, &treedata->iter,
					   display_data, NO_VAL,
					   treedata->treeview);
			break;
		default:
			g_print("common admin got %d %d\n",
				display_data->extra,
				display_data->id);
		}
		break;
	default:
		g_print("common got %d %d\n", display_data->extra,
			display_data->id);
	}
Danny Auble's avatar
Danny Auble committed
	if (each.pfunc)
		gtk_tree_selection_selected_foreach(
			gtk_tree_view_get_selection(treedata->treeview),
			_foreach_popup_all, &each);

extern char * replspace (char *str)
	int pntr = 0;
	while (str[pntr]) {
		if (str[pntr] == ' ')
			str[pntr] = '_';
		pntr++;
	}
	return str;
}
extern char * replus (char *str)
{
	int pntr = 0;
	while (str[pntr]) {
		if (str[pntr] == '_')
			str[pntr] = ' ';
		pntr++;
	return str;
}

extern char *delstr(char *str, char *orig)
{
	static char buffer[150];
	char *p;

	if (!(p = strstr(str, orig)))
		return NULL;

	strncpy(buffer, str, p-str);
	strncpy(buffer+(p-str-1), p+strlen(orig), strlen(str)-(p-str));
	buffer[strlen(str) - strlen(orig)] = '\0';

	if (_DEBUG)
		g_print("delstr: new string <%s>\n", buffer);

	return buffer;
}


Danny Auble's avatar
Danny Auble committed
extern void free_switch_nodes_maps(
	switch_record_bitmaps_t *sw_nodes_bitmaps_ptr)
Danny Auble's avatar
Danny Auble committed
	while (sw_nodes_bitmaps_ptr++) {
		if (!sw_nodes_bitmaps_ptr->node_bitmap)
			break;
		bit_free(sw_nodes_bitmaps_ptr->node_bitmap);
		if (sw_nodes_bitmaps_ptr->node_bitmap)
			xfree(sw_nodes_bitmaps_ptr->nodes);
	}
	g_switch_nodes_maps = NULL;
}

extern int build_nodes_bitmap(char *node_names, bitstr_t **bitmap)

{
	char *this_node_name;
	bitstr_t *my_bitmap;
	hostlist_t host_list;
	int node_inx = -1;

	if (TOPO_DEBUG)
		g_print("...............build_nodes_bitmap............%s\n",
			node_names);
	my_bitmap = (bitstr_t *) bit_alloc(g_node_info_ptr->record_count);
Danny Auble's avatar
Danny Auble committed
	if (!my_bitmap) {
		fatal("bit_alloc malloc failure");
	}
	*bitmap = my_bitmap;

Danny Auble's avatar
Danny Auble committed
	if (!node_names) {
		error("build_nodes_bitmap: node_names is NULL");
Danny Auble's avatar
Danny Auble committed
	if (!(host_list = hostlist_create(node_names))) {
		error("build_nodes_bitmap: hostlist_create(%s) error",
		      node_names);
		return EINVAL;
	}

	/*spin hostlist and map nodes into a bitmap*/
Danny Auble's avatar
Danny Auble committed
	while ((this_node_name = hostlist_shift(host_list))) {
		node_inx = _find_node_inx(this_node_name);
		free(this_node_name);

		if (node_inx == -1)
Danny Auble's avatar
Danny Auble committed

		bit_set(my_bitmap, (bitoff_t)node_inx);
	}
	hostlist_destroy(host_list);

	return SLURM_SUCCESS;
}


extern int get_topo_conf(void)
{
	int i;
	switch_record_bitmaps_t sw_nodes_bitmaps;
	switch_record_bitmaps_t *sw_nodes_bitmaps_ptr;
	if (TOPO_DEBUG)
		g_print("get_topo_conf\n");

Danny Auble's avatar
Danny Auble committed
	if (!g_topo_info_msg_ptr && slurm_load_topo(&g_topo_info_msg_ptr)) {
		slurm_perror ("slurm_load_topo error");
		if (TOPO_DEBUG)
			g_print("get_topo_conf error !!\n");
		return SLURM_ERROR;
	}

Danny Auble's avatar
Danny Auble committed
	if (g_topo_info_msg_ptr->record_count == 0) {
		slurm_free_topo_info_msg(g_topo_info_msg_ptr);
		g_topo_info_msg_ptr = NULL;
		return SLURM_ERROR;
	}

		free_switch_nodes_maps(g_switch_nodes_maps);
Danny Auble's avatar
Danny Auble committed
	g_switch_nodes_maps = xmalloc(sizeof(sw_nodes_bitmaps)
				      * g_topo_info_msg_ptr->record_count);
	sw_nodes_bitmaps_ptr = g_switch_nodes_maps;

	if (TOPO_DEBUG)
		g_print("_display_topology,  record_count = %d\n",
			g_topo_info_msg_ptr->record_count);
	for (i = 0; i < g_topo_info_msg_ptr->record_count;
	     i++, sw_nodes_bitmaps_ptr++) {
		if (!g_topo_info_msg_ptr->topo_array[i].nodes)
			continue;
		if (TOPO_DEBUG)  {
			g_print("ptr->nodes =  %s \n",
				g_topo_info_msg_ptr->topo_array[i].nodes);
		}
		if (build_nodes_bitmap(
			    g_topo_info_msg_ptr->topo_array[i].nodes,
			    &sw_nodes_bitmaps_ptr->node_bitmap)) {
			g_print("Invalid node name (%s) in switch %s\n",
				g_topo_info_msg_ptr->topo_array[i].nodes,
				g_topo_info_msg_ptr->topo_array[i].name);
extern int get_row_number(GtkTreeView *tree_view, GtkTreePath *path)
{
	GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
	GtkTreeIter iter;
	int line = 0;
Danny Auble's avatar
Danny Auble committed
	if (!model) {
		g_error("error getting the model from the tree_view");
		return -1;
	}
	if (!gtk_tree_model_get_iter(model, &iter, path)) {
Danny Auble's avatar
Danny Auble committed
		g_error("get row, error getting iter from model");
	gtk_tree_model_get(model, &iter, POS_LOC, &line, -1);
	return line;
}

extern int find_col(display_data_t *display_data, int type)
{
	int i = 0;

Danny Auble's avatar
Danny Auble committed
	while (display_data++) {
		if (display_data->id == -1)
Danny Auble's avatar
Danny Auble committed
		if (display_data->id == type)
			return i;
		i++;
	}
	return -1;
}

extern const char *find_col_name(display_data_t *display_data, int type)
{
Danny Auble's avatar
Danny Auble committed
	while (display_data++) {
		if (display_data->id == -1)
Danny Auble's avatar
Danny Auble committed
		if (display_data->id == type)
			return display_data->name;
	}
	return NULL;
}

extern void *get_pointer(GtkTreeView *tree_view, GtkTreePath *path, int loc)
{
	GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
	GtkTreeIter iter;
	void *ptr = NULL;
Danny Auble's avatar
Danny Auble committed
	if (!model) {
		g_error("error getting the model from the tree_view");
		return ptr;
	}
	if (!gtk_tree_model_get_iter(model, &iter, path)) {
Danny Auble's avatar
Danny Auble committed
		g_error("get pointer, error getting iter from model");
	gtk_tree_model_get(model, &iter, loc, &ptr, -1);
	return ptr;
}

extern void make_fields_menu(popup_info_t *popup_win, GtkMenu *menu,
			     display_data_t *display_data, int count)
	display_data_t *first_display_data = display_data;
	int i = 0;

	/* we don't want to display anything on the full info page */
Danny Auble's avatar
Danny Auble committed
	if (popup_win && popup_win->spec_info->type == INFO_PAGE)
	g_signal_connect(G_OBJECT(menu), "button-press-event",
			 G_CALLBACK(_menu_button_pressed),
			 NULL);
	g_signal_connect(G_OBJECT(menu), "button-release-event",
			 G_CALLBACK(_menu_button_released),
			 NULL);

	for(i=0; i<count; i++) {
Danny Auble's avatar
Danny Auble committed
		while (display_data++) {
Danny Auble's avatar
Danny Auble committed
			if (display_data->id == -1)
Danny Auble's avatar
Danny Auble committed
			if (!display_data->name)
Danny Auble's avatar
Danny Auble committed
			if (display_data->id != i)
			menuitem = gtk_check_menu_item_new_with_label(
			gtk_check_menu_item_set_active(
				GTK_CHECK_MENU_ITEM(menuitem),
				display_data->show);
Danny Auble's avatar
Danny Auble committed
			if (popup_win) {
				display_data->user_data = popup_win;
				g_signal_connect(
					menuitem, "toggled",
					display_data);
			} else {
				g_signal_connect(
					menuitem, "toggled",
			gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
		}
		display_data = first_display_data;
Danny Auble's avatar
Danny Auble committed
extern void set_page_opts(int page, display_data_t *display_data,
Danny Auble's avatar
Danny Auble committed
			  int count, char* initial_opts)
	page_opts_t *page_opts;
Danny Auble's avatar
Danny Auble committed
	ListIterator itr = NULL;
	char *col_name = NULL;
Danny Auble's avatar
Danny Auble committed
	xassert(page < PAGE_CNT);
Danny Auble's avatar
Danny Auble committed
	page_opts = &working_sview_config.page_opts[page];
	if (!page_opts->col_list) {
		page_opts->def_col_list = 1;
Danny Auble's avatar
Danny Auble committed
		page_opts->col_list = list_create(slurm_destroy_char);
		slurm_addto_char_list(page_opts->col_list, initial_opts);
	}

	page_opts->display_data = display_data;
Danny Auble's avatar
Danny Auble committed
	itr = list_iterator_create(page_opts->col_list);
	while ((col_name = list_next(itr))) {
		replus(col_name);
		if (strstr(col_name, "list")) {
			if (cluster_flags & CLUSTER_FLAG_BG)
				xstrsubstitute(col_name, "node", "bp");
			else
				xstrsubstitute(col_name, "bp", "node");
		}

Danny Auble's avatar
Danny Auble committed
		while (display_data++) {
			if (display_data->id == -1)
				break;
			if (!display_data->name)
				continue;
			if (!strcasecmp(col_name, display_data->name)) {
				display_data->show = TRUE;
				break;
			}
		}
		display_data = page_opts->display_data;
Danny Auble's avatar
Danny Auble committed
	list_iterator_destroy(itr);
extern void make_options_menu(GtkTreeView *tree_view, GtkTreePath *path,
			      GtkMenu *menu, display_data_t *display_data)
{
	GtkWidget *menuitem = NULL;
	treedata_t *treedata = xmalloc(sizeof(treedata_t));
	treedata->model = gtk_tree_view_get_model(tree_view);
	g_signal_connect(G_OBJECT(menu), "button-press-event",
			 G_CALLBACK(_menu_button_pressed),
			 NULL);
	g_signal_connect(G_OBJECT(menu), "button-release-event",
			 G_CALLBACK(_menu_button_released),
			 NULL);

	if (!gtk_tree_model_get_iter(treedata->model, &treedata->iter, path)) {
Danny Auble's avatar
Danny Auble committed
		g_error("make menus error getting iter from model\n");
	global_row_count = gtk_tree_selection_count_selected_rows(