Include a Other Software section in Help file
[geeqie.git] / src / collect-io.c
index 8f6b3a2..464f997 100644 (file)
@@ -78,6 +78,9 @@ static gboolean collection_load_private(CollectionData *cd, const gchar *path, C
        guint flush = !!(flags & COLLECTION_LOAD_FLUSH);
        guint append = !!(flags & COLLECTION_LOAD_APPEND);
        guint only_geometry = !!(flags & COLLECTION_LOAD_GEOMETRY);
+       gboolean reading_extended_filename = FALSE;
+       GString *extended_filename_buffer = g_string_new(NULL);
+       gchar *buffer2;
 
        if (!only_geometry)
                {
@@ -118,60 +121,104 @@ static gboolean collection_load_private(CollectionData *cd, const gchar *path, C
                gchar *buf;
                gchar *p = s_buf;
 
-               /* Skip whitespaces and empty lines */
-               while (*p && g_ascii_isspace(*p)) p++;
-               if (*p == '\n' || *p == '\r') continue;
+               if (!reading_extended_filename)
+                       {
+                       /* Skip whitespaces and empty lines */
+                       while (*p && g_ascii_isspace(*p)) p++;
+                       if (*p == '\n' || *p == '\r') continue;
+
+                       /* Parse comments */
+                       if (*p == '#')
+                               {
+                               if (!need_header) continue;
+                               if (g_ascii_strncasecmp(p, GQ_COLLECTION_MARKER, strlen(GQ_COLLECTION_MARKER)) == 0)
+                                       {
+                                       /* Looks like an official collection, allow unchecked input.
+                                        * All this does is allow adding files that may not exist,
+                                        * which is needed for the collection manager to work.
+                                        * Also unofficial files abort after too many invalid entries.
+                                        */
+                                       has_official_header = TRUE;
+                                       limit_failures = FALSE;
+                                       }
+                               else if (strncmp(p, "#geometry:", 10 ) == 0 &&
+                                        scan_geometry(p + 10, &cd->window_x, &cd->window_y, &cd->window_w, &cd->window_h))
+                                       {
+                                       has_geometry_header = TRUE;
+                                       cd->window_read = TRUE;
+                                       if (only_geometry) break;
+                                       }
+                               else if (g_ascii_strncasecmp(p, "#GQview collection", strlen("#GQview collection")) == 0)
+                                       {
+                                       /* As 2008/04/15 there is no difference between our collection file format
+                                        * and GQview 2.1.5 collection file format so ignore failures as well. */
+                                       has_gqview_header = TRUE;
+                                       limit_failures = FALSE;
+                                       }
+                               need_header = (!has_official_header && !has_gqview_header) || !has_geometry_header;
+                               continue;
+                               }
 
-               /* Parse comments */
-               if (*p == '#')
+                       if (only_geometry) continue;
+                       }
+
+               /* Read filenames */
+               /** @todo This is not safe! */
+               /* Updated: anything within double quotes is considered a filename */
+               if (!reading_extended_filename)
                        {
-                       if (!need_header) continue;
-                       if (g_ascii_strncasecmp(p, GQ_COLLECTION_MARKER, strlen(GQ_COLLECTION_MARKER)) == 0)
+                       /* not yet reading filename */
+                       while (*p && *p != '"') p++;
+                       if (*p) p++;
+                       /* start of filename read */
+                       buf = p;
+                       while (*p && *p != '"') p++;
+                       if (p[0] != '"')
                                {
-                               /* Looks like an official collection, allow unchecked input.
-                                * All this does is allow adding files that may not exist,
-                                * which is needed for the collection manager to work.
-                                * Also unofficial files abort after too many invalid entries.
-                                */
-                               has_official_header = TRUE;
-                               limit_failures = FALSE;
+                               /* first part of extended filename */
+                               g_string_append(extended_filename_buffer, buf);
+                               reading_extended_filename = TRUE;
+                               continue;
                                }
-                       else if (strncmp(p, "#geometry:", 10 ) == 0 &&
-                                scan_geometry(p + 10, &cd->window_x, &cd->window_y, &cd->window_w, &cd->window_h))
+                       }
+               else
+                       {
+                       buf = p;
+                       while (*p && *p != '"') p++;
+                       if (p[0] != '"')
                                {
-                               has_geometry_header = TRUE;
-                               cd->window_read = TRUE;
-                               if (only_geometry) break;
+                               /* end of extended filename still not found */
+                               g_string_append(extended_filename_buffer, buf);
+                               continue;
                                }
-                       else if (g_ascii_strncasecmp(p, "#GQview collection", strlen("#GQview collection")) == 0)
+                       else
                                {
-                               /* As 2008/04/15 there is no difference between our collection file format
-                                * and GQview 2.1.5 collection file format so ignore failures as well. */
-                               has_gqview_header = TRUE;
-                               limit_failures = FALSE;
+                               /* end of extended filename found */
+                               g_string_append_len(extended_filename_buffer, buf, p - buf);
+                               reading_extended_filename = FALSE;
                                }
-                       need_header = (!has_official_header && !has_gqview_header) || !has_geometry_header;
-                       continue;
                        }
 
-               if (only_geometry) continue;
+               if (strlen(extended_filename_buffer->str) > 0)
+                       {
+                       buffer2 = g_strdup(extended_filename_buffer->str);
+                       g_string_erase(extended_filename_buffer, 0, -1);
+                       }
+               else
+                       {
+                       *p = 0;
+                       buffer2 = g_strdup(buf);
+                       }
 
-               /* Read filenames */
-               /* TODO: This is not safe! */
-               while (*p && *p != '"') p++;
-               if (*p) p++;
-               buf = p;
-               while (*p && *p != '"') p++;
-               *p = 0;
-               if (*buf)
+               if (*buffer2)
                        {
                        gboolean valid;
 
                        if (!flush)
-                               changed |= collect_manager_process_action(entry, &buf);
+                               changed |= collect_manager_process_action(entry, &buffer2);
 
-                       valid = (buf[0] == G_DIR_SEPARATOR && collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE));
-                       if (!valid) DEBUG_1("collection invalid file: %s", buf);
+                       valid = (buffer2[0] == G_DIR_SEPARATOR && collection_add_check(cd, file_data_new_simple(buffer2), FALSE, TRUE));
+                       if (!valid) DEBUG_1("collection invalid file: %s", buffer2);
 
                        total++;
                        if (!valid)
@@ -187,8 +234,11 @@ static gboolean collection_load_private(CollectionData *cd, const gchar *path, C
                                        }
                                }
                        }
+               g_free(buffer2);
                }
 
