#include "snd.h"
#include <X11/cursorfont.h>

enum {menu_menu,
        file_menu,f_cascade_menu,
          f_open_menu,f_close_menu,f_save_menu,f_save_as_menu,f_revert_menu,f_exit_menu,f_new_menu,
          f_view_menu,f_print_menu,f_mix_menu,f_update_menu,f_record_menu,
        edit_menu,e_cascade_menu,
          e_cut_menu,e_paste_menu,e_mix_menu,e_play_menu,e_save_as_menu,e_undo_menu,
          e_redo_menu,e_find_menu,e_edenv_menu,e_header_menu,e_history_menu,
        help_menu,h_cascade_menu,
          h_click_for_help_menu,h_about_snd_menu,h_fft_menu,h_find_menu,h_undo_menu,h_sync_menu,h_speed_menu,
          h_expand_menu,h_contrast_menu,h_reverb_menu,h_env_menu,h_marks_menu,h_sound_files_menu,h_init_file_menu,
          h_mix_menu,h_recording_menu,
        option_menu,o_cascade_menu,
          o_transform_menu,
          o_focus_style_menu,o_focus_cascade_menu,
            o_focus_right_menu,o_focus_left_menu,o_focus_middle_menu,o_focus_active_menu,
          o_subsampling_menu,o_save_menu,o_session_menu,
          o_speed_menu,o_speed_cascade_menu,
            o_speed_float_menu,o_speed_ratio_menu,o_speed_semitone_menu,
        view_menu,v_cascade_menu,
          v_normalize_menu, 
          v_graph_style_menu, v_graph_style_cascade_menu,
            v_lines_menu,v_dots_menu,v_filled_menu,
          v_marks_menu, v_zero_menu, v_cursor_menu, v_ctrls_menu, v_listener_menu,
          v_region_menu,
          v_combine_menu, v_combine_cascade_menu,
            v_combine_separate_menu,v_combine_combined_menu,v_combine_superimposed_menu,
          v_color_menu, v_orientation_menu, 
          v_files_menu, v_groups_menu, v_consoles_menu,
          v_x_axis_menu,v_x_axis_cascade_menu,
            v_x_axis_seconds_menu,v_x_axis_samples_menu,v_x_axis_percentage_menu
};

#define NUM_MENU_WIDGETS 92
static Widget mw[NUM_MENU_WIDGETS];

enum {W_pop_menu,W_pop_sep,W_pop_play,W_pop_undo,W_pop_redo,W_pop_save,W_pop_normalize,W_pop_info};
#define NUM_POPUP_CHILDREN 8
static Widget popup_menu = NULL;
static Widget popup_children[NUM_POPUP_CHILDREN];

void reflect_file_open_in_menu (void)
{
  XtSetSensitive(mw[f_close_menu],TRUE);
  XtSetSensitive(mw[f_print_menu],TRUE);
  XtSetSensitive(mw[f_mix_menu],TRUE);
  XtSetSensitive(mw[f_save_as_menu],TRUE);
  XtSetSensitive(mw[f_update_menu],TRUE);  
  XtSetSensitive(mw[v_normalize_menu],TRUE);  
  XtSetSensitive(mw[e_header_menu],TRUE);
  XtSetSensitive(mw[e_find_menu],TRUE);
  if (popup_menu)
    {
      XtSetSensitive(popup_children[W_pop_normalize],TRUE);
      XtSetSensitive(popup_children[W_pop_play],TRUE);
      XtSetSensitive(popup_children[W_pop_info],TRUE);
    }
}

void reflect_file_change_in_menu (void)
{
  XtSetSensitive(mw[f_save_menu],TRUE);
  XtSetSensitive(mw[f_revert_menu],TRUE);
  XtSetSensitive(mw[e_undo_menu],TRUE);
  if (popup_menu)
    {
      XtSetSensitive(popup_children[W_pop_undo],TRUE);
      XtSetSensitive(popup_children[W_pop_save],TRUE);
      XtSetSensitive(popup_children[W_pop_play],TRUE);
    }
}

void reflect_file_lack_in_menu (void)
{
  XtSetSensitive(mw[f_close_menu],FALSE);
  XtSetSensitive(mw[f_save_as_menu],FALSE);
  XtSetSensitive(mw[f_save_menu],FALSE);
  XtSetSensitive(mw[f_revert_menu],FALSE);
  XtSetSensitive(mw[f_print_menu],FALSE);
  XtSetSensitive(mw[f_mix_menu],FALSE);
  XtSetSensitive(mw[f_update_menu],FALSE);
  XtSetSensitive(mw[e_undo_menu],FALSE);
  XtSetSensitive(mw[e_redo_menu],FALSE);
  XtSetSensitive(mw[v_normalize_menu],FALSE);
  XtSetSensitive(mw[e_header_menu],FALSE);
  XtSetSensitive(mw[e_find_menu],FALSE);
  if (popup_menu)
    {
      XtSetSensitive(popup_children[W_pop_undo],FALSE);
      XtSetSensitive(popup_children[W_pop_redo],FALSE);
      XtSetSensitive(popup_children[W_pop_save],FALSE);
      XtSetSensitive(popup_children[W_pop_play],FALSE);
      XtSetSensitive(popup_children[W_pop_info],FALSE);
      XtSetSensitive(popup_children[W_pop_normalize],FALSE);
    }
}

void set_normalize_option(int on)
{
  XtSetSensitive(mw[v_normalize_menu],on);
}

static int find_any_edits (chan_info *cp, void *ptr)
{
  return(cp->edit_ctr);
}

static int find_any_possible_edits (chan_info *cp, void *ptr)
{
  return(cp->edit_size);
}

void reflect_file_revert_in_menu (snd_state *ss)
{
  int editing;
  editing = map_over_chans(ss,find_any_edits,NULL);
  if (!editing)
    {
      XtSetSensitive(mw[f_save_menu],FALSE);
      XtSetSensitive(mw[f_revert_menu],FALSE);
      XtSetSensitive(mw[e_undo_menu],FALSE);
      if (popup_menu)
	{
	  XtSetSensitive(popup_children[W_pop_undo],FALSE);
	  XtSetSensitive(popup_children[W_pop_save],FALSE);
	}
    }
  XtSetSensitive(mw[e_redo_menu],TRUE);
  if (popup_menu) XtSetSensitive(popup_children[W_pop_redo],TRUE);
}

void reflect_file_save_in_menu (snd_state *ss)
{
  int editing;
  editing = map_over_chans(ss,find_any_edits,NULL);
  if (!editing)
    {
      XtSetSensitive(mw[f_save_menu],FALSE);
      XtSetSensitive(mw[f_revert_menu],FALSE);
      XtSetSensitive(mw[e_undo_menu],FALSE);
      if (popup_menu)
	{
	  XtSetSensitive(popup_children[W_pop_undo],FALSE);
	  XtSetSensitive(popup_children[W_pop_save],FALSE);
	  XtSetSensitive(popup_children[W_pop_redo],FALSE);
	}
      XtSetSensitive(mw[e_redo_menu],FALSE);
    }
  editing = map_over_chans(ss,find_any_possible_edits,NULL);
}

void reflect_file_revert_in_label (snd_info *sp)
{
  int editing;
  editing = map_over_sound_chans(sp,find_any_edits,NULL);
  if (!editing)
    {
      make_name_label(snd_widget(sp,W_snd_name),shortname(sp));
      make_a_big_star_outa_me(sp->state,sp->shortname,0);
    }
}

void reflect_no_more_redo_in_menu(void)
{
  XtSetSensitive(mw[e_redo_menu],FALSE);
  if (popup_menu) XtSetSensitive(popup_children[W_pop_redo],FALSE);
}

void reflect_edit_with_selection_in_menu (void)
{
  XtSetSensitive(mw[e_cut_menu],TRUE);
  XtSetSensitive(mw[e_play_menu],TRUE);
  XtSetSensitive(mw[e_mix_menu],TRUE);
  XtSetSensitive(mw[e_save_as_menu],TRUE);
}

void reflect_edit_without_selection_in_menu (void)
{
  XtSetSensitive(mw[e_cut_menu],FALSE);
  XtSetSensitive(mw[e_play_menu],FALSE);
}

void reflect_undo_in_menu(void)
{
  XtSetSensitive(mw[e_redo_menu],TRUE);
  if (popup_menu) XtSetSensitive(popup_children[W_pop_redo],TRUE);
}

void reflect_redo_in_menu(void)
{
  XtSetSensitive(mw[e_undo_menu],TRUE);
  if (popup_menu) XtSetSensitive(popup_children[W_pop_undo],TRUE);
  reflect_file_change_in_menu();
}

void reflect_undo_ok_in_menu(void)
{
  XtSetSensitive(mw[e_undo_menu],TRUE);
  if (popup_menu) XtSetSensitive(popup_children[W_pop_undo],TRUE);
}

