/**
 *  File ge_set.c
 *   Copyright (c) 2010 P. Vincent.    See GNU GPL ../LICENCE
 *  Replace Grace file setappwin.c
 *   Home page: http://plasma-gate.weizmann.ac.il/Grace/
 *   Copyright (c) 1991-1995 Paul J Turner, Portland, OR
 *   Copyright (c) 1996-2003 Grace Development Team
 */

#define _GE_SET_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*  unistd.h pour la fonction unlink */
#include <unistd.h>

#include <gtk/gtk.h>

#include "globals.h"

#include "graphs.h"
#include "graphutils.h"
#include "utils.h"
#include "files.h"

#include "noxprotos.h"
#include "t1fonts.h"

#include "gw_pannel.h"
#include "gw_choice.h"
#include "gw_list.h"

#include "gg_gutil.h"
#include "gg_gtkinc.h"
#include "gg_protos.h"
#include "gg_events.h"
#include "gg_glyph_choice.h"

#include "ng_objects.h"
#include "wu.h"
#include "zc.h"

#include "ge_tree.h"
#include "ge_protos.h"
#include "gg_icons_xfig.h"

extern void gg_cmd_prt (char *buf);  // provisoire

/* static gint popup_width = 350 ,popup_height = 700 ,list_height = 250; */

extern GdkColor  bleuciel ,wheat;
extern GdkColor  gg_colors[MAXCOLORS];

/* From ge.c */
extern Ge_tree *get_getree (void);


#define cg get_cg()

#define CSYNC_LINE      0
#define CSYNC_SYM       1

/************************************************************/
static int menu_finalized 	= FALSE;
static int block_instant_update = FALSE;

static int cset = 0;            /* the current set from the symbols panel */

/* Follow me variables */
static plotarr pa;

static GtkWidget *titre_item = NULL;

/************************************************************/
/*  Widgets for plotarr struct elements (see graphs.h 101) */
/************************************************************/
static GtkWidget *w_hidden;
static GtkWidget *w_type;
static GtkWidget *w_comments;
static Wu sym;
static Wu symsize;
static Wu sym_color;
static Wu sym_pattern;
static Wu symfill_color;
static Wu symfill_pattern;
static Wu symlines;
static Wu symlinew;
static Wu symskip;
static Wu symstart;
static Wu symchar;
static Wu charfont;
static Wu linet;
static Wu lines;
static Wu linew;
static Wu line_color;
static Wu line_pattern;
static Wu baseline_type;
static Wu baseline;
static Wu filltype;
/* GTK does not work with FILLRULE_EVENODD static GtkWidget *w_fillrule; */
static Wu setfillpen_color;
static Wu setfillpen_pattern;
static Wu avalue_active;
static Wu avalue_type;
static Wu avalue_size;
static Wu avalue_font;
static Wu avalue_color;
static Wu avalue_angle;
static Wu avalue_format;
static Wu avalue_prec;
static Wu avalue_prestr;
static Wu avalue_appstr;
static Wu avalue_offset_x;
static Wu avalue_offset_y;
static Wu avalue_skip;
static Wu avalue_start;
static Wu errbar_active;
static Wu errbar_ptype;
static Wu errbar_pen_color;
static Wu errbar_pen_pattern;
static Wu errbar_linew;
static Wu errbar_lines;
static Wu errbar_riser_linew;
static Wu errbar_riser_lines;
static Wu errbar_barsize;
static Wu errbar_arrow_clip;
static Wu errbar_cliplen;
static Wu meshlen;
static Wu method;
static Wu legend_on;
static Wu dropline;
static Wu xspline_s;
static Wu xspline_p;

/************************************************************/
/*  Widgets for QDobject struct  elements (see defines.h 483) */
static Wu layer;
/*  Vector map arrows */
static Wu vmap_norm;
static Wu vmap_color;
static Wu vmap_linew;
static Wu vmap_lines;
static Wu vmap_a_L;
static Wu vmap_a_type;
static Wu vmap_a_dL_ff;
static Wu vmap_a_lL_ff;
/*  Color map SET_XYCMAP  tab  */
static Wu cmap_nmap;
static Wu contour_hidden;
static Wu contour_line_color;
static Wu contour_linew;
static int nmap = MAX_PREDEF_CMAP-1;
static GtkWidget *contour_frame;

/************************************************************/
/* Notebook */
static GtkWidget *w_notebook;
/* tab Widgets for the notebook */
static GtkWidget *w_tab_main;
static GtkWidget *w_tab_line;
static GtkWidget *w_tab_symbols;
static GtkWidget *w_tab_avalue;
static GtkWidget *w_tab_errbar;
static GtkWidget *w_tab_vmap;
static GtkWidget *w_tab_cmap;

static GtkWidget *vbox    ,*vbox1;
static GtkWidget *duplegs_item;
static GtkWidget *csync_item;

static GtkWidget *symchar_frame;
static GtkWidget *sym1_frame           ,*sym2_frame;
static GtkWidget *spline_frame;

static GtkWidget *warn_linsym;

static GtkWidget *index_item             ,*xyz_item;
static GtkWidget *list_bt ,*edit_bt;
static GtkWidget *w_cmap_place ,*w_cmap_kill;

static GtkWidget *w_blank;

static void ge_set_index_CB  	      (GtkWidget *w ,gpointer p);
static void ge_linet_changed_CB       (GtkWidget *w ,gpointer p);
static void ge_set_list_CB   	      (GtkWidget *w ,gpointer p);
static void ge_set_editor_CB 	      (GtkWidget *w ,gpointer p);
static void ge_method_changed_CB      (GtkWidget *w ,gpointer p);
static void ge_symbol_changed_CB      (GtkWidget *w ,gpointer p);
static void ge_symfont_changed_CB     (GtkWidget *w ,gpointer p);
static void ge_symskip_changed_CB     (GtkWidget *w ,gpointer p);
static void ge_avalue_skip_changed_CB (GtkWidget *w ,gpointer p);
static void ge_set_warn_linsym        (int lint  ,int symb ,int type);
static void ge_zcmap_changed_CB       (GtkWidget *w ,gpointer p);

static int rpane_set = -2;

/*
 *  gtk_widget_hide_all in ge_tree_CB emits the "switch-page" signal
 *  successively for each page => need block/unblock
 *  Idem when the notebook is created => current_page is initialized at -1
 *  				      while the notebook is not created.
 *  Moreover, the numbering change when some pages are hidden
 */
static gint current_page = -1;
static gulong handler_id;

void ge_set_page_block (void)
{
  g_signal_handler_block (w_notebook ,handler_id);
}
void ge_set_page_unblock (void)
{
  g_signal_handler_unblock (w_notebook ,handler_id);
}
static void ge_set_store_page_CB (GtkNotebook     *notebook,
				  GtkNotebookPage *page,
				  guint            page_num,
				  gpointer         user_data)
{
  if (current_page >= 0) current_page = page_num;
}

void ge_set_set_page (void)
{
  if (current_page >= 0) {
    gtk_notebook_set_current_page (GTK_NOTEBOOK (w_notebook) ,current_page);
  }
}

/**
 * Show/hide notebook page according to set type
 */
static void ge_set_show_w (GtkWidget *w ,gboolean sw)
{
  if (sw) {
    gtk_widget_show_all (w);
  } else {
    gtk_widget_hide (w);
  }
}

static void ge_set_show_hide_pages (gboolean sw_line
				    ,gboolean sw_symbols
				    ,gboolean sw_avalue
				    ,gboolean sw_errbar
				    ,gboolean sw_vmap
				    ,gboolean sw_cmap
				    )
{
  ge_set_show_w (w_tab_line    ,sw_line);
  ge_set_show_w (w_tab_symbols ,sw_symbols);
  ge_set_show_w (w_tab_avalue  ,sw_avalue);
  ge_set_show_w (w_tab_errbar  ,sw_errbar);
  ge_set_show_w (w_tab_vmap    ,sw_vmap);
  ge_set_show_w (w_tab_cmap    ,sw_cmap);
}

/*
 * See plotone.c to know what items are used
 */
static void ge_set_hide_pages (int settyp)
{
  if (titre_item != NULL) {
    ge_set_page_block ();
    gtk_widget_show_all (w_notebook);
    switch (settyp) {
    case SET_XY:
    case SET_XYSIZE:
    case SET_XYCOLOR:
    case SET_XYZ:
    case SET_BAR:          /* line  sym   aval  errbar vmap   cmap */
      ge_set_show_hide_pages (TRUE ,TRUE ,TRUE ,FALSE ,FALSE ,FALSE);
      break;
    case SET_XYDX:
    case SET_XYDY:
    case SET_XYDXDX:
    case SET_XYDYDY:
    case SET_XYDXDY:
    case SET_XYDXDXDYDY:
    case SET_BARDY:
    case SET_BARDYDY:
      ge_set_show_hide_pages (TRUE ,TRUE ,TRUE ,TRUE ,FALSE ,FALSE);
      break;
    case SET_XYHILO:
      ge_set_show_hide_pages (FALSE ,TRUE ,TRUE ,FALSE ,FALSE ,FALSE);
      break;
    case SET_XYR:
      ge_set_show_hide_pages (TRUE ,TRUE ,TRUE ,FALSE ,FALSE ,FALSE);
      break;
    case SET_BOXPLOT:
      ge_set_show_hide_pages (TRUE ,TRUE ,TRUE ,TRUE ,FALSE ,FALSE);
      break;
    case SET_XYCMAP:
      ge_set_show_hide_pages (FALSE ,FALSE ,TRUE ,FALSE ,FALSE ,TRUE);
      break;
    case SET_XYVMAP:
      ge_set_show_hide_pages (FALSE ,TRUE ,TRUE ,FALSE ,TRUE ,FALSE);
      break;
    default:
      ge_set_show_hide_pages (TRUE ,TRUE ,TRUE ,FALSE ,FALSE ,FALSE);
      break;
    }
    ge_set_page_unblock ();
    ge_set_set_page ();
  }
}

