]> granicus.if.org Git - graphviz/commitdiff
Add smyrna to main graphviz tree
authorellson <devnull@localhost>
Wed, 23 Jan 2008 20:52:43 +0000 (20:52 +0000)
committerellson <devnull@localhost>
Wed, 23 Jan 2008 20:52:43 +0000 (20:52 +0000)
cmd/smyrna/tvnodes.c [new file with mode: 0755]
cmd/smyrna/tvnodes.h [new file with mode: 0755]
cmd/smyrna/viewport.c [new file with mode: 0755]
cmd/smyrna/viewport.h [new file with mode: 0755]

diff --git a/cmd/smyrna/tvnodes.c b/cmd/smyrna/tvnodes.c
new file mode 100755 (executable)
index 0000000..66a88c2
--- /dev/null
@@ -0,0 +1,679 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+#include "topview.h"
+#include "tvnodes.h"
+#include "btree.h"
+tv_nodes TV_Nodes;
+static char buf [255];
+int MP_Flag=0;
+tv_filter* create_tv_filter()
+{
+       tv_filter* f;
+       f=(tv_filter*)malloc(sizeof(tv_filter));
+       clear_tv_filter(f);
+       return f;
+}
+void init_tv_nodes(tv_nodes* TV_Nodes)
+{
+       int i;
+       TV_Nodes->filtered=0;
+       TV_Nodes->activepage=-1;
+       TV_Nodes->firstnodeid=0;
+       TV_Nodes->pagecount=0;
+       TV_Nodes->recordperpage=22;
+       TV_Nodes->page_data_index=0;
+       TV_Nodes->Y_Gap=25;
+       TV_Nodes->Y=12;
+       TV_Nodes->initial_Y=12;
+       TV_Nodes->chkSelected_X=5;
+       TV_Nodes->IDLabel_X=10;
+       TV_Nodes->chkVisible_X=55;
+       TV_Nodes->chkHighlighted_X=85;
+       TV_Nodes->Data1_X=105;
+       TV_Nodes->Data2_X=305;
+       TV_Nodes->page_data_node_index=0;
+       reset_page_History();
+
+       //null gui elemetns
+       for (i=0;i < MAX_NODE_PER_PAGE ;i ++)
+       {
+               TV_Nodes->TV_Node[i].chkHighlighted=NULL;
+               TV_Nodes->TV_Node[i].chkSelected=NULL;
+               TV_Nodes->TV_Node[i].chkVisible=NULL;
+               TV_Nodes->TV_Node[i].Data1=NULL;
+               TV_Nodes->TV_Node[i].Data2=NULL;
+               TV_Nodes->TV_Node[i].IDLabel=NULL;
+       }
+       TV_Nodes->initialized=1;
+}
+
+void clear_tv_filter(tv_filter* TV_Filter)
+{
+       TV_Filter->highlighted=-1;
+       TV_Filter->visible=-1;
+       TV_Filter->min_data1=NULL;
+       TV_Filter->max_data1=NULL;
+       TV_Filter->min_data2=NULL;
+       TV_Filter->max_data2=NULL;
+       
+       TV_Nodes.filtered=0;
+
+}
+
+extern int set_filter(tv_filter* TV_Filter,char* MinData1,char* MaxData1,char* MinData2,char* MaxData2,char* Filter_String,int selected,int visible,int highlighted)
+{
+       TV_Filter->selected=selected;
+       TV_Filter->highlighted=highlighted;
+       TV_Filter->visible=visible;
+       TV_Filter->min_data1=MinData1;
+       TV_Filter->max_data1=MaxData1;
+       TV_Filter->min_data2=MinData2;
+       TV_Filter->max_data2=MaxData2;
+       TV_Filter->filter_string=Filter_String;
+       TV_Nodes.filtered=1;
+}
+int reverse_selection()
+{
+       int i=0;
+       for (i; i < Topview.Nodecount ; i ++)
+       {
+               if (((custom_object_data*)AGDATA(Topview.Nodes[i].Node))->Selected )
+                       deselect_node(view.g[view.activeGraph],Topview.Nodes[i].Node);
+               else
+                       select_node(view.g[view.activeGraph],Topview.Nodes[i].Node);
+       }
+       for (i=0; i < Topview.Edgecount ; i ++)
+       {
+               if (((custom_object_data*)AGDATA(Topview.Edges[i].Edge))->Selected )
+                       deselect_edge(view.g[view.activeGraph],Topview.Edges[i].Edge);
+               else
+                       select_edge(view.g[view.activeGraph],Topview.Edges[i].Edge);
+       }
+}
+int validate_node(tv_node* TV_Node)
+{
+       static btree_node* n=0;
+       char* data_attr1;
+       char* data_attr2;
+       char* data1;
+       char* data2;
+//             n=tree_from_filter_string("([IP=\"^10.*\",min=\"0\",max=\"0\"])");
+       // get attributes from graph
+       data_attr1=agget(view.g[view.activeGraph],"DataAttribute1");
+       data_attr2=agget(view.g[view.activeGraph],"DataAttribute2");
+
+
+       if (TV_Nodes.filtered)
+       {
+               int valid=1;
+               if((MP_Flag==1) || (!n))
+               {
+                       n=tree_from_filter_string(TV_Nodes.filter.filter_string);
+                       MP_Flag=0;
+                       if (strcmp(TV_Nodes.filter.min_data1,  agget(Topview.Nodes[TV_Node->index].Node,data_attr1)   ))
+                               valid=0;
+               }
+               if (data_attr1 && TV_Nodes.filter.max_data1 && agget(Topview.Nodes[TV_Node->index].Node,data_attr1))
+               {
+                       if (strcmp(agget(Topview.Nodes[TV_Node->index].Node,data_attr1),TV_Nodes.filter.min_data1))
+                               valid=0;
+               }
+               //string data checks attr2
+               if (data_attr2 && TV_Nodes.filter.min_data2 && agget(Topview.Nodes[TV_Node->index].Node,data_attr2))
+               {
+                       if (strcmp(TV_Nodes.filter.min_data2,  agget(Topview.Nodes[TV_Node->index].Node,data_attr2)   ))
+                               valid=0;
+               }
+               if (data_attr2 && TV_Nodes.filter.max_data2 && agget(Topview.Nodes[TV_Node->index].Node,data_attr2))
+               {
+                       if (agget(Topview.Nodes[TV_Node->index].Node,data_attr2),TV_Nodes.filter.min_data2)
+                               valid=0;
+               }
+               if (strlen(TV_Nodes.filter.filter_string)>0)
+                       valid=evaluate_expresions (TV_Node,n);
+               //if show only highlighted 
+               if (TV_Nodes.filter.highlighted >= 0)   
+               {
+                       if(((custom_object_data*)AGDATA(Topview.Nodes[TV_Node->index].Node))->Highlighted!= TV_Nodes.filter.highlighted)
+                               valid=0;
+               }
+               //if show only visibles
+               if (TV_Nodes.filter.visible >= 0)       
+               {
+                       if(((custom_object_data*)AGDATA(Topview.Nodes[TV_Node->index].Node))->Visible!= TV_Nodes.filter.visible)
+                               valid=0;
+               }
+               //if show only selected
+               if (TV_Nodes.filter.selected >= 0)      
+               {
+                       if(((custom_object_data*)AGDATA(Topview.Nodes[TV_Node->index].Node))->Selected!= TV_Nodes.filter.selected)
+                               valid=0;
+               }
+               return valid;
+       }
+       else
+               return 1;
+}
+
+int update_node_gui_objects(tv_node* TV_Node)
+{
+       char* data_attr1;
+       char* data_attr2;
+       char buf[255];
+       GtkLayout* layout;
+
+       // get attributes from graph
+       data_attr1=agget(view.g[view.activeGraph],"DataAttribute1");
+       data_attr2=agget(view.g[view.activeGraph],"DataAttribute2");
+
+       //create if objects are null    
+       layout=glade_xml_get_widget(xml, "layoutTVData");
+       //select box
+       if (!TV_Node->chkSelected)
+       {
+               TV_Node->chkSelected=gtk_check_button_new();
+               gtk_layout_put  (layout,TV_Node->chkSelected,LOCATION_X_CHKSELECTED,TV_Nodes.Y);
+       }
+       gtk_widget_show(TV_Node->chkSelected);
+       gtk_toggle_button_set_active(TV_Node->chkSelected,((custom_object_data*)AGDATA(Topview.Nodes[TV_Node->index].Node))->Selected);
+
+       //Id Label
+       if (!TV_Node->IDLabel)
+       {
+               TV_Node->IDLabel=gtk_label_new("");
+               gtk_layout_put  (layout,TV_Node->IDLabel,LOCATION_X_IDLABEL,TV_Nodes.Y);
+       }
+       sprintf(buf, "%d", TV_Node->index);
+       gtk_label_set_text (TV_Node->IDLabel,buf);
+       gtk_widget_show(TV_Node->IDLabel);
+
+       //visible
+       if (!TV_Node->chkVisible)
+       {               
+               TV_Node->chkVisible=gtk_check_button_new();
+               gtk_layout_put  (layout,TV_Node->chkVisible,LOCATION_X_CHKVISIBLE,TV_Nodes.Y);
+       }
+
+       gtk_widget_show(TV_Node->chkVisible);
+       gtk_toggle_button_set_active(TV_Node->chkVisible,((custom_object_data*)AGDATA(Topview.Nodes[TV_Node->index].Node))->Visible);
+       //highlighted
+       if (!TV_Node->chkHighlighted)
+       {
+               TV_Node->chkHighlighted=gtk_check_button_new();
+               gtk_layout_put  (layout,TV_Node->chkHighlighted,LOCATION_X_CHKHIGHLIGHTED,TV_Nodes.Y);
+       }
+       gtk_widget_show(TV_Node->chkHighlighted);
+       gtk_toggle_button_set_active(TV_Node->chkHighlighted,((custom_object_data*)AGDATA(Topview.Nodes[TV_Node->index].Node))->Highlighted);
+
+       
+       //DATA 1
+       if (!TV_Node->Data1)
+       {
+               TV_Node->Data1=gtk_entry_new();
+               gtk_layout_put  (layout,TV_Node->Data1,LOCATION_X_DATA1,TV_Nodes.Y);
+               gtk_widget_set_size_request(TV_Node->Data1,300,23);
+
+       }
+       if(data_attr1)
+       {
+               gtk_entry_set_text (TV_Node->Data1,agget(Topview.Nodes[TV_Node->index].Node,data_attr1));
+       }
+       else
+               gtk_entry_set_text (TV_Node->Data1,"");
+       gtk_widget_show(TV_Node->Data1);
+
+       //DATA 2
+       if (!TV_Node->Data2)
+       {
+               TV_Node->Data2=gtk_entry_new();
+               gtk_layout_put  (layout,TV_Node->Data2,LOCATION_X_DATA2,TV_Nodes.Y);
+               gtk_widget_set_size_request(TV_Node->Data2,300,23);
+       }
+       if(data_attr2)
+       {
+               gtk_entry_set_text (TV_Node->Data2,agget(Topview.Nodes[TV_Node->index].Node,data_attr2));
+       }
+       else
+               gtk_entry_set_text (TV_Node->Data2,"");
+       gtk_widget_show(TV_Node->Data2);
+}
+
+
+extern int     tv_nodes_last_page()
+{
+       if (TV_Nodes.activepage<TV_Nodes.pagecount)
+               return tv_nodes_goto_page(TV_Nodes.pagecount);
+       else
+               return 0;
+}
+extern int     tv_nodes_first_page()
+{
+       if (TV_Nodes.activepage>0)
+               return tv_nodes_goto_page(0);
+       else
+               return 0;
+}
+
+extern int tv_nodes_goto_page(int page)
+{
+       GtkSpinButton* spn;
+       tv_node* tvn;
+       GtkLabel* lblTVPage;
+
+       if ((page >=0) && page <= TV_Nodes.pagecount)
+       {
+               if(TV_Nodes.general_purpose_flag==1)
+               {
+                       update_TV_data_from_gui();
+                       TV_Nodes.general_purpose_flag=0;
+               }
+               TV_Nodes.activepage=page;
+               TV_Nodes.page_data_node_index=TV_Nodes.page_history[TV_Nodes.activepage];
+               TV_Nodes.page_data_index=0;
+               TV_Nodes.firstnodeid=TV_Nodes.page_data_node_index;
+               TV_Nodes.Y=TV_Nodes.initial_Y;
+               hide_data_widgets();
+       }
+       else
+               return 0;
+       while ((TV_Nodes.page_data_index < TV_Nodes.recordperpage)&&(TV_Nodes.page_data_node_index < Topview.Nodecount))
+       {
+               tvn=&TV_Nodes.TV_Node[TV_Nodes.page_data_index];
+               tvn->index=TV_Nodes.page_data_node_index;
+               if(Topview.Nodes[TV_Nodes.page_data_node_index].valid==1)
+               {
+                       TV_Nodes.page_data_index++;
+                       update_node_gui_objects(tvn);
+                       TV_Nodes.Y=TV_Nodes.Y+TV_Nodes.Y_Gap;
+               }
+               TV_Nodes.page_data_node_index++;
+       }
+       lblTVPage=glade_xml_get_widget(xml, "lblTVPage");
+       sprintf(buf,"(%i / %i)", TV_Nodes.activepage+1,TV_Nodes.pagecount+1);
+       gtk_label_set_text(lblTVPage,buf);
+       spn=glade_xml_get_widget(xml, "spnTVGotopage");
+       gtk_spin_button_set_value(spn,page+1);
+
+
+
+
+       return 1;
+}
+
+extern int tv_nodes_prior_page()
+{
+       tv_node* tvn;
+       GtkLabel* lblTVPage;
+       if (TV_Nodes.activepage >0)
+       {
+               return tv_nodes_goto_page(TV_Nodes.activepage -1);
+       }
+       else
+               return 0;
+}
+
+
+extern int tv_nodes_next_page()
+{
+       tv_node* tvn;
+       GtkLabel* lblTVPage;
+       if (TV_Nodes.activepage < TV_Nodes.pagecount)
+       {
+               return tv_nodes_goto_page(TV_Nodes.activepage +1);
+       }
+       else
+               return 0;
+}
+extern void execute_tv_nodes()
+{
+
+           gtk_widget_hide(glade_xml_get_widget(xml, "frmTVNodes"));
+               gtk_widget_show(glade_xml_get_widget(xml, "frmTVNodes"));
+//             gtk_window_set_keep_above           (glade_xml_get_widget(xml, "frmTVNodes"),1);
+               if(TV_Nodes.initialized < 1)
+               {
+                       init_tv_nodes(&TV_Nodes);
+               }
+               //test filter
+               prepare_page_history();
+               TV_Nodes.general_purpose_flag=1;
+               tv_nodes_next_page();
+}
+
+
+static int hide_data_widgets()
+{
+       int i;
+       for (i=0;i < MAX_NODE_PER_PAGE ;i ++)
+       {
+               if (TV_Nodes.TV_Node[i].chkHighlighted) 
+               {               
+                       gtk_widget_hide(TV_Nodes.TV_Node[i].chkHighlighted);
+                       gtk_widget_hide(TV_Nodes.TV_Node[i].chkSelected);
+                       gtk_widget_hide(TV_Nodes.TV_Node[i].chkVisible);
+                       gtk_widget_hide(TV_Nodes.TV_Node[i].Data1);
+                       gtk_widget_hide(TV_Nodes.TV_Node[i].Data2);
+                       gtk_widget_hide(TV_Nodes.TV_Node[i].IDLabel);
+               }
+       }
+       
+
+}
+extern int reset_page_History()
+{
+/*     if(TV_Nodes.page_history_count > 0)
+       {
+               free(TV_Nodes.page_history);
+               TV_Nodes.page_history_count=0;
+       }*/
+       TV_Nodes.page_history_count=0;
+       TV_Nodes.page_history=realloc(TV_Nodes.page_history,sizeof(int) * TV_Nodes.page_history_count);
+
+}
+static int push_to_page_history(int index)
+{
+       TV_Nodes.page_history_count++;
+       TV_Nodes.page_history=realloc(TV_Nodes.page_history,sizeof(int) * TV_Nodes.page_history_count);
+       TV_Nodes.page_history[TV_Nodes.page_history_count-1]=index;
+       return 1;
+}
+static int pop_from_page_history()
+{
+       if(TV_Nodes.page_history_count > 0)
+       {
+               int return_value;
+               return_value=TV_Nodes.page_history[TV_Nodes.page_history_count-1];
+               TV_Nodes.page_history_count--;
+               TV_Nodes.page_history=realloc(TV_Nodes.page_history,sizeof(int) * TV_Nodes.page_history_count);
+               return return_value;
+       }
+       return 0;
+}
+
+extern int prepare_page_history()
+{
+       GtkLabel* lblTVPage;
+       GtkSpinButton* spn;
+       int i=0;
+       int count=0;
+       tv_node tvn;
+       TV_Nodes.pagecount=0;
+       TV_Nodes.activepage=-1;
+       reset_page_History();
+       push_to_page_history(0);
+       
+       for (i;i < Topview.Nodecount ; i++)
+       {
+               tvn.index=i;
+               if(validate_node(&tvn))
+               {
+                       count ++;
+                       Topview.Nodes[i].valid=1;
+               }
+               else
+                       Topview.Nodes[i].valid=0;
+               if (count== TV_Nodes.recordperpage)
+               {
+                       push_to_page_history(i+1);
+                       TV_Nodes.pagecount++;
+                       count=0;
+               }
+       }
+       spn=glade_xml_get_widget(xml, "spnTVGotopage");
+       gtk_spin_button_set_value(spn,0);
+       gtk_spin_button_set_range(spn,0,TV_Nodes.pagecount+1);
+
+
+       lblTVPage=glade_xml_get_widget(xml, "lblTVPage");
+       sprintf(buf,"(%i / %i)", 1,TV_Nodes.pagecount+1);
+       gtk_label_set_text(lblTVPage,buf);
+       set_data_attributes();
+}
+static int set_data_attributes()
+{
+       GtkLabel* lblData1;
+       GtkLabel* lblData2;
+       char* data_attr1;
+       char* data_attr2;
+       char buf[255];
+       // get attributes from graph
+       data_attr1=agget(view.g[view.activeGraph],"DataAttribute1");
+       data_attr2=agget(view.g[view.activeGraph],"DataAttribute2");
+       if (!data_attr1)
+       {
+               agattr(view.g[view.activeGraph],AGRAPH,"DataAttribute1","DATA1");
+               agattr(view.g[view.activeGraph],AGNODE,"DATA1","");
+       }
+       if (!data_attr2)
+       {
+               agattr(view.g[view.activeGraph],AGRAPH,"DataAttribute2","DATA2");
+               agattr(view.g[view.activeGraph],AGNODE,"DATA2","");
+       }
+
+       data_attr1=agget(view.g[view.activeGraph],"DataAttribute1");
+       data_attr2=agget(view.g[view.activeGraph],"DataAttribute2");
+
+       lblData1=glade_xml_get_widget(xml, "lblTVData1");
+       lblData2=glade_xml_get_widget(xml, "lblTVData2");
+       gtk_label_set_text (lblData1,data_attr1);
+       gtk_label_set_text (lblData2,data_attr2);
+       return 1;
+
+}
+
+extern int update_TV_data_from_gui()
+{
+       int i=0;
+       int index=0;
+       char* data_attr1;
+       char* data_attr2;
+       // get attributes from graph
+       data_attr1=agget(view.g[view.activeGraph],"DataAttribute1");
+       data_attr2=agget(view.g[view.activeGraph],"DataAttribute2");
+
+       for (i;i < TV_Nodes.recordperpage ; i++)
+       {
+               index=TV_Nodes.TV_Node[i].index;
+               if (index < Topview.Nodecount)
+               {
+                       // apply if selected
+                       if(gtk_toggle_button_get_active(TV_Nodes.TV_Node[i].chkSelected))
+                       {
+                               if (!((custom_object_data*)AGDATA(Topview.Nodes[index].Node))->Selected)
+                                       select_node(view.g[view.activeGraph],Topview.Nodes[index].Node);                                        
+                       }
+                       else
+                       {
+                               if (((custom_object_data*)AGDATA(Topview.Nodes[index].Node))->Selected)
+                                       deselect_node(view.g[view.activeGraph],Topview.Nodes[index].Node);                                      
+                       }
+                       // apply if Visible
+                       if(gtk_toggle_button_get_active(TV_Nodes.TV_Node[i].chkVisible))
+                       {
+                               if (!((custom_object_data*)AGDATA(Topview.Nodes[index].Node))->Visible)
+                                       ((custom_object_data*)AGDATA(Topview.Nodes[index].Node))->Visible=1;
+                       }
+                       else
+                       {
+                               if (((custom_object_data*)AGDATA(Topview.Nodes[index].Node))->Visible)
+                                       ((custom_object_data*)AGDATA(Topview.Nodes[index].Node))->Visible=0;
+                       }
+                       // apply if Highlighted
+                       if(gtk_toggle_button_get_active(TV_Nodes.TV_Node[i].chkHighlighted))
+                       {
+                               if (!((custom_object_data*)AGDATA(Topview.Nodes[index].Node))->Highlighted)
+                                       ((custom_object_data*)AGDATA(Topview.Nodes[index].Node))->Highlighted=1;
+                       }
+                       else
+                       {
+                               if (((custom_object_data*)AGDATA(Topview.Nodes[index].Node))->Highlighted)
+                                       ((custom_object_data*)AGDATA(Topview.Nodes[index].Node))->Highlighted=0;
+                       }
+                       //Data1 
+                       agset(Topview.Nodes[index].Node,data_attr1,gtk_entry_get_text (TV_Nodes.TV_Node[i].Data1));
+                       //Data2 
+                       agset(Topview.Nodes[index].Node,data_attr2,gtk_entry_get_text (TV_Nodes.TV_Node[i].Data2));
+
+               }
+       }
+
+}
+
+extern int apply_filter_from_gui()
+{
+       int selected;
+       int visible;
+       int highlighted;
+
+       if(gtk_toggle_button_get_active(glade_xml_get_widget(xml,"rbTVFilterSel1")))    
+                       selected=-1;
+               if(gtk_toggle_button_get_active(glade_xml_get_widget(xml,"rbTVFilterSel2")))    
+                       selected=1;
+               if(gtk_toggle_button_get_active(glade_xml_get_widget(xml,"rbTVFilterSel3")))    
+                       selected=0;
+
+               if(gtk_toggle_button_get_active(glade_xml_get_widget(xml,"rbTVFilterVisible1")))        
+                       visible=-1;
+               if(gtk_toggle_button_get_active(glade_xml_get_widget(xml,"rbTVFilterVisible2")))        
+                       visible=1;
+               if(gtk_toggle_button_get_active(glade_xml_get_widget(xml,"rbTVFilterVisible3")))        
+                       visible=0;
+
+               if(gtk_toggle_button_get_active(glade_xml_get_widget(xml,"rbTVFilterHigh1")))   
+                       highlighted=-1;
+               if(gtk_toggle_button_get_active(glade_xml_get_widget(xml,"rbTVFilterHigh2")))   
+                       highlighted=1;
+               if(gtk_toggle_button_get_active(glade_xml_get_widget(xml,"rbTVFilterHigh3")))   
+                       highlighted=0;
+               set_filter(&TV_Nodes.filter,
+               gtk_entry_get_text ( glade_xml_get_widget(xml,"edtTVFilterMinData1") ),
+               gtk_entry_get_text ( glade_xml_get_widget(xml,"edtTVFilterMaxData1") ),
+               gtk_entry_get_text ( glade_xml_get_widget(xml,"edtTVFilterMinData2") ),
+               gtk_entry_get_text ( glade_xml_get_widget(xml,"edtTVFilterMaxData2") ),
+               gtk_entry_get_text ( glade_xml_get_widget(xml,"edtTVFilterString") ),
+                       selected,visible,highlighted);
+               MP_Flag=1;
+               prepare_page_history();
+               tv_nodes_next_page();
+               return 1;
+}
+
+
+extern int tv_select_all()
+{
+
+       tv_node tvn;
+       int i=0;
+       for (i;i < Topview.Nodecount ; i++)
+       {
+               tvn.index=i;
+               if(validate_node(&tvn))
+               {
+                       select_node(view.g[view.activeGraph],Topview.Nodes[i].Node);
+               }
+       }
+       apply_filter_from_gui();
+}
+extern int tv_unselect_all()
+{
+
+       tv_node tvn;
+       int i=0;
+       for (i;i < Topview.Nodecount ; i++)
+       {
+               tvn.index=i;
+               if(validate_node(&tvn))
+               {
+                       deselect_node(view.g[view.activeGraph],Topview.Nodes[i].Node);
+               }
+       }
+       apply_filter_from_gui();
+}
+extern int tv_highligh_all()
+{
+       tv_node tvn;
+       int i=0;
+       for (i;i < Topview.Nodecount ; i++)
+       {
+               tvn.index=i;
+               if(validate_node(&tvn))
+               {
+                       ((custom_object_data*)AGDATA(Topview.Nodes[i].Node))->Highlighted=1;
+               }
+       }
+       apply_filter_from_gui();
+       return 1;
+
+
+}
+extern int tv_unhighligh_all()
+{
+       tv_node tvn;
+       int i=0;
+       for (i;i < Topview.Nodecount ; i++)
+       {
+               tvn.index=i;
+               if(validate_node(&tvn))
+               {
+                       ((custom_object_data*)AGDATA(Topview.Nodes[i].Node))->Highlighted=0;
+               }
+       }
+       apply_filter_from_gui();
+       return 1;
+
+}
+extern int tv_show_all()
+{
+       tv_node tvn;
+       int i=0;
+       for (i;i < Topview.Nodecount ; i++)
+       {
+               tvn.index=i;
+               if(validate_node(&tvn))
+               {
+                       ((custom_object_data*)AGDATA(Topview.Nodes[i].Node))->Visible=1;
+               }
+       }
+       apply_filter_from_gui();
+       return 1;
+
+
+
+}
+extern int tv_hide_all()
+{
+       tv_node tvn;
+       int i=0;
+       for (i;i < Topview.Nodecount ; i++)
+       {
+               tvn.index=i;
+               if(validate_node(&tvn))
+               {
+                       ((custom_object_data*)AGDATA(Topview.Nodes[i].Node))->Visible=0;
+               }
+       }
+       apply_filter_from_gui();
+       return 1;
+
+
+}
+
+
+
+
+
+
diff --git a/cmd/smyrna/tvnodes.h b/cmd/smyrna/tvnodes.h
new file mode 100755 (executable)
index 0000000..7120594
--- /dev/null
@@ -0,0 +1,142 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+#ifndef TVNODES_H
+#define TVNODES_H
+
+#include "gui.h"
+
+#define MAX_NODE_PER_PAGE 100
+#define LOCATION_X_CHKSELECTED 16
+#define LOCATION_X_IDLABEL 45
+#define LOCATION_X_CHKVISIBLE 139
+#define LOCATION_X_CHKHIGHLIGHTED 202
+#define LOCATION_X_DATA1 276
+#define LOCATION_X_DATA2 600
+
+typedef struct token_info
+{
+        int op_index;   // has to 
+        int op1_length;
+        int op2_length;
+
+}token_info;
+
+typedef struct btree_node
+{
+        int child_count;
+        struct btree_node** childs;
+        struct btree_node* parent;
+        int rank;       //0 root
+        char op;// & | + - whatever
+        int node_type;  //0 and 1 or 2 atom
+        char* attr_name;
+        char* regex;
+        float min;
+        float max;
+        int value; //filter result true false, 0 , 1
+        int active;
+}btree_node;
+
+typedef struct _tv_filter
+{
+       btree_node* root;
+       char * min_data1;
+       char * min_data2;
+       char * max_data1;
+       char * max_data2;
+       char* filter_string;
+       int active;
+       int visible;    //-1 all 0 not not visible 1 only visibles
+       int highlighted;        //same above
+       int selected;   //same above
+}tv_filter;
+
+typedef struct _tv_node
+{
+       int index;
+       GtkCheckButton* chkSelected;
+       GtkCheckButton* chkVisible;
+       GtkCheckButton* chkHighlighted;
+       GtkLabel* IDLabel;
+       GtkEntry* Data1;
+       GtkEntry* Data2;
+       int valid;
+}tv_node;
+
+
+typedef struct _tv_nodes
+{
+       int pagecount;
+       int activepage;
+       int firstnodeid;
+       int* page_history;
+       int page_history_count;
+       int recordperpage;      //dynamic so that can be changed by plugins etc 
+       int filtered ;
+       int page_data_index;
+       int page_data_node_index;
+       tv_node TV_Node[MAX_NODE_PER_PAGE];
+       tv_filter filter;
+       int Y;
+       int Y_Gap;
+       int initial_Y;
+       int chkSelected_X;
+       int IDLabel_X;
+       int chkVisible_X;
+       int chkHighlighted_X;
+       int Data1_X;
+       int Data2_X;
+       int initialized;
+       int general_purpose_flag;               //dont forget to to set it back
+}tv_nodes;
+extern tv_nodes TV_Nodes;
+
+
+
+extern void execute_tv_nodes();
+static void init_tv_nodes(tv_nodes* TV_Nodes);
+static tv_filter* create_tv_filter();
+static void clear_tv_filter(tv_filter* TV_Filter);
+extern int set_filter(tv_filter* TV_Filter,char* MinData1,char* MaxData1,char* MinData2,char* MaxData2,char* Filter_String,int selected,int visible,int highlighted);
+static int reverse_selection();
+static int validate_node(tv_node* TV_Node);
+static int update_node_gui_objects(tv_node* TV_Node);
+extern int tv_nodes_goto_page(int page);
+extern int tv_nodes_next_page();
+extern int tv_nodes_prior_page();
+extern int     tv_nodes_last_page();
+extern int     tv_nodes_first_page();
+
+static int hide_data_widgets();
+extern int reset_page_History();
+static int push_to_page_history(int index);
+static int pop_from_page_history();
+extern int prepare_page_history();
+extern int update_TV_data_from_gui();
+static int set_data_attributes();
+extern int apply_filter_from_gui();
+extern int tv_select_all();
+extern int tv_unselect_all();
+extern int tv_highligh_all();
+extern int tv_unhighligh_all();
+extern int tv_show_all();
+extern int tv_hide_all();
+
+
+#endif
+
+
diff --git a/cmd/smyrna/viewport.c b/cmd/smyrna/viewport.c
new file mode 100755 (executable)
index 0000000..9dac28b
--- /dev/null
@@ -0,0 +1,867 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include "compat.h"
+#include "viewport.h"
+#include "color.h"
+#include <glade/glade.h>
+#include "gui.h"
+#include "string.h"
+
+#define countof( array ) ( sizeof( array )/sizeof( array[0] ) )
+
+char* globalString;
+ViewInfo       view;
+Agraph_t* tempG;       //helper graph for default attr values,
+int SignalBlock;
+
+float TopViewPointsX [50000];
+float TopViewPointsY [50000];
+
+float TopViewEdgesHeadX[50000];
+float TopViewEdgesHeadY[50000];
+float TopViewEdgesTailX[50000];
+float TopViewEdgesTailY[50000];
+
+int    TopViewNodeCount;
+int    TopViewEdgeCount;
+GtkMessageDialog*  Dlg;
+int respond;
+
+void init_viewport(ViewInfo* view)
+{
+
+       //init graphs
+       view->g=NULL;           //no graph, gl screen should check it
+       view->graphCount=0;     //and disable interactivity if count is zero
+
+
+       view->bdxLeft=0;
+       view->bdxRight=500;
+       view->bdyBottom=0;
+       view->bdyTop=500;
+       view->bdzBottom=0;
+       view->bdzTop=0;
+
+       view->bdA=1;
+       view->bdR=1;
+       view->bdG=0;
+       view->bdB=0;
+       view->bdVisible=0;              //show borders red
+       
+       view->gridSize=10;
+       view->grR=0.5;  
+       view->grG=0.5;  
+       view->grB=0.5;  
+       view->grA=1;
+       view->gridVisible=0;    //show grids in light gray
+
+       //mouse mode=pan
+       view->mouse.mouse_mode=0;
+       //pen color
+       view->penColor.R=0;
+       view->penColor.G=0;
+       view->penColor.B=0;
+       view->penColor.A=1;
+
+       view->fillColor.R=1;
+       view->fillColor.G=0;
+       view->fillColor.B=0;
+       view->fillColor.A=1;
+       //background color , default white
+       view->bgColor.R=1;
+       view->bgColor.G=1;
+       view->bgColor.B=1;
+       view->bgColor.A=1;
+
+       //selected objets are drawn with this color
+       view->selectColor.R=1;
+       view->selectColor.G=0;
+       view->selectColor.B=0;
+       view->selectColor.A=1;
+
+       //default line width;
+       view->LineWidth=1;
+
+       //default view settings , camera is not active
+       view->GLDepth=1;        //should be set before GetFixedOGLPos(int x, int y,float kts) funtion is used!!!!
+       view->panx=0;
+       view->pany=0;
+       view->panz=0;
+
+       view->prevpanx=0;
+       view->prevpany=0;
+
+
+       view->zoom=-20;
+       view->texture=1;
+       view->font_textures=NULL;
+       view->font_texture_count=0;     //number of openGL textures, used internally
+       view->FontSize=52;
+               
+       view->mg.active=0;
+       view->mg.x=0;
+       view->mg.y=0;
+       view->mg.width=DEFAULT_MAGNIFIER_WIDTH;
+       view->mg.height=DEFAULT_MAGNIFIER_HEIGHT;
+       view->mg.kts=DEFAULT_MAGNIFIER_KTS;
+       view->fmg.R=DEFAULT_FISHEYE_MAGNIFIER_RADIUS;
+       view->fmg.active=0;
+       view->mouse.mouse_down=0;
+       view->activeGraph=-1;
+       SignalBlock=0;
+       view->Selection.Active=0;
+       view->Selection.SelectionColor.R=0.5;
+       view->Selection.SelectionColor.G=0.2;
+       view->Selection.SelectionColor.B=1;
+       view->Selection.SelectionColor.A=1;
+       view->Selection.Anti=0;
+}
+
+int add_graph_to_viewport_from_file (char* fileName)
+{
+       //returns 1 if successfull else 0
+       Agraph_t* graph;
+       graph=loadGraph(fileName);
+       if(graph)
+       {
+               view.graphCount = view.graphCount + 1; 
+               view.g= (Agraph_t**)realloc(view.g,sizeof(Agraph_t*)*view.graphCount);
+               view.g[view.graphCount-1]=graph;
+               view.activeGraph=view.graphCount-1;
+               //GUI update , graph combo box on top-right should be updated
+               refreshControls(&view);
+               return 1;
+       }
+       else
+               return 0;
+       
+}
+
+int add_new_graph_to_viewport()
+{
+       //returns graph index , otherwise -1
+       Agraph_t* graph;
+       graph=(Agraph_t*) malloc(sizeof(Agraph_t));
+       if(graph)
+       {
+               view.graphCount = view.graphCount + 1; 
+               view.g[view.graphCount-1]=graph;
+               return (view.graphCount-1);
+       }
+       else
+               return -1;
+}
+
+
+void refreshControls(ViewInfo* v)
+{
+
+       int i=0;
+       GtkComboBox* widget;
+       widget=get_SelectGraph();
+       //load graph names to combobox
+       for (i=0; i < v->graphCount; i ++)
+       {
+               gtk_combo_box_append_text(widget,((custom_graph_data*)(AGDATA(v->g[i])))->GraphFileName);
+       }
+       SignalBlock=1;  //HACK
+       gtk_combo_box_set_active (widget,view.activeGraph);
+       SignalBlock=0;
+
+
+       //change button colors
+       Color_Widget_bg ("gray",glade_xml_get_widget(xml, "btnDot"));   
+       Color_Widget_bg ("gray",glade_xml_get_widget(xml, "btnNeato")); 
+       Color_Widget_bg ("gray",glade_xml_get_widget(xml, "btnTwopi")); 
+       Color_Widget_bg ("gray",glade_xml_get_widget(xml, "btnCirco")); 
+       Color_Widget_bg ("gray",glade_xml_get_widget(xml, "btnFdp"));   
+
+
+       switch( ((custom_graph_data*)(AGDATA(view.g[view.activeGraph])))->Engine )
+       {
+               case 0: 
+                       Color_Widget_bg ("red",glade_xml_get_widget(xml, "btnDot"));    
+                       break;
+
+               case 1: 
+                       Color_Widget_bg ("red",glade_xml_get_widget(xml, "btnNeato"));  
+                       break;
+
+               case 2: 
+                       Color_Widget_bg ("red",glade_xml_get_widget(xml, "btnTwopi"));  
+                       break;
+
+               case 3: 
+                       Color_Widget_bg ("red",glade_xml_get_widget(xml, "btnCirco"));  
+                       break;
+
+               case 4: 
+                       Color_Widget_bg ("red",glade_xml_get_widget(xml, "btnFdp"));    
+                       break;
+
+
+       }
+       expose_event (drawing_area,NULL,NULL);
+
+               
+
+
+
+}
+
+
+void update_graph_params(Agraph_t* graph)      //adds gledit params 
+{
+
+
+       char tempString[100];
+       agattr(graph,AGRAPH,"GraphFileName",((custom_graph_data*)(AGDATA(graph)))->GraphFileName);
+       agattr(graph,AGRAPH,"GraphName",((custom_graph_data*)(AGDATA(graph)))->GraphName);
+       sprintf( tempString, "%i", ((custom_graph_data*)(AGDATA(graph)))->AlwaysShow );
+       agattr(graph,AGRAPH,"AlwaysShow",tempString);
+       sprintf( tempString, "%i", ((custom_graph_data*)(AGDATA(graph)))->TopView);
+               agattr(graph,AGRAPH,"TopView",tempString);
+       sprintf( tempString, "%i", ((custom_graph_data*)(AGDATA(graph)))->Locked);
+               agattr(graph,AGRAPH,"Locked",tempString);
+       sprintf( tempString, "%i", ((custom_graph_data*)(AGDATA(graph)))->Engine);
+               agattr(graph,AGRAPH,"Engine",tempString);
+
+}
+
+void load_graph_params(Agraph_t* graph)        //run once right after loading graph
+{
+               //file may or may have not gl edit attributes
+               //first defaults are set in loading function
+               //here file is checked for previously saved gledit attributes
+       if(agget(graph, "GraphName"))           //Graph Name
+       {       
+               ((custom_graph_data*)AGDATA(graph))->GraphName=(char*)malloc((strlen(agget(graph, "GraphName"))+1)*sizeof(char)); 
+                       strcpy(((custom_graph_data*)AGDATA(graph))->GraphName,agget(graph, "GraphName")); 
+       }
+       if(agget(graph, "AlwaysShow"))          //Graph Name
+               ((custom_graph_data*)AGDATA(graph))->AlwaysShow=atoi(agget(graph, "AlwaysShow"));
+       else
+               ((custom_graph_data*)AGDATA(graph))->AlwaysShow=0;
+
+       if(agget(graph, "TopView"))             //Graph Name
+               ((custom_graph_data*)AGDATA(graph))->TopView=atoi(agget(graph, "TopView"));
+       else
+               ((custom_graph_data*)AGDATA(graph))->TopView=0;
+       if(agget(graph, "Locked"))              //Graph Name
+               ((custom_graph_data*)AGDATA(graph))->Locked=atoi(agget(graph, "Locked"));
+       else
+               ((custom_graph_data*)AGDATA(graph))->Locked=0;
+       if(agget(graph, "Engine"))              //Graph Name
+               ((custom_graph_data*)AGDATA(graph))->Engine=atoi(agget(graph, "Engine"));
+       else
+               ((custom_graph_data*)AGDATA(graph))->Engine=0;  //DOT
+
+       ((custom_graph_data*)AGDATA(graph))->Modified=0;        //not modified yet
+       ((custom_graph_data*)AGDATA(graph))->selectedEdges='\0';
+       ((custom_graph_data*)AGDATA(graph))->selectedNodes='\0';
+       ((custom_graph_data*)AGDATA(graph))->selectedGraphs='\0';
+
+       ((custom_graph_data*)AGDATA(graph))->selectedNodesCount=0;
+       ((custom_graph_data*)AGDATA(graph))->selectedEdgesCount=0;
+       ((custom_graph_data*)AGDATA(graph))->selectedGraphsCount=0;
+
+       
+       
+/*             if(agget((void*)g, "xdotversion"))      //xdot exists
+                       ((custom_graph_data*)AGDATA(g))->TopView=0; //need to check xdot version attribute
+               else            //we dont know if it is topview or simply a graph with no xdot, for testing i ll use topview
+                       ((custom_graph_data*)AGDATA(g))->TopView=1;  */
+
+
+
+
+
+}
+
+int save_graph()       //save without prompt
+{
+       //check if there is an active graph
+       if(view.activeGraph > -1)
+       {
+               //check if active graph has a file name
+               if (((custom_graph_data*)AGDATA(view.g[view.activeGraph]))->GraphFileName)
+               {
+                       return save_graph_with_file_name(view.g[view.activeGraph],((custom_graph_data*)AGDATA(view.g[view.activeGraph]))->GraphFileName);
+               }
+               else
+                       return save_as_graph();
+       }
+
+}
+int save_as_graph() //save with prompt
+{
+       //check if there is an active graph
+       if(view.activeGraph > -1)
+       {
+               GtkWidget *dialog;
+               dialog = gtk_file_chooser_dialog_new ("Save File",
+                                     NULL,
+                                     GTK_FILE_CHOOSER_ACTION_SAVE,
+                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                     GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                     NULL);
+               gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+               if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+               {
+                       char *filename;
+                       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+                       save_graph_with_file_name(view.g[view.activeGraph],filename);
+                       g_free (filename);
+                       gtk_widget_destroy (dialog);
+
+                       return 1;
+               }
+               else
+               {
+                       gtk_widget_destroy (dialog);
+                       return 0;
+               }
+       }
+}
+int save_graph_with_file_name(Agraph_t* graph,char* fileName)  //saves graph with file name,if file name is NULL save as is ++
+{
+       //if file name is NULL save to graph's filename
+       //else use file name, this implements save as..
+       FILE* output_file;
+       update_graph_params(graph);
+       if(fileName)    
+               output_file = fopen(fileName, "w");
+       else
+       {
+               if  ( ((custom_graph_data*)(AGDATA(graph)))->GraphFileName )
+                       output_file = fopen(((custom_graph_data*)(AGDATA(graph)))->GraphFileName, "w");
+               else
+               {
+                       g_print("there is no file name to save! Programmer error\n");
+                       return 0;
+               }
+       }
+       if (output_file  == NULL)
+       {
+               g_print("Cannot create file \n");
+               return 0;
+       }
+       else if (agwrite(graph,(void*) output_file))
+       {
+               g_print("%s sucessfully saved \n", fileName);
+                       return 1;
+       }
+}
+
+int create_xdot_for_graph(Agraph_t* graph,int keeppos)
+{
+       //0 failed , 1 successfull
+       //save graph to __temp.dot
+       //run dot/neato whatever to create the xdot version __temp.xdot
+       //delete temp files
+       //use this function to do layouts too   
+       int r=0;
+       FILE* output_file;
+       update_graph_params(graph);
+#ifdef _WIN3
+       if(output_file = fopen("c:/__tempfile.dot", "w"))
+#else
+       if(output_file = fopen("/tmp/__tempfile.dot", "w"))
+#endif
+       {
+               clear_graph_xdot(graph);
+               agwrite(graph,(void*) output_file);             //save graph
+               fclose(output_file);//close file desc
+
+               if(keeppos==0)
+               {
+#ifdef _WIN32
+                       if ( ((custom_graph_data*)AGDATA(graph))->Engine == 0)
+                               system("\"C:/Program Files/Graphviz2.15/bin/dot.exe\" -Txdot -Kdot c:/__tempfile.dot -oc:/__tempfile.xdot");
+                       if ( ((custom_graph_data*)AGDATA(graph))->Engine == 1)
+                               system("\"C:/Program Files/Graphviz2.15/bin/dot.exe\" -Txdot -Kneato c:/__tempfile.dot -oc:/__tempfile.xdot");
+                       if ( ((custom_graph_data*)AGDATA(graph))->Engine == 2)
+                               system("\"C:/Program Files/Graphviz2.15/bin/dot.exe\" -Txdot -Ktwopi c:/__tempfile.dot -oc:/__tempfile.xdot");
+                       if ( ((custom_graph_data*)AGDATA(graph))->Engine == 3)
+                               system("\"C:/Program Files/Graphviz2.15/bin/dot.exe\" -Txdot -Kcirco c:/__tempfile.dot -oc:/__tempfile.xdot");
+                       if ( ((custom_graph_data*)AGDATA(graph))->Engine == 4)
+                               system("\"C:/Program Files/Graphviz2.15/bin/dot.exe\" -Txdot -Kfdp c:/__tempfile.dot -oc:/__tempfile.xdot");
+#else
+                       if ( ((custom_graph_data*)AGDATA(graph))->Engine == 0)
+                               system("\"dot\" -Txdot -Kdot /tmp/__tempfile.dot -o/tmp/__tempfile.xdot");
+                       if ( ((custom_graph_data*)AGDATA(graph))->Engine == 1)
+                               system("\"dot\" -Txdot -Kneato /tmp/__tempfile.dot -o/tmp/__tempfile.xdot");
+                       if ( ((custom_graph_data*)AGDATA(graph))->Engine == 2)
+                               system("\"dot\" -Txdot -Ktwopi /tmp/__tempfile.dot -o/tmp/__tempfile.xdot");
+                       if ( ((custom_graph_data*)AGDATA(graph))->Engine == 3)
+                               system("\"dot\" -Txdot -Kcirco /tmp/__tempfile.dot -o/tmp/__tempfile.xdot");
+                       if ( ((custom_graph_data*)AGDATA(graph))->Engine == 4)
+                               system("\"dot\" -Txdot -Kfdp /tmp/__tempfile.dot -o/tmp/__tempfile.xdot");
+#endif
+               }
+
+               //no position change
+               else
+#ifdef _WIN32
+                               system("\"C:/Program Files/Graphviz2.15/bin/neato.exe\" -n2 -Txdot  c:/__tempfile.dot -oc:/__tempfile.xdot");
+#else
+                               system("\"neato\" -n2 -Txdot  /tmp/__tempfile.dot -o/tmp/__tempfile.xdot");
+#endif
+                       
+               if(r)           //load the new graph and change file name
+               {
+                       clear_graph(graph);     //i am not sure about this, need to talk to North
+                       return TRUE;    
+
+               }
+       }
+       else
+               return FALSE;
+
+}
+int do_graph_layout(Agraph_t* graph,int Engine,int keeppos) //changes the layout, all user relocations are reset unless keeppos is set to 1
+{
+/*     Agnode_t *v;
+       Agedge_t *e;
+       Agsym_t *attr;
+       Dict_t *d;
+       int cnt;*/
+//     mydata *p;
+       FILE* input_file;
+       char* _filename=(char*)malloc((strlen(((custom_graph_data*)(AGDATA(view.g[view.activeGraph])))->GraphFileName)+1)*sizeof(char));
+               strcpy(_filename,((custom_graph_data*)AGDATA(view.g[view.activeGraph]))->GraphFileName); 
+
+       
+       ((custom_graph_data*)AGDATA(view.g[view.activeGraph]))->Engine=Engine;
+               create_xdot_for_graph(view.g[view.activeGraph],keeppos);
+
+#ifdef _WIN32
+       input_file = fopen("c:/__tempfile.xdot", "r");
+#else
+       input_file = fopen("/tmp/__tempfile.xdot", "r");
+#endif
+       clear_graph(view.g[view.activeGraph]);
+       agclose(view.g[view.activeGraph]);
+       if (input_file  == NULL)
+               g_print("temp file Cannot open n");
+       else if (view.g[view.activeGraph]= agread(input_file,NIL(Agdisc_t*)))
+       {
+               fclose(input_file);
+               //attaching rec for graph fields
+               attach_object_custom_data_to_graph(view.g[view.activeGraph]);
+               //set real file name
+               ((custom_graph_data*)AGDATA(view.g[view.activeGraph]))->GraphFileName=(char*)malloc((strlen(_filename)+1)*sizeof(char)); 
+               load_graph_params(view.g[view.activeGraph]);    //init glparams
+               strcpy(((custom_graph_data*)AGDATA(view.g[view.activeGraph]))->GraphFileName,_filename); 
+               free(_filename);
+               //set engine
+               ((custom_graph_data*)AGDATA(view.g[view.activeGraph]))->Engine=Engine;
+               ((custom_graph_data*)AGDATA(view.g[view.activeGraph]))->Modified=1;
+               refreshControls(&view);
+               return 1;
+       }
+       else
+       {
+               printf("failed to read temp filen");
+               return 0;
+       }
+
+       
+
+
+}
+
+void clear_graph(Agraph_t* graph)
+//clears custom data binded
+{
+       
+
+}
+
+Agraph_t* loadGraph(char* filename)
+{
+       Agraph_t *g;
+       Agnode_t *v;
+       Agedge_t *e;
+       Agsym_t *attr;
+       Dict_t *d;
+       int cnt;
+//     mydata *p;
+       FILE* input_file;
+       input_file = fopen(filename, "r");
+       if (input_file  == NULL)
+               g_print("Cannot open %s\n", filename);
+       else if (g = agread(input_file,NIL(Agdisc_t*)))
+       {
+               printf("%s has been loaded sucessfully\n",filename);
+               printf("Graph statistics\n");
+               printf("----------------\n");
+               printf("# of edges %i\n",agnnodes(g));
+               printf("# of nodes %i\n",agnedges(g));
+               printf("checking xdot data\n");
+               printf("binding graph record\n");
+               attach_object_custom_data_to_graph(g);
+               load_graph_params(g);
+
+               if ( 
+                       ( !agget(g, "xdotversion"))
+                                &&  
+                       ( 
+                               ( agget(g, "TopView")=="0")
+                               || 
+                               !agget(g, "TopView")
+                               ) 
+                       
+                       )
+               
+               {
+               create_xdot_for_graph(g,0);
+               fclose(input_file);
+#ifdef _WIN32
+               input_file = fopen("c:/__tempfile.xdot", "r");
+#else
+               input_file = fopen("/tmp/__tempfile.xdot", "r");
+#endif
+               while(input_file== NULL)        //HACK!!!!
+               {
+                       input_file = fopen("c:/__tempfile.xdot", "r");
+//                     g_print("Cannot open xdot  error %si\n",strerror(errno));
+                               
+               }
+               g = agread(input_file,NIL(Agdisc_t*));
+               g_print("xdot is being loaded\n");
+               //attaching rec for graph fields
+               attach_object_custom_data_to_graph(g);
+               load_graph_params(g);
+               //      fclose(input_file);
+               }
+               ((custom_graph_data*)AGDATA(g))->GraphFileName=(char*)malloc((strlen(filename)+1)*sizeof(char)); 
+               //attaching rec for graph objects
+               strcpy(((custom_graph_data*)AGDATA(g))->GraphFileName,filename); 
+               printf("topview:%s------",agget(g, "TopView"));
+               if(strcasecmp(agget(g, "TopView"),"1")==0)
+               {
+                       if(TopViewNodeCount > 0)
+                       {
+                               Dlg=gtk_message_dialog_new (NULL,
+                                                                       GTK_DIALOG_MODAL,
+                                         GTK_MESSAGE_WARNING,
+                                                                       GTK_BUTTONS_OK,
+                                                                       "For Performance issues , this program does not support multiple topview graphs!");
+                               respond=gtk_dialog_run (Dlg);
+                               gtk_object_destroy (Dlg);
+                               agclose(g);
+                               return 0;
+                       }
+                       else
+                       {
+                               PrepareTopview(g);
+                       }
+               }
+               return g;
+       }
+       else
+       {
+               printf("failed to load %s\n",filename);
+               return 0;
+       }
+
+}
+int clear_object_xdot(void* obj)
+{
+       if (obj)
+       {
+               if(agattrsym(obj,"_draw_"))
+                       agset(obj,"_draw_","");
+               if(agattrsym(obj,"_ldraw_"))
+                       agset(obj,"_ldraw_","");
+               if(agattrsym(obj,"_hdraw_"))
+                       agset(obj,"_hdraw_","");
+               if(agattrsym(obj,"_tdraw_"))
+                       agset(obj,"_tdraw_","");
+               if(agattrsym(obj,"_hldraw_"))
+                       agset(obj,"_hldraw_","");
+               if(agattrsym(obj,"_tldraw_"))
+                       agset(obj,"_tldraw_","");
+               return 1;
+       }
+       return 0;
+}
+
+
+int clear_graph_xdot(Agraph_t* graph)  //clears all xdot  attributes, used especially before layout change
+{
+   Agnode_t *n;
+       Agedge_t *e;
+       Agraph_t *s;
+
+       
+       clear_object_xdot(graph);
+       n = agfstnode(graph);
+       
+       for (s = agfstsubg(graph); s; s = agnxtsubg(s))
+               clear_object_xdot(s);
+
+       for (n = agfstnode(graph); n; n = agnxtnode(graph, n))
+       {
+               clear_object_xdot(n);
+               for (e = agfstout(graph,n) ; e ; e = agnxtout (graph,e))
+               {
+                       clear_object_xdot(e);
+               }
+       }
+       return 1;       
+
+
+}
+
+/*
+
+Object Custom Data Functions
+
+*/
+
+
+int attach_object_custom_data_to_graph(Agraph_t* graph)
+{
+    Agnode_t *n;
+       Agedge_t *e;
+       Agraph_t *s;
+
+       agbindrec(graph,"custom_graph_data",sizeof(custom_graph_data),TRUE);//graph custom data
+       init_object_custom_data(graph,graph);   //attach to graph itself
+
+       n = agfstnode(graph);
+       
+       for (s = agfstsubg(graph); s; s = agnxtsubg(s))
+               init_object_custom_data(graph,s);       //attach to subgraph 
+
+       for (n = agfstnode(graph); n; n = agnxtnode(graph, n))
+       {
+               init_object_custom_data(graph,n);       //attach to node
+               for (e = agfstout(graph,n) ; e ; e = agnxtout (graph,e))
+               {
+                       init_object_custom_data(graph,e);       //attach to edge
+               }
+       }
+       
+
+}
+
+
+int init_object_custom_data(Agraph_t* graph,void* obj)//creates a custom_object_data 
+{
+       agdelrec(graph, "custom_object_data");
+    agbindrec(obj,"custom_object_data",sizeof(custom_object_data),TRUE);
+       ((custom_object_data*)AGDATA(obj))->ID=0;
+       ((custom_object_data*)AGDATA(obj))->ObjName=NULL;
+       ((custom_object_data*)AGDATA(obj))->ObjType=AGTYPE(obj);
+       ((custom_object_data*)AGDATA(obj))->Layer=-1;
+       ((custom_object_data*)AGDATA(obj))->Visible=1;
+       ((custom_object_data*)AGDATA(obj))->Locked=0;
+       ((custom_object_data*)AGDATA(obj))->Highlighted=0;
+       ((custom_object_data*)AGDATA(obj))->NumDataCount=0;
+       ((custom_object_data*)AGDATA(obj))->NumData=NULL;
+       ((custom_object_data*)AGDATA(obj))->StrDataCount=0;
+       ((custom_object_data*)AGDATA(obj))->StrData=NULL; 
+       return 1;
+}
+
+
+int clear_object_custom_data(void* obj) //frees memory allocated for cutom object data
+{
+       return ( (clear_string_data_from_object_custom_data(obj)) || (clear_numeric_data_from_object_custom_data(obj)));
+}
+
+int add_string_data_to_object_custom_data(void* obj,char* data)
+{
+       if ((obj != NULL) && (data !=NULL))
+       {
+                       ((custom_object_data*)AGDATA(obj))->StrData=realloc( ((custom_object_data*)AGDATA(obj))->StrData , sizeof(char*)*(((custom_object_data*)AGDATA(obj))->StrDataCount +1));
+                       ((custom_object_data*)AGDATA(obj))->StrData[((custom_object_data*)AGDATA(obj))->StrDataCount]=malloc((strlen(data)+1) * sizeof(char));
+                       strcpy(((custom_object_data*)AGDATA(obj))->StrData[((custom_object_data*)AGDATA(obj))->StrDataCount],data);
+                       ((custom_object_data*)AGDATA(obj))->StrDataCount++;
+                       return 1;
+       }
+               return 0;
+}
+
+int add_numeric_data_to_object_custom_data(void* obj,float data)
+{
+       if (obj != NULL)
+       {
+               ((custom_object_data*)AGDATA(obj))->NumData=realloc( ((custom_object_data*)AGDATA(obj))->StrData , sizeof(char*)*(((custom_object_data*)AGDATA(obj))->NumDataCount+1));
+               ((custom_object_data*)AGDATA(obj))->NumData[((custom_object_data*)AGDATA(obj))->NumDataCount]=data;
+               ((custom_object_data*)AGDATA(obj))->NumDataCount++;
+                       return 1;
+       }
+               return 0;
+}
+
+int clear_string_data_from_object_custom_data(void* obj)
+{
+       if(obj != NULL)
+       {
+               int ind=0;
+               for (ind=0; ind < ((custom_object_data*)AGDATA(obj))->StrDataCount;ind ++)
+               {
+                       free ( ((custom_object_data*)AGDATA(obj))->StrData[ind]);
+               }
+               free(((custom_object_data*)AGDATA(obj))->StrData);
+               return 1;
+       }
+       return 0;       
+}
+
+int clear_numeric_data_from_object_custom_data(void* obj)
+{
+       if(obj != NULL)
+       {
+               free(((custom_object_data*)AGDATA(obj))->NumData);
+               return 1;
+       }
+       return 0;       
+}
+void move_node(void* obj,float dx,float dy)
+{
+       char buf[512];
+       char buf2[512];
+       char* pch;
+       int a=0;
+       int i=0;
+       if( (agget(obj,"pos")) && ( AGTYPE(obj)==AGNODE ))
+       {
+               //tokenize 
+               strcpy(buf,agget(obj, "pos"));
+               printf ("org pos: %s\n",buf);
+
+               pch=strtok (buf,"," );
+               while (pch != NULL)
+               {
+                       if(i==0)
+                               a=sprintf(buf2+a,"%i,",atoi(pch)-(int)dx);
+                       else
+                               a=sprintf(buf2+a,"%i,",atoi(pch)-(int)dy);
+                       pch=strtok (NULL,"," );
+                       i++;
+               }
+               buf2[strlen(buf2)-1]='\0';
+               printf ("new pos: %s\n",buf2);
+               agset(obj,"pos",buf2);
+       }
+}
+
+void move_nodes(Agraph_t* g)   //move selected nodes 
+{
+       Agnode_t* obj;
+       Agedge_t* e;
+
+       float dx,dy;
+       xdot* bf;
+       int i=0;
+       dx=view.GLx-view.GLx2;
+       dy=view.GLy-view.GLy2;
+
+       if(((custom_graph_data*)AGDATA(view.g[view.activeGraph]))->TopView == 0)
+       {
+               for (i=0;i < ((custom_graph_data*)AGDATA(g))->selectedNodesCount;i++)
+               {       
+                       obj=((custom_graph_data*)AGDATA(g))->selectedNodes[i];
+                       bf=parseXDot (agget(obj,"_draw_"));
+                       agset(obj,"_draw_",move_xdot(obj,bf,(int)dx,(int)dy,0.00));
+                       free(bf);
+                       bf=parseXDot (agget(obj,"_ldraw_"));
+                       agset(obj,"_ldraw_",move_xdot(obj,bf,(int)dx,(int)dy,0.00));
+                       free(bf);
+                       move_node(obj,dx,dy);
+                       //iterate edges
+                       /*for (e = agfstout(g,obj) ; e ; e = agnxtout (g,e))
+                       {
+                               bf=parseXDot (agget(e,"_tdraw_"));
+                               agset(e,"_tdraw_",move_xdot(e,bf,(int)dx,(int)dy,0.00));
+                               free(bf);
+                               bf=parseXDot (agget(e,"_tldraw_"));
+                               agset(e,"_tldraw_",move_xdot(e,bf,(int)dx,(int)dy,0.00));
+                               free(bf);
+                               bf=parseXDot (agget(e,"_draw_"));
+                               agset(e,"_draw_",offset_spline(bf,(int)dx,(int)dy,0.00,0.00,0.00));
+                               free(bf);
+                               bf=parseXDot (agget(e,"_ldraw_"));
+                               agset(e,"_ldraw_",offset_spline(bf,(int)dx,(int)dy,0.00,0.00,0.00));
+                               free (bf);
+                       }*/
+       /*              for (e = agfstin(g,obj) ; e ; e = agnxtin (g,e))
+                       {
+                               free(bf);
+                               bf=parseXDot (agget(e,"_hdraw_"));
+                               agset(e,"_hdraw_",move_xdot(e,bf,(int)dx,(int)dy,0.00));
+                               free(bf);
+                               bf=parseXDot (agget(e,"_hldraw_"));
+                               agset(e,"_hldraw_",move_xdot(e,bf,(int)dx,(int)dy,0.00));
+                               free(bf);
+                               bf=parseXDot (agget(e,"_draw_"));
+                               agset(e,"_draw_",offset_spline(e,bf,(int)dx,(int)dy,0.00,0.00,0.00));
+                               free(bf);
+                               bf=parseXDot (agget(e,"_ldraw_"));
+                               agset(e,"_ldraw_",offset_spline(e,bf,(int)dx,(int)dy,0.00,0.00,0.00));
+                       }*/
+               }
+       }
+}
+
+
+
+
+RGBColor GetRGBColor(char* color)
+{
+       gvcolor_t cl;   
+       RGBColor c;
+       if(color != '\0')
+       {
+               colorxlate(color, &cl, RGBA_DOUBLE);
+               c.R=cl.u.RGBA[0];
+               c.G=cl.u.RGBA[1];
+               c.B=cl.u.RGBA[2];
+               c.A=cl.u.RGBA[3];
+       }
+       else
+       {
+               c.R=view.penColor.R;
+               c.G=view.penColor.G;
+               c.B=view.penColor.B;
+               c.A=view.penColor.A;
+       }
+       return c;
+}
+int SetGdkColor(GdkColor* c,char* color)
+{
+       gvcolor_t cl;   
+       if (color != '\0')
+       {
+               colorxlate(color, &cl, RGBA_DOUBLE);
+               c->red=cl.u.RGBA[0]*65535;
+               c->green=cl.u.RGBA[1]*65535;
+               c->blue=cl.u.RGBA[2]*65535;
+               return 1;
+       }
+       else
+               return 0;
+
+}
diff --git a/cmd/smyrna/viewport.h b/cmd/smyrna/viewport.h
new file mode 100755 (executable)
index 0000000..eebff1b
--- /dev/null
@@ -0,0 +1,273 @@
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+*      This software is part of the graphviz package      *
+*                http://www.graphviz.org/                 *
+*                                                         *
+*            Copyright (c) 1994-2004 AT&T Corp.           *
+*                and is licensed under the                *
+*            Common Public License, Version 1.0           *
+*                      by AT&T Corp.                      *
+*                                                         *
+*        Information and Software Systems Research        *
+*              AT&T Research, Florham Park NJ             *
+**********************************************************/
+
+//view data structure
+#ifndef VIEWPORT_H
+#define VIEWPORT_H
+#define bool int
+#include <glTemplate.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkgl.h>
+#include "xdot.h"
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <pango/pangoft2.h>
+#include "cgraph.h"
+#include "selection.h"
+#include "draw.h"
+#define IS_TEST_MODE_ON                                0
+#define        DEFAULT_MAGNIFIER_WIDTH         300
+#define        DEFAULT_MAGNIFIER_HEIGHT        225
+#define DEFAULT_MAGNIFIER_KTS          10      //x10
+#define DEFAULT_FISHEYE_MAGNIFIER_RADIUS 250;
+//=======
+#define MAX_ZOOM       -1.000033
+#define MIN_ZOOM       -89.00000
+#define ZOOM_STEP      1;
+//>>>>>>> 1.8
+enum
+{
+  COL_NAME = 0,
+  COL_FILENAME,
+  NUM_COLS
+} ;
+//atributes
+typedef struct _mouse_attr
+{
+       int mouse_down;
+       int mouse_mode;
+       int mouse_X;
+       int mouse_Y;
+}mouse_attr;
+
+
+typedef struct _attribute
+{
+       char Type;
+       char* Name;
+       char* Default;
+       char ApplyTo[4];
+       char Engine[5];
+       char** ComboValues;
+       int ComboValuesCount;
+       GtkWidget* attrWidget;
+
+}attribute;
+
+//bind this to cgraph g
+typedef struct _custom_graph_data
+{
+       Agrec_t h;
+       char* GraphName;
+       char* GraphFileName;
+       int AlwaysShow; //active or not draw it 
+       int TopView;    //default 0, 1 for topview data, dots and lines
+       int Locked;
+       int Engine;     //enum GVEngine{DOT,NEATO,TWOPI,CIRCO,FDP};
+       //graph's location, change these to move the whole graph
+       int Modified;   //if graph has been modified after loading
+       GLfloat offsetx;
+       GLfloat offsety;
+       GLfloat offsetz;
+
+       Agraph_t** selectedGraphs;              //clusters , subgraphs indeed
+       Agnode_t** selectedNodes;
+       Agedge_t** selectedEdges;
+
+       int selectedGraphsCount;
+       int selectedNodesCount;
+       int selectedEdgesCount;
+} custom_graph_data;
+
+
+
+enum GEunit{GEpixels,GEinches,GEmm};
+
+typedef struct{
+       float R;
+       float G;
+       float B;
+       float A;        //Alpha
+} RGBColor;
+
+typedef struct _custom_object_data             //has to be attached to every Node, Edge, Graph and cluster
+{
+       Agrec_t h;
+       int ID;
+       char* ObjName;
+       int ObjType;
+       int Layer;
+       int Visible;
+       int Locked;
+       int Highlighted;
+       int Selected;
+       int Preselected;
+       int NumDataCount;
+       float* NumData;
+       int StrDataCount;
+       char** StrData;
+       int selectionflag;
+       int param;              //generic purpose param
+       int TVRef;              //Topview reference
+
+}custom_object_data;
+
+typedef struct _selection
+{
+       int Active;             //0 there is no selection need to be applied
+       char Type;              //0     single selection , 1 rectangle , 2 rectangleX 
+       float X,Y,W,H;  //selection boundries
+       int Anti;       //subtract selections if 1
+       int AlreadySelected; //for single selections to avoid selecting more than one object
+       RGBColor SelectionColor;
+
+}selection;
+typedef struct _magnifier
+{
+       GLfloat x,y;
+       GLfloat kts;    //zoom X
+       GLfloat GLwidth,GLheight;
+       int width,height;       //how big is the magnifier referenced from windows
+       int active;
+} magnifier;
+
+typedef struct _fisheye_magnifier
+{
+       GLfloat x,y;//center coords of active circle
+       GLfloat distortion_factor;      //distortion factor ,default 1
+       int R;  //radius of  the magnifier referenced from windows
+       int active;
+} fisheye_magnifier;
+
+typedef struct _ViewInfo
+{
+       GLfloat panx;
+       GLfloat pany;
+       GLfloat panz;
+       GLfloat prevpanx;
+       GLfloat prevpany;
+       GLfloat prevpanz;
+
+       GLfloat zoom;
+
+       RGBColor bgColor;
+       RGBColor penColor;
+       RGBColor fillColor;
+       RGBColor selectColor;
+
+
+       GLfloat LineWidth;
+       GLfloat grR,grG,grB,grA;        //grid color
+       bool gridVisible;       //if the grid sis visible
+       GLfloat gridSize;       //grid cell size
+
+       bool bdVisible; //if borders are visible (boundries of the drawing,
+       GLuint bdR,bdG,bdB,bdA; //border colors
+       GLfloat bdxLeft,bdyTop,bdzTop;  //border top coordinates
+       GLfloat bdxRight,bdyBottom,bdzBottom; //border bottom coordinates
+
+       //defaults
+       enum GEunit unit;       //default pixels :0  
+       //***mouse variables
+       GLfloat GLx,GLy,GLz;            //real GL coordinates of xwin mouse coords
+       GLfloat GLx2,GLy2,GLz2;         //real GL coordinates(second) of win mouse coords
+       float clipX1,clipX2,clipY1,clipY2,clipZ1,clipZ2;
+       Agraph_t** g;
+       int graphCount;         //number of graphs loaded
+       int activeGraph; //
+
+
+
+       int texture;            //boolean , to disable and enable texturing, if graph does not have an embedded image
+       TextTexture* font_textures;     //text textures
+       int font_texture_count; //count of text  textures uploaded to gl engine
+       float GLDepth;          //opengl depth value to convert mouse to GL coords
+
+       GtkWidget* pango_widget;
+       char* FontName;
+       float FontSize;
+       //selection
+//     int mousedown;  //0 down , 1 up , used for selection boxes
+       mouse_attr mouse;
+       selection Selection;
+       magnifier mg;
+       fisheye_magnifier fmg;
+       //data attributes are read from graph's attributes DataAttribute1 and DataAttribute2
+       char* node_data_attribute1;     //for topview graphs this is the node data attribute to put as label
+       char* node_data_attribute2;     //for topview graphs this is the node data attribute to be stored and used for something else
+
+}ViewInfo;
+
+extern char* globalString;
+extern ViewInfo        view;
+extern Agraph_t* tempG;        //helper graph for default attr values,
+extern int SignalBlock;
+
+extern float TopViewPointsX [50000];
+extern float TopViewPointsY [50000];
+
+extern float TopViewEdgesHeadX[50000];
+extern float TopViewEdgesHeadY[50000];
+extern float TopViewEdgesTailX[50000];
+extern float TopViewEdgesTailY[50000];
+
+extern int     TopViewNodeCount;
+extern int     TopViewEdgeCount;
+extern GtkMessageDialog*  Dlg;
+extern int respond;
+
+//ss
+void init_viewport(ViewInfo* view);
+int add_graph_to_viewport_from_file (char* fileName);  //returns 1 if successfull else 0 ++
+int add_new_graph_to_viewport();       //returns graph index , otherwise -1
+int create_xdot_for_graph(Agraph_t* graph,int keeppos);        //0 failed , 1 successfull ++
+void update_graph_params(Agraph_t* graph);     //adds gledit params  ++
+extern Agraph_t* loadGraph(char* filename); //dont use directly, use add_graph_to_viewport_from_file instead 
+void load_graph_params(Agraph_t* graph);       //run once right after loading graph++
+void clear_graph(Agraph_t* graph);     //clears custom data binded,
+int save_graph();      //save without prompt
+int save_as_graph(); //save with prompt
+int save_graph_with_file_name(Agraph_t* graph,char* fileName); //saves graph with file name,if file name is NULL save as is ++
+
+int do_graph_layout(Agraph_t* graph,int Engine,int keeppos); //changes the layout, all user relocations are reset
+void refreshControls(ViewInfo* v);
+
+
+int attach_object_custom_data_to_graph(Agraph_t* graph);//run once or to reset all data !! prev data is removed
+// int init_object_custom_data(void* obj);//creates a custom_object_data and return its pointer.obj is used to clear prev data
+int clear_object_custom_data(void* obj);       //frees memory allocated for cutom object data
+int add_string_data_to_object_custom_data(void* obj,char* data);
+int add_numeric_data_to_object_custom_data(void* obj,float data);
+int clear_string_data_from_object_custom_data(void* obj);
+int clear_numeric_data_from_object_custom_data(void* obj);
+
+int clear_object_xdot(void* obj);      //clear single object's xdot info
+int clear_graph_xdot(Agraph_t* graph); //clears all xdot  attributes, used especially before layout change
+
+char* get_object_attribute(void* obj,char* attr);      //returns an attribute value no matter what,
+
+void move_node(void* n,float dx,float dy);
+
+
+
+
+void move_nodes(Agraph_t* g);  //move selected nodes 
+//helper functions
+RGBColor GetRGBColor(char* color);
+int SetGdkColor(GdkColor* c,char* color);
+#endif