Index: trunk/plugins/launcher/launcher-dialog.c
===================================================================
--- trunk/plugins/launcher/launcher-dialog.c	(Revision 29703)
+++ trunk/plugins/launcher/launcher-dialog.c	(Arbeitskopie)
@@ -71,6 +71,7 @@
     LauncherEntry  *entry;
 
     /* entry widgets */
+    GtkWidget      *entry_dialog;
     GtkWidget      *entry_name;
     GtkWidget      *entry_comment;
     GtkWidget      *entry_icon;
@@ -80,6 +81,19 @@
 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
     GtkWidget      *entry_startup;
 #endif
+
+    /* extension by FN to get the normal sort order back as in 4.4 */
+    GtkWidget       *entry_invert;
+
+    /* FN: separator item extension */
+    GtkWidget       *radio_type_image;
+    GtkWidget       *radio_type_separator;
+
+    /* extension by FN to easily add the icons by typing in their icon
+     * name */
+    GtkWidget       *entry_iconName;
+    // which position is the currently selected icon?
+    guint position; 
 };
 
 
@@ -111,7 +125,8 @@
                                                                LauncherDialog        *ld);
 static void        launcher_dialog_save_button               (GtkWidget             *button,
                                                               LauncherDialog        *ld);
-static void        launcher_dialog_update_entries            (LauncherDialog        *ld);
+static void        launcher_dialog_update_entries            (LauncherDialog        *ld,
+                                                                gboolean toggle_type_buttons);
 static void        launcher_dialog_update_icon               (LauncherDialog        *ld);
 static void        launcher_dialog_command_chooser           (LauncherDialog        *ld);
 static void        launcher_dialog_icon_chooser              (LauncherDialog        *ld);
@@ -187,7 +202,8 @@
     value = xfce_rc_read_entry_untranslated (rc, "Icon", NULL);
     if (G_LIKELY (value != NULL))
     {
-        g_free (entry->icon);
+        if (strlen(entry->icon)>0)
+            g_free (entry->icon);
 
         /* get rid of extensions in non-absolute names */
         if (G_UNLIKELY (g_path_is_absolute (value) == FALSE) &&
@@ -300,6 +316,16 @@
                 break;
          }
 
+         if (position==0)
+         {
+             // swap ancient first and new item so that ancient first will be after separator
+         }
+         else if (position==1)
+         {
+            // move to position 2
+            position++;
+         }
+
         /* we need to update the button icon afterwards */
         if (i == 0)
             update_icon = TRUE;
@@ -406,7 +432,7 @@
             if (G_LIKELY (launcher_dialog_read_desktop_file (file, ld->entry) == TRUE))
             {
                 /* update the widgets */
-                launcher_dialog_update_entries (ld);
+                launcher_dialog_update_entries (ld, TRUE);
 
                 /* update the tree */
                 launcher_dialog_tree_update_row (ld, COLUMN_NAME);
@@ -470,9 +496,15 @@
         if (G_UNLIKELY (text == NULL || *text == '\0'))
             text = NULL;
 
-        /* save new value */
-        if (entry == ld->entry_name)
+        /* save new value if not a separator entry.
+         * for a separator entry, we prefer keeping this value to gain it back */
+        /* FN: might want to change that to gtk_toggl_button_get_active(ld->separator_button) */
+        if (ld->entry->type==SEPARATOR_ENTRY)
         {
+            // do nothing then
+        }
+        else if (entry == ld->entry_name) 
+        {
             g_free (ld->entry->name);
             ld->entry->name = g_strdup (text);
 
@@ -490,6 +522,7 @@
             ld->entry->exec = text ? xfce_expand_variables (text, NULL) : NULL;
         }
     }
+    /* FN: do not handel entry_iconname as this one is handled separately */
 
     /* update panel */
     launcher_plugin_rebuild (ld->launcher, FALSE);
@@ -521,24 +554,62 @@
 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
     else if (button == ld->entry_startup)
         ld->entry->startup = active;
+    else if (button == ld->entry_invert)
+        ld->launcher->invert = active;
+    else
+       g_assert(FALSE);
 #endif
 }
 
 
 
 static void