+       g_string_free(extended_filename_buffer, TRUE);
+
        DEBUG_1("collection files: total = %d fail = %d official=%d gqview=%d geometry=%d",
                          total, fail, has_official_header, has_gqview_header, has_geometry_header);
 
@@ -674,9 +724,7 @@ static gboolean collect_manager_process_action(CollectManagerEntry *entry, gchar
 
        if (action)
                {
-               g_free(path);
-               path = g_strdup(action->newpath);
-               *path_ptr = path;
+               strcpy(*path_ptr, action->newpath);
                return TRUE;
                }
 
@@ -969,6 +1017,75 @@ void collect_manager_notify_cb(FileData *fd, NotifyType type, gpointer data)
                case FILEDATA_CHANGE_WRITE_METADATA:
                        break;
                }
+}
+
+static gint collection_manager_sort_cb(gconstpointer a, gconstpointer b)
+{
+       const gchar *char_a = a;
+       const gchar *char_b = b;
+
+       return g_strcmp0(char_a, char_b);
+}
+/**
+ * @brief Creates sorted list of collections
+ * @param[out] names_exc sorted list of collections names excluding extension
+ * @param[out] names_inc sorted list of collections names including extension
+ * @param[out] paths sorted list of collection paths
+ * 
+ * Lists of type gchar.
+ * Used lists must be freed with string_list_free()
+ */
+void collect_manager_list(GList **names_exc, GList **names_inc, GList **paths)
+{
+       FileData *dir_fd;
+       GList *list = NULL;
+       gchar *name;
+       FileData *fd;
+       gchar *filename;
+
+       if (names_exc == NULL && names_inc == NULL && paths == NULL)
+               {
+               return;
+               }
+
+       dir_fd = file_data_new_dir((get_collections_dir()));
 
+       filelist_read(dir_fd, &list, NULL);
+
+       while (list)
+               {
+               fd = list->data;
+               filename = g_strdup(filename_from_path((gchar *)fd->path));
+
+               if (file_extension_match(filename, GQ_COLLECTION_EXT))
+                       {
+                       name = remove_extension_from_path(filename);
+
+                       if (names_exc != NULL)
+                               {
+                               *names_exc = g_list_insert_sorted(*names_exc, g_strdup(name),
+                                                                                       collection_manager_sort_cb);
+                               *names_exc = g_list_first(*names_exc);
+                               }
+                       if (names_inc != NULL)
+                               {
+                               *names_inc = g_list_insert_sorted(*names_inc,filename,
+                                                                                       collection_manager_sort_cb);
+                               *names_inc = g_list_first(*names_inc);
+                               }
+                       if (paths != NULL)
+                               {
+                               *paths = g_list_insert_sorted(*paths,fd->path,
+                                                                                       collection_manager_sort_cb);
+                               *paths = g_list_first(*paths);
+                               }
+                       g_free(name);
+                       }
+               list = list->next;
+               g_free(filename);
+               }
+
+       filelist_free(list);
 }
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */