add lastitem and adapt code to general code style
[xmenu] / xmenu.c
diff --git a/xmenu.c b/xmenu.c
index 141551f..76761cc 100644 (file)
--- a/xmenu.c
+++ b/xmenu.c
@@ -333,9 +333,9 @@ initmonitor(void)
 static void
 initresources(void)
 {
 static void
 initresources(void)
 {
-       char *xrm;
        long n;
        char *type;
        long n;
        char *type;
+       char *xrm;
        XrmDatabase xdb;
        XrmValue xval;
 
        XrmDatabase xdb;
        XrmValue xval;
 
@@ -1015,16 +1015,21 @@ drawitems(struct Menu *menu)
                                             Convex, CoordModeOrigin);
                        }
 
                                             Convex, CoordModeOrigin);
                        }
 
-                       /* draw icon */
-                       if (item->file && !iflag)
+                       /* try to load icon */
+                       if (item->file && !iflag) {
                                item->icon = loadicon(item->file);
                                item->icon = loadicon(item->file);
+                               free(item->file);
+                       }
 
 
+                       /* draw icon if properly loaded */
                        if (item->icon) {
                                imlib_context_set_image(item->icon);
                                imlib_context_set_drawable(item->sel);
                                imlib_render_image_on_drawable(config.horzpadding, config.iconpadding);
                                imlib_context_set_drawable(item->unsel);
                                imlib_render_image_on_drawable(config.horzpadding, config.iconpadding);
                        if (item->icon) {
                                imlib_context_set_image(item->icon);
                                imlib_context_set_drawable(item->sel);
                                imlib_render_image_on_drawable(config.horzpadding, config.iconpadding);
                                imlib_context_set_drawable(item->unsel);
                                imlib_render_image_on_drawable(config.horzpadding, config.iconpadding);
+                               imlib_context_set_image(item->icon);
+                               imlib_free_image();
                        }
                }
        }
                        }
                }
        }