static void ge_set_contour_kill_CB (GtkWidget *w ,gpointer p)
{
  killsetcontours (cur_parent_id ,cur_obj_id);
  gg_drawgraph ();
}


/**
 *  Create set rpane menu
 */
GtkWidget *ge_set_create_menu (GtkWidget *parent)
{
  GtkWidget *menubar ,*menupane;
  GtkWidget *hbox ,*rc  ,*hb ,*rc1 ,*rc2 ,*bt;
  int nbtyp;

  gg_set_wait_cursor();
  if (titre_item == NULL) {
    vbox = gg_CreateVContainer (parent);
    titre_item = gg_label_new (vbox ,"Set");

    /* Menubar */
    menubar = gg_CreateMenuBar (vbox);

    menupane 	 = gg_CreateMenu       (menubar ,"Options" ,'O' ,FALSE);
    duplegs_item = gg_CreateMenuToggle (menupane ,"Duplicate legends" ,'D' ,NULL ,NULL ,FALSE);
    csync_item   = gg_CreateMenuToggle (menupane ,"Color sync"        ,'s' ,NULL ,NULL ,TRUE);
    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(csync_item) ,TRUE);

    menupane 	 = gg_CreateMenu (menubar ,"Help" ,'H' ,TRUE);
    // A COMPLETER

    vbox1= gg_CreateVContainer (vbox);
    /* Notebook */
    w_notebook = gtk_notebook_new ();
    gtk_box_pack_start_defaults (GTK_BOX (vbox1) ,w_notebook);

    /* ------------ Main tab -------------- */
    gg_frame_connect (ge_set_apply_CB);
    w_tab_main = gg_CreateTabPage (w_notebook ,"Main");

    hb         = gg_frame (w_tab_main  ,"Presentation" ,&bleuciel ,1 ,0);
    nbtyp      = NUMBER_OF_SETTYPES;
    w_type     = gg_combo_fun (hb ,"Set type:" ,&nbtyp ,set_types ,0);
    gtk_combo_box_set_wrap_width (GTK_COMBO_BOX (w_type) ,3);
 
    rc 	       = gg_frame     (w_tab_main ,"Comment" ,&wheat ,0 ,1);
    w_comments = gg_entry_new (rc ," " ,40);
    rc 	       = gg_frame     (w_tab_main ,"Point location" ,&wheat ,0 ,1);
    gg_frame_connect (NULL);
    index_item = gg_spin_new  (rc ,"Index:" ,0.0 ,0.0 ,1.0);
    gg_frame_connect (ge_set_apply_CB);
    xyz_item   = gg_entry_new (rc ,"data:" ,35);

    gg_frame_connect (NULL);
    list_bt = gg_button_new (w_tab_main ,"List values on stdout");
    gtk_widget_modify_bg (list_bt ,GTK_STATE_NORMAL ,&bleuciel);

    edit_bt = gg_button_new (w_tab_main ,"Edit with text editor");
    gtk_widget_modify_bg ( edit_bt ,GTK_STATE_NORMAL ,&bleuciel);

    //      calc_bt = gg_button_new (setapp_explore ,"Edit with soffice -calc ");
    //      gtk_widget_modify_bg ( edit_bt ,GTK_STATE_NORMAL ,&bleuciel);


    hbox = gtk_hbox_new (FALSE ,3);
    gtk_box_pack_end (GTK_BOX (w_tab_main) ,hbox  ,FALSE ,TRUE ,1);


    rc = gg_frame (w_tab_main ,"Edit points with mouse" ,&wheat ,3 ,2);
    gint d = gg_get_depth ();
    bt = gg_buttonB (rc ,22 ,d ,movepx_bits   ,gg_act_on_cur_obj_CB ,MOVX_POINT1ST ,"Click a point in the set to move it along Ox");
    bt = gg_buttonB (rc ,22 ,d ,movepy_bits   ,gg_act_on_cur_obj_CB ,MOVY_POINT1ST ,"Click a point in the set to move it along Oy");
    bt = gg_buttonB (rc ,22 ,d ,movept_bits   ,gg_act_on_cur_obj_CB ,MOVE_POINT1ST ,"Click a point in the set to move it");
    bt = gg_buttonB (rc ,22 ,d ,addpt_bits    ,gg_act_on_cur_obj_CB ,ADD_POINT_1ST ,"Click a point in the set to add a point after it");
    bt = gg_buttonB (rc ,22 ,d ,deletept_bits ,gg_act_on_cur_obj_CB ,DEL_POINT     ,"Click a point in the set to delete it");

    /* ------------ Line tab -------------- */
    gg_frame_connect (ge_set_apply_CB);
    w_tab_line = gg_CreateTabPage (w_notebook ,"Line");

    rc 	    = gg_frame 	   (w_tab_line ,"Line properties" ,&bleuciel ,1 ,0);
    linet.w = gg_combo_new (rc 	       ,"Connection:" ,8
			    ,"None"              		    /* 0: LINE_TYPE_NONE       */
			    ,"Straight"          		    /* 1: LINE_TYPE_STRAIGHT   */
			    ,"Left stairs"       		    /* 2: LINE_TYPE_LEFTSTAIR  */
			    ,"Right stairs"      		    /* 3: LINE_TYPE_RIGHTSTAIR */
			    ,"Segments"          		    /* 4: LINE_TYPE_SEGMENT2   */
			    ,"3-Segments"        		    /* 5: LINE_TYPE_SEGMENT3   */
			    ,"Spline");          		    /* 6: LINE_TYPE_SPLINE     */

    spline_frame = gg_frame 	(w_tab_line   ,"Spline interpolation/approximation" ,&bleuciel ,2 ,2);
    method.w 	 = gg_combo_new (spline_frame ,"Method:" ,6
				 ,"Linear"            	    	    /* INTERP_LINEAR  */
				 ,"Cubic spline"      	    	    /* INTERP_SPLINE  */
				 ,"Akima spline"    	    	    /* INTERP_ASPLINE */
				 ,"X-spline"    	    	    /* INTERP_XSPLINE */
				 ,"XY-spline");    	    	    /* INTERP_XYSPLINE */
    meshlen.w    = gg_spin_new (spline_frame ,"nb points" 	   ,10.0 ,1000.0 ,1.0);
    xspline_s.w  = gg_spin_new (spline_frame ,"X-spline param s"   ,-1.0   ,1.0  ,0.1);
    xspline_p.w  = gg_spin_new (spline_frame ,"p"                  ,0.002  ,0.5  ,0.002);
#ifdef WITH_TOOLTIPS
  gtk_widget_set_tooltip_text (xspline_s.w ,"<0 : interpolation ,>0:approximation");
  gtk_widget_set_tooltip_text (xspline_p.w ,"Precision for XY-splines");
#endif

    rc 		 = gg_frame 	(w_tab_line ,"Line style" ,&wheat ,2 ,2);
    lines.w 	 = gg_lines_new (rc 	    ,"Style:");
    linew.w 	 = gg_spin_new  (rc 	    ,"Width:" ,0.0 ,MAX_LINEWIDTH ,0.5);
    line_color.w = gg_color_new (rc 	    ,"Color:");

    rc 		    = gg_frame 	   (w_tab_line ,"Drop lines & fill properties" ,&wheat ,2 ,5);
    dropline.w      = gg_check_new (rc ,"Draw drop lines");
    baseline.w      = gg_check_new (rc ,"Draw base line");
    line_pattern.w  = gg_lines_new (rc ,"Line pattern:");
    baseline_type.w = gg_combo_new (rc ,"Base:" ,7
				    ,"Zero"
				    ,"Set min"
				    ,"Set max"
				    ,"Graph min"
				    ,"Graph max"
				    ,"Set average");
    filltype.w 	    = gg_combo_new (rc ,"Fill type:" ,4
				    ,"None"
				    ,"As polygon"
				    ,"To baseline");
    /* GTK does not work with FILLRULE_EVENODD */
    /* fillrule.w = gg_combo_new     (rc ,"Rule:" ,3   */
    /*						     ,"Winding"          */ /* FILLRULE_WINDING = 0 */
    /*						     ,"Even-Odd");       */ /* FILLRULE_EVENODD = 1*/

    setfillpen_pattern.w = gg_pattern_new (rc ,"Fill pattern:");
    setfillpen_color.w   = gg_color_new   (rc ,"Fill color:");


    /* ------------ Symbols tab -------------- */

    w_tab_symbols = gg_CreateTabPage (w_notebook ,"Symbols");

    rc 	  = gg_frame (w_tab_symbols ,"Properties of symbols ,characters or bars" ,&bleuciel ,2 ,3);
    sym.w = gg_combo_new (rc ,"Type:" ,13    /* 14 */
			  ,"None"            /*  0 SYM_NONE */
			  ,"Circle"          /*  1 SYM_CIRCLE */
			  ,"Square"          /*  2 SYM_SQUARE */
			  ,"Diamond"         /*  3 SYM_DIAMOND */
			  ,"Triangle up"     /*  4 SYM_TRIANG1 */
			  ,"Triangle left"   /*  5 SYM_TRIANG2 */
			  ,"Triangle down"   /*  6 SYM_TRIANG3 */
			  ,"Triangle right"  /*  7 SYM_TRIANG4 */
			  ,"Plus"            /*  8 SYM_PLUS */
			  ,"X"               /*  9 SYM_X */
			  ,"Star"            /* 10 SYM_SPLAT */
			  ,"Character"       /* 11 SYM_CHAR */
			  /* ,"Object"     */     /* 12 SYM_OBJ */
			  ,NULL);
    gg_label_new (rc ," ");                                      /* Dummy: it is  for gg_frame_attach */
    sym_color.w   = gg_color_new    (rc 	   ,"Color:");
    symsize.w     = gg_charsize_new (rc 	   ,"Size");
    rc 		  = gg_frame 	    (w_tab_symbols ,"Skipping points" ,&wheat  ,2 ,1);
    symskip.w  	  = gg_spin_new     (rc 	   ,"Skip:"      ,0.0  ,1000.0  ,1.0);
    symstart.w 	  = gg_spin_new     (rc 	   ,"Start at:"  ,0.0   ,  0.0  ,1.0);

    symchar_frame = gg_frame 	    (w_tab_symbols ,"Character properties" ,&wheat ,2 ,3);
    symchar.w     = gg_glyph_new    (symchar_frame ,"Symbol char:");
    charfont.w    = gg_font_new     (symchar_frame ,"Font");

    sym1_frame 	  = gg_frame 	    (w_tab_symbols ,"Symbol outline" ,&wheat ,2 ,2);
    symlines.w 	  = gg_lines_new    (sym1_frame    ,"Style:");
    symlinew.w 	  = gg_spin_new     (sym1_frame    ,"Width:" ,0.0 ,MAX_LINEWIDTH ,0.5);
    sym_pattern.w = gg_pattern_new  (sym1_frame    ,"Pattern:");

    sym2_frame 	      = gg_frame       (w_tab_symbols ,"Symbol fill" ,&wheat ,1 ,0);
    symfill_color.w   = gg_color_new   (sym2_frame ,"Color:");
    symfill_pattern.w = gg_pattern_new (sym2_frame ,"Pattern:");

    /* ------------ Ann. values tab -------------- */

    w_tab_avalue = gg_CreateTabPage (w_notebook ,"Ann. values");

    avalue_font.w     = gg_font_new     (w_tab_avalue ,"Font:");
    rc 		      = gg_frame (w_tab_avalue ,"Text properties" ,&bleuciel  ,2 ,3);
    avalue_color.w    = gg_color_new    (rc ,"Color:");
    w_blank           = gg_label_new    (rc ,NULL);
    avalue_size.w     = gg_charsize_new (rc ,"Char size");
    avalue_angle.w    = gg_angle_new    (rc ,"Angle");
    avalue_prestr.w   = gg_string_new   (rc ,"Prepend:" ,10);
    avalue_appstr.w   = gg_string_new   (rc ,"Append:"  ,10);
    rc 		      = gg_frame (w_tab_avalue ,"Skipping points" ,&wheat  ,2,1);
    avalue_skip.w     = gg_spin_new     (rc ,"Skip:"   ,0.0  ,1000.0  ,1.0);
    avalue_start.w    = gg_spin_new     (rc ,"Start at:"  ,0.0   ,  0.0  ,1.0);
    rc 		      = gg_frame 	 (w_tab_avalue ,"Format options" ,&bleuciel ,0 ,1);
    avalue_type.w     = gg_combo_new (rc ,"Type:" ,8
				      ,"None"
				      ,"X"
				      ,"Y"
				      ,"X ,Y"
				      ,"String"
				      ,"Z"
				      ,"Index"
				      ,NULL);
    avalue_prec.w     = gg_spin_new   (rc ,"Precision:" ,0.0 ,9.0 ,1.0);
    avalue_format.w   = gg_format_new (rc ,"Format:");
    rc 		      = gg_frame (w_tab_avalue ,"Placement" ,&wheat  ,0 ,1);
    avalue_offset_x.w = gg_spin_new (rc ,"X offset:" ,-0.5 ,0.5 ,0.005);
    avalue_offset_y.w = gg_spin_new (rc ,"Y offset:" ,-0.5 ,0.5 ,0.005);
    gg_set_dble (avalue_offset_x.w ,0.0);
    gg_set_dble (avalue_offset_y.w ,0.0);

    /* ------------ Errbar tab -------------- */
    w_tab_errbar = gg_CreateTabPage (w_notebook ,"Error bars");

    rc2 = gg_CreateHContainer (w_tab_errbar);

    rc1 = gg_CreateVContainer (rc2);

    rc 		   = gg_frame 	  (rc1 ,"Common" ,&wheat ,0 ,1);
    errbar_ptype.w = gg_combo_new (rc  ,"Placement:" ,4
				   ,"Normal"
				   ,"Opposite"
				   ,"Both"
				   ,NULL);
    errbar_pen_color.w   = gg_color_new   (rc ,"Color:");
    errbar_pen_pattern.w = gg_pattern_new (rc ,"Pattern:");

    rc 			= gg_frame     (rc1 ,"Clipping" ,&wheat ,0 ,1);
    errbar_arrow_clip.w = gg_check_new (rc  ,"Arrow clip");
    errbar_cliplen.w 	= gg_spin_new  (rc  ,"Max length:" ,0.0 ,10.0 ,0.1);

    rc1 = gg_CreateVContainer (rc2);

    rc 			= gg_frame 	   (rc1 ,"Bar line" ,&wheat ,0 ,1);
    errbar_barsize.w    = gg_charsize_new  (rc 	,"Size");
    errbar_linew.w      = gg_spin_new 	   (rc 	,"Width:" ,0.0 ,MAX_LINEWIDTH ,0.5);
    errbar_lines.w      = gg_lines_new 	   (rc 	,"Style:");

    rc = gg_frame (rc1 ,"Riser line" ,&wheat ,0 ,1);
    errbar_riser_linew.w = gg_spin_new (rc ,"Width:" ,0.0 ,MAX_LINEWIDTH ,0.5);
    errbar_riser_lines.w = gg_lines_new (rc ,"Style:");

    /* ------------ Vector vmap SET_XYVMAP tab -------------- */
    w_tab_vmap      = gg_CreateTabPage (w_notebook ,"Vector map");
    vmap_norm.w     = gg_entry_new     (w_tab_vmap ,"Graph normalization" ,15);
    rc 		    = gg_frame 	       (w_tab_vmap ,"Arrows" ,&wheat ,2 ,3);
    vmap_linew.w    = gg_spin_new      (rc ,"Line width:" ,0.0 ,MAX_LINEWIDTH ,0.5);
    vmap_lines.w    = gg_lines_new     (rc ,"Style:");
    vmap_a_L.w      = gg_spin_new      (rc ,"L:" ,0.0 ,10.0 ,0.1);
    vmap_a_dL_ff.w  = gg_spin_new      (rc ,"form factors d/L" ,0.0   ,10.0 ,0.1);
    vmap_a_lL_ff.w  = gg_spin_new      (rc ,"l/L"              ,-1.0  ,1.0  ,0.1);
    vmap_a_type.w   = gg_combo_new     (rc ,"Type:" ,4 ,"Line" ,"Filled" ,"Opaque");
    vmap_color.w    = gg_color_new     (rc ,"Color:");

    /* ------------ Color cmap SET_XYCMAP  tab -------------- */
    w_tab_cmap      = gg_CreateTabPage (w_notebook ,"Color map");

    rc 		     = gg_frame        (w_tab_cmap ,"Color map" ,&wheat ,2,2);
    nmap = MAX_PREDEF_CMAP;
    cmap_nmap.w     = gg_combo_fun     (rc ,"Map" ,&nmap ,zc_cmap_get_name ,0);
    w_blank         = gg_label_new     (rc ,NULL);

    contour_frame = rc   = gg_frame     (w_tab_cmap ,"Contour lines" ,&wheat ,2 ,2);
    contour_hidden.w 	 = gg_check_new (rc ,"Hide");
    gg_buttonA   (rc ,"Kill" ,ge_set_contour_kill_CB ,0);
    contour_linew.w 	 = gg_spin_new  (rc ,"Width:" ,0.0 ,MAX_LINEWIDTH ,0.5);
    contour_line_color.w = gg_color_new (rc ,"Color:");
    w_blank              = gg_label_new (w_tab_cmap ,"z levels are defined by the colorbar ticks");
    w_blank              = gg_label_new (w_tab_cmap ,"contour labels param. from Ann. values tab");
    contour_frame = rc   = gg_frame     (w_tab_cmap ,"Contour lines labels" ,&wheat ,1 ,0);
    w_cmap_place     	 = gg_buttonB   (rc ,22 ,d ,place_bits  ,gg_act_on_cur_obj_CB ,PLACE_LABEL ,"Place label on contour with mouse");
    w_cmap_kill      	 = gg_buttonB   (rc ,22 ,d ,delete_bits ,gg_act_on_cur_obj_CB ,KILL_LABEL  ,"Kill label on contour with mouse");

    /* --------------- Bottom widgets  ------------------ */
    warn_linsym     = gg_label_new (vbox1 ,"Warning: line connection and symbol type\n both set to NONE");
    gtk_widget_modify_fg (warn_linsym  ,GTK_STATE_NORMAL ,&gg_colors[2]); /* red */
    hbox 	    = gg_CreateHContainer  (vbox1);
    avalue_active.w = gg_check_new (hbox ,"Annotate values");
    errbar_active.w = gg_check_new (hbox ,"Display error bars");
    hbox 	    = gg_CreateHContainer  (vbox);
    w_hidden 	    = gg_check_new (hbox ,"Hide");
    legend_on.w     = gg_check_new (hbox ,"Show in graph legend box");
    hbox 	    = gg_CreateHContainer  (vbox);
    layer.w 	    = gg_layer_new (hbox ,"Layer");

    /* ---------------- Connect handlers ---------------- */
    handler_id = g_signal_connect (w_notebook ,"switch-page" ,G_CALLBACK(ge_set_store_page_CB) ,NULL);
    g_signal_connect (index_item    ,"value-changed" ,G_CALLBACK (ge_set_index_CB)     ,NULL);
    g_signal_connect (linet.w 	    ,"changed" 	     ,G_CALLBACK (ge_linet_changed_CB) ,NULL);

    g_signal_connect (list_bt ,"clicked" ,G_CALLBACK (ge_set_list_CB)   ,NULL);
    g_signal_connect (edit_bt 	    ,"clicked" 	     ,G_CALLBACK (ge_set_editor_CB) ,NULL);
    //  g_signal_connect (calc_bt ,"clicked" ,G_CALLBACK (ge_set_calc_CB) ,NULL);

    g_signal_connect (method.w      ,"changed" 	     ,G_CALLBACK (ge_method_changed_CB)      ,NULL);
    g_signal_connect (sym.w    	    ,"changed" 	     ,G_CALLBACK (ge_symbol_changed_CB)      ,NULL);
    g_signal_connect (charfont.w    ,"changed" 	     ,G_CALLBACK (ge_symfont_changed_CB)     ,NULL);
    g_signal_connect (symskip.w     ,"value-changed" ,G_CALLBACK (ge_symskip_changed_CB)     ,NULL);
    g_signal_connect (avalue_skip.w ,"value-changed" ,G_CALLBACK (ge_avalue_skip_changed_CB) ,NULL);
    g_signal_connect (cmap_nmap.w   ,"changed" 	     ,G_CALLBACK (ge_zcmap_changed_CB)       ,NULL);

    gg_unset_wait_cursor ();
    gtk_widget_show_all  (vbox);
    gtk_widget_hide 	 (warn_linsym);
    gg_frame_connect 	 (NULL);
    current_page   = 0;
    menu_finalized = TRUE;
  }
  return vbox;
}