void reflect_undo_or_redo_in_menu(chan_info *cp)
{
  int undoable,redoable;
  if (cp)
    {
      undoable = (cp->edit_ctr > 0);
      redoable = (!(((cp->edit_ctr+1) == cp->edit_size) || (!(cp->edits[cp->edit_ctr+1]))));
      XtSetSensitive(mw[e_undo_menu],undoable);
      if (popup_menu) XtSetSensitive(popup_children[W_pop_undo],undoable);
      XtSetSensitive(mw[e_redo_menu],redoable);
      if (popup_menu) XtSetSensitive(popup_children[W_pop_redo],redoable);
    }
}

void reflect_regions_in_menu(void)
{
  XtSetSensitive(mw[v_region_menu],TRUE);
  XtSetSensitive(mw[e_save_as_menu],TRUE);
}

void reflect_no_regions_in_menu(void)
{
  XtSetSensitive(mw[v_region_menu],FALSE);
  XtSetSensitive(mw[e_save_as_menu],FALSE);
}

void reflect_raw_open_in_menu(void)
{
  XtSetSensitive(mw[f_open_menu],TRUE);
  XtSetSensitive(mw[f_view_menu],TRUE);
  XtSetSensitive(mw[f_new_menu],TRUE);
}

void reflect_raw_pending_in_menu(void)
{
  XtSetSensitive(mw[f_open_menu],FALSE);
  XtSetSensitive(mw[f_view_menu],FALSE);
  XtSetSensitive(mw[f_new_menu],FALSE);
}


/* -------------------------------- FILE MENU -------------------------------- */

static void File_Open_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  snd_open_file_dialog(w,(snd_state *)clientData);
}

static void File_View_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  snd_state *ss = (snd_state *)clientData;
  ss->viewing = 1;
  snd_open_file_dialog(w,ss);
}

static void File_New_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  snd_new_file((snd_state *)clientData,NULL);
}

static void File_Help_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,"File Menu","#fileoperations");
#else
  ssnd_help((snd_state *)clientData,
          "File Menu",
"The File menu provides one way to open,\n\
close, and save files. Its options are:\n\
\n",
get_file_menu_help(),
"\n\
The Print option produces a Postscript file;\n\
you can print it with lpr.\n",
NULL);
#endif
}

static void File_Record_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  snd_record_file((snd_state *)clientData);
}

static void File_Close_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  snd_info *sp;
  finish_keyboard_selection();
  sp = any_selected_sound(ss);
  if (!sp) return;
  snd_close_file(sp,ss);
}

static void File_Save_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_info *sp;
  snd_state *ss = (snd_state *)clientData;
  finish_keyboard_selection();
  sp = any_selected_sound(ss);
  save_edits(sp,NULL);
}

static void File_Update_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  snd_info *sp;
  finish_keyboard_selection();
  sp = any_selected_sound(ss);
  if (!sp) return;
  snd_update(ss,sp);
}

static void File_Save_As_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_save_as_dialog(w,(snd_state *)clientData);
}

static void File_Revert_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  snd_info *sp;
  int i;
  finish_keyboard_selection();
  sp = any_selected_sound(ss);
  for (i=0;i<sp->nchans;i++) revert_edits(sp->chans[i],NULL);
  reflect_file_revert_in_label(sp);
  reflect_file_revert_in_menu(ss);
}

static void File_Exit_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  finish_keyboard_selection();
  if (dont_exit(ss)) return;
  snd_exit_cleanly(ss);
  exit(1);
}



/* -------------------------------- EDIT MENU -------------------------------- */


static void Edit_Mix_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  chan_info *cp;
  finish_keyboard_selection();
  cp = selected_channel((snd_state *)clientData);
  if (cp) add_region(0,cp,"Edit: mix");
}

static void Edit_Envelope_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  create_envelope_editor((snd_state *)clientData);
}

static void Edit_Help_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,"Edit Menu","#editoperations");
#else
  ssnd_help((snd_state *)clientData,
	    "Edit Menu",
"The Edit Menu options apply to the\n\
current selection in most cases.  The\n\
successive selections are saved on a stack\n\
of 'regions' accessible via ctrl-Y.\n\
The selection can be retrieved by or\n\
from other programs or within Snd with\n\
the middle mouse button.  The options are:\n\
\n",
get_edit_menu_help(),
NULL);
#endif
}

static void Edit_Cut_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  finish_keyboard_selection();
  if (region_ok(0))
    {
      delete_selection("Edit: Cut");
    }
}

static void Edit_Paste_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  chan_info *cp;
  finish_keyboard_selection();
  cp = selected_channel((snd_state *)clientData);
  if (cp) paste_region(0,cp,"Edit: Paste");
}

static void Edit_Save_As_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  /* refers to the selection */
  snd_edit_save_as_dialog(w,(snd_state *)clientData);
}

static void Edit_Undo_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  finish_keyboard_selection();
  undo_EDIT((void *)clientData,1);
}

static void Edit_Redo_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  finish_keyboard_selection();
  redo_EDIT((void *)clientData,1);
}

static void Edit_Header_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  snd_info *sp;
  sp = selected_sound(ss);
  if (sp) edit_header(sp);
}

static void Edit_Play_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  finish_keyboard_selection();
  if (region_ok(0)) play_region((snd_state *)clientData,0,NULL);
}

void edit_history(snd_state *ss, int on)
{
  /* update menu label also */
  int wid;
  if ((on) && (edit_history_width(ss) == 0))
    {
      wid = get_window_width(main_PANE(ss));
      if (wid > 200) wid = 100; else wid = wid/2;
      in_set_edit_history_width(ss,wid); 
    }
  set_show_edit_history(ss,on);
  make_name_label(mw[e_history_menu],(on) ? snd_string_Hide_edit_history : snd_string_Show_edit_history);
  if (on)
    map_over_chans(ss,open_edit_histories,NULL);
  else map_over_chans(ss,close_edit_histories,NULL);
}

static void Edit_History_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  edit_history(ss,(!(show_edit_history(ss))));
}


/* -------------------------------- VIEW MENU -------------------------------- */

static void View_Help_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,"View Menu","#viewing");
#else
  ssnd_help((snd_state *)clientData,
	    "View Menu",
"The View Menu affects the overall Snd display.\n\
Its options are:\n\
\n\
",
get_view_menu_help(),
NULL);
#endif
}

static void update_all_graphs(snd_state *ss)
{
  map_over_chans(ss,update_graph,NULL);
}

static int update_axes(chan_info *cp, void *ptr)
{
  set_xy_bounds(cp,cp->axis);
  return(0);
}

void set_wavo(snd_state *ss, int on)
{
  in_set_wavo(ss,on);
  if (on == 0) map_over_chans(ss,update_axes,NULL);
  update_all_graphs(ss);
}

static int update_sound(snd_info *sp, void *ptr)
{
  snd_state *ss = (snd_state *)ptr;
  if (sp)
    {
      switch (channel_style(ss))
	{
	case CHANNELS_SEPARATE: separate_sound(sp); break;
	case CHANNELS_COMBINED: combine_sound(sp); break;
	case CHANNELS_SUPERIMPOSED: superimpose_sound(sp); break;
	}
    }
  return(0);
}

static void update_all_sounds(snd_state *ss)
{
  map_over_sounds(ss,update_sound,(void *)ss);
}

void set_channel_style(snd_state *ss, int val)
{
  switch (channel_style(ss))
    {
    case CHANNELS_SEPARATE: XtSetSensitive(mw[v_combine_separate_menu],TRUE); break;
    case CHANNELS_COMBINED: XtSetSensitive(mw[v_combine_combined_menu],TRUE); break;
    case CHANNELS_SUPERIMPOSED: XtSetSensitive(mw[v_combine_superimposed_menu],TRUE); break;
    }
  in_set_channel_style(ss,val);
  switch (val)
    {
    case CHANNELS_SEPARATE: XtSetSensitive(mw[v_combine_separate_menu],FALSE); break;
    case CHANNELS_COMBINED: XtSetSensitive(mw[v_combine_combined_menu],FALSE); break;
    case CHANNELS_SUPERIMPOSED: XtSetSensitive(mw[v_combine_superimposed_menu],FALSE); break;
    }
  update_all_sounds(ss);
  update_all_graphs(ss);
}

static void View_Separate_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  set_channel_style(ss,CHANNELS_SEPARATE);
}

static void View_Combined_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  set_channel_style(ss,CHANNELS_COMBINED);
}

static void View_Superimposed_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  set_channel_style(ss,CHANNELS_SUPERIMPOSED);
}


static void View_Normalize_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  normalize_all_sounds((snd_state *)clientData);
}