-launcher_dialog_update_entries (LauncherDialog *ld)
+launcher_dialog_type_button_toggled (GtkWidget *w,
+                                                             LauncherDialog *ld)
 {
+    g_assert (ld->entry != NULL);
+    /* if (strcmp(gtk_button_get_label(GTK_BUTTON(w)), _("_Separator item"))==0) */
+
+
+    if ( ! gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
+        return;
+
+    if (w == ld->radio_type_separator && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
+    {
+        /* g_printf("  Separator\n"); */
+        ld->entry->type = SEPARATOR_ENTRY;
+        /* if (ld->entry->icon==NULL) ld->entry->icon = ""; ??? */
+    }
+    else
+    {
+        /* g_printf(" Image\n"); */
+        ld->entry->type = IMAGE_ENTRY;
+    }
+    /* update the tree */
+    launcher_dialog_tree_update_row (ld, COLUMN_NAME);
+    launcher_dialog_tree_update_row (ld, COLUMN_ICON);
+
+    launcher_dialog_update_entries (ld, FALSE);
+}
+
+
+
+
+/* FN: want to use function overrinding actually with the second argument set to TRUE by default. */
+static void
+launcher_dialog_update_entries (LauncherDialog *ld, gboolean toggle_type_buttons)
+{
     gchar *dir;
+    GtkTreePath *path;
     
     /* quit if locked or no active entry set */
-    if (G_UNLIKELY (ld->updating == TRUE || ld->entry == NULL))
+    if (G_UNLIKELY (ld->updating == TRUE ))
         return;
-
-    /* lock the save functions */
+/*
+    // lock the save functions
     ld->updating = TRUE;
 
-    /* set new entry values */
+    // set new entry values
     gtk_entry_set_text (GTK_ENTRY (ld->entry_name),
                         (ld->entry->name != NULL) ? ld->entry->name : "");
 
@@ -558,7 +629,7 @@
     if (dir != ld->entry->path)
       g_free (dir);
 
-    /* set toggle buttons */
+    // set toggle buttons
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->entry_terminal),
                                   ld->entry->terminal);
 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
@@ -567,7 +638,147 @@
 
     gtk_widget_set_sensitive (ld->entry_startup, !ld->entry->terminal);
 #endif
+* */
 
+/* FN: Separator item extension, null is used for menu content shower thingie */
+    else if (ld->entry == NULL || ld->entry->type == SEPARATOR_ENTRY || ld->position==1)
+    {
+        ld->updating = TRUE;
+
+        /* clear fields */
+        gtk_entry_set_text (GTK_ENTRY (ld->entry_name), "");
+        gtk_entry_set_text (GTK_ENTRY (ld->entry_comment), "");
+        gtk_entry_set_text (GTK_ENTRY (ld->entry_iconName), "");
+        //gtk_entry_set_text (GTK_ENTRY (ld->entry_path), "");
+        gtk_entry_set_text (GTK_ENTRY (ld->entry_exec), "");
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(ld->entry_startup), FALSE);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(ld->entry_terminal), FALSE);
+
+        dir = g_strdup("");
+        gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (ld->entry_path), dir);
+
+        /* remove icon */
+        //launcher_dialog_update_icon (ld);
+
+        /* make all widgets insensitive */
+        gtk_widget_set_sensitive (ld->entry_name, FALSE);
+        gtk_widget_set_sensitive (ld->entry_comment, FALSE);
+        gtk_widget_set_sensitive (ld->entry_exec, FALSE);
+        gtk_widget_set_sensitive (ld->entry_iconName, FALSE);
+        gtk_widget_set_sensitive (ld->entry_path, FALSE);
+        gtk_widget_set_sensitive (ld->entry_terminal, FALSE);
+        gtk_widget_set_sensitive (ld->entry_startup, FALSE);
+        gtk_widget_set_sensitive (ld->entry_icon, FALSE);
+
+        if (toggle_type_buttons)
+        {
+            if (!ld->entry)
+            {
+                gtk_widget_set_sensitive (ld->radio_type_separator, FALSE);
+                gtk_widget_set_sensitive (ld->radio_type_image, FALSE);
+                gtk_widget_set_sensitive (ld->entry_dialog, FALSE);
+            }
+            else
+            {
+                gtk_widget_set_sensitive (ld->radio_type_separator, TRUE);
+                gtk_widget_set_sensitive (ld->radio_type_image, TRUE);
+
+                /* if (ld->entry->type == SEPARATOR_ENTRY)
+                { */
+                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ld->radio_type_separator), TRUE);
+                /* }
+                else
+                {
+                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ld->radio_type_image), TRUE);
+                } */
+                //gtk_widget_show_all(ld->entry_dialog);
+                gtk_widget_set_sensitive (ld->entry_dialog, TRUE);
+            }
+        }
+
+        /* and finally, return in order to not have ugly "else" paths */
+        /* return; */
+    }
+    else
+    {
+        gtk_widget_set_sensitive (ld->entry_dialog, TRUE);
+        gtk_widget_set_sensitive (ld->entry_name, TRUE);
+        gtk_widget_set_sensitive (ld->entry_comment, TRUE);
+        gtk_widget_set_sensitive (ld->entry_exec, TRUE);
+        gtk_widget_set_sensitive (ld->entry_iconName, TRUE);
+        gtk_widget_set_sensitive (ld->entry_path, TRUE);
+        gtk_widget_set_sensitive (ld->entry_terminal, TRUE);
+        gtk_widget_set_sensitive (ld->entry_startup, TRUE);
+        gtk_widget_set_sensitive (ld->radio_type_separator, TRUE);
+        gtk_widget_set_sensitive (ld->radio_type_image, TRUE);
+        gtk_widget_set_sensitive (ld->entry_icon, TRUE);
+
+        /* lock the save functions */
+        ld->updating = TRUE;
+
+        /* set new entry values */
+        gtk_entry_set_text (GTK_ENTRY (ld->entry_name),
+                            (ld->entry->name != NULL) ? ld->entry->name : "");
+
+        gtk_entry_set_text (GTK_ENTRY (ld->entry_comment),
+                            (ld->entry->comment != NULL) ? ld->entry->comment : "");
+
+        gtk_entry_set_text (GTK_ENTRY (ld->entry_exec),
+                            (ld->entry->exec != NULL) ? ld->entry->exec : "");
+
+        gtk_entry_set_text (GTK_ENTRY (ld->entry_iconName),
+                            (ld->entry->icon != NULL) ? ld->entry->icon : "");
+
+        gtk_entry_set_text (GTK_ENTRY (ld->entry_path),
+                            (ld->entry->path != NULL) ? ld->entry->path : "");
+
+        if (ld->entry->path != NULL)
+          dir = ld->entry->path;
+        else
+          dir = g_get_current_dir ();
+
+        gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (ld->entry_path), dir);
+
+        if (dir != ld->entry->path)
+          g_free (dir);
+
+        /* set toggle buttons */
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->entry_terminal),
+                                      ld->entry->terminal);
+
+    #ifdef HAVE_LIBSTARTUP_NOTIFICATION
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->entry_startup),
+                                      ld->entry->startup);
+
+        gtk_widget_set_sensitive (ld->entry_startup, !ld->entry->terminal);
+    #endif
+
+        /* extension by FN to get the normal sort order back as in 4.4 */
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->entry_invert),
+                                      ld->launcher->invert);
+
+        /* FN: Separator item extension */
+        /* but do not set them again; they are set on their own and aove! */
+        path = gtk_tree_path_new_first();
+        
+        if (ld->position==0)
+        {
+          gtk_widget_set_sensitive (ld->radio_type_separator, FALSE);
+          gtk_widget_set_sensitive (ld->radio_type_image, FALSE);
+        }
+        else
+        {
+          gtk_widget_set_sensitive (ld->radio_type_separator, TRUE);
+          gtk_widget_set_sensitive (ld->radio_type_image, TRUE);
+        }
+        
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->radio_type_image),
+                                  ld->entry->type==IMAGE_ENTRY);
+        /* gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->radio_type_separator),
+                                      ld->entry->type==SEPARATOR_ENTRY); */
+
+    }
+
     /* update icon button */
     launcher_dialog_update_icon (ld);
 
@@ -587,9 +798,25 @@
     if (GTK_BIN (ld->entry_icon)->child != NULL)
         gtk_widget_destroy (GTK_BIN (ld->entry_icon)->child);
 
-    if (G_LIKELY (ld->entry->icon))
+    /* FN: make it more secure, as it might be called when ld->entry is NULL! */
+    if (ld->entry && G_LIKELY (ld->entry->icon) && ld->entry->type==IMAGE_ENTRY)
+    {
         icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->entry_icon), ld->entry->icon, LAUNCHER_CHOOSER_ICON_SIZE);
 
+        /* FN: FIXME: this belongs elsewhere, but not here */
+        /* gtk_widget_set_sensitive(ld->entry_icon, TRUE); */
+    }
+    else if (ld->entry && G_LIKELY (ld->entry->icon) && ld->entry->type!=IMAGE_ENTRY)
+    {
+        // icon = NULL;
+    }
+    else if (!ld->entry) /* FN: make button unclickable */
+    {
+        /* FN: FIXME: this belongs elsewhere, but not here */
+        /* gtk_widget_set_sensitive(ld->entry_icon, FALSE); */
+        /* return; */ /* bottom part handles that, how nice. */
+    }
+
     /* create icon button */
     if (G_LIKELY (icon != NULL))
     {
@@ -762,7 +989,9 @@
 
     /* set the current icon, if there is any */
     if (G_LIKELY (ld->entry->icon))
+    {
         exo_icon_chooser_dialog_set_icon (EXO_ICON_CHOOSER_DIALOG (chooser), ld->entry->icon);
+    }
 
     /* run the icon chooser dialog */
     if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
@@ -783,6 +1012,10 @@
         }
 #endif
 
+        /* FN: get string into our good, old, old-fashioned style, plain entry
+         * field */
+        gtk_entry_set_text(GTK_ENTRY(ld->entry_iconName), ld->entry->icon);
+
         /* update the icon button */
         launcher_dialog_update_icon (ld);
 
@@ -814,6 +1047,7 @@
     GtkTreeIter       iter;
     GdkPixbuf        *icon = NULL;
     const gchar      *name;
+    char *tmpicon;
 
     selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ld->treeview));
 
@@ -823,8 +1057,15 @@
         {
             case COLUMN_ICON:
                 /* load entry icon */
-                icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), ld->entry->icon, LAUNCHER_TREE_ICON_SIZE);
+                /* g_assert (ld->entry->icon!=NULL); */ /* this fails sometimes */
+                /* if (ld->entry->icon==NULL) ld->entry->icon==""; ??? */
+                if (ld->entry->type==IMAGE_ENTRY)
+                    tmpicon = ld->entry->icon;
+                else
+                    tmpicon = "";
 