/**
 *  Update the set menu
 */
void ge_set_update  (int gno ,int cset)
{
  char val[64] ,buf[64];
  plotarr p;
  QDobject *po;
  int  num;

  if (titre_item == NULL) return;
  if (cset == -2) cset = rpane_set;
  if (is_valid_setno (gno ,cset) != TRUE) return;
  if (block_instant_update 	 == TRUE) return;
  block_instant_update = TRUE;

  po = obj_tid_get_pointer (Q_Set ,cset ,gno);

  sprintf (buf ,"  Graph %d  Set %d   [%d]" ,gno ,cset ,getsetlength (gno ,cset));
  gtk_label_set_text (GTK_LABEL (titre_item) ,buf);

  num = obj_tid_get_set_num (gno ,cset);
  if (num < 0) {
    block_instant_update = FALSE;
    return;
  }
  gg_set_int (layer.w ,objs[num].layer);

  get_graph_plotarr (gno ,cset ,&p);
  gg_set_int  (w_type            ,p.type);
  gg_set_int  (sym.w         	 ,p.sym);
  gg_set_dble (symsize.w         ,p.symsize);
  gg_set_int  (symskip.w         ,p.symskip);
  gg_set_int  (symstart.w        ,p.symstart);
  gtk_widget_set_sensitive (symstart.w ,p.symskip > 0);
  gtk_spin_button_set_range (GTK_SPIN_BUTTON (symstart.w) ,0.0 ,(gdouble)(p.symskip));
  gg_set_int  (symchar.w         ,p.symchar);
  gg_set_int  (sym_color.w       ,p.sympen.color);
  gg_set_int  (sym_pattern.w     ,p.sympen.pattern);
  gg_set_int  (symfill_color.w   ,p.symfillpen.color);
  gg_set_int  (symfill_pattern.w ,p.symfillpen.pattern);
  gg_set_dble (symlinew.w        ,p.symlinew);
  gg_set_int  (symlines.w        ,p.symlines);
  gg_set_int  (charfont.w        ,p.charfont);

  gg_set_int  (linet.w    	 ,p.linet);
  gg_set_int  (line_color.w      ,p.linepen.color);
  gg_set_int  (line_pattern.w    ,p.linepen.pattern);
  gg_set_dble (linew.w    	 ,p.linew);
  gg_set_int  (dropline.w        ,p.dropline);
  gg_set_int  (lines.w    	 ,p.lines);
  gg_set_int  (filltype.w 	 ,p.filltype);
  /*  gg_set_int  (fillrule.w    ,p.fillrule); */
  p.fillrule = FILLRULE_WINDING;
  gg_set_int  (setfillpen_color.w    ,p.setfillpen.color);
  gg_set_int  (setfillpen_pattern.w  ,p.setfillpen.pattern);
  gg_set_int  (baseline.w            ,p.baseline);
  gg_set_int  (baseline_type.w       ,p.baseline_type);
  gtk_widget_set_sensitive (spline_frame ,p.linet == LINE_TYPE_SPLINE);
  gg_set_int  (method.w        	     ,p.method);
  gg_set_int  (meshlen.w      	     ,p.meshlen);
  gg_set_dble (xspline_s.w           ,po->xspline_s);
  gg_set_dble (xspline_p.w           ,po->xspline_p);


  gtk_widget_set_sensitive (meshlen.w   ,p.method != INTERP_XYSPLINE);
  gtk_widget_set_sensitive (xspline_s.w ,p.method == INTERP_XYSPLINE || p.method == INTERP_XSPLINE);
  gtk_widget_set_sensitive (xspline_p.w ,p.method == INTERP_XYSPLINE);

  ge_label_update_current (p.lstr);
  gg_setstr   (w_comments    	,p.comments);
  gg_set_int  (errbar_active.w  ,p.errbar.active);

  if (!(p.type == SET_XY || p.type == SET_XYVMAP)) {
      gg_set_int  (errbar_ptype.w       ,p.errbar.ptype);
      gg_set_int  (errbar_pen_color.w   ,p.errbar.pen.color);
      gg_set_int  (errbar_pen_pattern.w ,p.errbar.pen.pattern);
      gg_set_int  (errbar_arrow_clip.w  ,p.errbar.arrow_clip);
      gg_set_dble (errbar_cliplen.w     ,p.errbar.cliplen);
      gg_set_dble (errbar_linew.w       ,p.errbar.linew);
      gg_set_int  (errbar_lines.w       ,p.errbar.lines);
      gg_set_dble (errbar_riser_linew.w ,p.errbar.riser_linew);
      gg_set_int  (errbar_riser_lines.w ,p.errbar.riser_lines);
      gg_set_dble (errbar_barsize.w     ,p.errbar.barsize);
  }
  gg_set_int  (avalue_active.w      ,p.avalue.active);
  gg_set_int  (avalue_type.w        ,p.avalue.type);
  gg_set_dble (avalue_size.w        ,p.avalue.size);
  gg_set_int  (avalue_font.w        ,p.avalue.font);
  gg_set_int  (avalue_color.w       ,p.avalue.color);
  gg_set_int  (avalue_angle.w       ,p.avalue.angle);
  gg_set_int  (avalue_format.w      ,p.avalue.format);
  gg_set_int  (avalue_prec.w        ,p.avalue.prec);

  gg_setstr   (avalue_prestr.w          ,p.avalue.prestr);
  gg_setstr   (avalue_appstr.w          ,p.avalue.appstr);
  gg_setstr_d (avalue_offset_x.w  ,"%f" ,p.avalue.offset.x ,val);
  gg_setstr_d (avalue_offset_y.w  ,"%f" ,p.avalue.offset.y ,val);
  gg_set_int  (avalue_skip.w         	,p.avalue.skip);
  gg_set_int  (avalue_start.w        	,p.avalue.start);

  gg_set_int  (w_hidden      	,p.hidden);
  gg_set_int  (legend_on.w     ,p.legend_on);

  gtk_spin_button_set_range (GTK_SPIN_BUTTON (index_item)
			     ,0.0
			     ,(gdouble)(getsetlength (gno ,cset) - 1) );

  gtk_widget_set_sensitive      (vbox1 ,p.hidden == FALSE);
  ge_set_warn_linsym            (p.linet ,p.sym ,p.type);
  ge_set_set_page ();
  ge_tree_need_update           (!ge_select_current ());
  rpane_set = cset;

  switch (p.type) {
  case SET_XYCMAP:
    gg_set_int  (cmap_nmap.w    	 ,p.contour.nmap);
#if defined (HAVE_CONTOURS)
    gtk_widget_set_sensitive (contour_frame ,TRUE);
    gg_set_int  (contour_hidden.w        ,p.contour.hidden);
    gg_set_int  (contour_line_color.w    ,p.contour.line_color);
    gg_set_dble (contour_linew.w    	 ,p.linew);
#else
    p.contour.hidden = TRUE;
    gtk_widget_set_sensitive (contour_frame ,FALSE);
#endif  /* HAVE_CONTOURS */
    break;
  case SET_XYVMAP:
    gg_setstr_d   (vmap_norm.w  ,"%g" ,get_graph_znorm (gno) ,buf);
    po->arrow_end = 1;
    gg_set_dble   (vmap_a_L.w     ,po->arrow.length);
    gg_set_int    (vmap_a_type.w  ,po->arrow.type);
    gg_set_dble   (vmap_linew.w   ,po->linew);
    gg_set_int    (vmap_lines.w   ,po->lines);
    gg_set_dble   (vmap_a_dL_ff.w ,po->arrow.dL_ff);
    gg_set_dble   (vmap_a_lL_ff.w ,po->arrow.lL_ff);
    gg_set_int    (vmap_color.w   ,po->color);
    break;
  default:
    break;
  }
  ge_set_hide_pages    (p.type);
//044f   ge_set_index_CB      (index_item ,NULL);
//044f   ge_linet_changed_CB  (linet.w    ,NULL);
//044f   ge_method_changed_CB (method.w   ,NULL);
//044f   ge_symbol_changed_CB (sym.w 	   ,NULL);

  block_instant_update = FALSE;
}

void ge_set_apply (int gno ,int setno)
{
  char buf[128];
  gboolean duplegs;
  int type;
  Errbar errbar;
  AValue avalue;
  plotarr p;
  double znorm;
  QDobject *po ,oobj ,*pocolorbar;
  int num ,icb;

  if (titre_item != NULL) {
    block_instant_update = TRUE;
    if (is_valid_setno (cg ,setno) == TRUE)   cset = setno;

    num = obj_tid_get_set_num (gno ,setno);
    oobj = objs[num];
    objs[num].layer = gg_get_int (layer.w);
    gg_update_layers_hbox ();

    get_graph_plotarr (gno ,setno ,&pa);

    sprintf (buf ,"  Graph %d  Set %d   [%d]" ,gno ,cset ,getsetlength (gno ,cset));
    gtk_label_set_text (GTK_LABEL (titre_item) ,buf);

    duplegs = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (duplegs_item));

    get_graph_plotarr (get_cg(), setno, &p);
    po = obj_tid_get_pointer (Q_Set ,setno ,get_cg());

    type     	   	 = gg_get_int  (w_type);
    p.sym      	   	 = gg_get_int  (sym.w);
    p.symsize  	   	 = gg_get_dble (symsize.w);
    p.sympen.color       = gg_get_int  (sym_color.w);
    p.sympen.pattern     = gg_get_int  (sym_pattern.w);
    p.symfillpen.color 	 = gg_get_int  (symfill_color.w);
    p.symfillpen.pattern = gg_get_int  (symfill_pattern.w);
    p.symlines       	 = gg_get_int  (symlines.w);
    p.symlinew       	 = gg_get_dble (symlinew.w);
    p.symskip        	 = gg_get_int  (symskip.w);
    p.symstart       	 = gg_get_int  (symstart.w);
    p.symchar        	 = gg_get_int  (symchar.w);
    p.charfont       	 = gg_get_int  (charfont.w);
    p.linet          	 = gg_get_int  (linet.w);
    p.lines          	 = gg_get_int  (lines.w);
    p.linew    	     	 = gg_get_dble (linew.w);
    p.linepen.color  	 = gg_get_int  (line_color.w);
    p.linepen.pattern 	 = gg_get_int  (line_pattern.w);
    p.baseline_type   	 = gg_get_int  (baseline_type.w);
    p.baseline 	   	 = gg_get_int  (baseline.w);
    p.filltype       	 = gg_get_int  (filltype.w);
    p.fillrule		 = FILLRULE_WINDING;         /* fillrule = gg_get_int (fillrule.w); */
    p.setfillpen.color   = gg_get_int (setfillpen_color.w);
    p.setfillpen.pattern = gg_get_int (setfillpen_pattern.w);
    avalue.active   	 = gg_get_int (avalue_active.w);
    avalue.type     	 = gg_get_int (avalue_type.w);
    avalue.size     	 = gg_get_dble(avalue_size.w);
    avalue.font     	 = gg_get_int (avalue_font.w);
    avalue.color    	 = gg_get_int (avalue_color.w);
    avalue.angle    	 = gg_get_int (avalue_angle.w);
    avalue.format   	 = gg_get_int (avalue_format.w);
    avalue.prec     	 = gg_get_int (avalue_prec.w);
    strncpy (avalue.prestr ,gg_getstr  (avalue_prestr.w) ,63);
    strncpy (avalue.appstr ,gg_getstr  (avalue_appstr.w) ,63);
    gg_evalexpr (avalue_offset_x.w ,&avalue.offset.x );
    gg_evalexpr (avalue_offset_y.w ,&avalue.offset.y);
    avalue.skip     	 = gg_get_int (avalue_skip.w);
    avalue.start    	 = gg_get_int (avalue_start.w);

    errbar.active      = gg_get_int  (errbar_active.w);
    errbar.ptype       = gg_get_int  (errbar_ptype.w);
    errbar.pen.color   = gg_get_int  (errbar_pen_color.w);
    errbar.pen.pattern = gg_get_int  (errbar_pen_pattern.w);
    errbar.linew       = gg_get_dble  (errbar_linew.w);
    errbar.lines       = gg_get_int  (errbar_lines.w);
    errbar.riser_linew = gg_get_dble (errbar_riser_linew.w);
    errbar.riser_lines = gg_get_int  (errbar_riser_lines.w);
    errbar.barsize     = gg_get_dble (errbar_barsize.w);
    errbar.arrow_clip  = gg_get_int  (errbar_arrow_clip.w);
    errbar.cliplen     = gg_get_dble (errbar_cliplen.w);
    p.meshlen          = gg_get_int  (meshlen.w);
    p.method           = gg_get_int  (method.w);
    po->xspline_s        = gg_get_dble (xspline_s.w);
    po->xspline_p        = gg_get_dble (xspline_p.w);

    p.dropline         = gg_get_int  (dropline.w);
    strncpy (p.comments ,gtk_entry_get_text (GTK_ENTRY (w_comments)) ,MAX_STRING_LENGTH -1);

    p.errbar = errbar;
    p.avalue = avalue;
    p.hidden = gg_get_int (w_hidden);
    ge_hidden_update (Q_Set ,setno ,Q_Graph ,get_cg() ,p.hidden);

    p.legend_on = gg_get_int (legend_on.w);

    pocolorbar = NULL;
    switch (p.type) {
    case SET_XYVMAP:
      gg_evalexpr     (vmap_norm.w ,&znorm);
      set_graph_znorm (gno ,znorm);
      po = obj_tid_get_pointer (Q_Set ,cset ,gno);
      po->linew        = gg_get_dble (vmap_linew.w);
      po->lines        = gg_get_int  (vmap_lines.w);
      po->arrow.type   = gg_get_int  (vmap_a_type.w);
      po->arrow.length = gg_get_dble (vmap_a_L.w);
      po->arrow.dL_ff  = gg_get_dble (vmap_a_dL_ff.w);
      po->arrow.lL_ff  = gg_get_dble (vmap_a_lL_ff.w);
      po->color        = gg_get_int  (vmap_color.w);
      break;
    case SET_XYCMAP:
      p.contour.nmap   	    = gg_get_int  (cmap_nmap.w);
      p.contour.hidden 	    = gg_get_int  (contour_hidden.w);
      p.linew          	    = gg_get_dble (contour_linew.w);
      p.contour.line_color  = gg_get_int  (contour_line_color.w);
      po = obj_tid_get_pointer (Q_Set ,cset ,gno);
      if (obj_is_active (po->child)) {
	pocolorbar = &objs[po->child];
      } else {
	/* we need to create a colorbar  */
	icb = obj_t_next_colorbar (gno ,cset);
	pocolorbar = &objs[icb];
	ge_update_explorer ();
      }
      break;
    default:
      break;
    }
    if (type != p.type) {
      Dataset dataset;
      if ((set_dataset_type (get_cg() ,setno ,type)    == RETURN_SUCCESS) &&
	  (set_get_dataset (get_cg() ,setno ,&dataset) == RETURN_SUCCESS)   ) {
	p.type = type;
	set_graph_plotarr (get_cg() ,setno ,&p);
	set_set_dataset   (get_cg() ,setno ,dataset);
      } else {
	block_instant_update = FALSE;
	errmsg ("Error when changing set type");
	return;
      }
    } else {
      set_graph_plotarr  (get_cg(), setno, &p);
    }
    ge_set_warn_linsym (p.linet ,p.sym ,p.type);
    gg_drawgraph ();
    /* undo/redo and follow_me_on */
    nn_cmd_set (gno ,setno ,&pa ,&oobj ,pocolorbar ,p ,objs[num] ,FALSE ,TRUE);
  }
  gtk_widget_set_sensitive (vbox1 ,p.hidden == FALSE);
  ge_set_hide_pages (p.type);
  current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK(w_notebook));
  block_instant_update = FALSE;
}