void set_graph_style(snd_state *ss, int val)
{
  switch (graph_style(ss))
    {
    case GRAPH_LINES: XtSetSensitive(mw[v_lines_menu],TRUE); break;
    case GRAPH_DOTS: XtSetSensitive(mw[v_dots_menu],TRUE); break;
    case GRAPH_FILLED: XtSetSensitive(mw[v_filled_menu],TRUE); break;
    }
  in_set_graph_style(ss,val);
  update_all_graphs(ss);
  switch (val)
    {
    case GRAPH_LINES: XtSetSensitive(mw[v_lines_menu],FALSE); break;
    case GRAPH_DOTS: XtSetSensitive(mw[v_dots_menu],FALSE); break;
    case GRAPH_FILLED: XtSetSensitive(mw[v_filled_menu],FALSE); break;
    }
}

static void View_Dots_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  set_graph_style(ss,GRAPH_DOTS);
}

static void View_Lines_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  set_graph_style(ss,GRAPH_LINES);
}

static void View_Filled_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  set_graph_style(ss,GRAPH_FILLED);
}

void set_show_marks(snd_state *ss, int val)
{
  in_set_show_marks(ss,val);
  if (mw[v_marks_menu])
    {
      make_name_label(mw[v_marks_menu],(val) ? snd_string_Hide_marks : snd_string_Show_marks);
      update_all_graphs(ss);
    }
}

static void View_Marks_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  /* similar to subsampling or dots menus */
  snd_state *ss = (snd_state *)clientData;
  set_show_marks(ss,(!(show_marks(ss))));
}

void set_show_y_zero(snd_state *ss, int val)
{
  in_set_show_y_zero(ss,val);
  if (mw[v_zero_menu])
    {
      make_name_label(mw[v_zero_menu],(val) ? snd_string_Hide_Y0 : snd_string_Show_Y0);
      update_all_graphs(ss);
    }
}

static void View_Zero_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  set_show_y_zero(ss,(!(show_y_zero(ss))));
}

static int clrmini(snd_info *sp, void *ptr) {clear_minibuffer(sp); return(0);}

void set_verbose_cursor(snd_state *ss, int val)
{
  in_set_verbose_cursor(ss,val);
  if (val == 0) map_over_sounds(ss,clrmini,NULL);
  if (mw[v_cursor_menu])
	make_name_label(mw[v_cursor_menu],(val) ? snd_string_Silent_cursor : snd_string_Verbose_cursor);
}

static void View_Cursor_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  set_verbose_cursor(ss,(!(verbose_cursor(ss))));
}

void set_view_ctrls_label(char *lab)
{
  make_name_label(mw[v_ctrls_menu],lab);
}

static void View_Ctrls_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  if (ss->ctrls_height < 100) show_controls(ss); else hide_controls(ss);
}

void set_view_listener_label(char *lab)
{
  make_name_label(mw[v_listener_menu],lab);
}

static void View_Listener_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  handle_listener(ss);
}

void set_show_mix_consoles(snd_state *ss, int on)
{
  in_set_show_mix_consoles(ss,on);
  make_name_label(mw[v_consoles_menu],(on) ? snd_string_Hide_consoles : snd_string_Show_consoles);
  update_all_consoles(ss);
}

static void View_Groups_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  fire_up_group_browser((snd_state *)clientData);
}

static void View_Consoles_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  set_show_mix_consoles(ss,!(show_mix_consoles(ss)));
}


/* -------------------------------- OPTIONS MENU -------------------------------- */

static void Options_Help_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,"Options Menu","#options");
#else
  ssnd_help((snd_state *)clientData,
	   "Options Menu",
"The Options menu items affect how the FFT\n\
operates, and whatnot.  The items are:\n\
\n\
",
get_options_menu_help(),
NULL);
#endif
}

static void Options_Transform_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  fire_up_transform_dialog((snd_state *)clientData);
}


/* Save Options */

static void Options_Save_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  snd_state *ss = (snd_state *)clientData;
  if (save_options(ss) == 0)
    {
      if (any_selected_sound(ss))
	report_in_minibuffer(any_selected_sound(ss),"saved");
    }
  else snd_printf(ss,"options not saved!");
}

void set_subsampling(snd_state *ss, int val)
{
  in_set_subsampling(ss,val);
  if (mw[o_subsampling_menu])
    {
      make_name_label(mw[o_subsampling_menu],(val) ? snd_string_Subsampling_off : snd_string_Subsampling_on);
      if (!(ss->graph_hook_active)) update_all_graphs(ss);
    }
}

static void Options_Subsampling_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  snd_state *ss = (snd_state *)clientData;
  set_subsampling(ss,(!(subsampling(ss))));
}


void activate_focus_menu(snd_state *ss, int new_focus)
{
  if (mw[o_focus_left_menu])
    {
      switch (zoom_focus_style(ss))
	{
	case FOCUS_LEFT: XtSetSensitive(mw[o_focus_left_menu],TRUE); break;
	case FOCUS_RIGHT: XtSetSensitive(mw[o_focus_right_menu],TRUE); break;
	case FOCUS_MIDDLE: XtSetSensitive(mw[o_focus_middle_menu],TRUE); break;
	case FOCUS_ACTIVE: XtSetSensitive(mw[o_focus_active_menu],TRUE); break;
	}
    }
  set_zoom_focus_style(ss,new_focus);
  if (mw[o_focus_left_menu])
    {
      switch (new_focus)
	{
	case FOCUS_LEFT: XtSetSensitive(mw[o_focus_left_menu],FALSE); break;
	case FOCUS_RIGHT: XtSetSensitive(mw[o_focus_right_menu],FALSE); break;
	case FOCUS_MIDDLE: XtSetSensitive(mw[o_focus_middle_menu],FALSE); break;
	case FOCUS_ACTIVE: XtSetSensitive(mw[o_focus_active_menu],FALSE); break;
	}
    }
}  

static void Options_Focus_Right_Callback(Widget w,XtPointer clientData,XtPointer Data) {activate_focus_menu((snd_state *)clientData,FOCUS_RIGHT);}
static void Options_Focus_Left_Callback(Widget w,XtPointer clientData,XtPointer Data) {activate_focus_menu((snd_state *)clientData,FOCUS_LEFT);}
static void Options_Focus_Middle_Callback(Widget w,XtPointer clientData,XtPointer Data) {activate_focus_menu((snd_state *)clientData,FOCUS_MIDDLE);}
static void Options_Focus_Active_Callback(Widget w,XtPointer clientData,XtPointer Data) {activate_focus_menu((snd_state *)clientData,FOCUS_ACTIVE);}


void activate_speed_in_menu(snd_state *ss, int newval)
{
  if (mw[o_speed_ratio_menu])
    {
      switch (speed_style(ss))
	{
	case SPEED_AS_RATIO: XtSetSensitive(mw[o_speed_ratio_menu],TRUE); break;
	case SPEED_AS_SEMITONE: XtSetSensitive(mw[o_speed_semitone_menu],TRUE); break;
	default: XtSetSensitive(mw[o_speed_float_menu],TRUE); break;
	}
    }
  in_set_speed_style(ss,newval);
  if (mw[o_speed_ratio_menu])
    {
      switch (speed_style(ss))
	{
	case SPEED_AS_RATIO: XtSetSensitive(mw[o_speed_ratio_menu],FALSE); break;
	case SPEED_AS_SEMITONE: XtSetSensitive(mw[o_speed_semitone_menu],FALSE); break;
	default: XtSetSensitive(mw[o_speed_float_menu],FALSE); break;
	}
    }
}

static void Options_Speed_Float_Callback(Widget w,XtPointer cD,XtPointer Data) {activate_speed_in_menu((snd_state *)cD,SPEED_AS_FLOAT);}
static void Options_Speed_Ratio_Callback(Widget w,XtPointer cD,XtPointer Data) {activate_speed_in_menu((snd_state *)cD,SPEED_AS_RATIO);}
static void Options_Speed_Semitone_Callback(Widget w,XtPointer cD,XtPointer Data) {activate_speed_in_menu((snd_state *)cD,SPEED_AS_SEMITONE);}

static void reflect_x_axis_unit_change_in_menu(int oldval, int newval)
{
  switch (oldval)
    {
    case X_IN_SECONDS: XtSetSensitive(mw[v_x_axis_seconds_menu],TRUE); break;
    case X_IN_SAMPLES: XtSetSensitive(mw[v_x_axis_samples_menu],TRUE); break;
    case X_TO_ONE: XtSetSensitive(mw[v_x_axis_percentage_menu],TRUE); break;
    default: XtSetSensitive(mw[v_x_axis_seconds_menu],TRUE); break;
    }
  switch (newval)
    {
    case X_IN_SECONDS: XtSetSensitive(mw[v_x_axis_seconds_menu],FALSE); break;
    case X_IN_SAMPLES: XtSetSensitive(mw[v_x_axis_samples_menu],FALSE); break;
    case X_TO_ONE: XtSetSensitive(mw[v_x_axis_percentage_menu],FALSE); break;
    default: XtSetSensitive(mw[v_x_axis_seconds_menu],FALSE); break;
    }
}
  
