Merge branch 'lua53'
authorKlaus Ethgen <Klaus@Ethgen.de>
Wed, 7 Aug 2019 14:55:15 +0000 (15:55 +0100)
committerKlaus Ethgen <Klaus@Ethgen.de>
Wed, 7 Aug 2019 14:55:15 +0000 (15:55 +0100)
* lua53:
  Compatibility function for lua > 5.1

28 files changed:
.travis.yml
configure.ac
doc/docbook/GuideMainWindowMenus.xml
doc/docbook/GuideMainWindowStatusBar.xml
doc/docbook/GuideOptionsToolbar.xml
doc/docbook/GuideReferenceKeyboardShortcuts.xml
src/filedata.c
src/filedata.h
src/icons/Makefile.am
src/icons/icon_next_page.png [deleted file]
src/icons/icon_previous_page.png [deleted file]
src/image-load.c
src/image_load_djvu.c
src/image_load_gdk.c
src/image_load_tiff.c
src/layout.c
src/layout_image.c
src/layout_util.c
src/misc.c
src/pan-view/pan-util.c
src/pixbuf_util.c
src/pixbuf_util.h
src/preferences.c
src/rcfile.c
src/toolbar.c
src/toolbar.h
src/typedefs.h
web/index.html

index 6229169..23693a8 100644 (file)
@@ -1,32 +1,10 @@
 language: c
 os: linux
-dist: trusty
+dist: bionic
 sudo: required
 compiler:
   - gcc
   - clang
-addons:
-  apt:
-    sources:
-      - trusty
-    packages:
-      - autoconf
-      - automake
-      - autotools-dev
-      - build-essential
-      - debhelper
-      - dh-autoreconf
-      - dpkg-dev
-      - gnome-doc-utils
-      - gnome-doc-utils
-      - imagemagick
-      - intltool
-      - libexiv2-dev
-      - libgtk2.0-dev
-      - libjpeg-dev
-      - liblcms2-dev
-      - liblircclient-dev
-      - liblua5.1-0-dev
-      - libtiff-dev
-      - libtool
-script: (CFLAGS= ./autogen.sh) && make
+before_install:
+  - sudo apt-get install -y autoconf automake autotools-dev build-essential debhelper dh-autoreconf dpkg-dev gnome-doc-utils gnome-doc-utils imagemagick intltool libexiv2-dev libgtk2.0-dev libjpeg-dev liblcms2-dev liblircclient-dev liblua5.1-0-dev libtiff-dev libtool
+script: (CFLAGS="-fPIC" ./autogen.sh) && make
index c21b91b..b5c28dc 100644 (file)
@@ -197,7 +197,7 @@ else
   prefix=$prefix
 fi
 
-AM_PATH_GLIB_2_0(2.24.0,,AC_MSG_ERROR(GLIB >= 2.24.0 not installed.))
+AM_PATH_GLIB_2_0(2.52.0,,AC_MSG_ERROR(GLIB >= 2.52.0 not installed.))
 AC_ARG_ENABLE([gtk3], AC_HELP_STRING([--disable-gtk3], [use gtk2 instead of gtk3]),[gtk3="${enableval}"], [gtk3=m4_ifdef([AM_PATH_GTK_3_0], [auto], [no])])
 
 if test x$gtk3 = xyes; then
@@ -663,6 +663,21 @@ AC_SUBST(DJVU_LIBS)
 
 AM_CONDITIONAL(HAVE_MARKDOWN, [ "$(command -v markdown)" ])
 
+# _NL_TIME_FIRST_WEEKDAY support
+# note that it is an enum and not a define
+# ----------------------------------------------------------------------
+
+AC_MSG_CHECKING([for _NL_TIME_FIRST_WEEKDAY])
+AC_TRY_LINK([#include <langinfo.h>], [
+char c;
+c = *((unsigned char *)  nl_langinfo(_NL_TIME_FIRST_WEEKDAY));
+], nl_ok=yes, nl_ok=no)
+AC_MSG_RESULT($nl_ok)
+if test "$nl_ok" = "yes"; then
+  AC_DEFINE([HAVE__NL_TIME_FIRST_WEEKDAY], [1],
+      [Define if _NL_TIME_FIRST_WEEKDAY is available])
+fi
+
 # ----------------------------------------------------------------------
 
 AH_TOP([
index 0c58c5c..3f1f93b 100644 (file)
   </section>\r
   <section id="Gomenu">\r
     <title>Go menu</title>\r
+    <para>The Page commands are for files which contain multiple images e.g. .tiff files</para>\r
     <variablelist>\r
       <varlistentry>\r
         <term>\r
           </menuchoice>\r
         </term>\r
         <listitem>\r
-          <para>Goes tothe first image.</para>\r
+          <para>Goes to the first image.</para>\r
         </listitem>\r
       </varlistentry>\r
       <varlistentry>\r
           </para>\r
         </listitem>\r
       </varlistentry>\r
+      <varlistentry>\r
+        <term>\r
+          <menuchoice>\r
+            <shortcut>\r
+              <keycombo>\r
+                <keycap>Ctrl</keycap>\r
+                <keycap>Home</keycap>\r
+              </keycombo>\r
+            </shortcut>\r
+            <guimenu>First Page</guimenu>\r
+          </menuchoice>\r
+        </term>\r
+        <listitem>\r
+          <para>Goes to the first page.</para>\r
+        </listitem>\r
+      </varlistentry>\r
+      <varlistentry>\r
+        <term>\r
+          <menuchoice>\r
+            <shortcut>\r
+              <keycombo>\r
+                <keycap>Ctrl</keycap>\r
+                <keycap>End</keycap>\r
+              </keycombo>\r
+            </shortcut>\r
+            <guimenu>Last Page</guimenu>\r
+          </menuchoice>\r
+        </term>\r
+        <listitem>\r
+          <para>Goes to the last page.</para>\r
+        </listitem>\r
+      </varlistentry>\r
+      <varlistentry>\r
+        <term>\r
+          <menuchoice>\r
+            <shortcut>\r
+              <keycombo>\r
+                <keycap>Ctrl</keycap>\r
+                <keycap>PageUp</keycap>\r
+              </keycombo>\r
+            </shortcut>\r
+            <guimenu>Previous Page</guimenu>\r
+          </menuchoice>\r
+        </term>\r
+        <listitem>\r
+          <para>Goes to the previous page.</para>\r
+        </listitem>\r
+      </varlistentry>\r
+      <varlistentry>\r
+        <term>\r
+          <menuchoice>\r
+            <shortcut>\r
+              <keycombo>\r
+                <keycap>Ctrl</keycap>\r
+                <keycap>PageDown</keycap>\r
+              </keycombo>\r
+            </shortcut>\r
+            <guimenu>Next Page</guimenu>\r
+          </menuchoice>\r
+        </term>\r
+        <listitem>\r
+          <para>Goes to the next page.</para>\r
+        </listitem>\r
+      </varlistentry>\r
     </variablelist>\r
     <para />\r
   </section>\r
index 76a5146..d72f8f7 100644 (file)
     <para>This section displays the dimensions (width x height) and file byte size of the image that is active in the image pane. When the format of the file in the image pane can not be determined the dimensions will show as “(0 x 0)”, in addition “(no read permision)” may appear if the file permissions do not allow reading the contents of the file.</para>\r
     <para />\r
   </section>\r
+  <section id="ZoomAndScroll">\r
+    <title>Zoom and Scroll</title>\r
+    <para>The button label displays the current zoom ratio. A ratio of 1:1 is the image's original size. When the left number is larger the image is displayed larger than original size, when the right number is larger the image is displayed smaller.</para>\r
+    <para>A tilde (~) appears within the ratio display when the zoom is set to fit the image within the display area. In this zoom mode the ratio is automatically adjusted, and the displayed ratio may not be the actual ratio because the status bar display rounds the actual value to the nearest tenth (0.1).</para>\r
+    <para />\r
+    <para>Clicking this button permits control of the behavior of the zoom and scroll settings used when changing the displayed image.</para>\r
+    <variablelist>\r
+      <varlistentry>\r
+        <term>\r
+          <guilabel>Zoom to original size</guilabel>\r
+        </term>\r
+        <listitem>\r
+          <para>The new image is set to its original size.</para>\r
+        </listitem>\r
+      </varlistentry>\r
+      <varlistentry>\r
+        <term>\r
+          <guilabel>Fit image to window</guilabel>\r
+        </term>\r
+        <listitem>\r
+          <para>The new image's zoom is changed so that the image will fit within the current view area.</para>\r
+        </listitem>\r
+      </varlistentry>\r
+      <varlistentry>\r
+        <term>\r
+          <guilabel>Leave zoom at previous setting</guilabel>\r
+        </term>\r
+        <listitem>\r
+          <para>The zoom setting is unchanged, the new image will be scaled the same as the previous image.</para>\r
+        </listitem>\r
+      </varlistentry>\r
+    </variablelist>\r
+    <variablelist>\r
+      <varlistentry>\r
+        <term>\r
+          <guilabel>Scroll to top left corner</guilabel>\r
+        </term>\r
+        <listitem>\r
+          <para>The new image is displayed from top left corner.</para>\r
+        </listitem>\r
+      </varlistentry>\r
+      <varlistentry>\r
+        <term>\r
+          <guilabel>Scroll to image center</guilabel>\r
+        </term>\r
+        <listitem>\r
+          <para>The new image is centered</para>\r
+        </listitem>\r
+      </varlistentry>\r
+      <varlistentry>\r
+        <term>\r
+          <guilabel>Keep the region from previous iamge</guilabel>\r
+        </term>\r
+        <listitem>\r
+          <para>The new image is positioned as the previous one, whenever possible.</para>\r
+        </listitem>\r
+      </varlistentry>\r
+    </variablelist>\r
+  </section>\r
   <section id="Buttons">\r
     <title>Buttons</title>\r
-    <para>Statusbar buttons corresponds to selected menu action.</para>\r
+    <para>\r
+      The Status bar toolbar buttons, the defaults are shown below, correspond to selected menu action. The buttons displayed may be changed in the\r
+      <link linkend="GuideOptionsToolbar">Toolbar tab of Preferences.</link>\r
+    </para>\r
     <para />\r
-    <section id="ZoomAndScroll">\r
-      <title>Zoom and Scroll</title>\r
-      <para>The button label displays the current zoom ratio. A ratio of 1:1 is the image's original size. When the left number is larger the image is displayed larger than original size, when the right number is larger the image is displayed smaller.</para>\r
-      <para>A tilde (~) appears within the ratio display when the zoom is set to fit the image within the display area. In this zoom mode the ratio is automatically adjusted, and the displayed ratio may not be the actual ratio because the status bar display rounds the actual value to the nearest tenth (0.1).</para>\r
-      <para />\r
-      <para>Clicking this button permits control of the behavior of the zoom and scroll settings used when changing the displayed image.</para>\r
-      <variablelist>\r
-        <varlistentry>\r
-          <term>\r
-            <guilabel>Zoom to original size</guilabel>\r
-          </term>\r
-          <listitem>\r
-            <para>The new image is set to its original size.</para>\r
-          </listitem>\r
-        </varlistentry>\r
-        <varlistentry>\r
-          <term>\r
-            <guilabel>Fit image to window</guilabel>\r
-          </term>\r
-          <listitem>\r
-            <para>The new image's zoom is changed so that the image will fit within the current view area.</para>\r
-          </listitem>\r
-        </varlistentry>\r
-        <varlistentry>\r
-          <term>\r
-            <guilabel>Leave zoom at previous setting</guilabel>\r
-          </term>\r
-          <listitem>\r
-            <para>The zoom setting is unchanged, the new image will be scaled the same as the previous image.</para>\r
-          </listitem>\r
-        </varlistentry>\r
-      </variablelist>\r
-      <variablelist>\r
-        <varlistentry>\r
-          <term>\r
-            <guilabel>Scroll to top left corner</guilabel>\r
-          </term>\r
-          <listitem>\r
-            <para>The new image is displayed from top left corner.</para>\r
-          </listitem>\r
-        </varlistentry>\r
-        <varlistentry>\r
-          <term>\r
-            <guilabel>Scroll to image center</guilabel>\r
-          </term>\r
-          <listitem>\r
-            <para>The new image is centered</para>\r
-          </listitem>\r
-        </varlistentry>\r
-        <varlistentry>\r
-          <term>\r
-            <guilabel>Keep the region from previous iamge</guilabel>\r
-          </term>\r
-          <listitem>\r
-            <para>The new image is positioned as the previous one, whenever possible.</para>\r
-          </listitem>\r
-        </varlistentry>\r
-      </variablelist>\r
-    </section>\r
     <section id="ExifRotate">\r
       <title>Exif rotate</title>\r
       <para>\r
index 95fe2cc..6f9ac54 100644 (file)
@@ -2,7 +2,7 @@
 <section id="GuideOptionsToolbar">\r
   <title>Toolbar</title>\r
   <para>\r
-    This dialogue enables you to change the items displayed on the Toolbar.\r
+    This dialogue enables you to change the items displayed on either the Main Toolbar or the Status Toolbar.\r
     <para />\r
     The initial display shows the current setup. You may re-order these items by right-clicking on any item.\r
     <para />\r
index 7b5993d..0a55378 100644 (file)
             <entry colsep="0" />\r
             <entry colsep="0" />\r
           </row>\r
+          <row>\r
+            <entry colsep="0">\r
+              <emphasis role="strong">For files with multiple pages e.g. tiff files</emphasis>\r
+            </entry>\r
+            <entry colsep="0" />\r
+            <entry colsep="0" />\r
+          </row>\r
+          <row>\r
+            <entry>\r
+              <code>\r
+                Ctrl +\r
+                <keycap>Home</keycap>\r
+              </code>\r
+            </entry>\r
+            <entry />\r
+            <entry>Go to first page</entry>\r
+          </row>\r
+          <row>\r
+            <entry>\r
+              <code>\r
+                Ctrl +\r
+                <keycap>End</keycap>\r
+              </code>\r
+            </entry>\r
+            <entry />\r
+            <entry>Go to last page</entry>\r
+          </row>\r
+          <row>\r
+            <entry>\r
+              <code>\r
+                Ctrl +\r
+                <keycap>PageUp</keycap>\r
+              </code>\r
+            </entry>\r
+            <entry />\r
+            <entry>Go to previous page</entry>\r
+          </row>\r
+          <row>\r
+            <entry>\r
+              <code>\r
+                Ctrl +\r
+                <keycap>PageDown</keycap>\r
+              </code>\r
+            </entry>\r
+            <entry />\r
+            <entry>Go to next page</entry>\r
+          </row>\r
           <row>\r
             <entry colsep="0">\r
               <emphasis role="strong">File Menu</emphasis>\r
           </row>\r
           <row>\r
             <entry>\r
-              <code>\r
-                Shift + Delete\r
-              </code>\r
+              <code>Shift + Delete</code>\r
             </entry>\r
             <entry />\r
             <entry>Permanently delete selected images.</entry>\r
index 2a2a645..e258052 100644 (file)
@@ -3397,6 +3397,23 @@ void marks_clear_all()
        g_hash_table_foreach(file_data_pool, marks_clear, NULL);
 }
 
+void file_data_set_page_num(FileData *fd, gint page_num)
+{
+       if (fd->page_total > 1 && page_num < 0)
+               {
+               fd->page_num = fd->page_total - 1;
+               }
+       else if (fd->page_total > 1 && page_num <= fd->page_total)
+               {
+               fd->page_num = page_num - 1;
+               }
+       else
+               {
+               fd->page_num = 0;
+               }
+       file_data_send_notification(fd, NOTIFY_REREAD);
+}
+
 void file_data_inc_page_num(FileData *fd)
 {
        if (fd->page_total > 0 && fd->page_num < fd->page_total - 1)
index 201c120..4664ded 100644 (file)
@@ -176,5 +176,6 @@ void read_rating_data(FileData *file);
 void file_data_inc_page_num(FileData *fd);
 void file_data_dec_page_num(FileData *fd);
 void file_data_set_page_total(FileData *fd, gint page_total);
+void file_data_set_page_num(FileData *fd, gint page_num);
 #endif
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
index df90eea..2ecc437 100644 (file)
@@ -50,9 +50,7 @@ ICONS_INLINE = \
        icon_trash.png \
        icon_heic.png \
        icon_grayscale.png \
-       icon_exposure.png \
-       icon_next_page.png \
-       icon_previous_page.png
+       icon_exposure.png
 
 ICONS_INLINE_PAIRS = \
        folder_closed           $(srcdir)/folder_closed.png     \
@@ -101,9 +99,7 @@ ICONS_INLINE_PAIRS = \
        icon_trash      $(srcdir)/icon_trash.png \
        icon_heic       $(srcdir)/icon_heic.png \
        icon_grayscale  $(srcdir)/icon_grayscale.png \
-       icon_exposure   $(srcdir)/icon_exposure.png \
-       icon_next_page  $(srcdir)/icon_next_page.png \
-       icon_previous_page      $(srcdir)/icon_previous_page.png
+       icon_exposure   $(srcdir)/icon_exposure.png
 
 icons_inline.h: $(ICONS_INLINE) Makefile.in
        @sh -ec "echo '/* Auto generated file, do not edit */'; echo; \
diff --git a/src/icons/icon_next_page.png b/src/icons/icon_next_page.png
deleted file mode 100644 (file)
index e3b023b..0000000
Binary files a/src/icons/icon_next_page.png and /dev/null differ
diff --git a/src/icons/icon_previous_page.png b/src/icons/icon_previous_page.png
deleted file mode 100644 (file)
index f3fcdf9..0000000
Binary files a/src/icons/icon_previous_page.png and /dev/null differ
index 578e0ae..8cee6e7 100644 (file)
@@ -698,6 +698,15 @@ static void image_loader_setup_loader(ImageLoader *il)
 
        il->loader = il->backend.loader_new(image_loader_area_updated_cb, image_loader_size_cb, image_loader_area_prepared_cb, il);
 
+#ifdef HAVE_TIFF
+       format = il->backend.get_format_name(il->loader);
+       if (g_strcmp0(format, "tiff") == 0)
+               {
+               il->backend.set_page_num(il->loader, il->fd->page_num);
+               }
+       g_free(format);
+#endif
+
 #ifdef HAVE_PDF
        format = il->backend.get_format_name(il->loader);
        if (g_strcmp0(format, "pdf") == 0)
@@ -818,6 +827,15 @@ static gboolean image_loader_begin(ImageLoader *il)
                }
        g_free(format);
 #endif
+#ifdef HAVE_TIFF
+       format = il->backend.get_format_name(il->loader);
+       if (g_strcmp0(format, "tiff") == 0)
+               {
+               gint i = il->backend.get_page_total(il->loader);
+               file_data_set_page_total(il->fd, i);
+               }
+       g_free(format);
+#endif
 
        il->bytes_read += b;
 
index 61d4efc..f69d0f8 100644 (file)
@@ -60,13 +60,13 @@ static gboolean image_loader_djvu_load(gpointer loader, const guchar *buf, gsize
        gint stride;
        gboolean alpha = FALSE;
        cairo_surface_t *surface;
-       gchar *pixels;
+       guchar *pixels;
 
        ctx = ddjvu_context_create(NULL);
 
        doc = ddjvu_document_create(ctx, NULL, FALSE);
 
-       ddjvu_stream_write(doc, 0, buf, count );
+       ddjvu_stream_write(doc, 0, (char *)buf, count );
        while (!ddjvu_document_decoding_done(doc));
 
        ld->page_total = ddjvu_document_get_pagenum(doc);
@@ -80,7 +80,7 @@ static gboolean image_loader_djvu_load(gpointer loader, const guchar *buf, gsize
        height = ddjvu_page_get_height(page);
        stride = width * 4;
 
-       pixels = (gchar *)g_malloc(height * stride);
+       pixels = (guchar *)g_malloc(height * stride);
 
        prect.x = 0;
        prect.y = 0;
@@ -88,9 +88,9 @@ static gboolean image_loader_djvu_load(gpointer loader, const guchar *buf, gsize
        prect.h = height;
        rrect = prect;
 
-       surface = cairo_image_surface_create_for_data((guchar *)pixels, CAIRO_FORMAT_RGB24, width, height, stride);
+       surface = cairo_image_surface_create_for_data(pixels, CAIRO_FORMAT_RGB24, width, height, stride);
 
-       ddjvu_page_render(page, DDJVU_RENDER_COLOR, &prect, &rrect, fmt, stride, pixels);
+       ddjvu_page_render(page, DDJVU_RENDER_COLOR, &prect, &rrect, fmt, stride, (char *)pixels);
 
        /* FIXME implementation of rotation is not correct */
        GdkPixbuf *tmp1;
index 2a04298..91cc875 100644 (file)
 
 static gchar* image_loader_gdk_get_format_name(gpointer loader)
 {
-       return gdk_pixbuf_format_get_name(gdk_pixbuf_loader_get_format(GDK_PIXBUF_LOADER(loader)));
+       GdkPixbufFormat *format;
+
+       format = gdk_pixbuf_loader_get_format(GDK_PIXBUF_LOADER(loader));
+       if (format)
+               {
+               return gdk_pixbuf_format_get_name(format);
+               }
+       else
+               {
+               return NULL;
+               }
 }
 static gchar** image_loader_gdk_get_format_mime_types(gpointer loader)
 {
index a3c8ce6..03315c0 100644 (file)
@@ -51,6 +51,8 @@ struct _ImageLoaderTiff {
        const guchar *buffer;
        toff_t used;
        toff_t pos;
+       gint page_num;
+       gint page_total;
 };
 
 static void free_buffer (guchar *pixels, gpointer data)
@@ -144,6 +146,7 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
        gint width, height, rowstride;
        size_t bytes;
        uint32 rowsperstrip;
+       gint dircount = 0;
 
        lt->buffer = buf;
        lt->used = count;
@@ -161,7 +164,21 @@ static gboolean image_loader_tiff_load (gpointer loader, const guchar *buf, gsiz
                DEBUG_1("Failed to open TIFF image");
                return FALSE;
                }
+       else
+               {
+               do
+                       {
+                       dircount++;
+                       } while (TIFFReadDirectory(tiff));
+               lt->page_total = dircount;
+               }
 
+    if (!TIFFSetDirectory(tiff, lt->page_num))
+               {
+               DEBUG_1("Failed to open TIFF image");
+               TIFFClose(tiff);
+               return FALSE;
+               }
 
        if (!TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width))
                {
@@ -364,6 +381,20 @@ static void image_loader_tiff_free(gpointer loader)
        g_free(lt);
 }
 
+static void image_loader_tiff_set_page_num(gpointer loader, gint page_num)
+{
+       ImageLoader *il = (ImageLoader *) loader;
+       ImageLoaderTiff *lt = (ImageLoaderTiff *) loader;
+
+       lt->page_num = page_num;
+}
+
+static gint image_loader_tiff_get_page_total(gpointer loader)
+{
+       ImageLoaderTiff *lt = (ImageLoaderTiff *) loader;
+
+       return lt->page_total;
+}
 
 void image_loader_backend_set_tiff(ImageLoaderBackend *funcs)
 {
@@ -378,6 +409,9 @@ void image_loader_backend_set_tiff(ImageLoaderBackend *funcs)
 
        funcs->get_format_name = image_loader_tiff_get_format_name;
        funcs->get_format_mime_types = image_loader_tiff_get_format_mime_types;
+
+       funcs->set_page_num = image_loader_tiff_set_page_num;
+       funcs->get_page_total = image_loader_tiff_get_page_total;
 }
 
 
index 2508496..d7edb2d 100644 (file)
@@ -63,7 +63,7 @@
 #define TOOLWINDOW_DEF_HEIGHT 450
 
 #define PROGRESS_WIDTH 150
-#define ZOOM_LABEL_WIDTH 64
+#define ZOOM_LABEL_WIDTH 120
 
 #define PANE_DIVIDER_SIZE 10
 
@@ -726,7 +726,7 @@ void layout_status_update_image(LayoutWindow *lw)
 
                        if (page_total > 0)
                                {
-                               text = g_strdup_printf(_("( %d x %d ) %s bytes%s%d%s%d%s"), width, height, b, "[", page_num, "/", page_total, "]");
+                               text = g_strdup_printf(_("( %d x %d ) %s bytes %s%d%s%d%s"), width, height, b, "[", page_num, "/", page_total, "]");
                                }
                        else
                                {
@@ -838,7 +838,7 @@ static void layout_status_setup(LayoutWindow *lw, GtkWidget *box, gboolean small
                }
        lw->info_details = layout_status_label(NULL, hbox, TRUE, 0, TRUE);
        DEBUG_NAME(lw->info_details);
-       gtk_widget_set_tooltip_text(GTK_WIDGET(lw->info_details), _("(Image dimensions) Image size"));
+       gtk_widget_set_tooltip_text(GTK_WIDGET(lw->info_details), _("(Image dimensions) Image size [page n of m]"));
        toolbar = layout_actions_toolbar(lw, TOOLBAR_STATUS);
 
        toolbar_frame = gtk_frame_new(NULL);
@@ -2641,6 +2641,7 @@ void layout_write_config(LayoutWindow *lw, GString *outstr, gint indent)
 
        WRITE_SEPARATOR();
        layout_toolbar_write_config(lw, TOOLBAR_MAIN, outstr, indent + 1);
+       layout_toolbar_write_config(lw, TOOLBAR_STATUS, outstr, indent + 1);
 
        WRITE_NL(); WRITE_STRING("</layout>");
 }
index 1a6cd59..60bdd5a 100644 (file)
@@ -283,6 +283,7 @@ static void image_animation_data_free(AnimationData *fd)
        if(!fd) return;
        if(fd->iter) g_object_unref(fd->iter);
        if(fd->gpa) g_object_unref(fd->gpa);
+       if(fd->cancellable) g_object_unref(fd->cancellable);
        g_free(fd);
 }
 
@@ -347,6 +348,10 @@ static gboolean layout_image_animate_check(LayoutWindow *lw)
                if(lw->animation)
                        {
                        lw->animation->valid = FALSE;
+                       if (lw->animation->cancellable)
+                               {
+                               g_cancellable_cancel(lw->animation->cancellable);
+                               }
                        lw->animation = NULL;
                        }
                return FALSE;
@@ -368,32 +373,86 @@ static void layout_image_animate_update_image(LayoutWindow *lw)
                }
 }
 
+
+static void animation_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
+{
+       GError *error = NULL;
+       AnimationData *animation = data;
+
+       if (animation)
+               {
+               if (g_cancellable_is_cancelled(animation->cancellable))
+                       {
+                       gdk_pixbuf_animation_new_from_stream_finish(res, NULL);
+                       g_object_unref(animation->in_file);
+                       g_object_unref(animation->gfstream);
+                       image_animation_data_free(animation);
+                       return;
+                       }
+
+               animation->gpa = gdk_pixbuf_animation_new_from_stream_finish(res, &error);
+               if (animation->gpa)
+                       {
+                       if (!gdk_pixbuf_animation_is_static_image(animation->gpa))
+                               {
+                               if (animation->iter = gdk_pixbuf_animation_get_iter(animation->gpa,NULL))
+                                       {
+                                       animation->iter = gdk_pixbuf_animation_get_iter(animation->gpa, NULL);
+                                       // FIXME: the reference count is being incremented here. Reason unknown.
+                                       g_object_unref(animation->gpa);
+                                       animation->data_adr = animation->lw->image->image_fd;
+                                       animation->delay = gdk_pixbuf_animation_iter_get_delay_time(animation->iter);
+                                       animation->valid = TRUE;
+
+                                       layout_image_animate_update_image(animation->lw);
+
+                                       g_timeout_add(animation->delay, show_next_frame, animation);
+                                       }
+                               }
+                       }
+               else
+                       {
+                       log_printf("Error reading GIF file: %s\n", error->message);
+                       }
+
+               g_object_unref(animation->in_file);
+               g_object_unref(animation->gfstream);
+               }
+}
+
 static gboolean layout_image_animate_new_file(LayoutWindow *lw)
 {
-       GError *err=NULL;
+       GFileInputStream *gfstream;
+       GError *error = NULL;
+       AnimationData *animation;
+       GFile *in_file;
 
        if(!layout_image_animate_check(lw)) return FALSE;
 
        if(lw->animation) lw->animation->valid = FALSE;
 
-       lw->animation = g_malloc0(sizeof(AnimationData));
-
-       if(!(lw->animation->gpa = gdk_pixbuf_animation_new_from_file(lw->image->image_fd->path,&err)) || err ||
-               gdk_pixbuf_animation_is_static_image(lw->animation->gpa) ||
-               !(lw->animation->iter = gdk_pixbuf_animation_get_iter(lw->animation->gpa,NULL)))
+       if (lw->animation)
                {
-               image_animation_data_free(lw->animation);
-               lw->animation = NULL;
-               return FALSE;
+               g_cancellable_cancel(lw->animation->cancellable);
                }
 
-       lw->animation->data_adr = lw->image->image_fd;
-       lw->animation->delay = gdk_pixbuf_animation_iter_get_delay_time(lw->animation->iter);
-       lw->animation->valid = TRUE;
-
-       layout_image_animate_update_image(lw);
+       animation = g_new0(AnimationData, 1);
+       lw->animation = animation;
+       animation->lw = lw;
+       animation->cancellable = g_cancellable_new();
 
-       g_timeout_add(lw->animation->delay, show_next_frame, lw->animation);
+       in_file = g_file_new_for_path(lw->image->image_fd->path);
+       animation->in_file = in_file;
+       gfstream = g_file_read(in_file, NULL, &error);
+       if (gfstream)
+               {
+               animation->gfstream = gfstream;
+               gdk_pixbuf_animation_new_from_stream_async((GInputStream*)gfstream, animation->cancellable, animation_async_ready_cb, animation);
+               }
+       else
+               {
+               log_printf("Error reading GIF file: %s\nError: %s\n", lw->image->image_fd->path, error->message);
+               }
 
        return TRUE;
 }
@@ -820,7 +879,7 @@ static void layout_image_dnd_receive(GtkWidget *widget, GdkDragContext *context,
 
        if (info == TARGET_TEXT_PLAIN)
                {
-               url = g_strdup(gtk_selection_data_get_data(selection_data));
+               url = g_strdup((gchar *)gtk_selection_data_get_data(selection_data));
                download_web_file(url, lw);
                g_free(url);
                }
index 5c3aa73..c818bde 100644 (file)
@@ -1541,6 +1541,22 @@ static void layout_menu_image_next_cb(GtkAction *action, gpointer data)
        layout_image_next(lw);
 }
 
+static void layout_menu_page_first_cb(GtkAction *action, gpointer data)
+{
+       LayoutWindow *lw = data;
+       FileData *fd = layout_image_get_fd(lw);
+
+       file_data_set_page_num(fd, 1);
+}
+
+static void layout_menu_page_last_cb(GtkAction *action, gpointer data)
+{
+       LayoutWindow *lw = data;
+       FileData *fd = layout_image_get_fd(lw);
+
+       file_data_set_page_num(fd, -1);
+}
+
 static void layout_menu_page_next_cb(GtkAction *action, gpointer data)
 {
        LayoutWindow *lw = data;
@@ -1906,8 +1922,10 @@ static GtkActionEntry menu_entries[] = {
   { "NextImage",       GTK_STOCK_GO_DOWN,      N_("_Next Image"),                      "space",                N_("Next Image"),                       CB(layout_menu_image_next_cb) },
   { "NextImageAlt1",   GTK_STOCK_GO_DOWN,      N_("_Next Image"),                      "Page_Down",            N_("Next Image"),                       CB(layout_menu_image_next_cb) },
 
-  { "NextPage",        PIXBUF_INLINE_ICON_NEXT_PAGE,   N_("_Next Page"),                       "<control>Page_Down",   N_("Next Page"),        CB(layout_menu_page_next_cb) },
-  { "PrevPage",        PIXBUF_INLINE_ICON_PREVIOUS_PAGE,       N_("_Previous Page"),   "<control>Page_Up",             N_("Previous Page"),    CB(layout_menu_page_previous_cb) },
+  { "FirstPage",       GTK_STOCK_MEDIA_PREVIOUS,       N_("_First Page"),      "<control>Home",        N_( "First Page"),      CB(layout_menu_page_first_cb) },
+  { "LastPage",        GTK_STOCK_MEDIA_NEXT,   N_("_Last Page"),       "<control>End",         N_("Last Page"),        CB(layout_menu_page_last_cb) },
+  { "NextPage",        GTK_STOCK_MEDIA_FORWARD,        N_("_Next Page"),                       "<control>Page_Down",   N_("Next Page"),        CB(layout_menu_page_next_cb) },
+  { "PrevPage",        GTK_STOCK_MEDIA_REWIND, N_("_Previous Page"),   "<control>Page_Up",             N_("Previous Page"),    CB(layout_menu_page_previous_cb) },
 
 
   { "NextImageAlt2",   GTK_STOCK_GO_DOWN,      N_("_Next Image"),                      "KP_Page_Down",         N_("Next Image"),                       CB(layout_menu_image_next_cb) },
@@ -2142,6 +2160,8 @@ static const gchar *menu_ui_description =
 "      <menuitem action='Up'/>"
 "      <menuitem action='Home'/>"
 "      <separator/>"
+"      <menuitem action='FirstPage'/>"
+"      <menuitem action='LastPage'/>"
 "      <menuitem action='NextPage'/>"
 "      <menuitem action='PrevPage'/>"
 "    </menu>"
@@ -2344,10 +2364,6 @@ static const gchar *menu_ui_description =
 "  <toolbar name='ToolBar'>"
 "  </toolbar>"
 "  <toolbar name='StatusBar'>"
-"    <toolitem action='ExifRotate'/>"
-"    <toolitem action='ShowInfoPixel'/>"
-"    <toolitem action='UseColorProfiles'/>"
-"    <toolitem action='SaveMetadata'/>"
 "  </toolbar>"
 "<accelerator action='PrevImageAlt1'/>"
 "<accelerator action='PrevImageAlt2'/>"
@@ -2628,6 +2644,7 @@ static void layout_actions_setup_editors(LayoutWindow *lw)
 void layout_actions_setup(LayoutWindow *lw)
 {
        GError *error;
+       gint i;
 
        DEBUG_1("%s layout_actions_setup: start", get_exec_time());
        if (lw->ui_manager) return;
@@ -2675,8 +2692,12 @@ void layout_actions_setup(LayoutWindow *lw)
                exit(EXIT_FAILURE);
                }
 
-       layout_toolbar_clear(lw, TOOLBAR_MAIN);
-       layout_toolbar_add_default(lw, TOOLBAR_MAIN);
+       DEBUG_1("%s layout_actions_setup: add toolbar", get_exec_time());
+       for (i = 0; i < TOOLBAR_COUNT; i++)
+               {
+               layout_toolbar_clear(lw, i);
+               layout_toolbar_add_default(lw, i);
+               }
 
        DEBUG_1("%s layout_actions_setup: marks", get_exec_time());
        layout_actions_setup_marks(lw);
@@ -2849,6 +2870,9 @@ void layout_toolbar_add(LayoutWindow *lw, ToolbarType type, const gchar *action)
                case TOOLBAR_MAIN:
                        path = "/ToolBar";
                        break;
+               case TOOLBAR_STATUS:
+                       path = "/StatusBar";
+                       break;
                default:
                        break;
                }
@@ -2933,6 +2957,36 @@ void layout_toolbar_add_default(LayoutWindow *lw, ToolbarType type)
                                layout_toolbar_add(lw, type, "FloatTools");
                                }
                        break;
+               case TOOLBAR_STATUS:
+                       if (layout_window_list)
+                               {
+                               lw_first = layout_window_list->data;
+                               if (lw_first->toolbar_actions[TOOLBAR_MAIN])
+                                       {
+                                       work_action = lw_first->toolbar_actions[type];
+                                       while (work_action)
+                                               {
+                                               gchar *action = work_action->data;
+                                               work_action = work_action->next;
+                                               layout_toolbar_add(lw, type, action);
+                                               }
+                                       }
+                               else
+                                       {
+                                       layout_toolbar_add(lw, type, "ExifRotate");
+                                       layout_toolbar_add(lw, type, "ShowInfoPixel");
+                                       layout_toolbar_add(lw, type, "UseColorProfiles");
+                                       layout_toolbar_add(lw, type, "SaveMetadata");
+                                       }
+                               }
+                       else
+                               {
+                               layout_toolbar_add(lw, type, "ExifRotate");
+                               layout_toolbar_add(lw, type, "ShowInfoPixel");
+                               layout_toolbar_add(lw, type, "UseColorProfiles");
+                               layout_toolbar_add(lw, type, "SaveMetadata");
+                               }
+                       break;
                default:
                        break;
                }
@@ -2950,6 +3004,9 @@ void layout_toolbar_write_config(LayoutWindow *lw, ToolbarType type, GString *ou
                case TOOLBAR_MAIN:
                        name = "toolbar";
                        break;
+               case TOOLBAR_STATUS:
+                       name = "statusbar";
+                       break;
                default:
                        break;
                }
index d780795..85c8765 100644 (file)
@@ -23,6 +23,7 @@
 #include "ui_fileops.h"
 
 #include <langinfo.h>
+#include <locale.h>
 
 gdouble get_zoom_increment(void)
 {
@@ -243,13 +244,32 @@ int runcmd(gchar *cmd)
  * @brief Returns integer representing first_day_of_week
  * @returns Integer in range 1 to 7
  * 
- * Uses current locale to get first day of week
+ * Uses current locale to get first day of week.
+ * If _NL_TIME_FIRST_WEEKDAY is not available, ISO 8601
+ * states first day of week is Monday.
+ * USA, Mexico and Canada (and others) use Sunday as first day of week.
  * 
  * Sunday == 1
  */
 gint date_get_first_day_of_week()
 {
+       gchar *dot;
+       gchar *current_locale;
+
+#ifdef HAVE__NL_TIME_FIRST_WEEKDAY
        return nl_langinfo(_NL_TIME_FIRST_WEEKDAY)[0];
+#else
+       current_locale = setlocale(LC_ALL, NULL);
+       dot = strstr(current_locale, ".");
+       if ((strncmp(dot - 2, "US", 2) == 0) || (strncmp(dot - 2, "MX", 2) == 0) || (strncmp(dot - 2, "CA", 2) == 0))
+               {
+               return 1;
+               }
+       else
+               {
+               return 2;
+               }
+#endif
 }
 
 /**
index 3fd5cc8..317660b 100644 (file)
@@ -82,6 +82,12 @@ gint pan_date_value(time_t d, PanDateLengthType length)
        return -1;
 }
 
+#if defined(__GLIBC_PREREQ)
+# if __GLIBC_PREREQ(2, 27)
+#  define HAS_GLIBC_STRFTIME_EXTENSIONS
+# endif
+#endif
+
 gchar *pan_date_value_string(time_t d, PanDateLengthType length)
 {
        struct tm td;
@@ -99,7 +105,7 @@ gchar *pan_date_value_string(time_t d, PanDateLengthType length)
                        format = "%A %e";
                        break;
                case PAN_DATE_LENGTH_MONTH:
-#if __GLIBC_PREREQ(2, 27)
+#if defined(HAS_GLIBC_STRFTIME_EXTENSIONS) || defined(__FreeBSD__)
                        format = "%OB %Y";
 #else
                        format = "%B %Y";
index 4243537..2a6f79d 100644 (file)
@@ -149,8 +149,6 @@ static PixbufInline inline_pixbuf_data[] = {
        { PIXBUF_INLINE_ICON_HEIF,      icon_heic },
        { PIXBUF_INLINE_ICON_GRAYSCALE, icon_grayscale },
        { PIXBUF_INLINE_ICON_EXPOSURE,  icon_exposure },
-       { PIXBUF_INLINE_ICON_NEXT_PAGE, icon_next_page },
-       { PIXBUF_INLINE_ICON_PREVIOUS_PAGE,     icon_previous_page },
        { NULL, NULL }
 };
 
index 5bd748e..bcec3ae 100644 (file)
@@ -77,8 +77,6 @@ gboolean pixbuf_scale_aspect(gint req_w, gint req_h, gint old_w, gint old_h, gin
 #define PIXBUF_INLINE_ICON_HEIF        "icon_heic"
 #define PIXBUF_INLINE_ICON_GRAYSCALE   "icon_grayscale"
 #define PIXBUF_INLINE_ICON_EXPOSURE            "icon_exposure"
-#define PIXBUF_INLINE_ICON_NEXT_PAGE   "icon_next_page"
-#define PIXBUF_INLINE_ICON_PREVIOUS_PAGE       "icon_previous_page"
 
 #define PIXBUF_INLINE_ICON_CW  "icon_rotate_clockwise"
 #define PIXBUF_INLINE_ICON_CCW "icon_rotate_counter_clockwise"
index c3e9329..41304ba 100644 (file)
@@ -465,7 +465,8 @@ static void config_window_apply(void)
 
        if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
 
-       toolbar_apply();
+       toolbar_apply(TOOLBAR_MAIN);
+       toolbar_apply(TOOLBAR_STATUS);
 }
 
 /*
@@ -653,8 +654,10 @@ static const UseableMouseItems useable_mouse_items[] = {
        {"Forward",     N_("Forward"), GTK_STOCK_GO_FORWARD},
        {"Home",        N_("Home"), GTK_STOCK_HOME},
        {"Up",  N_("Up"), GTK_STOCK_GO_UP},
-       {"NextPage",    N_("Next Page"), PIXBUF_INLINE_ICON_NEXT_PAGE},
-       {"PrevPage",    N_("Previous Page"), PIXBUF_INLINE_ICON_PREVIOUS_PAGE},
+       {"FirstPage",   N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
+       {"LastPage",    N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
+       {"NextPage",    N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
+       {"PrevPage",    N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
        {"NewWindow",   N_("New _window"), GTK_STOCK_NEW},
        {"NewCollection",       N_("New collection"), GTK_STOCK_INDEX},
        {"OpenCollection",      N_("Open collection"), GTK_STOCK_OPEN},
@@ -3429,8 +3432,8 @@ static void config_tab_accelerators(GtkWidget *notebook)
        gtk_widget_show(button);
 }
 
-/* toolbar tab */
-static void config_tab_toolbar(GtkWidget *notebook)
+/* toolbar main tab */
+static void config_tab_toolbar_main(GtkWidget *notebook)
 {
        GtkWidget *vbox;
        GtkWidget *toolbardata;
@@ -3438,9 +3441,25 @@ static void config_tab_toolbar(GtkWidget *notebook)
 
        lw = layout_window_list->data;
 
-       vbox = scrolled_notebook_page(notebook, _("Toolbar"));
+       vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
 
-       toolbardata = toolbar_select_new(lw);
+       toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
+       gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
+       gtk_widget_show(vbox);
+}
+
+/* toolbar status tab */
+static void config_tab_toolbar_status(GtkWidget *notebook)
+{
+       GtkWidget *vbox;
+       GtkWidget *toolbardata;
+       LayoutWindow *lw;
+
+       lw = layout_window_list->data;
+
+       vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
+
+       toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
        gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
        gtk_widget_show(vbox);
 }
@@ -3562,7 +3581,8 @@ static void config_window_create(void)
        config_tab_color(notebook);
        config_tab_stereo(notebook);
        config_tab_behavior(notebook);
-       config_tab_toolbar(notebook);
+       config_tab_toolbar_main(notebook);
+       config_tab_toolbar_status(notebook);
 
        hbox = gtk_hbutton_box_new();
        gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
index 9e1119f..9484132 100644 (file)
@@ -1306,6 +1306,27 @@ static void options_parse_toolbar(GQParserData *parser_data, GMarkupParseContext
                options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL);
                }
 }
+
+static void options_parse_statusbar(GQParserData *parser_data, GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer data, GError **error)
+{
+       LayoutWindow *lw = data;
+       if (g_ascii_strcasecmp(element_name, "toolitem") == 0)
+               {
+               layout_toolbar_add_from_config(lw, TOOLBAR_STATUS, attribute_names, attribute_values);
+               options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL);
+               }
+       else if (g_ascii_strcasecmp(element_name, "clear") == 0)
+               {
+               layout_toolbar_clear(lw, TOOLBAR_STATUS);
+               options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL);
+               }
+       else
+               {
+               log_printf("unexpected in <statusbar>: <%s>\n", element_name);
+               options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL);
+               }
+}
+
 static void options_parse_dialogs(GQParserData *parser_data, GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer data, GError **error)
 {
        if (g_ascii_strcasecmp(element_name, "window") == 0)
@@ -1348,7 +1369,7 @@ static void options_parse_layout(GQParserData *parser_data, GMarkupParseContext
                }
        else if (g_ascii_strcasecmp(element_name, "statusbar") == 0)
                {
-               options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL);
+               options_parse_func_push(parser_data, options_parse_statusbar, NULL, lw);
                }
        else if (g_ascii_strcasecmp(element_name, "dialogs") == 0)
                {
index 71ac3e2..4a484a9 100644 (file)
@@ -55,7 +55,7 @@ struct _ToolbarButtonData
        gchar *stock_id;
 };
 
-static         ToolbarData *toolbarlist;
+static ToolbarData *toolbarlist[2];
 
 typedef struct _UseableToolbarItems UseableToolbarItems;
 struct _UseableToolbarItems
@@ -79,8 +79,10 @@ static const UseableToolbarItems useable_toolbar_items[] = {
        {"Forward",     N_("Forward"), GTK_STOCK_GO_FORWARD},
        {"Home",        N_("Home"), GTK_STOCK_HOME},
        {"Up",  N_("Up"), GTK_STOCK_GO_UP},
-       {"NextPage",    N_("Next page"), PIXBUF_INLINE_ICON_NEXT_PAGE},
-       {"PrevPage",    N_("Previous Page"), PIXBUF_INLINE_ICON_PREVIOUS_PAGE},
+       {"FirstPage",   N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
+       {"LastPage",    N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
+       {"NextPage",    N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
+       {"PrevPage",    N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
        {"NewWindow",   N_("New _window"), GTK_STOCK_NEW},
        {"NewCollection",       N_("New collection"), GTK_STOCK_INDEX},
        {"OpenCollection",      N_("Open collection"), GTK_STOCK_OPEN},
@@ -123,6 +125,10 @@ static const UseableToolbarItems useable_toolbar_items[] = {
        {"ConnectZoomIn",       N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
        {"Grayscale",   N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
        {"OverUnderExposed",    N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
+       {"ShowInfoPixel",       N_("Pixel Info"),       GTK_STOCK_COLOR_PICKER},
+       {"ExifRotate",  N_("_Exif rotate"),     GTK_STOCK_ORIENTATION_PORTRAIT},
+       {"UseColorProfiles",    N_("Use color profiles"),       GTK_STOCK_SELECT_COLOR},
+       {"SaveMetadata",        N_("Save metadata"),    GTK_STOCK_SAVE},
        {"HideTools",   N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
        {"SlideShowPause",      N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
        {"SlideShowFaster",     N_("Slideshow Faster"), GTK_STOCK_FILE},
@@ -424,9 +430,10 @@ static gboolean toolbar_menu_add_cb(GtkWidget *widget, gpointer data)
 
 /**
  * @brief For each layoutwindow, clear toolbar and reload with current selection
+ * @param bar Main or Status toolbar
  * 
  */
-void toolbar_apply()
+void toolbar_apply(ToolbarType bar)
 {
        LayoutWindow *lw;
        GList *work_windows;
@@ -437,16 +444,16 @@ void toolbar_apply()
                {
                lw = work_windows->data;
 
-               layout_toolbar_clear(lw, TOOLBAR_MAIN);
+               layout_toolbar_clear(lw, bar);
 
-               work_toolbar = gtk_container_get_children(GTK_CONTAINER(toolbarlist->vbox));
+               work_toolbar = gtk_container_get_children(GTK_CONTAINER(toolbarlist[bar]->vbox));
                while (work_toolbar)
                        {
                        GtkButton *button = work_toolbar->data;
                        ToolbarButtonData *tbbd;
 
                        tbbd = g_object_get_data(G_OBJECT(button),"toolbarbuttondata");
-                       layout_toolbar_add(lw, TOOLBAR_MAIN, tbbd->name);
+                       layout_toolbar_add(lw, bar, tbbd->name);
 
                        work_toolbar = work_toolbar->next;
                        }
@@ -461,13 +468,14 @@ void toolbar_apply()
  * @brief Load the current toolbar items into the vbox
  * @param lw 
  * @param box The vbox displayed in the preferences Toolbar tab
+ * @param bar Main or Status toolbar
  * 
  * Get the current contents of the toolbar, both menu items
  * and desktop items, and load them into the vbox
  */
-static void toolbarlist_populate(LayoutWindow *lw, GtkBox *box)
+static void toolbarlist_populate(LayoutWindow *lw, GtkBox *box, ToolbarType bar)
 {
-       GList *work = g_list_first(lw->toolbar_actions[TOOLBAR_MAIN]);
+       GList *work = g_list_first(lw->toolbar_actions[bar]);
 
        while (work)
                {
@@ -488,7 +496,7 @@ static void toolbarlist_populate(LayoutWindow *lw, GtkBox *box)
                }
 }
 
-GtkWidget *toolbar_select_new(LayoutWindow *lw)
+GtkWidget *toolbar_select_new(LayoutWindow *lw, ToolbarType bar)
 {
        GtkWidget *scrolled;
        GtkWidget *tbar;
@@ -496,40 +504,40 @@ GtkWidget *toolbar_select_new(LayoutWindow *lw)
 
        if (!lw) return NULL;
 
-       if (!toolbarlist)
+       if (!toolbarlist[bar])
                {
-               toolbarlist = g_new0(ToolbarData, 1);
+               toolbarlist[bar] = g_new0(ToolbarData, 1);
                }
-       toolbarlist->lw = lw;
+       toolbarlist[bar]->lw = lw;
 
-       toolbarlist->widget = gtk_vbox_new(FALSE, PREF_PAD_GAP);
-       gtk_widget_show(toolbarlist->widget);
+       toolbarlist[bar]->widget = gtk_vbox_new(FALSE, PREF_PAD_GAP);
+       gtk_widget_show(toolbarlist[bar]->widget);
 
        scrolled = gtk_scrolled_window_new(NULL, NULL);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
                                                        GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_NONE);
-       gtk_box_pack_start(GTK_BOX(toolbarlist->widget), scrolled, TRUE, TRUE, 0);
+       gtk_box_pack_start(GTK_BOX(toolbarlist[bar]->widget), scrolled, TRUE, TRUE, 0);
        gtk_widget_show(scrolled);
 
-       toolbarlist->vbox = gtk_vbox_new(FALSE, 0);
-       gtk_widget_show(toolbarlist->vbox);
-       gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled), toolbarlist->vbox);
+       toolbarlist[bar]->vbox = gtk_vbox_new(FALSE, 0);
+       gtk_widget_show(toolbarlist[bar]->vbox);
+       gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled), toolbarlist[bar]->vbox);
        gtk_viewport_set_shadow_type(GTK_VIEWPORT(gtk_bin_get_child(GTK_BIN(scrolled))),
                                                                                                                                GTK_SHADOW_NONE);
 
        add_box = gtk_vbox_new(FALSE, 0);
        gtk_widget_show(add_box);
-       gtk_box_pack_end(GTK_BOX(toolbarlist->widget), add_box, FALSE, FALSE, 0);
+       gtk_box_pack_end(GTK_BOX(toolbarlist[bar]->widget), add_box, FALSE, FALSE, 0);
        tbar = pref_toolbar_new(add_box, GTK_TOOLBAR_ICONS);
-       toolbarlist->add_button = pref_toolbar_button(tbar, GTK_STOCK_ADD, "NULL", FALSE,
+       toolbarlist[bar]->add_button = pref_toolbar_button(tbar, GTK_STOCK_ADD, "NULL", FALSE,
                                                                                        _("Add Toolbar Item"),
-                                                                                       G_CALLBACK(toolbar_menu_add_cb), toolbarlist);
-       gtk_widget_show(toolbarlist->add_button);
+                                                                                       G_CALLBACK(toolbar_menu_add_cb), toolbarlist[bar]);
+       gtk_widget_show(toolbarlist[bar]->add_button);
 
-       toolbarlist_populate(lw,GTK_BOX(toolbarlist->vbox));
+       toolbarlist_populate(lw,GTK_BOX(toolbarlist[bar]->vbox), bar);
 
-       return toolbarlist->widget;
+       return toolbarlist[bar]->widget;
 }
 
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
index a86099e..703d847 100644 (file)
@@ -22,8 +22,8 @@
 #ifndef TOOLBAR_H
 #define TOOLBAR_H
 
-GtkWidget *toolbar_select_new(LayoutWindow *lw);
-void toolbar_apply();
+GtkWidget *toolbar_select_new(LayoutWindow *lw, ToolbarType bar);
+void toolbar_apply(ToolbarType bar);
 #endif
 
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
index 729a9f9..1067798 100644 (file)
@@ -362,12 +362,16 @@ struct _ThumbLoader
 struct _AnimationData
 {
        ImageWindow *iw;
+       LayoutWindow *lw;
        GdkPixbufAnimation *gpa;
        GdkPixbufAnimationIter *iter;
        GdkPixbuf *gpb;
        FileData *data_adr;
        guint delay;
        gboolean valid;
+       GCancellable *cancellable;
+       GFile *in_file;
+       GFileInputStream *gfstream;
 };
 
 struct _CollectInfo
index 17986e6..30fb338 100644 (file)
         window.open(  this.options[ this.selectedIndex ].value );
         };
         </script>
-        <p>MacOS X <a href="http://brewformulas.org/Geeqie">Brewformulas.org</a></p>
+        <p>MacOS X <a href="https://formulae.brew.sh/formula/geeqie">Homebrew Formulae</a></p>
         <p>Solaris <a href="https://www.opencsw.org/package/geeqie/">Openscw.org Solaris 10 &amp; 11</a></p>
-        <p>The source tar for Geeqie v1.4 is available <a href="http://geeqie.org/geeqie-1.4.tar.xz">here.</a></p>
+       <p>The source tar for Geeqie v1.5 is available <a href="/geeqie-1.5.tar.xz">here.</a> (Signature also available under <a href="/geeqie-1.5.tar.xz.asc">geeqie-1.5.tar.xz.asc</a>)</p>
         <p>However if you are compiling from sources it is recommended that you get the latest sources from the
-        <a href="http://geeqie.org/cgi-bin/gitweb.cgi?p=geeqie.git">Geeqie repository.</a></p>Geeqie is stable, there
+        <a href="/cgi-bin/gitweb.cgi?p=geeqie.git">Geeqie repository.</a></p>Geeqie is stable, there
         are frequent updates, and compiling is a quick and painless task. The instructions for <a href=
         "installing.html">downloading and installing</a> are easy to follow.
         <p>For Ubuntu and other Debian-based systems, <a href="http://www.geeqie.org/web/geeqie-install-debian.sh"> this script</a> will download Geeqie sources, all dependencies, and compile and install Geeqie. You may also select which optional libraries to install.</p>