void ge_set_apply_CB (GtkWidget *w ,gpointer p)
{
  int gno   = cur_parent_id;
  int setno = cur_obj_id;
  if (instant_update && menu_finalized && 
      block_instant_update == FALSE && is_valid_setno (gno ,setno)) {
    ge_set_apply (gno ,setno);
  }
}

int ge_set_point2str (int gno ,int setno ,int i ,char **s)
{
  int ncols ,col;
  Datapoint dpoint;
  char buf[64];

  if (get_datapoint (gno ,setno ,i ,&ncols ,&dpoint) == RETURN_SUCCESS) {
    *s = copy_string (NULL ,"(");
    for (col = 0; col < ncols; col++) {
      sprintf (buf ,"%g" ,dpoint.ex[col]);
      *s = concat_strings (*s ,buf);
      if (col != ncols - 1) {
	*s = concat_strings(*s ," ,");
      }
    }
    if (dpoint.s != NULL) {
      *s = concat_strings (*s ," ,\"");
      *s = concat_strings (*s ,dpoint.s);
      *s = concat_strings (*s ,"\"");
    }
    *s = concat_strings (*s ,")");
    return RETURN_SUCCESS;
  }
  return RETURN_FAILURE;
}


/**
 *   Replace gg_update_point_locator
 */