@@ -1145,38 +1150,53 @@ getitem(struct Menu *menu, int y)
 static struct Item *
 itemcycle(struct Menu *currmenu, int direction)
 {
 static struct Item *
 itemcycle(struct Menu *currmenu, int direction)
 {
-       struct Item *item;
+       struct Item *item = NULL;
        struct Item *lastitem;
 
        struct Item *lastitem;
 
-       item = NULL;
+       for (lastitem = currmenu->list; lastitem && lastitem->next; lastitem = lastitem->next)
+               ;
 
 
-       if (direction == ITEMNEXT) {
+       /* select item (either separator or labeled item) in given direction */
+       switch (direction) {
+       case ITEMNEXT:
                if (currmenu->selected == NULL)
                        item = currmenu->list;
                else if (currmenu->selected->next != NULL)
                        item = currmenu->selected->next;
                if (currmenu->selected == NULL)
                        item = currmenu->list;
                else if (currmenu->selected->next != NULL)
                        item = currmenu->selected->next;
-
-               while (item != NULL && item->label == NULL)
-                       item = item->next;
-
-               if (item == NULL)
-                       item = currmenu->list;
-       } else {
-               for (lastitem = currmenu->list;
-                    lastitem != NULL && lastitem->next != NULL;
-                    lastitem = lastitem->next)
-                       ;
-
+               break;
+       case ITEMPREV:
                if (currmenu->selected == NULL)
                        item = lastitem;
                else if (currmenu->selected->prev != NULL)
                        item = currmenu->selected->prev;
                if (currmenu->selected == NULL)
                        item = lastitem;
                else if (currmenu->selected->prev != NULL)
                        item = currmenu->selected->prev;
+               break;
+       case ITEMFIRST:
+               item = currmenu->list;
+               break;
+       case ITEMLAST:
+               item = lastitem;
+               break;
+       }
 
 
+       /*
+        * the selected item can be a separator
+        * let's select the closest labeled item (ie., one that isn't a separator)
+        */
+       switch (direction) {
+       case ITEMNEXT:
+       case ITEMFIRST:
+               while (item != NULL && item->label == NULL)
+                       item = item->next;
+               if (item == NULL)
+                       item = currmenu->list;
+               break;
+       case ITEMPREV:
+       case ITEMLAST:
                while (item != NULL && item->label == NULL)
                        item = item->prev;
                while (item != NULL && item->label == NULL)
                        item = item->prev;
-
                if (item == NULL)
                        item = lastitem;
                if (item == NULL)
                        item = lastitem;
+               break;
        }
 
        return item;
        }
 
        return item;
@@ -1189,6 +1209,7 @@ run(struct Menu *currmenu)
        struct Menu *menu;
        struct Item *item;
        struct Item *previtem = NULL;
        struct Menu *menu;
        struct Item *item;
        struct Item *previtem = NULL;
+       struct Item *lastitem;
        KeySym ksym;
        XEvent ev;
 
        KeySym ksym;
        XEvent ev;
 
@@ -1252,15 +1273,26 @@ selectitem:
 
                        /* cycle through menu */
                        item = NULL;
 
                        /* cycle through menu */
                        item = NULL;
-                       if (ksym == XK_ISO_Left_Tab || ksym == XK_Up) {
+                       if (ksym == XK_Home || ksym == KSYMFIRST) {
+                               item = itemcycle(currmenu, ITEMFIRST);
+                       } else if (ksym == XK_End || ksym == KSYMLAST) {
+                               item = itemcycle(currmenu, ITEMLAST);
+                       } else if (ksym == XK_ISO_Left_Tab || ksym == XK_Up || ksym == KSYMUP) {
                                item = itemcycle(currmenu, ITEMPREV);
                                item = itemcycle(currmenu, ITEMPREV);
-                       } else if (ksym == XK_Tab || ksym == XK_Down) {
+                       } else if (ksym == XK_Tab || ksym == XK_Down || ksym == KSYMDOWN) {
                                item = itemcycle(currmenu, ITEMNEXT);
                                item = itemcycle(currmenu, ITEMNEXT);
-                       } else if ((ksym == XK_Return || ksym == XK_Right) &&
-                                  currmenu->selected != NULL) {
+                       } else if (ksym >= XK_1 && ksym <= XK_9){
+                               item = itemcycle(currmenu, ITEMFIRST);
+                               lastitem = itemcycle(currmenu, ITEMLAST);
+                               for (int i = ksym - XK_1; i > 0 && item != lastitem; i--) {
+                                       currmenu->selected = item;
+                                       item = itemcycle(currmenu, ITEMNEXT);
+                               }
+                       } else if ((ksym == XK_Return || ksym == XK_Right || ksym == KSYMRIGHT) &&
+                                   currmenu->selected != NULL) {
                                item = currmenu->selected;
                                goto selectitem;
                                item = currmenu->selected;
                                goto selectitem;
-                       } else if ((ksym == XK_Escape || ksym == XK_Left) &&
+                       } else if ((ksym == XK_Escape || ksym == XK_Left || ksym == KSYMLEFT) &&
                                   currmenu->parent != NULL) {
                                item = currmenu->parent->selected;
                                currmenu = currmenu->parent;
                                   currmenu->parent != NULL) {
                                item = currmenu->parent->selected;
                                currmenu = currmenu->parent;
@@ -1316,13 +1348,6 @@ cleanmenu(struct Menu *menu)
                if (tmp->label != tmp->output)
                        free(tmp->label);
                free(tmp->output);
                if (tmp->label != tmp->output)
                        free(tmp->label);
                free(tmp->output);
-               if (tmp->file != NULL) {
-                       free(tmp->file);
-                       if (tmp->icon != NULL) {
-                               imlib_context_set_image(tmp->icon);
-                               imlib_free_image();
-                       }
-               }
                item = item->next;
                free(tmp);
        }
                item = item->next;
                free(tmp);
        }