]> www.fi.muni.cz Git - evince.git/blobdiff - backend/comics/comics-document.c
a11: using ATK_ROLE_DOCUMENT_FRAME it's more correct
[evince.git] / backend / comics / comics-document.c
index 9f657c24e1be667943bef0ce3e49532722267ef1..0481de864b586ce7e118820fddd422a4d0907c4d 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
 /*
- * Copyright (C) 2009, Juanjo Marín <juanj.marin@juntadeandalucia.es>
+ * Copyright (C) 2009-2010 Juanjo Marín <juanj.marin@juntadeandalucia.es>
  * Copyright (C) 2005, Teemu Tervo <teemu.tervo@gmx.net>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 #include <config.h>
 
 #include "comics-document.h"
 #include "ev-document-misc.h"
-#include "ev-document-thumbnails.h"
 #include "ev-file-helpers.h"
 
+#ifdef G_OS_WIN32
+/* On windows g_spawn_command_line_sync reads stdout in O_BINARY mode, not in O_TEXT mode.
+ * As a consequence, newlines are in a platform dependent representation (\r\n). This
+ * might be considered a bug in glib.
+ */
+#define EV_EOL "\r\n"
+#else
+#define EV_EOL "\n"
+#endif
+
 typedef enum
 {
        RARLABS,
@@ -64,13 +73,15 @@ struct _ComicsDocument
 
        gchar    *archive, *dir;
        GPtrArray *page_names;
-       gchar    *selected_command;
+       gchar    *selected_command, *alternative_command;
        gchar    *extract_command, *list_command, *decompress_tmp;
+       gboolean regex_arg;
        gint     offset;
        ComicBookDecompressType command_usage;
 };
 
 #define OFFSET_7Z 53
+#define OFFSET_ZIP 2
 #define NO_OFFSET 0
 
 /* For perfomance reasons of 7z* we've choosen to decompress on the temporary 
@@ -82,6 +93,7 @@ struct _ComicsDocument
  * @list: command line arguments to list the archive contents
  * @decompress_tmp: command line arguments to pass to extract the archive
  *   into a directory.
+ * @regex_arg: whether the command can accept regex expressions
  * @offset: the position offset of the filename on each line in the output of
  *   running the @list command
  */
@@ -89,28 +101,27 @@ typedef struct {
         char *extract;
         char *list;
         char *decompress_tmp;
+        gboolean regex_arg;
         gint offset;
 } ComicBookDecompressCommand;
 
 static const ComicBookDecompressCommand command_usage_def[] = {
         /* RARLABS unrar */
-       {"%s p -c- -ierr --", "%s vb -c- -- %s", NULL             , NO_OFFSET},
+       {"%s p -c- -ierr --", "%s vb -c- -- %s", NULL             , FALSE, NO_OFFSET},
 
         /* GNA! unrar */
-       {NULL               , "%s t %s"        , "%s -xf %s %s"   , NO_OFFSET},
+       {NULL               , "%s t %s"        , "%s -xf %s %s"   , FALSE, NO_OFFSET},
 
         /* unzip */
-       {"%s -p -C --"      , "%s -Z -1 -- %s" , NULL             , NO_OFFSET},
+       {"%s -p -C --"      , "%s %s"          , NULL             , TRUE , OFFSET_ZIP},
 
         /* 7zip */
-       {NULL               , "%s l -- %s"     , "%s x -y %s -o%s", OFFSET_7Z},
+       {NULL               , "%s l -- %s"     , "%s x -y %s -o%s", FALSE, OFFSET_7Z},
 
         /* tar */
-       {"%s -xOf"          , "%s -tf %s"      , NULL             , NO_OFFSET}
+       {"%s -xOf"          , "%s -tf %s"      , NULL             , FALSE, NO_OFFSET}
 };
 
-static void       comics_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface);
-
 static GSList*    get_supported_image_extensions (void);
 static void       get_page_size_area_prepared_cb (GdkPixbufLoader *loader,
                                                  gpointer data);
@@ -122,11 +133,60 @@ static char**     extract_argv                   (EvDocument *document,
                                                  gint page);
 
 
-EV_BACKEND_REGISTER_WITH_CODE (ComicsDocument, comics_document,
-       {
-               EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_THUMBNAILS,
-                                               comics_document_document_thumbnails_iface_init);
-       } );
+EV_BACKEND_REGISTER (ComicsDocument, comics_document)
+
+/**
+ * comics_regex_quote:
+ * @unquoted_string: a literal string
+ *
+ * Quotes a string so unzip will not interpret the regex expressions of
+ * @unquoted_string. Basically, this functions uses [] to disable regex 
+ * expressions. The return value must be freed with * g_free()
+ *
+ * Return value: quoted and disabled-regex string
+ **/
+static gchar *
+comics_regex_quote (const gchar *unquoted_string)
+{
+       const gchar *p;
+       GString *dest;
+
+       dest = g_string_new ("'");
+
+       p = unquoted_string;
+
+       while (*p) {
+               switch (*p) {
+                       /* * matches a sequence of 0 or more characters */
+                       case ('*'):
+                       /* ? matches exactly 1 charactere */
+                       case ('?'):
+                       /* [...]  matches any single character found inside
+                        * the brackets. Disabling the first bracket is enough.
+                        */
+                       case ('['):
+                               g_string_append (dest, "[");
+                               g_string_append_c (dest, *p);
+                               g_string_append (dest, "]");
+                               break;
+                       /* Because \ escapes regex expressions that we are
+                        * disabling for unzip, we need to disable \ too */
+                       case ('\\'):
+                               g_string_append (dest, "[\\\\]");
+                               break;
+                       /* Escape single quote inside the string */
+                       case ('\''):
+                               g_string_append (dest, "'\\''");
+                               break;
+                       default:
+                               g_string_append_c (dest, *p);
+                               break;
+               }
+               ++p;
+       }
+       g_string_append_c (dest, '\'');
+       return g_string_free (dest, FALSE);
+}
 
 
 /* This function manages the command for decompressing a comic book */