static gboolean track_old = FALSE;
static VPoint   track_old_vp;
static int      loc = 0;

static void ge_set_index_CB (GtkWidget *w ,gpointer p)
{
  if (block_instant_update == TRUE) return;
  loc =  gg_get_int (index_item);
  int gno   = cur_parent_id;
  int setno = cur_obj_id;
  if (is_valid_setno (gno ,setno) && loc >=0 && loc < getsetlength(gno ,setno)) {
    VPoint vp;
    char *s ,buf[64];
    get_clipped_vp (gno ,setno ,loc ,&vp);
    if (track_old) gg_draw_rect (track_old_vp);
    gg_draw_rect (vp);
    track_old = TRUE;
    track_old_vp = vp;
    if (ge_set_point2str (gno ,setno ,loc ,&s) == RETURN_SUCCESS) {
      gtk_entry_set_text ( GTK_ENTRY (xyz_item) ,s);
      xfree (s);
      sprintf (buf ,"%d" ,loc);
      gg_setstr (index_item ,buf);
    } else {
      gtk_entry_set_text (GTK_ENTRY (index_item) ,"");
    }
  }
}


static void ge_set_warn_linsym (int lint ,int symb ,int type)
{
  int bar = (type == SET_BAR) || (type == SET_BARDY) || (type == SET_BARDYDY);
  if (symb == 0 && lint == 0 && bar == 0) {
    gtk_widget_show (warn_linsym);
  } else {
    gtk_widget_hide (warn_linsym);
  }
}

void ge_set_warn_linsym_null (void)
{
  int set_typ = gg_get_int (w_type);
  int linetyp = gg_get_int (linet.w);
  int symb    = gg_get_int (sym.w);
  ge_set_warn_linsym (linetyp ,symb ,set_typ);

}

static void ge_linet_changed_CB (GtkWidget *w ,gpointer p)
{
  int set_typ = gg_get_int (w_type);
  int linetyp = gg_get_int (linet.w);
  gtk_widget_set_sensitive (spline_frame ,linetyp == LINE_TYPE_SPLINE);
  ge_set_warn_linsym (linetyp ,gg_get_int (sym.w) ,set_typ);
}

static void ge_method_changed_CB   (GtkWidget *w ,gpointer p)
{
  int m = gg_get_int (w);
  gtk_widget_set_sensitive (meshlen.w   ,m != INTERP_XYSPLINE);
  gtk_widget_set_sensitive (xspline_s.w ,m == INTERP_XYSPLINE|| m == INTERP_XSPLINE);
  gtk_widget_set_sensitive (xspline_p.w ,m == INTERP_XYSPLINE);
}

static void ge_symbol_changed_CB (GtkWidget *w ,gpointer p)
{
  int set_typ = gg_get_int (w_type);
  int symb    = gg_get_int (sym.w);
  gtk_widget_set_sensitive (symchar_frame ,symb == SYM_CHAR && set_typ != SET_XYHILO);			    
  gtk_widget_set_sensitive (sym1_frame    ,symb <  SYM_CHAR);
  gtk_widget_set_sensitive (sym2_frame    ,symb <  SYM_CHAR);
  ge_set_warn_linsym (gg_get_int (linet.w) ,symb ,set_typ);
}

/**
 *
 */
static void ge_symfont_changed_CB (GtkWidget *w ,gpointer p)
{
  int font = gg_get_int(w);
  gg_update_glyph_choice (GW_CHOICE (symchar.w) ,font);
  gtk_widget_show_all (symchar.w);
}

static void ge_symskip_changed_CB (GtkWidget *w ,gpointer p)
{
  if (block_instant_update == TRUE) return;
  int skip = gg_get_int (w);
  gtk_widget_set_sensitive (symstart.w ,skip > 0);
  gtk_spin_button_set_range (GTK_SPIN_BUTTON (symstart.w) ,0.0 ,(gdouble)skip);
}

static void ge_avalue_skip_changed_CB (GtkWidget *w ,gpointer p)
{
  if (block_instant_update == TRUE) return;
  int skip = gg_get_int (w);
  gtk_widget_set_sensitive (avalue_start.w ,skip > 0);
  gtk_spin_button_set_range (GTK_SPIN_BUTTON (avalue_start.w) ,0.0 ,(gdouble)skip);
}

/*
 *  Replace do_ext_editor editpwinc  777
 */
static void ge_set_do_edit_CB (int gno ,int setno ,gboolean with_calc)
{
  char *fname ,ebuf[256];
  FILE *cp;
  int save_autos;
  fname = copy_string (NULL ,"gracegtk_tmpXXXXXX");
  cp = gg_tmpfile (fname);
  if (cp == NULL) {
    return;
  }

  if (block_instant_update == TRUE) return;
  write_set (gno ,setno ,cp ,"%.8g  \t" ,FALSE);
  grace_close (cp);

  if (with_calc) {
    sprintf (ebuf ,"soffice -calc %s" ,fname);
  } else {
    sprintf (ebuf ,"%s %s" ,get_editor() ,fname);
  }
  system_wrap (ebuf);

  /* temporarily disable autoscale */
  save_autos = autoscale_onread;
  autoscale_onread = AUTOSCALE_NONE;
  if (is_set_active (gno ,setno)) {
    curtype = dataset_type (gno ,setno);
    killsetdata (gno ,setno);
  }
  getdata (gno ,fname ,SOURCE_DISK ,LOAD_SINGLE);
  autoscale_onread = save_autos;
  unlink (fname);
  gg_update_all();
  gg_drawgraph();
}

static void ge_set_list_CB (GtkWidget *w ,gpointer p)
{
  int i;
  int n = getsetlength (cur_parent_id ,cur_obj_id);
  char *s;
  printf ("\n Graph %d  set %d data\n" ,cur_parent_id ,cur_obj_id);
  for (i = 0; i < n; i++) {
    if (ge_set_point2str (cur_parent_id ,cur_obj_id ,i ,&s) == RETURN_SUCCESS) {
      printf ("%s \n" ,s);
    }
  }
  printf ("\n");
  xfree (s);
}

static void ge_set_editor_CB (GtkWidget *w ,gpointer p)
{
  ge_set_do_edit_CB (cur_parent_id ,cur_obj_id ,FALSE);
}

void ge_set_reset_rect (void)
{
  if (track_old) {
    gg_draw_rect (track_old_vp);
    track_old = FALSE;
  }
}

static void ge_zcmap_changed_CB (GtkWidget *w ,gpointer gp)
{
  plotarr p;
  QDobject oobj;
  int num ,gno ,setno ,nmap;
  if (titre_item != NULL) {
    if (block_instant_update == TRUE) return;
    gno   = cur_parent_id;
    setno = cur_obj_id;
    get_graph_plotarr (gno ,setno  ,&pa);
    num   = obj_tid_get_set_num (gno ,setno);
    oobj  = objs[num];
    nmap  = gg_get_int (cmap_nmap.w);
    set_set_nmap (gno ,setno ,nmap);
    gg_drawgraph ();
    /* undo/redo and follow_me_on */
    get_graph_plotarr (gno ,setno ,&p);
    nn_cmd_set        (gno ,setno ,&pa ,&oobj ,NULL ,p ,objs[num] ,FALSE ,TRUE);
  }
}

/***************************** Button 3 menu **************************/
/**
 *  ge_sets_menu3_CB creates and execute the menu
 *                  when set(s) are clicked with mouse button 3
 *  Called by ge_tree_CB via gg_graph_popup_menu3 
 *  Compare to gg_sets_menu_CB
 *  Compare to ge_graph_menu3_CB and ge_axis_menu3_CB
 */

static GtkWidget *u_sets_dialog = NULL;

static GtkWidget *ge_sets_u_new (void);
static void  	  ge_sets_u_AAC_CB (GtkWidget *widget ,gint reponse);