void set_x_axis_style(snd_state *ss, int val)
{
  reflect_x_axis_unit_change_in_menu(x_axis_style(ss),val);
  in_set_x_axis_style(ss,val);
}

static void Options_X_Axis_Seconds_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  set_x_axis_style((snd_state *)clientData,X_IN_SECONDS);
}

static void Options_X_Axis_Samples_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  set_x_axis_style((snd_state *)clientData,X_IN_SAMPLES);
}

static void Options_X_Axis_Percentage_Callback(Widget w,XtPointer clientData,XtPointer callData)
{
  set_x_axis_style((snd_state *)clientData,X_TO_ONE);
}



/* -------------------------------- HELP MENU -------------------------------- */

static void Help_Help_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,"Help Menu","#menus");
#else
  ssnd_help((snd_state *)clientData,
          "Help Menu",
"The Help menu tries to provide quick\n\
help for the most common Snd operations.\n\
The menu items are:\n\
\n",
get_help_menu_help(),
NULL);
#endif
}

static void Help_Context_Help_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *)callData;
  Widget selectedWidget = NULL;
  static Cursor cursor = 0;
  Widget parent = XtParent(w);
  snd_state *ss = (snd_state *)clientData;
  Widget mainWindow;
  mainWindow = main_PANE(ss);
  if (!cursor) cursor = XCreateFontCursor(XtDisplay(parent),XC_question_arrow); 
  selectedWidget = XmTrackingLocate(mainWindow,cursor,FALSE);
  if (selectedWidget)
    {
      XmAnyCallbackStruct cb;
      cb.reason = XmCR_HELP;
      cb.event = cbs->event;
      do
        {
	  if ((XtHasCallbacks(selectedWidget,XmNhelpCallback) == XtCallbackHasSome))
            {
	      XtCallCallbacks(selectedWidget,XmNhelpCallback,&cb);
	      return;
            }
	  else
	    selectedWidget = XtParent(selectedWidget);
        } while (selectedWidget != NULL);
    }
}

static void Help_About_Snd_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,"Snd","#gettingstarted");
#else
  ssnd_help((snd_state *)clientData,
               "Snd",
get_about_snd_help(),
"The various Help menu items are:\n\
\n",
get_help_menu_help(),
"\n",
"The main menu items are:\n\
  File: operations on files.\n\
  Edit: operations on the current selection.\n\
  View: change Snd display choices.\n\
  Options: change Snd analysis choices.\n\
  Help: this menu.\n\
The main menu bar itself is Snd's 'drop' box.\n\
\n\
The File menu's options are:\n\
",
get_file_menu_help(),
"\n\
The Edit menu's options are:\n\
",
get_edit_menu_help(),
"\n\
The View menu's options are:\n\
",
get_view_menu_help(),
"\n\
The Options menu's items are:\n\
",
get_options_menu_help(),
"\n\
The graph editing commands are:\n\
",
get_graph_help(),
"\n\
",
get_edit_history_help(),
"\n\
",
get_fft_keypad_help(),
"\n\
",
get_mark_help(),
"\n\
",
get_init_file_help(),
"\n\
",
get_resource_help(),
"\n\
",
get_expression_help(),
NULL);
#endif
}

static void Help_FFT_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_FFT,"#viewfft");
#else
  ssnd_help((snd_state *)clientData,
	    snd_string_FFT,
get_fft_menu_help(),
"\n\
",
get_fft_keypad_help(),
NULL);
#endif
}

static void Help_Find_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Find,"#find");
#else
  ssnd_help((snd_state *)clientData,
	    snd_string_Find,
get_find_menu_help(),
"\n\
",
get_expression_help(),
NULL);
#endif
}

static void Help_Undo_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Undo,"#undoredo");
#else
  snd_help((snd_state *)clientData,snd_string_Undo,get_undo_menu_help());
#endif
}

static void Help_Sync_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Sync,"#multichannel");
#else
  snd_help((snd_state *)clientData,snd_string_Sync,get_sync_menu_help());
#endif
}

static void Help_Speed_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Speed,"#speed");
#else
  snd_help((snd_state *)clientData,snd_string_Speed,get_speed_menu_help());
#endif
}

static void Help_Expand_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Expand,"#expand");
#else
  snd_help((snd_state *)clientData,snd_string_Expand,get_expand_menu_help());
#endif
}

static void Help_Reverb_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Reverb,"#reverb");
#else
  snd_help((snd_state *)clientData,snd_string_Reverb,get_reverb_menu_help());
#endif
}

static void Help_Contrast_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Contrast,"#contrast");
#else
  snd_help((snd_state *)clientData,snd_string_Contrast,get_contrast_menu_help());
#endif
}

static void Help_Env_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Envelope,"#editenvelope");
#else
  ssnd_help((snd_state *)clientData,
	    snd_string_Envelope,
get_env_menu_help(),
"\n\
The simplest way to define and apply envelopes\n\
is to use the envelope editor via the Edit menu.\n\
\n\
",
get_envelope_editor_help(),
NULL);
#endif
}

static void Help_Marks_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Marks,"#marks");
#else
  snd_help((snd_state *)clientData,snd_string_Marks,get_mark_help());
#endif
}

static void Help_Mix_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Mixing,"#mixingfiles");
#else
  ssnd_help((snd_state *)clientData,snd_string_Mixing,get_mixing_help(),"\n",get_grouping_help(),NULL);
#endif
}

static void Help_Sound_Files_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Format,"#formats");
#else
  snd_help((snd_state *)clientData,snd_string_Format,get_format_menu_help());
#endif
}

static void Help_Init_File_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Customization,"#customization");
#else
  ssnd_help((snd_state *)clientData,snd_string_Customization,get_init_file_help(),"\n",get_resource_help(),NULL);
#endif
}

static void Help_Recording_Callback (Widget w,XtPointer clientData,XtPointer callData) 
{
#if HAVE_XmHTML
  snd_help((snd_state *)clientData,snd_string_Recording,"#recordfile");
#else
  snd_help((snd_state *)clientData,snd_string_Recording,get_recording_help());
#endif
}



/* -------------------------------- MAIN MENU -------------------------------- */

Widget get_menubar(void) {return(mw[menu_menu]);}