+                icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), tmpicon, LAUNCHER_TREE_ICON_SIZE);
+
                 /* set new icon */
                 gtk_list_store_set (ld->store, &iter,
                                     COLUMN_ICON, icon,
@@ -837,8 +1078,12 @@
                 break;
 
             case COLUMN_NAME:
-                /* TRANSLATORS: Fallback name for a launcher item without a name */
-                name = ld->entry->name ? ld->entry->name : _("Unnamed");
+                if (ld->entry->type==IMAGE_ENTRY)
+                    /* TRANSLATORS: Fallback name for a launcher item without a name */
+                    name = ld->entry->name ? ld->entry->name : _("Unnamed");
+                else
+                    /* TRANSLATORS: name for a separator item */
+                    name = _("--- Separator ---"); /* FN: better use g_strdup()? */
             
                 /* set new name */
                 gtk_list_store_set (ld->store, &iter,
@@ -878,12 +1123,27 @@
 
         /* get position */
         position = gtk_tree_path_get_indices (path)[0];
+        ld->position = position;
 
-        /* set new active entry */
-        ld->entry = (LauncherEntry *) g_list_nth (ld->launcher->entries, position)->data;
+        /* extension by FN to add separation bar */
 
+        if (position==1)
+        {
+            /* set no active entry */
+            ld->entry = NULL;
+            selected = FALSE;
+        }
+        else
+        {
+            /* set new active entry */
+            if (position>1)
+                position--;
+
+            ld->entry = (LauncherEntry *) g_list_nth (ld->launcher->entries, position)->data;
+        }
+
         /* update fields */
-        launcher_dialog_update_entries (ld);
+        launcher_dialog_update_entries (ld, TRUE);
 
         /* scroll new item to center of window */
         gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (ld->treeview), path, NULL,
@@ -898,8 +1158,8 @@
 
     /* change sensitivity of buttons */
     gtk_widget_set_sensitive (ld->up, selected && (position > 0));
-    gtk_widget_set_sensitive (ld->down, selected && (position < items - 1));
-    gtk_widget_set_sensitive (ld->remove, selected && (items > 1));
+    gtk_widget_set_sensitive (ld->down, selected && (position < items-2)); /* FN: items - 1, when we didn't have a separator */
+    gtk_widget_set_sensitive (ld->remove, selected && (items > 2));
 }
 
 
@@ -936,9 +1196,19 @@
         /* position of the item in the list */
         position = gtk_tree_path_get_indices (path)[0];
 
+        /* cant have position one, because we're moving upwards;
+         * and can't have position 1, because that would be a separator */
+        g_assert(position>1);
+
         /* check if we need to update the icon button image */
-        if (position == 1)
+        /* FN: position == 1, when there was no separator */
+        if (position == 2)
+        {
+            /* need to get even one earlier item lateron;
+             * thus decrease path counter already here by one */
+            gtk_tree_path_prev (path);
             update_icon = TRUE;
+        }
 
         /* get previous path */
         if (G_LIKELY (gtk_tree_path_prev (path)))
@@ -950,7 +1220,8 @@
             gtk_list_store_swap (ld->store, &iter_a, &iter_b);
 
             /* swap items in the list */
-            li = g_list_nth (ld->launcher->entries, position);
+            /* FN: need to decrease position by 1, because tree has one more entry */
+            li = g_list_nth (ld->launcher->entries, position-1);
             launcher_dialog_g_list_swap (li, li->prev);
         }
 
@@ -969,8 +1240,14 @@
         position = gtk_tree_path_get_indices (path)[0];
 
         /* check if we need to update the icon button image*/
+        /* FN: same game again; need to advance tree by one more item! */
         if (position == 0)
+        {
+            gtk_tree_path_next (path);
             update_icon = TRUE;
+        }
+        else
+            position--; /* need to increase position for all other items */
 
         /* get next item in the list */
         gtk_tree_path_next (path);
@@ -982,6 +1259,7 @@
             gtk_list_store_swap (ld->store, &iter_a, &iter_b);
 
             /* swap items in the list */
+            /* FN: same game again, need a lower position. but that's done above when position!=0 */
             li = g_list_nth (ld->launcher->entries, position);
             launcher_dialog_g_list_swap (li, li->next);
         }
@@ -1000,7 +1278,15 @@
         /* load new launcher icon */
         icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
 
-        /* append new entry */
+        /* FN: check that we insert _after_ the separator */
+        path = gtk_tree_model_get_path (model, &iter_a);
+
+        if (gtk_tree_path_get_indices (path)[0] == 0)
+            gtk_tree_model_iter_next (model, &iter_a);
+
+        /* g_assert (gtk_tree_path_get_indices (path)[0] > 0); */
+
+        /* append new entry - now after the separator */
         gtk_list_store_insert_after (ld->store, &iter_b, &iter_a);
         gtk_list_store_set (ld->store, &iter_b,
                             COLUMN_ICON, icon,
@@ -1018,8 +1304,10 @@
         position = gtk_tree_path_get_indices (path)[0];
 
         /* insert in list */
+        /* FN: need to decrease position by one to handle shorter launcher
+         * list */
         ld->launcher->entries = g_list_insert (ld->launcher->entries,
-                                               entry, position);
+                                               entry, position-1);
 
         /* select the new item (also updates treeview buttons) */
         gtk_tree_view_set_cursor (GTK_TREE_VIEW (ld->treeview), path, NULL, FALSE);