void ge_sets_menu3_CB  (GtkWidget *w ,gpointer pact)
{
  gint action = GPOINTER_TO_INT (pact);
  GtkTreeIter iter;
  GtkTreeSelection *select;
  GList *lpath = NULL;
  int n ,setno ,j ,gno ,gnou;
  gboolean same_gno = TRUE;
  Ge_tree *getree;

  switch (action) {
  case MenuSetsUpdate:
    ge_sets_u_new ();
    wu_update_on (TRUE);
    break;
  default:
    getree = get_getree ();
    select = gtk_tree_view_get_selection (GTK_TREE_VIEW (getree->view));
    n      = gtk_tree_selection_count_selected_rows (select);
    lpath  = gtk_tree_selection_get_selected_rows (select ,&(getree->model));
    /* the list must be traversed un reverse order */
    lpath = g_list_last (lpath);
    gnou = -1;    /* uniquely to avoid compiler message: should be set to gno(j=0) */
    j = 0;
    while (lpath != NULL) {
      if (gtk_tree_model_get_iter (getree->model ,&iter ,lpath->data)) {
	gtk_tree_model_get (getree->model ,&iter
			    ,GE_TREE_ID         ,&setno
			    ,GE_TREE_PARENT_ID  ,&gno
			    ,-1);
	if (j == 0) gnou = gno;
	same_gno = (gnou == gno);
	gg_sets_menu3_actions (action ,n ,gno ,setno ,j);
	lpath = g_list_previous (lpath);
	j++;
      }
    }
    gg_update_all ();
    ge_update_explorer ();
    if (same_gno) ge_expand_graph (gnou);
    gg_drawgraph();
  }
}

/************** COLLECTIVE and SELECTIVE UPDATE of SETS *******************/

#define U_SETS_RESET 1001


static GtkWidget *ge_sets_u_new (void)
{
  GtkWidget *vb ,*ta;
  if (u_sets_dialog == NULL) {
    u_sets_dialog = gg_CreateAACDialog ("Update params." ,ge_sets_u_AAC_CB ,0 ,0 ,&vb);
    gtk_dialog_add_buttons (GTK_DIALOG (u_sets_dialog) ,"Reset" ,U_SETS_RESET ,NULL);
    gg_label_new (vb ,"Choose items to update in the selected sets");

    ta 	      	       	 = gg_frame     (vb ,"Sets layer"  	  ,&wheat ,4,1);
    layer.u            	 = gg_check_new (ta ,"Layer");

    legend_on.u          = gg_check_new (vb ,"Show in graph legend box");

    ta 	      	    	 = gg_frame     (vb ,"Line properties"  	  ,&bleuciel ,4 ,1);
    linet.u   	    	 = gg_check_new (ta ,"Connection");

    ta 	      	    	 = gg_frame     (vb ,"Spline interpolation"  ,&bleuciel ,4 ,1);
    method.u  	    	 = gg_check_new (ta ,"Method");
    meshlen.u 	    	 = gg_check_new (ta ,"nb points");
    xspline_s.u          = gg_check_new (ta ,"X-spline param s");
    xspline_p.u          = gg_check_new (ta ,"p");

    ta 	      	    	 = gg_frame     (vb ,"Line style"  ,&wheat ,4 ,1);
    lines.u 	    	 = gg_check_new (ta ,"Style");
    linew.u 	    	 = gg_check_new (ta ,"Width");
    line_color.u    	 = gg_check_new (ta ,"Color");

    ta 	      	    	 = gg_frame     (vb ,"Drop lines & fill properties"  ,&wheat ,4 ,2);
    dropline.u      	 = gg_check_new (ta ,"Draw drop lines");
    baseline.u      	 = gg_check_new (ta ,"Draw base line");
    line_pattern.u  	 = gg_check_new (ta ,"Line style");
    baseline_type.u 	 = gg_check_new (ta ,"Base");
    filltype.u 	    	 = gg_check_new (ta ,"Fill type");
    setfillpen_pattern.u = gg_check_new (ta ,"Fill pattern");
    setfillpen_color.u 	 = gg_check_new (ta ,"Fill color");

    ta 	      	    	 = gg_frame     (vb ,"Properties of symbols ,characters or bars"  ,&bleuciel ,4 ,2);
    sym.u 	 	 = gg_check_new (ta ,"Type");
    sym_color.u  	 = gg_check_new (ta ,"Color");
    symsize.u 	 	 = gg_check_new (ta ,"Size");
    symskip.u 	 	 = gg_check_new (ta ,"Skip");
    symstart.u 	 	 = gg_check_new (ta ,"Start");

    ta 	      	    	 = gg_frame     (vb ,"Character properties"  ,&wheat ,4 ,1);
    symchar.u 	 	 = gg_check_new (ta ,"Symbol char");
    charfont.u 	 	 = gg_check_new (ta ,"Font");

    ta 	      	    	 = gg_frame     (vb ,"Symbol outline"  ,&wheat ,4 ,1);
    symlines.u 		 = gg_check_new (ta ,"Style");
    symlinew.u 		 = gg_check_new (ta ,"Width");
    sym_pattern.u 	 = gg_check_new (ta ,"Pattern");

    ta 	      	    	 = gg_frame     (vb ,"Symbol fill"  ,&wheat ,4 ,1);
    symfill_color.u 	 = gg_check_new (ta ,"Color");
    symfill_pattern.u 	 = gg_check_new (ta ,"Pattern");

    ta 	      	    	 = gg_frame     (vb ,"Annotations"  ,&bleuciel ,4 ,4);
    avalue_active.u 	 = gg_check_new (ta ,"active");
    avalue_font.u 	 = gg_check_new (ta ,"Font");
    avalue_color.u 	 = gg_check_new (ta ,"Color");
    avalue_size.u 	 = gg_check_new (ta ,"Char size");
    avalue_angle.u 	 = gg_check_new (ta ,"Angle");
    avalue_prestr.u 	 = gg_check_new (ta ,"Prepend");
    avalue_appstr.u 	 = gg_check_new (ta ,"Append");
    avalue_skip.u 	 = gg_check_new (ta ,"Skip");
    avalue_start.u 	 = gg_check_new (ta ,"Start");
    avalue_type.u 	 = gg_check_new (ta ,"Type");
    avalue_prec.u 	 = gg_check_new (ta ,"Precision");
    avalue_format.u 	 = gg_check_new (ta ,"Format");
    w_blank 		 = gg_label_new (ta ,NULL);
    avalue_offset_x.u 	 = gg_check_new (ta ,"X offset");
    avalue_offset_y.u 	 = gg_check_new (ta ,"Y offset");

    ta 	      	    	 = gg_frame     (vb ,"Error bars"  ,&wheat ,4 ,2);
    errbar_active.u 	 = gg_check_new (ta ,"active");
    errbar_ptype.u 	 = gg_check_new (ta ,"Placement");
    errbar_pen_color.u   = gg_check_new (ta ,"Color");
    errbar_pen_pattern.u = gg_check_new (ta ,"Pattern");
    errbar_arrow_clip.u  = gg_check_new (ta ,"Arrow clip");
    errbar_cliplen.u 	 = gg_check_new (ta ,"Max length");
    errbar_barsize.u 	 = gg_check_new (ta ,"Bar size");
    errbar_linew.u 	 = gg_check_new (ta ,"Width");
    errbar_lines.u 	 = gg_check_new (ta ,"Style");
    errbar_riser_linew.u = gg_check_new (ta ,"Riser width");
    errbar_riser_lines.u = gg_check_new (ta ,"Riser style");


    ta 	      	    	 = gg_frame     (vb ,"Vector map"  ,&bleuciel ,4 ,4);
    vmap_norm.u 	 = gg_check_new (ta ,"Normalization");
    vmap_linew.u 	 = gg_check_new (ta ,"Arrows width");
    vmap_a_L.u 	 	 = gg_check_new (ta ,"Arrows size");
    vmap_lines.u 	 = gg_check_new (ta ,"style");
    vmap_a_dL_ff.u 	 = gg_check_new (ta ,"d/L");
    vmap_a_lL_ff.u 	 = gg_check_new (ta ,"l/L");
    vmap_a_type.u 	 = gg_check_new (ta ,"type");
    vmap_color.u 	 = gg_check_new (ta ,"Color");

    ta 	      	    	 = gg_frame     (vb ,"Colormap"  ,&wheat ,4 ,2);
    cmap_nmap.u          = gg_check_new (ta ,"Map");
    contour_hidden.u     = gg_check_new (ta ,"Hide");
    contour_linew.u      = gg_check_new (ta ,"Width");
    contour_line_color.u = gg_check_new (ta ,"Color");
  }
  gtk_widget_show_all (u_sets_dialog);
  return u_sets_dialog;
}