Widget add_menu(snd_state *state)
{
  static Arg main_args[6];
  static Arg in_args[6];
  static Arg high_args[12];
  int in_n,n,high_n,main_n,start_high_n,k,p;
  /* this mainly passes the global data pointer (state) to all the menu-related callbacks */
  
  in_n=0;
  main_n=0;
  high_n=0;
  if (!(state->using_schemes))
    {
      main_n = background_main_color(main_args,main_n,state);
      high_n = background_high_color(high_args,high_n,state);
      in_n = background_main_color(in_args,in_n,state);
    }
  start_high_n = high_n;
  XtSetArg(in_args[in_n],XmNsensitive,FALSE); in_n++;
  
  n = high_n;
  XtSetArg(high_args[n],XmNuserData,state); n++; /* used in snd-xclip by drop site to get main state data from whatever widget got the drop */
  p = n;
  XtSetArg(high_args[p],XmNtopAttachment,XmATTACH_FORM); p++;
  XtSetArg(high_args[p],XmNbottomAttachment,XmATTACH_NONE); p++;
  XtSetArg(high_args[p],XmNleftAttachment,XmATTACH_FORM); p++;
  XtSetArg(high_args[p],XmNrightAttachment,XmATTACH_FORM); p++;
  mw[menu_menu] = XmCreateMenuBar(main_PANE(state),"menuBar",high_args,p);


  /* FILE MENU */
  mw[file_menu] = XmCreatePulldownMenu(mw[menu_menu],"filem",main_args,main_n);
  
  high_n = start_high_n;
  XtSetArg(high_args[high_n],XmNsubMenuId,mw[file_menu]); high_n++;
  XtSetArg(high_args[high_n],XmNmnemonic,'F'); high_n++;
  mw[f_cascade_menu] = XtCreateManagedWidget(snd_string_File,xmCascadeButtonWidgetClass,mw[menu_menu],high_args,high_n);
  XtAddCallback(mw[f_cascade_menu],XmNhelpCallback,File_Help_Callback,state);

  mw[f_open_menu] = XtCreateManagedWidget(snd_string_Open,xmPushButtonWidgetClass,mw[file_menu],main_args,main_n);
  XtAddCallback(mw[f_open_menu],XmNactivateCallback,File_Open_Callback,state);
  XtVaSetValues(mw[f_open_menu],XmNmnemonic,'O',NULL);

  mw[f_close_menu] = XtCreateManagedWidget(snd_string_Close,xmPushButtonWidgetClass,mw[file_menu],in_args,in_n);
  XtAddCallback(mw[f_close_menu],XmNactivateCallback,File_Close_Callback,state);
  XtVaSetValues(mw[f_close_menu],XmNmnemonic,'C',NULL);
  
  mw[f_save_menu] = XtCreateManagedWidget(snd_string_Save,xmPushButtonWidgetClass,mw[file_menu],in_args,in_n);
  XtAddCallback(mw[f_save_menu],XmNactivateCallback,File_Save_Callback,state);
  XtVaSetValues(mw[f_save_menu],XmNmnemonic,'S',NULL);
  
  mw[f_save_as_menu] = XtCreateManagedWidget(snd_string_Save_as,xmPushButtonWidgetClass,mw[file_menu],in_args,in_n);
  XtAddCallback(mw[f_save_as_menu],XmNactivateCallback,File_Save_As_Callback,state);
  XtVaSetValues(mw[f_save_as_menu],XmNmnemonic,'a',NULL);
  
  mw[f_revert_menu] = XtCreateManagedWidget(snd_string_Revert,xmPushButtonWidgetClass,mw[file_menu],in_args,in_n);
  XtAddCallback(mw[f_revert_menu],XmNactivateCallback,File_Revert_Callback,state);
  XtVaSetValues(mw[f_revert_menu],XmNmnemonic,'R',NULL);
  
  mw[f_mix_menu] = XtCreateManagedWidget(snd_string_Mix,xmPushButtonWidgetClass,mw[file_menu],in_args,in_n);
  XtAddCallback(mw[f_mix_menu],XmNactivateCallback,File_Mix_Callback,state);
  XtVaSetValues(mw[f_mix_menu],XmNmnemonic,'M',NULL);

  mw[f_update_menu] = XtCreateManagedWidget(snd_string_Update,xmPushButtonWidgetClass,mw[file_menu],in_args,in_n);
  XtAddCallback(mw[f_update_menu],XmNactivateCallback,File_Update_Callback,state);
  XtVaSetValues(mw[f_update_menu],XmNmnemonic,'U',NULL);

  mw[f_new_menu] = XtCreateManagedWidget(snd_string_New,xmPushButtonWidgetClass,mw[file_menu],main_args,main_n);
  XtAddCallback(mw[f_new_menu],XmNactivateCallback,File_New_Callback,state);
  XtVaSetValues(mw[f_new_menu],XmNmnemonic,'N',NULL);

  mw[f_record_menu] = XtCreateManagedWidget(snd_string_Record,xmPushButtonWidgetClass,mw[file_menu],main_args,main_n);
  XtAddCallback(mw[f_record_menu],XmNactivateCallback,File_Record_Callback,state);

  mw[f_view_menu] = XtCreateManagedWidget(snd_string_View,xmPushButtonWidgetClass,mw[file_menu],main_args,main_n);
  XtAddCallback(mw[f_view_menu],XmNactivateCallback,File_View_Callback,state);
  XtVaSetValues(mw[f_view_menu],XmNmnemonic,'V',NULL);

  mw[f_print_menu] = XtCreateManagedWidget(snd_string_Print,xmPushButtonWidgetClass,mw[file_menu],in_args,in_n);
  XtAddCallback(mw[f_print_menu],XmNactivateCallback,File_Print_Callback,state);
  XtVaSetValues(mw[f_print_menu],XmNmnemonic,'P',NULL);

  mw[f_exit_menu] = XtCreateManagedWidget(snd_string_Exit,xmPushButtonWidgetClass,mw[file_menu],main_args,main_n);
  XtAddCallback(mw[f_exit_menu],XmNactivateCallback,File_Exit_Callback,state);
  XtVaSetValues(mw[f_exit_menu],XmNmnemonic,'E',NULL);


  /* EDIT MENU */
  mw[edit_menu] = XmCreatePulldownMenu(mw[menu_menu],"editm",main_args,main_n);

  high_n = start_high_n;
  XtSetArg(high_args[high_n],XmNsubMenuId,mw[edit_menu]); high_n++;
  XtSetArg(high_args[high_n],XmNmnemonic,'E'); high_n++;
  mw[e_cascade_menu] = XtCreateManagedWidget(snd_string_Edit,xmCascadeButtonWidgetClass,mw[menu_menu],high_args,high_n);
  XtAddCallback(mw[e_cascade_menu],XmNhelpCallback,Edit_Help_Callback,state);
  
  mw[e_undo_menu] = XtCreateManagedWidget(snd_string_Undo,xmPushButtonWidgetClass,mw[edit_menu],in_args,in_n);
  XtAddCallback(mw[e_undo_menu],XmNactivateCallback,Edit_Undo_Callback,state);
  XtVaSetValues(mw[e_undo_menu],XmNmnemonic,'U',NULL);

  mw[e_redo_menu] = XtCreateManagedWidget(snd_string_Redo,xmPushButtonWidgetClass,mw[edit_menu],in_args,in_n);
  XtAddCallback(mw[e_redo_menu],XmNactivateCallback,Edit_Redo_Callback,state);
  XtVaSetValues(mw[e_redo_menu],XmNmnemonic,'R',NULL);

  mw[e_find_menu] = XtCreateManagedWidget(snd_string_Find,xmPushButtonWidgetClass,mw[edit_menu],in_args,in_n);
  XtAddCallback(mw[e_find_menu],XmNactivateCallback,Edit_Find_Callback,state);
  XtVaSetValues(mw[e_find_menu],XmNmnemonic,'F',NULL);

  mw[e_cut_menu] = XtCreateManagedWidget(snd_string_Cut,xmPushButtonWidgetClass,mw[edit_menu],in_args,in_n);
  XtAddCallback(mw[e_cut_menu],XmNactivateCallback,Edit_Cut_Callback,state);
  XtVaSetValues(mw[e_cut_menu],XmNmnemonic,'C',NULL);

  mw[e_paste_menu] = XtCreateManagedWidget(snd_string_Paste,xmPushButtonWidgetClass,mw[edit_menu],main_args,main_n);
  /* not in-args because the clipboard (for paste) might at any time have data */
  XtAddCallback(mw[e_paste_menu],XmNactivateCallback,Edit_Paste_Callback,state);
  XtVaSetValues(mw[e_paste_menu],XmNmnemonic,'P',NULL);

  mw[e_mix_menu] = XtCreateManagedWidget(snd_string_Mix_Selection,xmPushButtonWidgetClass,mw[edit_menu],in_args,in_n);
  XtAddCallback(mw[e_mix_menu],XmNactivateCallback,Edit_Mix_Callback,state);
  XtVaSetValues(mw[e_mix_menu],XmNmnemonic,'M',NULL);

  mw[e_play_menu] = XtCreateManagedWidget(snd_string_Play_selection,xmPushButtonWidgetClass,mw[edit_menu],in_args,in_n);
  XtAddCallback(mw[e_play_menu],XmNactivateCallback,Edit_Play_Callback,state);
  XtVaSetValues(mw[e_play_menu],XmNmnemonic,'P',NULL);

  mw[e_save_as_menu] = XtCreateManagedWidget(snd_string_Save_selection,xmPushButtonWidgetClass,mw[edit_menu],in_args,in_n);
  XtAddCallback(mw[e_save_as_menu],XmNactivateCallback,Edit_Save_As_Callback,state);
  XtVaSetValues(mw[e_save_as_menu],XmNmnemonic,'S',NULL);

  mw[e_edenv_menu] = XtCreateManagedWidget(snd_string_Edit_Envelope,xmPushButtonWidgetClass,mw[edit_menu],main_args,main_n);
  XtAddCallback(mw[e_edenv_menu],XmNactivateCallback,Edit_Envelope_Callback,state);
  XtVaSetValues(mw[e_edenv_menu],XmNmnemonic,'E',NULL);

  mw[e_header_menu] = XtCreateManagedWidget(snd_string_Edit_Header,xmPushButtonWidgetClass,mw[edit_menu],in_args,in_n);
  XtAddCallback(mw[e_header_menu],XmNactivateCallback,Edit_Header_Callback,state);
  XtVaSetValues(mw[e_header_menu],XmNmnemonic,'H',NULL);

  mw[e_history_menu] = XtCreateManagedWidget(snd_string_Show_edit_history,xmPushButtonWidgetClass,mw[edit_menu],main_args,main_n);
  XtAddCallback(mw[e_history_menu],XmNactivateCallback,Edit_History_Callback,state);



  /* VIEW MENU */
  mw[view_menu] = XmCreatePulldownMenu(mw[menu_menu],"viewm",main_args,main_n);

  high_n = start_high_n;
  XtSetArg(high_args[high_n],XmNsubMenuId,mw[view_menu]); high_n++;
  XtSetArg(high_args[high_n],XmNmnemonic,'V'); high_n++;
  mw[v_cascade_menu] = XtCreateManagedWidget(snd_string_View,xmCascadeButtonWidgetClass,mw[menu_menu],high_args,high_n);
  XtAddCallback(mw[v_cascade_menu],XmNhelpCallback,View_Help_Callback,state);

  mw[v_ctrls_menu] = XtCreateManagedWidget(snd_string_Show_controls,xmPushButtonWidgetClass,mw[view_menu],main_args,main_n);
  XtAddCallback(mw[v_ctrls_menu],XmNactivateCallback,View_Ctrls_Callback,state);
  XtVaSetValues(mw[v_ctrls_menu],XmNmnemonic,'S',NULL);

  mw[v_normalize_menu] = XtCreateManagedWidget(snd_string_Normalize,xmPushButtonWidgetClass,mw[view_menu],in_args,in_n);
  XtAddCallback(mw[v_normalize_menu],XmNactivateCallback,View_Normalize_Callback,state);
  XtVaSetValues(mw[v_normalize_menu],XmNmnemonic,'N',NULL);

  mw[v_listener_menu] = XtCreateManagedWidget(snd_string_Open_listener,xmPushButtonWidgetClass,mw[view_menu],main_args,main_n);
  XtAddCallback(mw[v_listener_menu],XmNactivateCallback,View_Listener_Callback,state);
  XtVaSetValues(mw[v_listener_menu],XmNmnemonic,'L',NULL);

  mw[v_combine_menu] = XmCreatePulldownMenu(mw[view_menu],"combine",main_args,main_n);

  k=main_n;
  XtSetArg(main_args[k],XmNsubMenuId,mw[v_combine_menu]); k++;
  mw[v_combine_cascade_menu] = XtCreateManagedWidget(snd_string_Channel_style,xmCascadeButtonWidgetClass,mw[view_menu],main_args,k);

  mw[v_combine_separate_menu] = XtCreateManagedWidget(snd_string_separate,xmPushButtonWidgetClass,mw[v_combine_menu],main_args,main_n);
  XtAddCallback(mw[v_combine_separate_menu],XmNactivateCallback,View_Separate_Callback,state); 
  if (channel_style(state) == CHANNELS_SEPARATE) XtSetSensitive(mw[v_combine_separate_menu],FALSE);

  mw[v_combine_combined_menu] = XtCreateManagedWidget(snd_string_combined,xmPushButtonWidgetClass,mw[v_combine_menu],main_args,main_n);
  XtAddCallback(mw[v_combine_combined_menu],XmNactivateCallback,View_Combined_Callback,state);  
  if (channel_style(state) == CHANNELS_COMBINED) XtSetSensitive(mw[v_combine_combined_menu],FALSE);

  mw[v_combine_superimposed_menu] = XtCreateManagedWidget(snd_string_superimposed,xmPushButtonWidgetClass,mw[v_combine_menu],main_args,main_n);
  XtAddCallback(mw[v_combine_superimposed_menu],XmNactivateCallback,View_Superimposed_Callback,state);  
  if (channel_style(state) == CHANNELS_SUPERIMPOSED) XtSetSensitive(mw[v_combine_superimposed_menu],FALSE);


  mw[v_graph_style_menu] = XmCreatePulldownMenu(mw[view_menu],"graph-style",main_args,main_n);

  k=main_n;
  XtSetArg(main_args[k],XmNsubMenuId,mw[v_graph_style_menu]); k++;
  mw[v_graph_style_cascade_menu] = XtCreateManagedWidget(snd_string_Graph_style,xmCascadeButtonWidgetClass,mw[view_menu],main_args,k);

  mw[v_lines_menu] = XtCreateManagedWidget(snd_string_lines,xmPushButtonWidgetClass,mw[v_graph_style_menu],main_args,main_n);
  XtAddCallback(mw[v_lines_menu],XmNactivateCallback,View_Lines_Callback,state); 
  if (graph_style(state) == GRAPH_LINES) XtSetSensitive(mw[v_lines_menu],FALSE);

  mw[v_dots_menu] = XtCreateManagedWidget(snd_string_dots,xmPushButtonWidgetClass,mw[v_graph_style_menu],main_args,main_n);
  XtAddCallback(mw[v_dots_menu],XmNactivateCallback,View_Dots_Callback,state);  
  if (graph_style(state) == GRAPH_DOTS) XtSetSensitive(mw[v_dots_menu],FALSE);

  mw[v_filled_menu] = XtCreateManagedWidget(snd_string_filled,xmPushButtonWidgetClass,mw[v_graph_style_menu],main_args,main_n);
  XtAddCallback(mw[v_filled_menu],XmNactivateCallback,View_Filled_Callback,state);  
  if (graph_style(state) == GRAPH_FILLED) XtSetSensitive(mw[v_filled_menu],FALSE);


  mw[v_cursor_menu] = XtCreateManagedWidget(snd_string_Verbose_cursor,xmPushButtonWidgetClass,mw[view_menu],main_args,main_n);
  XtAddCallback(mw[v_cursor_menu],XmNactivateCallback,View_Cursor_Callback,state);

  mw[v_region_menu] = XtCreateManagedWidget(snd_string_Regions,xmPushButtonWidgetClass,mw[view_menu],in_args,in_n);
  XtAddCallback(mw[v_region_menu],XmNactivateCallback,View_Region_Callback,state);
  XtVaSetValues(mw[v_region_menu],XmNmnemonic,'R',NULL);

  mw[v_files_menu] = XtCreateManagedWidget(snd_string_Files,xmPushButtonWidgetClass,mw[view_menu],main_args,main_n);
  XtAddCallback(mw[v_files_menu],XmNactivateCallback,View_Files_Callback,state);
  XtVaSetValues(mw[v_files_menu],XmNmnemonic,'F',NULL);

  mw[v_color_menu] = XtCreateManagedWidget(snd_string_Color,xmPushButtonWidgetClass,mw[view_menu],main_args,main_n);
  XtAddCallback(mw[v_color_menu],XmNactivateCallback,View_Color_Callback,state);

  mw[v_orientation_menu] = XtCreateManagedWidget(snd_string_Orientation,xmPushButtonWidgetClass,mw[view_menu],main_args,main_n);
  XtAddCallback(mw[v_orientation_menu],XmNactivateCallback,View_Orientation_Callback,state);
  XtVaSetValues(mw[v_orientation_menu],XmNmnemonic,'O',NULL);

  mw[v_groups_menu] = XtCreateManagedWidget(snd_string_Groups,xmPushButtonWidgetClass,mw[view_menu],main_args,main_n);
  XtAddCallback(mw[v_groups_menu],XmNactivateCallback,View_Groups_Callback,state);

  mw[v_marks_menu] = XtCreateManagedWidget((show_marks(state)) ? snd_string_Hide_marks : snd_string_Show_marks,
					   xmPushButtonWidgetClass,mw[view_menu],main_args,main_n);
  XtAddCallback(mw[v_marks_menu],XmNactivateCallback,View_Marks_Callback,state);
  XtVaSetValues(mw[v_marks_menu],XmNmnemonic,'m',NULL);

  mw[v_zero_menu] = XtCreateManagedWidget(snd_string_Show_Y0,xmPushButtonWidgetClass,mw[view_menu],main_args,main_n);
  XtAddCallback(mw[v_zero_menu],XmNactivateCallback,View_Zero_Callback,state);
  XtVaSetValues(mw[v_zero_menu],XmNmnemonic,'y',NULL);

  mw[v_consoles_menu] = XtCreateManagedWidget(snd_string_Hide_consoles,xmPushButtonWidgetClass,mw[view_menu],main_args,main_n);
  XtAddCallback(mw[v_consoles_menu],XmNactivateCallback,View_Consoles_Callback,state);

  mw[v_x_axis_menu] = XmCreatePulldownMenu(mw[view_menu],"xaxis",main_args,main_n);

  k=main_n;
  XtSetArg(main_args[k],XmNsubMenuId,mw[v_x_axis_menu]); k++;
  mw[v_x_axis_cascade_menu] = XtCreateManagedWidget(snd_string_X_axis_units,xmCascadeButtonWidgetClass,mw[view_menu],main_args,k);

  mw[v_x_axis_seconds_menu] = XtCreateManagedWidget(snd_string_seconds,xmPushButtonWidgetClass,mw[v_x_axis_menu],main_args,main_n);
  XtAddCallback(mw[v_x_axis_seconds_menu],XmNactivateCallback,Options_X_Axis_Seconds_Callback,state);  
  XtSetSensitive(mw[v_x_axis_seconds_menu],FALSE);

  mw[v_x_axis_samples_menu] = XtCreateManagedWidget(snd_string_samples,xmPushButtonWidgetClass,mw[v_x_axis_menu],main_args,main_n);
  XtAddCallback(mw[v_x_axis_samples_menu],XmNactivateCallback,Options_X_Axis_Samples_Callback,state);  

  mw[v_x_axis_percentage_menu] = XtCreateManagedWidget(snd_string_percentage,xmPushButtonWidgetClass,mw[v_x_axis_menu],main_args,main_n);
  XtAddCallback(mw[v_x_axis_percentage_menu],XmNactivateCallback,Options_X_Axis_Percentage_Callback,state);  



  /* OPTIONS MENU */
  mw[option_menu] = XmCreatePulldownMenu(mw[menu_menu],"optionm",main_args,main_n);

  high_n = start_high_n;
  XtSetArg(high_args[high_n],XmNsubMenuId,mw[option_menu]); high_n++;
  XtSetArg(high_args[high_n],XmNmnemonic,'O'); high_n++;
  mw[o_cascade_menu] = XtCreateManagedWidget(snd_string_Options,xmCascadeButtonWidgetClass,mw[menu_menu],high_args,high_n);
  XtAddCallback(mw[o_cascade_menu],XmNhelpCallback,Options_Help_Callback,state);

  mw[o_transform_menu] = XtCreateManagedWidget(snd_string_Transform_Options,xmPushButtonWidgetClass,mw[option_menu],main_args,main_n);
  XtAddCallback(mw[o_transform_menu],XmNactivateCallback,Options_Transform_Callback,state);
  XtVaSetValues(mw[o_transform_menu],XmNmnemonic,'t',NULL);


  mw[o_speed_menu] = XmCreatePulldownMenu(mw[option_menu],"speedstyle",main_args,main_n);

  k=main_n;
  XtSetArg(main_args[k],XmNsubMenuId,mw[o_speed_menu]); k++;
  mw[o_speed_cascade_menu] = XtCreateManagedWidget(snd_string_Speed_style,xmCascadeButtonWidgetClass,mw[option_menu],main_args,k);

  mw[o_speed_float_menu] = XtCreateManagedWidget(snd_string_float,xmPushButtonWidgetClass,mw[o_speed_menu],in_args,in_n);
  XtAddCallback(mw[o_speed_float_menu],XmNactivateCallback,Options_Speed_Float_Callback,state);  

  mw[o_speed_semitone_menu] = XtCreateManagedWidget(snd_string_semitone,xmPushButtonWidgetClass,mw[o_speed_menu],main_args,main_n);
  XtAddCallback(mw[o_speed_semitone_menu],XmNactivateCallback,Options_Speed_Semitone_Callback,state);  

  mw[o_speed_ratio_menu] = XtCreateManagedWidget(snd_string_ratio,xmPushButtonWidgetClass,mw[o_speed_menu],main_args,main_n);
  XtAddCallback(mw[o_speed_ratio_menu],XmNactivateCallback,Options_Speed_Ratio_Callback,state);  


  mw[o_focus_style_menu] = XmCreatePulldownMenu(mw[option_menu],"focusstyle",main_args,main_n);

  k=main_n;
  XtSetArg(main_args[k],XmNsubMenuId,mw[o_focus_style_menu]); k++;
  mw[o_focus_cascade_menu] = XtCreateManagedWidget(snd_string_Focus_style,xmCascadeButtonWidgetClass,mw[option_menu],main_args,k);

  mw[o_focus_left_menu] = XtCreateManagedWidget(snd_string_focus_left,xmPushButtonWidgetClass,mw[o_focus_style_menu],main_args,main_n);
  XtAddCallback(mw[o_focus_left_menu],XmNactivateCallback,Options_Focus_Left_Callback,state);  

  mw[o_focus_right_menu] = XtCreateManagedWidget(snd_string_focus_right,xmPushButtonWidgetClass,mw[o_focus_style_menu],main_args,main_n);
  XtAddCallback(mw[o_focus_right_menu],XmNactivateCallback,Options_Focus_Right_Callback,state);  

  mw[o_focus_middle_menu] = XtCreateManagedWidget(snd_string_focus_middle,xmPushButtonWidgetClass,mw[o_focus_style_menu],main_args,main_n);
  XtAddCallback(mw[o_focus_middle_menu],XmNactivateCallback,Options_Focus_Middle_Callback,state);  

  mw[o_focus_active_menu] = XtCreateManagedWidget(snd_string_focus_active,xmPushButtonWidgetClass,mw[o_focus_style_menu],main_args,main_n);
  XtAddCallback(mw[o_focus_active_menu],XmNactivateCallback,Options_Focus_Active_Callback,state);  
  activate_focus_menu(state,zoom_focus_style(state));

  mw[o_subsampling_menu] = XtCreateManagedWidget(snd_string_Subsampling_off,xmPushButtonWidgetClass,mw[option_menu],main_args,main_n);
  XtAddCallback(mw[o_subsampling_menu],XmNactivateCallback,Options_Subsampling_Callback,state);
  XtVaSetValues(mw[o_subsampling_menu],XmNmnemonic,'o',NULL);

  mw[o_save_menu] = XtCreateManagedWidget(snd_string_Save_options,xmPushButtonWidgetClass,mw[option_menu],main_args,main_n);
  XtAddCallback(mw[o_save_menu],XmNactivateCallback,Options_Save_Callback,state);
  XtVaSetValues(mw[o_save_menu],XmNmnemonic,'a',NULL);

  mw[o_session_menu] = XtCreateManagedWidget(snd_string_Session,xmPushButtonWidgetClass,mw[option_menu],main_args,main_n);
  XtAddCallback(mw[o_session_menu],XmNactivateCallback,Options_Session_Callback,state);



  /* HELP MENU */
  mw[help_menu] = XmCreatePulldownMenu(mw[menu_menu],"helpm",main_args,main_n);

  high_n = start_high_n;
  XtSetArg(high_args[high_n],XmNsubMenuId,mw[help_menu]); high_n++;
  XtSetArg(high_args[high_n],XmNmnemonic,'H'); high_n++;
  mw[h_cascade_menu] = XtCreateManagedWidget(snd_string_Help,xmCascadeButtonWidgetClass,mw[menu_menu],high_args,high_n);
  XtAddCallback(mw[h_cascade_menu],XmNhelpCallback,Help_Help_Callback,state);

  mw[h_click_for_help_menu] = XtCreateManagedWidget(snd_string_Click_for_help,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_click_for_help_menu],XmNactivateCallback,Help_Context_Help_Callback,state);
  XtVaSetValues(mw[h_click_for_help_menu],XmNmnemonic,'C',NULL);

  mw[h_about_snd_menu] = XtCreateManagedWidget(snd_string_Overview,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_about_snd_menu],XmNactivateCallback,Help_About_Snd_Callback,state);
  XtVaSetValues(mw[h_about_snd_menu],XmNmnemonic,'O',NULL);

  mw[h_fft_menu] = XtCreateManagedWidget(snd_string_FFT,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_fft_menu],XmNactivateCallback,Help_FFT_Callback,state);

  mw[h_find_menu] = XtCreateManagedWidget(snd_string_Find,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_find_menu],XmNactivateCallback,Help_Find_Callback,state);

  mw[h_undo_menu] = XtCreateManagedWidget(snd_string_Undo_and_redo,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_undo_menu],XmNactivateCallback,Help_Undo_Callback,state);

  mw[h_sync_menu] = XtCreateManagedWidget(snd_string_Sync,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_sync_menu],XmNactivateCallback,Help_Sync_Callback,state);

  mw[h_speed_menu] = XtCreateManagedWidget(snd_string_Speed,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_speed_menu],XmNactivateCallback,Help_Speed_Callback,state);

  mw[h_expand_menu] = XtCreateManagedWidget(snd_string_Expand,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_expand_menu],XmNactivateCallback,Help_Expand_Callback,state);

  mw[h_reverb_menu] = XtCreateManagedWidget(snd_string_Reverb,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_reverb_menu],XmNactivateCallback,Help_Reverb_Callback,state);

  mw[h_contrast_menu] = XtCreateManagedWidget(snd_string_Contrast,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_contrast_menu],XmNactivateCallback,Help_Contrast_Callback,state);

  mw[h_env_menu] = XtCreateManagedWidget(snd_string_Envelope,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_env_menu],XmNactivateCallback,Help_Env_Callback,state);

  mw[h_marks_menu] = XtCreateManagedWidget(snd_string_Marks,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_marks_menu],XmNactivateCallback,Help_Marks_Callback,state);

  mw[h_mix_menu] = XtCreateManagedWidget(snd_string_Mixing,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_mix_menu],XmNactivateCallback,Help_Mix_Callback,state);

  mw[h_sound_files_menu] = XtCreateManagedWidget(snd_string_Formats,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_sound_files_menu],XmNactivateCallback,Help_Sound_Files_Callback,state);

  mw[h_init_file_menu] = XtCreateManagedWidget(snd_string_Customization,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_init_file_menu],XmNactivateCallback,Help_Init_File_Callback,state);

  mw[h_recording_menu] = XtCreateManagedWidget(snd_string_Recording,xmPushButtonWidgetClass,mw[help_menu],main_args,main_n);
  XtAddCallback(mw[h_recording_menu],XmNactivateCallback,Help_Recording_Callback,state);

  XtVaSetValues(mw[menu_menu],XmNmenuHelpWidget,mw[h_cascade_menu],NULL);
  XtManageChild(mw[menu_menu]);

  return(mw[menu_menu]);
}

