X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fmenu.c;h=1f335c787dac724b26bc3b0a97c3f964b4cf861d;hb=5d5be2ba2a6e0b3886e0076475ed9d7a2d4ac9ab;hp=311701a7aa33cd5a4bd5d45474dc0d7356fee780;hpb=138d3e38d88dbcb1426bd1eb0cd8c43dd01777ad;p=chaz%2Fopenbox diff --git a/openbox/menu.c b/openbox/menu.c index 311701a7..1f335c78 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -54,6 +54,9 @@ static void parse_menu_separator(ObParseInst *i, gpointer data); static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, gpointer data); +static gunichar parse_shortcut(const gchar *label, gchar **strippedlabel, + guint *position); + static void client_dest(ObClient *client, gpointer data) { @@ -178,6 +181,56 @@ static ObMenu* menu_from_name(gchar *name) return self; } +#define VALID_SHORTCUT(c) (((c) >= '0' && (c) <= '9') || \ + ((c) >= 'A' && (c) <= 'Z') || \ + ((c) >= 'a' && (c) <= 'z')) + +static gunichar parse_shortcut(const gchar *label, gchar **strippedlabel, + guint *position) +{ + gunichar shortcut = 0; + + *position = 0; + + g_assert(strippedlabel != NULL); + + if (label == NULL) { + *strippedlabel = NULL; + } else { + gchar *i; + + *strippedlabel = g_strdup(label); + + i = strchr(*strippedlabel, '&'); + if (i != NULL) { + /* there is an ampersand in the string */ + + /* you have to use a printable ascii character for shortcuts + don't allow space either, so you can have like "a & b" + */ + if (VALID_SHORTCUT(*(i+1))) { + shortcut = g_unichar_tolower(g_utf8_get_char(i+1)); + *position = i - *strippedlabel; + + /* remove the & from the string */ + for (; *i != '\0'; ++i) + *i = *(i+1); + } + } else { + /* there is no ampersand, so find the first valid character to use + instead */ + + for (i = *strippedlabel; *i != '\0'; ++i) + if (VALID_SHORTCUT(*i)) { + *position = i - *strippedlabel; + shortcut = g_unichar_tolower(g_utf8_get_char(i)); + break; + } + } + } + return shortcut; +} + static void parse_menu_item(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, gpointer data) { @@ -262,9 +315,11 @@ ObMenu* menu_new(const gchar *name, const gchar *title, gpointer data) self = g_new0(ObMenu, 1); self->name = g_strdup(name); - self->title = g_strdup(title); self->data = data; + self->shortcut = parse_shortcut(title, &self->title, + &self->shortcut_position); + g_hash_table_replace(menu_hash, self->name, self); return self; @@ -325,7 +380,7 @@ void menu_show(gchar *name, gint x, gint y, ObClient *client) ObMenuEntryFrame *e = frame->entries->data; if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL && e->entry->data.normal.enabled) - menu_frame_select(frame, e); + menu_frame_select(frame, e, FALSE); } } @@ -409,9 +464,10 @@ ObMenuEntry* menu_add_normal(ObMenu *self, gint id, const gchar *label, ObMenuEntry *e; e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_NORMAL, id); - e->data.normal.label = g_strdup(label); e->data.normal.actions = actions; + menu_entry_set_label(e, label); + self->entries = g_list_append(self->entries, e); return e; } @@ -432,7 +488,8 @@ ObMenuEntry* menu_add_separator(ObMenu *self, gint id, const gchar *label) ObMenuEntry *e; e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_SEPARATOR, id); - e->data.separator.label = g_strdup(label); + + menu_entry_set_label(e, label); self->entries = g_list_append(self->entries, e); return e; @@ -480,3 +537,26 @@ void menu_find_submenus(ObMenu *self) e->data.submenu.submenu = menu_from_name(e->data.submenu.name); } } + +void menu_entry_set_label(ObMenuEntry *self, const gchar *label) +{ + switch (self->type) { + case OB_MENU_ENTRY_TYPE_SEPARATOR: + g_free(self->data.separator.label); + self->data.separator.label = g_strdup(label); + break; + case OB_MENU_ENTRY_TYPE_NORMAL: + g_free(self->data.normal.label); + self->data.normal.shortcut = + parse_shortcut(label, &self->data.normal.label, + &self->data.normal.shortcut_position); + break; + default: + g_assert_not_reached(); + } +} + +void menu_show_all_shortcuts(ObMenu *self, gboolean show) +{ + self->show_all_shortcuts = show; +}