static int ge_sets_u_apply (int gno ,int setno)
{
  plotarr p;
  int isymchar;
  QDobject *po;
  int num = obj_tid_get_set_num (gno ,setno);
  block_instant_update = TRUE;
  wu_get_int (layer ,&objs[num].layer);

  get_graph_plotarr (get_cg() ,setno ,&p);
  po = obj_tid_get_pointer (Q_Set ,setno ,get_cg());

  wu_get_int  (legend_on          ,&(p.legend_on));
  wu_get_int  (sym                ,&(p.sym));
  wu_get_dble (symsize            ,&(p.symsize));
  wu_get_int  (sym_color          ,&(p.sympen.color));
  wu_get_int  (sym_pattern        ,&(p.sympen.pattern));
  wu_get_int  (symfill_color      ,&(p.symfillpen.color));
  wu_get_int  (symfill_pattern    ,&(p.symfillpen.pattern));
  wu_get_int  (symlines           ,&(p.symlines));
  wu_get_dble (symlinew           ,&(p.symlinew));
  wu_get_int  (symskip            ,&(p.symskip));
  wu_get_int  (symstart           ,&(p.symstart));
  wu_get_int  (symchar            ,&isymchar); p.symchar = (unsigned char) isymchar;
  wu_get_int  (charfont           ,&(p.charfont));
  wu_get_int  (linet              ,&(p.linet));
  wu_get_int  (lines              ,&(p.lines));
  wu_get_dble (linew              ,&(p.linew));
  wu_get_int  (line_color         ,&(p.linepen.color));
  wu_get_int  (line_pattern       ,&(p.linepen.pattern));
  wu_get_int  (baseline_type      ,&(p.baseline_type));
  wu_get_int  (baseline           ,&(p.baseline));
  wu_get_int  (filltype           ,&(p.filltype));
  //    p.fillrule                 = FILLRULE_WINDING;         /* fillrule = gg_get_int (fillrule */
  wu_get_int  (setfillpen_color   ,&(p.setfillpen.color));
  wu_get_int  (setfillpen_pattern ,&(p.setfillpen.pattern));

  wu_get_int  (avalue_active      ,&(p.avalue.active));
  wu_get_int  (avalue_type        ,&(p.avalue.type));
  wu_get_dble (avalue_size        ,&(p.avalue.size));
  wu_get_int  (avalue_font        ,&(p.avalue.font));
  wu_get_int  (avalue_color       ,&(p.avalue.color));
  wu_get_int  (avalue_angle       ,&(p.avalue.angle));
  wu_get_int  (avalue_format      ,&(p.avalue.format));
  wu_get_int  (avalue_prec        ,&(p.avalue.prec));
  if (gg_get_int (avalue_prestr.u)) {
    strncpy (p.avalue.prestr ,gg_getstr (avalue_prestr.w) ,63);
  }
  if (gg_get_int (avalue_appstr.u)) {
    strncpy (p.avalue.appstr ,gg_getstr (avalue_appstr.w) ,63);
  }
  if (wu_evalexpr (avalue_offset_x ,&(p.avalue.offset.x)) == RETURN_FAILURE) {
    errmsg( "Error reading annotation X offset" );
    block_instant_update = FALSE;
    return RETURN_FAILURE;
  }
  if (wu_evalexpr (avalue_offset_y ,&(p.avalue.offset.y)) == RETURN_FAILURE) {
    errmsg( "Error reading annotation Y offset" );
    block_instant_update = FALSE;
    return RETURN_FAILURE;
  }
  wu_get_int  (avalue_skip        ,&(p.avalue.skip));
  wu_get_int  (avalue_start       ,&(p.avalue.start));

  wu_get_int  (errbar_active      ,&(p.errbar.active));
  wu_get_op   (errbar_ptype       ,&(p.errbar.ptype));
  wu_get_int  (errbar_pen_color   ,&(p.errbar.pen.color));
  wu_get_int  (errbar_pen_pattern ,&(p.errbar.pen.pattern));
  wu_get_dble (errbar_linew       ,&(p.errbar.linew));
  wu_get_int  (errbar_lines       ,&(p.errbar.lines));
  wu_get_dble (errbar_riser_linew ,&(p.errbar.riser_linew));
  wu_get_int  (errbar_riser_lines ,&(p.errbar.riser_lines));
  wu_get_dble (errbar_barsize     ,&(p.errbar.barsize));
  wu_get_int  (errbar_arrow_clip  ,&(p.errbar.arrow_clip));
  wu_get_dble (errbar_cliplen     ,&(p.errbar.cliplen));
  wu_get_int  (meshlen            ,&(p.meshlen));
  wu_get_int  (method             ,&(p.method));
  wu_get_dble (xspline_s          ,&(po->xspline_s));
  wu_get_dble (xspline_p          ,&(po->xspline_p));

  wu_get_int  (cmap_nmap          ,&(p.contour.nmap));
  wu_get_int  (contour_hidden     ,&(p.contour.hidden));
  wu_get_dble (contour_linew      ,&(p.linew));
  wu_get_int  (contour_line_color ,&(p.contour.line_color));

  set_graph_plotarr  (gno ,setno ,&p);
  block_instant_update = FALSE;
  return RETURN_SUCCESS;
}

static void ge_sets_u_AAC_CB (GtkWidget *widget ,gint reponse)
{
  int gno ,setno;
  if (reponse == U_SETS_RESET) {
    wu_reset_u (layer);
    wu_reset_u (legend_on);
    wu_reset_u (linet);
    wu_reset_u (method);
    wu_reset_u (meshlen);
    wu_reset_u (lines);
    wu_reset_u (linew);
    wu_reset_u (line_color);
    wu_reset_u (dropline);
    wu_reset_u (baseline);
    wu_reset_u (line_pattern);
    wu_reset_u (baseline_type);
    wu_reset_u (filltype);
    wu_reset_u (setfillpen_pattern);
    wu_reset_u (setfillpen_color);
    wu_reset_u (sym);
    wu_reset_u (sym_color);
    wu_reset_u (symsize);
    wu_reset_u (symskip);
    wu_reset_u (symstart);
    wu_reset_u (symchar);
    wu_reset_u (charfont);
    wu_reset_u (symlines);
    wu_reset_u (symlinew);
    wu_reset_u (sym_pattern);
    wu_reset_u (symfill_color);
    wu_reset_u (symfill_pattern);
    wu_reset_u (avalue_active);
    wu_reset_u (avalue_font);
    wu_reset_u (avalue_color);
    wu_reset_u (avalue_size);
    wu_reset_u (avalue_angle);
    wu_reset_u (avalue_prestr);
    wu_reset_u (avalue_appstr);
    wu_reset_u (avalue_skip);
    wu_reset_u (avalue_start);
    wu_reset_u (avalue_type);
    wu_reset_u (avalue_prec);
    wu_reset_u (avalue_format);
    wu_reset_u (avalue_offset_x);
    wu_reset_u (avalue_offset_y);
    wu_reset_u (errbar_active);
    wu_reset_u (errbar_ptype);
    wu_reset_u (errbar_pen_color);
    wu_reset_u (errbar_pen_pattern);
    wu_reset_u (errbar_arrow_clip);
    wu_reset_u (errbar_cliplen);
    wu_reset_u (errbar_barsize);
    wu_reset_u (errbar_linew);
    wu_reset_u (errbar_lines);
    wu_reset_u (errbar_riser_linew);
    wu_reset_u (errbar_riser_lines);
    wu_reset_u (vmap_norm);
    wu_reset_u (vmap_a_L);
    wu_reset_u (vmap_linew);
    wu_reset_u (vmap_lines);
    wu_reset_u (vmap_a_dL_ff);
    wu_reset_u (vmap_a_lL_ff);
    wu_reset_u (vmap_a_type);
    wu_reset_u (vmap_color);
    wu_reset_u (cmap_nmap);
    wu_reset_u (contour_hidden);
    wu_reset_u (contour_linew);
    wu_reset_u (contour_line_color);
  } else if (reponse == GTK_RESPONSE_ACCEPT || reponse == GTK_RESPONSE_APPLY) {
    Qtype typ;
    GtkTreeIter iter;
    GtkTreeSelection *select;
    GList *lpath = NULL;
    Ge_tree *getree;
    getree = get_getree ();
    int n = ge_selection_is_homogeneous (&typ);
    if (n < 1 || typ != Q_Set) {
      errmsg ("Selection must have one or several sets only");
      return;
    }
    select = gtk_tree_view_get_selection (GTK_TREE_VIEW (getree->view));
    lpath  = gtk_tree_selection_get_selected_rows (select ,&(getree->model));
    while (lpath != NULL) {
      if (gtk_tree_model_get_iter (getree->model ,&iter ,lpath->data)) {
	gtk_tree_model_get (getree->model ,&iter
			    ,GE_TREE_TYP       ,&typ
			    ,GE_TREE_ID        ,&setno
			    ,GE_TREE_PARENT_ID ,&gno
			    ,-1);
 	if (ge_sets_u_apply (gno ,setno) == RETURN_FAILURE) return;
	lpath = g_list_next (lpath);
      }
    }
    gg_update_layers_hbox ();
    set_dirtystate ();
    gg_drawgraph   ();
  }
  if (reponse == GTK_RESPONSE_ACCEPT || reponse == GTK_RESPONSE_CLOSE) {
    gtk_widget_hide (u_sets_dialog);
  }
  wu_update_on (FALSE);

}

/******************** GRACE-5 COMPATIBILITY ********************/

void ge_set_g5compat_CB (GtkWidget *w ,gpointer p)
{
  int gno = get_cg ();
  int i   = obj_tid_get_graph_num (gno);
  ge_explorer_popup ();
  ge_unselect_all   ();
  if (obj_is_active (i)) {
    if (is_valid_setno (gno ,0)) {
      i = obj_tid_get_set_num (gno ,0);
      obj_make_current (i);
    }
    obj_make_current (i);
    current_page = 0;
    ge_expand_current ();
    ge_select_current ();
  } else {                   /* should not happen */
    ge_project_set_page ();
  }
}