@@ -1039,6 +1327,9 @@
         /* get position of the item to remove */
         position = gtk_tree_path_get_indices (path)[0];
 
+        /* FN: check for valid position */
+        g_assert (position!=1);
+
         /* check if we need to update the icon button image*/
         if (position == 0)
             update_icon = TRUE;
@@ -1053,6 +1344,18 @@
         /* remove row from store */
         gtk_list_store_remove (ld->store, &iter_a);
 
+        /* FN: need to take care that wehen removing the first item, the
+         * separator and second item be swapped! */
+        if (position == 0)
+        {
+            /* swap separator now at pos 0 and next item at pos 1 */
+            gtk_tree_model_get_iter_first(model, &iter_a);
+            path = gtk_tree_model_get_path (model, &iter_a);
+            gtk_tree_path_next (path);
+            gtk_tree_model_get_iter (model, &iter_b, path);
+            gtk_list_store_swap (ld->store, &iter_a, &iter_b);
+        }
+
         /* unlock */
         ld->updating = FALSE;
 
@@ -1060,7 +1363,9 @@
         list_length = g_list_length (ld->launcher->entries);
 
         /* select previous item, if last item was removed */
-        if (position >= (guint) list_length)
+        /* FN: need to increase list_length because its one shorter due to
+         * separator */
+        if (position >= (guint) list_length+1)
             gtk_tree_path_prev (path);
 
         /* select the new item (also updates treeview buttons) */
@@ -1082,7 +1387,6 @@
 }
 
 
-
 static void
 launcher_dialog_arrow_position_changed (GtkComboBox    *combo,
                                         LauncherDialog *ld)
@@ -1093,7 +1397,56 @@
 }
 
 
+/* FN: Function to save toggled value. */
+static void
+launcher_dialog_entry_invert_toggled (GtkToggleButton *tb,
+                                        LauncherDialog *ld)
+{
+    ld->launcher->invert = gtk_toggle_button_get_active(tb);
+}
 
+
+/* FN: New function handle when a new icon name has been entered manually
+ */
+static void
+launcher_dialog_update_icon_from_entry (GtkWidget *entry,
+                                        LauncherDialog *ld)
+{
+    gchar *tmp;
+    gboolean update_icon = FALSE;
+
+    TRACE ("launcher_dialog_update_icon_from_entry entered.");
+
+    g_assert (entry);
+
+    if (!ld->entry)
+    {
+        return;
+    }
+
+    if (ld->entry->type==IMAGE_ENTRY)
+    {
+        tmp = (gchar *) gtk_entry_get_text(GTK_ENTRY(entry));
+        ld->entry->icon = g_strdup(tmp); /* const gchar* returned from gtk_entry_get_text that cannto be freed safely!!! */
+    }
+
+    launcher_dialog_update_icon(ld);
+
+    /* The following is just the same code as above in
+     * launcher_dialog_icon_chooser. Might want to extract it
+     * into a separate function. */
+    /* update the icon column in the tree */
+    launcher_dialog_tree_update_row (ld, COLUMN_ICON);
+
+    /* check if we need to update the icon button image */
+    if (g_list_index (ld->launcher->entries, ld->entry) == 0)
+        update_icon = TRUE;
+
+    /* update the panel widgets */
+    launcher_plugin_rebuild (ld->launcher, update_icon);
+}
+
+
 /**
  * Launcher dialog widgets
  **/
@@ -1112,6 +1465,23 @@
 
     sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
 
+    /* FN: type chooser radio buttons */
+    hbox = gtk_hbox_new (FALSE, BORDER);
+    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+    ld->radio_type_image = gtk_radio_button_new_with_mnemonic(NULL, _("_Image menu item"));
+    gtk_box_pack_start (GTK_BOX (hbox), ld->radio_type_image, FALSE, FALSE, 0);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ld->radio_type_image), TRUE);
+
+    g_signal_connect (G_OBJECT (ld->radio_type_image), "toggled",
+                      G_CALLBACK (launcher_dialog_type_button_toggled), ld);
+
+    ld->radio_type_separator = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(ld->radio_type_image), _("_Separator item"));
+    gtk_box_pack_start (GTK_BOX (hbox), ld->radio_type_separator, FALSE, FALSE, 0);
+
+    g_signal_connect (G_OBJECT (ld->radio_type_separator), "toggled",
+                      G_CALLBACK (launcher_dialog_type_button_toggled), ld);
+
     /* entry name field */
     hbox = gtk_hbox_new (FALSE, BORDER * 2);
     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