static void GH_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  int callb;
  XtVaGetValues(w,XmNuserData,&callb,NULL);
  g_snd_callback((snd_state *)clientData,callb);
}

static Widget added_menus[12]; /* main menus */
static int new_menu = 4;
static Widget *added_options = NULL;
static char **added_options_names = NULL;
static int *added_options_menus = NULL;
static int added_options_size = 0;
static int added_options_pos = 0;

static void add_option(Widget w,int which_menu,char *label)
{
  int i;
  if (added_options_pos == added_options_size)
    {
      added_options_size += 8;
      if (added_options_pos == 0)
	{
	  added_options = (Widget *)calloc(added_options_size,sizeof(Widget));
	  added_options_names = (char **)calloc(added_options_size,sizeof(char *));
	  added_options_menus = (int *)calloc(added_options_size,sizeof(int));
	}
      else
	{
	  added_options = (Widget *)realloc(added_options,added_options_size * sizeof(Widget));
	  added_options_names = (char **)realloc(added_options_names,added_options_size * sizeof(char *));
	  added_options_menus = (int *)realloc(added_options_menus,added_options_size * sizeof(int));
	  for (i=added_options_pos;i<added_options_size;i++) added_options[i] = NULL;
	}
    }
  added_options[added_options_pos] = w;
  added_options_menus[added_options_pos] = which_menu;
  added_options_names[added_options_pos] = copy_string(label);
  added_options_pos++;
}

static int remove_option(int which_menu,char *label)
{
  int i;
  for (i=0;i<added_options_pos;i++)
    {
      if ((added_options_menus[i] == which_menu) && (strcmp(label,added_options_names[i]) == 0) && (added_options[i]))
	{
	  XtDestroyWidget(added_options[i]);
	  added_options[i] = NULL;
	  added_options_menus[i] = -1;
	  free(added_options_names[i]);
	  added_options_names[i] = NULL;
	  return(0);
	}
    }
  return(-1);
}

int change_menu_label(int which_menu,char *old_label, char *new_label)
{
  int i;
  for (i=0;i<added_options_pos;i++)
    {
      if ((added_options_menus[i] == which_menu) && (strcmp(old_label,added_options_names[i]) == 0) && (added_options[i]))
	{
	  make_name_label(added_options[i],new_label);
	  if (added_options_names[i]) free(added_options_names[i]);
	  added_options_names[i] = copy_string(new_label);
	  return(0);
	}
    }
  return(-1);
}

int set_menu_sensitive(int which_menu,char *old_label, int on)
{
  int i;
  for (i=0;i<added_options_pos;i++)
    {
      if ((added_options_menus[i] == which_menu) && (strcmp(old_label,added_options_names[i]) == 0) && (added_options[i]))
	{
	  XtSetSensitive(added_options[i],on);
	  return(0);
	}
    }
  return(-1);
}

