#define MENU_HELPER_C

#include "main.h"

#define CONST_STR_LEN(x) (sizeof(x) - 1)

static int parse_accelerator(const char *accelerator,
                             char *key, guint8 *mods)
{
 g_return_val_if_fail(accelerator, FALSE);
 g_return_val_if_fail(key, FALSE);
 g_return_val_if_fail(mods, FALSE);
 
 *key = 0;
 *mods = 0;
 
 while (*accelerator)
 {
  if (!strncmp(accelerator, "<shift>", CONST_STR_LEN("<shift>")))
  {
   accelerator += CONST_STR_LEN("<shift>");
   if (*accelerator == '-') ++accelerator;
   *mods |= GDK_SHIFT_MASK;
  }
  else if (!strncmp(accelerator, "<alt>", CONST_STR_LEN("<alt>")))
  {
   accelerator += CONST_STR_LEN("<alt>");
   if (*accelerator == '-') ++accelerator;
   *mods |= GDK_MOD1_MASK;
  }
  else if (!strncmp(accelerator, "<control>", CONST_STR_LEN("<control>")))
  {
   accelerator += CONST_STR_LEN("<control>");
   if (*accelerator == '-') ++accelerator;
   *mods |= GDK_CONTROL_MASK;
  }
  else
  {
   *key = toupper((unsigned char) *accelerator);
   g_return_val_if_fail(!*(accelerator + 1), FALSE);
   return (TRUE);
  }
 }

 return (FALSE);
}

GtkWidget *menu_helper_add(GtkWidget *menu,
                           GtkAcceleratorTable **table,
                           const menu_helper *scan)
{
 assert(scan);
 
 if (!menu || !scan)
   return (NULL);
 
 while (scan->func)
 {
  GtkWidget *menu_item = NULL;
  
  if (scan->text)
    menu_item = gtk_menu_item_new_with_label(scan->text);
  else
    menu_item = gtk_menu_item_new(); /* separator */

  gtk_menu_append(GTK_MENU(menu), menu_item);
  gtk_signal_connect(GTK_OBJECT(menu_item), "activate",
                     scan->func, scan->data);
  gtk_widget_show(menu_item);

  if (scan->accelerator && table)
  {
   gchar key;
   gint8 mods;
   
   if (!*table)
     *table = gtk_accelerator_table_new();
   
   parse_accelerator(scan->accelerator, &key, &mods);
   
   gtk_widget_install_accelerator(menu_item, *table, "activate", key, mods);
  }
  
  ++scan;
 }

 if (table)
   gtk_menu_set_accelerator_table(GTK_MENU(menu), *table);
 
 assert(!scan->text && !scan->data);

 return (menu);
}