@@ -1159,6 +1529,12 @@
 
     gtk_size_group_add_widget (sg, label);
 
+    /* FN: old handling of icon names */
+    ld->entry_iconName = gtk_entry_new();
+    gtk_box_pack_start (GTK_BOX (hbox), ld->entry_iconName , FALSE, FALSE, 0);
+    g_signal_connect (G_OBJECT (ld->entry_iconName), "changed",
+                      G_CALLBACK (launcher_dialog_update_icon_from_entry), ld);
+
     ld->entry_icon = gtk_button_new ();
     gtk_box_pack_start (GTK_BOX (hbox), ld->entry_icon, FALSE, FALSE, 0);
 
@@ -1275,8 +1651,9 @@
     GtkTreeIter        iter;
     GList             *li;
     LauncherEntry     *entry;
-    GdkPixbuf         *icon;
+    GdkPixbuf         *icon = NULL;
     const gchar       *name;
+    gint count;
 
     /* scrolled window */
     scroll = gtk_scrolled_window_new (NULL, NULL);
@@ -1322,17 +1699,27 @@
                               G_CALLBACK (launcher_dialog_tree_selection_changed), ld);
 
     /* append current items */
-    for (li = ld->launcher->entries; li != NULL; li = li->next)
+    count = 0;
+    for (li = ld->launcher->entries; li != NULL; li = li->next, count++)
     {
         entry = li->data;
 
         if (G_LIKELY (entry))
         {
-            /* load icon */
-            icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
-            
-            name = entry->name ? entry->name : _("Unnamed");
+            if (entry->type==IMAGE_ENTRY)
+            {
+                /* build name */
+                name = entry->name ? entry->name : _("Unnamed");
 
+                /* load icon */
+                icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE);
+            }
+            else /* SEPARATOR_ENTRY */
+            {
+                /* build name */
+                name =  _("--- Separator ---"); /* FN: better use g_strdup()? */
+            }
+
             /* create new row and add the data */
             gtk_list_store_append (ld->store, &iter);
             gtk_list_store_set (ld->store, &iter,
@@ -1343,6 +1730,15 @@
             if (G_LIKELY (icon))
                 g_object_unref (G_OBJECT (icon));
         }
+
+        /* FN: extension to insert separator */
+        if (count==0)
+        {
+            gtk_list_store_append (ld->store, &iter);
+            name = g_strdup(_("--- Menu content below ---"));
+            gtk_list_store_set (ld->store, &iter,
+                                COLUMN_NAME, name, -1);
+        }
     }
 
     /* dnd support */
@@ -1537,9 +1933,9 @@
     gtk_container_set_border_width (GTK_CONTAINER (paned), BORDER);
 
     vbox = gtk_vbox_new (FALSE, BORDER);
-    gtk_paned_pack1 (GTK_PANED (paned), vbox, FALSE, FALSE);
+    gtk_paned_pack1 (GTK_PANED (paned), vbox, TRUE, TRUE); /* FALSE, FALSE */
 
-    /* arrow button position */
+    /* arrow button position in combo box */
     hbox = gtk_hbox_new (FALSE, BORDER);
     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
 
@@ -1562,17 +1958,23 @@
     g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (launcher_dialog_arrow_position_changed), ld);
     gtk_widget_show (combo);
 
+    /* FN: checkbox for selecting Nick's inverted sort order */
+    ld->entry_invert = gtk_check_button_new_with_mnemonic(_("_Invert menu sort order"));
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ld->entry_invert), ld->launcher->invert);
+    g_signal_connect (G_OBJECT (ld->entry_invert), "toggled", G_CALLBACK (launcher_dialog_entry_invert_toggled), ld);
+    gtk_box_pack_start (GTK_BOX (vbox),  ld->entry_invert, FALSE, FALSE, 0);
+
     /* add the entries list */
     widget = launcher_dialog_add_tree (ld);
-    gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
+    gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0); /* TRUE, FALSE */
 
     /* add the tree navigation buttons */
     widget = launcher_dialog_add_tree_buttons (ld);
     gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
 
     /* add the entry widgets */
-    widget = launcher_dialog_add_properties (ld);
-    gtk_paned_pack2 (GTK_PANED (paned), widget, TRUE, FALSE);
+    ld->entry_dialog = widget = launcher_dialog_add_properties (ld);
+    gtk_paned_pack2 (GTK_PANED (paned), widget, TRUE, TRUE);
 
     /* show all widgets inside dialog */
     gtk_widget_show_all (dialog_vbox);
Index: trunk/plugins/launcher/launcher.c
===================================================================
--- trunk/plugins/launcher/launcher.c	(Revision 29703)
+++ trunk/plugins/launcher/launcher.c	(Arbeitskopie)
@@ -665,12 +665,14 @@
 {
     GdkScreen     *screen;
     LauncherEntry *entry;
+    gint entry_number;
 
     /* get the widget screen */
     screen = gtk_widget_get_screen (mi);
 
-    /* get the item number */
+    /* get the associated entry */
     entry = g_object_get_data (G_OBJECT (mi), I_("entry"));
+
     if (G_LIKELY (entry))
     {
         if (event->button == 1)
@@ -834,8 +836,17 @@
     }
 }
 