@@ -185,20 +245,30 @@ static gboolean
 comics_generate_command_lines (ComicsDocument *comics_document, 
                               GError         **error)
 {
-       gchar *quoted_file;
+       gchar *quoted_file, *quoted_file_aux;
        gchar *quoted_command;
        ComicBookDecompressType type;
        
        type = comics_document->command_usage;
-       quoted_file = g_shell_quote (comics_document->archive);
+       comics_document->regex_arg = command_usage_def[type].regex_arg;
        quoted_command = g_shell_quote (comics_document->selected_command);
-
+       if (comics_document->regex_arg) {
+               quoted_file = comics_regex_quote (comics_document->archive);
+               quoted_file_aux = g_shell_quote (comics_document->archive);
+               comics_document->list_command =
+                          g_strdup_printf (command_usage_def[type].list,
+                                           comics_document->alternative_command,
+                                           quoted_file_aux);
+               g_free (quoted_file_aux);
+       } else {
+               quoted_file = g_shell_quote (comics_document->archive);
+               comics_document->list_command =
+                               g_strdup_printf (command_usage_def[type].list,
+                                                quoted_command, quoted_file);
+       }
        comics_document->extract_command =
                            g_strdup_printf (command_usage_def[type].extract,
                                             quoted_command);
-       comics_document->list_command =
-                           g_strdup_printf (command_usage_def[type].list,
-                                            quoted_command, quoted_file);
        comics_document->offset = command_usage_def[type].offset;
        if (command_usage_def[type].decompress_tmp) {
                comics_document->dir = ev_mkdtemp ("evince-comics-XXXXXX", error);
@@ -297,7 +367,10 @@ comics_check_decompress_command    (gchar          *mime_type,
                /* InfoZIP's unzip program */
                comics_document->selected_command = 
                                g_find_program_in_path ("unzip");
-               if (comics_document->selected_command) {
+               comics_document->alternative_command =
+                               g_find_program_in_path ("zipnote");
+               if (comics_document->selected_command &&
+                   comics_document->alternative_command) {
                        comics_document->command_usage = UNZIP;
                        return TRUE;
                }
@@ -414,7 +487,8 @@ comics_document_load (EvDocument *document,
        }
 
        /* FIXME: is this safe against filenames containing \n in the archive ? */
-       cb_files = g_strsplit (std_out, "\n", 0);
+       cb_files = g_strsplit (std_out, EV_EOL, 0);
+
        g_free (std_out);
 
        if (!cb_files) {
@@ -716,6 +790,7 @@ comics_document_finalize (GObject *object)
 
        g_free (comics_document->archive);
        g_free (comics_document->selected_command);
+       g_free (comics_document->alternative_command);
        g_free (comics_document->extract_command);
        g_free (comics_document->list_command);
 
@@ -769,52 +844,6 @@ get_supported_image_extensions()
        return extensions;
 }
 
-static GdkPixbuf *
-comics_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document,
-                                         EvRenderContext      *rc,
-                                         gboolean              border)
-{
-       GdkPixbuf *thumbnail;
-
-       thumbnail = comics_document_render_pixbuf (EV_DOCUMENT (document), rc);
-
-       if (border) {
-             GdkPixbuf *tmp_pixbuf = thumbnail;
-             
-             thumbnail = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf);
-             g_object_unref (tmp_pixbuf);
-       }
-
-       return thumbnail;
-}
-
-static void
-comics_document_thumbnails_get_dimensions (EvDocumentThumbnails *document,
-                                          EvRenderContext      *rc,
-                                          gint                 *width,
-                                          gint                 *height)
-{
-       gdouble page_width, page_height;
-       
-       comics_document_get_page_size (EV_DOCUMENT (document), rc->page,
-                                      &page_width, &page_height);
-
-       if (rc->rotation == 90 || rc->rotation == 270) {
-               *width = (gint) (page_height * rc->scale);
-               *height = (gint) (page_width * rc->scale);
-       } else {
-               *width = (gint) (page_width * rc->scale);
-               *height = (gint) (page_height * rc->scale);
-       }
-}
-
-static void
-comics_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
-{
-       iface->get_thumbnail = comics_document_thumbnails_get_thumbnail;
-       iface->get_dimensions = comics_document_thumbnails_get_dimensions;
-}
-
 static char**
 extract_argv (EvDocument *document, gint page)
 {
@@ -826,8 +855,14 @@ extract_argv (EvDocument *document, gint page)
         if (page >= comics_document->page_names->len)
                 return NULL;
 
-       quoted_archive = g_shell_quote (comics_document->archive);
-       quoted_filename = g_shell_quote (comics_document->page_names->pdata[page]);
+       if (comics_document->regex_arg) {
+               quoted_archive = comics_regex_quote (comics_document->archive);
+               quoted_filename =
+                       comics_regex_quote (comics_document->page_names->pdata[page]);
+       } else {
+               quoted_archive = g_shell_quote (comics_document->archive);
+               quoted_filename = g_shell_quote (comics_document->page_names->pdata[page]);
+       }
 
        command_line = g_strdup_printf ("%s %s %s",
                                        comics_document->extract_command,