int add_to_main_menu(snd_state *ss, char *label)
{
  static Arg args[12];
  Widget m,mc;
  int n;
  n=0;
  if (!(ss->using_schemes)) n = background_main_color(args,n,ss);
  m = XmCreatePulldownMenu(mw[menu_menu],label,args,n);

  n=0;
  if (!(ss->using_schemes)) n = background_high_color(args,n,ss);
  XtSetArg(args[n],XmNsubMenuId,m); n++;
  mc = XtCreateManagedWidget(label,xmCascadeButtonWidgetClass,mw[menu_menu],args,n);

  new_menu++;
  added_menus[new_menu] = m;
  return(new_menu);
}

void add_to_menu(snd_state *ss, int which_menu, char *label, int callb)
{
  Widget m,menw;
  static Arg args[12];
  int n;
  switch (which_menu)
    {
    case 0: menw = mw[file_menu]; break;
    case 1: menw = mw[edit_menu]; break;
    case 2: menw = mw[view_menu]; break;
    case 3: menw = mw[option_menu]; break;
    case 4: menw = mw[help_menu]; break;
    default: menw = added_menus[which_menu]; break;
    }
  n=0;
  if (!(ss->using_schemes)) n = background_main_color(args,n,ss);
  XtSetArg(args[n],XmNuserData,callb); n++;
  m = XtCreateManagedWidget(label,xmPushButtonWidgetClass,menw,args,n);
  XtAddCallback(m,XmNactivateCallback,GH_Callback,ss);
  add_option(m,which_menu,label);
}

int remove_from_menu(snd_state *ss, int which_menu, char *label)
{
  return(remove_option(which_menu,label));
}



/* -------------------------------- POPUP MENU -------------------------------- */

static void Popup_Play_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  snd_state *ss = (snd_state *)clientData;
  snd_info *sp;
  start_playing(sp=any_selected_sound(ss),0);
  set_play_button(sp,1);
}

static void Popup_Save_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  snd_state *ss = (snd_state *)clientData;
  save_edits(any_selected_sound(ss),NULL);
}

static void Popup_Undo_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  undo_EDIT((void *)clientData,1);
}

static void Popup_Redo_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  redo_EDIT((void *)clientData,1);
}

static void Popup_Normalize_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  normalize_all_sounds((snd_state *)clientData);
}

static void Popup_Info_Callback(Widget w,XtPointer clientData,XtPointer callData) 
{
  snd_state *ss = (snd_state *)clientData;
  snd_info *sp;
  sp = selected_sound(ss);
  if (sp) display_info(sp);
}

static void Post_Popup_Menu(Widget w,XtPointer clientData,XEvent *event,Boolean *flag)
{
  if (event->xbutton.button == Button3)
    {
      XmMenuPosition(popup_menu,(XButtonPressedEvent *)event);
      XtManageChild(popup_menu);
    }
}

void create_popup_menu(snd_state *ss)
{
  /* make it a child of the main window */
  Widget mainp;
  Arg args[20];
  int n;
  if (!popup_menu)
    {
      n=0;
      if (!ss->using_schemes) n = background_main_color(args,n,ss); else n=0;
      mainp = main_PANE(ss);
      popup_menu = XmCreatePopupMenu(mainp,"popup-menu",args,n);
      XtAddEventHandler(mainp,ButtonPressMask,FALSE,Post_Popup_Menu,popup_menu);

      popup_children[W_pop_menu] = XtCreateManagedWidget("snd",xmLabelWidgetClass,popup_menu,args,n);
      popup_children[W_pop_sep] = XtCreateManagedWidget("sep",xmSeparatorWidgetClass,popup_menu,args,n);
      popup_children[W_pop_play] = XtCreateManagedWidget(snd_string_Play,xmPushButtonWidgetClass,popup_menu,args,n);
      XtAddCallback(popup_children[W_pop_play],XmNactivateCallback,Popup_Play_Callback,ss);
      popup_children[W_pop_undo] = XtCreateManagedWidget(snd_string_Undo,xmPushButtonWidgetClass,popup_menu,args,n);
      XtVaSetValues(popup_children[W_pop_undo],XmNsensitive,FALSE,NULL);
      XtAddCallback(popup_children[W_pop_undo],XmNactivateCallback,Popup_Undo_Callback,ss);
      popup_children[W_pop_redo] = XtCreateManagedWidget(snd_string_Redo,xmPushButtonWidgetClass,popup_menu,args,n);
      XtVaSetValues(popup_children[W_pop_redo],XmNsensitive,FALSE,NULL);
      XtAddCallback(popup_children[W_pop_redo],XmNactivateCallback,Popup_Redo_Callback,ss);
      popup_children[W_pop_save] = XtCreateManagedWidget(snd_string_Save,xmPushButtonWidgetClass,popup_menu,args,n);
      XtAddCallback(popup_children[W_pop_save],XmNactivateCallback,Popup_Save_Callback,ss);
      popup_children[W_pop_normalize] = XtCreateManagedWidget(snd_string_Normalize,xmPushButtonWidgetClass,popup_menu,args,n);
      XtVaSetValues(popup_children[W_pop_normalize],XmNsensitive,FALSE,NULL);
      XtAddCallback(popup_children[W_pop_normalize],XmNactivateCallback,Popup_Normalize_Callback,ss);
      popup_children[W_pop_info] = XtCreateManagedWidget(snd_string_Info,xmPushButtonWidgetClass,popup_menu,args,n);
      XtVaSetValues(popup_children[W_pop_info],XmNsensitive,FALSE,NULL);
      XtAddCallback(popup_children[W_pop_info],XmNactivateCallback,Popup_Info_Callback,ss);
    }
}