+/*
+static void
+launcher_menu_tearoff_pressed (GtkWidget *w,
+                                                        LauncherPlugin *launcher)
+{
 
 
+    gtk_menu_set_tearoff_state (GTK_MENU(launcher->menu), TRUE);
+    gtk_window_set_default_size(GTK_WINDOW(launcher->menu)) ;
+} */
+
 static void
 launcher_menu_rebuild (LauncherPlugin *launcher)
 {
@@ -863,44 +874,76 @@
     /* get the arrow direction of the button */
     arrow_type = xfce_arrow_button_get_arrow_type (XFCE_ARROW_BUTTON (launcher->arrow_button));
 
+    if (launcher->invert)
+        li = launcher->entries;
+    else
+        li = g_list_last(launcher->entries);
+
     /* walk through the entries */
-    for (li = launcher->entries; li != NULL; li = li->next, n++)
+    while (li)
     {
-        /* skip the first entry when the arrow is visible */
-        if (n == 0 && launcher->arrow_position != LAUNCHER_ARROW_INSIDE_BUTTON)
-            continue;
+        /*for (li = launcher->entries; li != NULL; li = li->next, n++)
+        { */
+            /* skip the first entry when the arrow is visible */
+            /* FN: Note that this vast amount of checks should be superfluous as
+             * arrow_position is LAUNCHER_ARROW_INSIDE_BUTTON iff there is only
+             * one item. */
+            if (launcher->arrow_position != LAUNCHER_ARROW_INSIDE_BUTTON)
+            {
+                if ((n == 0 && launcher->invert) || (n == (g_list_length(launcher->entries)-1) && !launcher->invert))
+                {
+                    if (launcher->invert)
+                        li = g_list_next(li);
+                    else
+                        li = g_list_previous(li);
 
-        entry = li->data;
+                    n++;
+                    continue;
+                }
+            }
 
-        mi = gtk_image_menu_item_new_with_label (entry->name ? entry->name : _("New Item"));
-        gtk_widget_show (mi);
+            entry = li->data;
 
-        /* fix menu order when it's on the top or bottom of the screen */
-        if (arrow_type == GTK_ARROW_DOWN)
-            gtk_menu_shell_append (GTK_MENU_SHELL (launcher->menu), mi);
-        else
-            gtk_menu_shell_prepend (GTK_MENU_SHELL (launcher->menu), mi);
+            if (entry->type==SEPARATOR_ENTRY)
+            {
+                mi = gtk_separator_menu_item_new();
+                gtk_menu_shell_prepend (GTK_MENU_SHELL (launcher->menu), mi);
+                gtk_widget_show (mi);
+                /*n++;
+                continue; */
+            }
 
-        /* try to set an image */
-        if (G_LIKELY (entry->icon))
-        {
-            /* load pixbuf */
-            pixbuf = launcher_utility_load_pixbuf (screen, entry->icon, LAUNCHER_MENU_SIZE);
-
-            if (G_LIKELY (pixbuf))
+            else if (entry->type==IMAGE_ENTRY)
             {
-                /* set image */
-                image = gtk_image_new_from_pixbuf (pixbuf);
-                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
-                gtk_widget_show (image);
+                /* create menu item */
+                mi = gtk_image_menu_item_new_with_label (entry->name ? entry->name : _("New Item"));
+                gtk_menu_shell_prepend (GTK_MENU_SHELL (launcher->menu), mi);
+                gtk_widget_show (mi);
 
-                /* release reference */
-                g_object_unref (G_OBJECT (pixbuf));
+                /* try to set an image */
+                if (G_LIKELY (entry->icon))
+                {
+                    /* load pixbuf */
+                    pixbuf = launcher_utility_load_pixbuf (screen, entry->icon, LAUNCHER_MENU_SIZE);
+
+                    if (G_LIKELY (pixbuf))
+                    {
+                        /* set image */
+                        image = gtk_image_new_from_pixbuf (pixbuf);
+                        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
+                        gtk_widget_show (image);
+
+                        /* release reference */
+                        g_object_unref (G_OBJECT (pixbuf));
+                    }
+                }
             }
-        }
 
+
         /* set entry */
         g_object_set_data (G_OBJECT (mi), I_("entry"), entry);
+        /* and repair what nick broke */
+        g_object_set_data (G_OBJECT (mi), I_("entry-number"), n);
         
         /* dnd support */
         gtk_drag_dest_set (mi, GTK_DEST_DEFAULT_ALL, drop_targets, G_N_ELEMENTS (drop_targets), GDK_ACTION_COPY);
@@ -916,11 +959,26 @@
 
 #if !LAUNCHER_NEW_TOOLTIP_API
         /* set tooltip */
-        if (entry->comment)
+        if (entry->comment && entry->type==IMAGE_ENTRY)
             gtk_tooltips_set_tip (launcher->tips, mi, entry->comment, NULL);
 #endif
-    }
+     /*} */ /* end for all items */
 
+        if (launcher->invert)
+            li = g_list_next(li);
+        else
+            li = g_list_previous(li);
+
+        n++;
+    } /* end while */
+
+    /* FN: CHECKME: Was no longer in code at all; might be possible that
+     * at a different location the menu is built and shown; search it then!
+     */
+    mi = gtk_tearoff_menu_item_new();
+    gtk_menu_shell_prepend (GTK_MENU_SHELL (launcher->menu), mi);
+    gtk_widget_show (mi);
+
     /* connect deactivate signal */
     g_signal_connect_swapped (G_OBJECT (launcher->menu), "deactivate", G_CALLBACK (launcher_menu_deactivated), launcher);
 }
@@ -1221,6 +1279,9 @@
             launcher->move_first = xfce_rc_read_bool_entry (rc, "MoveFirst", FALSE);
             launcher->arrow_position = xfce_rc_read_int_entry (rc, "ArrowPosition", 0);
 
+            /* FN: Read our preferred sort order */
+            launcher->invert = xfce_rc_read_bool_entry (rc, "InvertSortOrder", FALSE);
+
             for (i = 0; i < 100 /* arbitrary */; ++i)
             {
                 /* create group name */
@@ -1242,6 +1303,7 @@
                 entry->icon = launcher_plugin_read_entry (rc, "Icon");
                 entry->exec = launcher_plugin_read_entry (rc, "Exec");
                 entry->path = launcher_plugin_read_entry (rc, "Path");
+                entry->type = (entry_type) xfce_rc_read_int_entry (rc, "Type", 0);
 
                 entry->terminal = xfce_rc_read_bool_entry (rc, "Terminal", FALSE);
 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
@@ -1316,6 +1378,9 @@
             xfce_rc_write_bool_entry (rc, "MoveFirst", launcher->move_first);
             xfce_rc_write_int_entry (rc, "ArrowPosition", launcher->arrow_position);
 
+            /* FN: Need to take care of saving our desired sort order */
+            xfce_rc_write_bool_entry (rc, "InvertSortOrder", launcher->invert);
+
             /* save all the entries */
             for (li = launcher->entries, i = 0; li != NULL; li = li->next, i++)
             {
@@ -1338,6 +1403,9 @@
                     xfce_rc_write_entry (rc, "Exec", entry->exec);
                 if (G_LIKELY (entry->path))
                     xfce_rc_write_entry (rc, "Path", entry->path);
+                /* FN: separator extension */
+                xfce_rc_write_int_entry (rc, "Type", entry->type);
+
                 xfce_rc_write_bool_entry (rc, "Terminal", entry->terminal);
 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
                 xfce_rc_write_bool_entry (rc, "StartupNotify", entry->startup);
Index: trunk/plugins/launcher/launcher-exec.c
===================================================================
--- trunk/plugins/launcher/launcher-exec.c	(Revision 29703)
+++ trunk/plugins/launcher/launcher-exec.c	(Arbeitskopie)
@@ -611,6 +611,10 @@
     /* maybe no command have been filed yet */
     if (G_UNLIKELY (entry->exec == NULL || *entry->exec == '\0'))
         return;
+    
+    /* separator items cannot be executed! */
+    if (entry->type == SEPARATOR_ENTRY)
+        return;
 
     /* check if the launcher supports (and needs) multiple instances */
     if (file_list != NULL &&
Index: trunk/plugins/launcher/launcher.h
===================================================================
--- trunk/plugins/launcher/launcher.h	(Revision 29703)
+++ trunk/plugins/launcher/launcher.h	(Arbeitskopie)
@@ -46,6 +46,12 @@
 typedef struct _LauncherEntry  LauncherEntry;
 typedef struct _LauncherPlugin LauncherPlugin;
 
+typedef enum entry_type_e
+{
+    IMAGE_ENTRY          = 0,
+    SEPARATOR_ENTRY
+} entry_type;
+
 struct _LauncherEntry
 {
     gchar    *name;
@@ -54,6 +60,8 @@
     gchar    *path;
     gchar    *icon;
 
+    entry_type type;
+
     guint     terminal : 1;
 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
     guint     startup : 1;
@@ -92,6 +100,10 @@
     /* settings */
     guint            move_first : 1;
     guint            arrow_position;
+
+    /* inverts the sort order as in Xfce 4.4 and as discussed extensively
+     *  by JH and FN somewhere between 2005 and 2006 */
+    gboolean      invert;
 };
 
 enum
@@ -108,7 +120,7 @@
 static const GtkTargetEntry drop_targets[] =
 {
     { (gchar *) "text/uri-list", 0, 0, },
-    { (gchar *) "STRING",	       0, 0 },
+    { (gchar *) "STRING",        0, 0 },
     { (gchar *) "UTF8_STRING",   0, 0 },
     { (gchar *) "text/plain",    0, 0 },
 };
