pspp-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Re: Problems with pspp on fresh toolchain


From: John Darrington
Subject: Re: Re: Problems with pspp on fresh toolchain
Date: Mon, 16 Jan 2012 18:43:41 +0000
User-agent: Mutt/1.5.18 (2008-05-17)

[ Adding address@hidden back ]

On Mon, Jan 16, 2012 at 07:21:45PM +0100, Harry Thijssen wrote:
     Hi John
     
     Took some time but I displayed the pointer and added more displays in
     psppire_output_submit. See the ouput below. I attached the source so you
     can see where the displays are placed.
     
     It looks weired to me as if GTK_WINDOW has the problem.
     
I don't think so.  You can leave that call out if you like - it'll generate a 
warning - nothing more.

I think the problem is with gtk_window_set_urgency_hint.  If you feel game, you 
can go into the gtk source and carry on the hunt there.

Either way, I think this should be reported to the Gtk developers.

In the meantime, you can just comment out that line - it's just supposed to 
make the output window's icon flash.

J'

     
     
     
     
     See the ugly output
     ============
     address@hidden:/usr/i686-w64-mingw32/sys-root/mingw/bin> wine psppire.exe
     
     (psppire.exe:8): Pango-WARNING **: couldn't load font "MS Shell Dlg
     Not-Rotated 8", falling back to "Sans Not-Rotated 8", expect ugly output.
     
     (psppire.exe:8): Pango-WARNING **: couldn't load font "MS Shell Dlg 8",
     falling back to "Sans 8", expect ugly output.
     
     (psppire.exe:8): Pango-WARNING **: failed to choose a font, expect ugly
     output. engine-type='PangoRenderWin32', script='common'
     <1>
     <1a>
     b: PsppireOutputWindow
     <2>
     <3>
     c: PsppireOutputWindow
     d: PsppireOutputWindow
     
     (psppire.exe:8): Pango-WARNING **: couldn't load font "MS Shell Dlg Italic
     Not-Rotated 8", falling back to "Sans Italic Not-Rotated 8", expect ugly
     output.
     e: PsppireOutputWindow
     f: PsppireOutputWindow
     g: PsppireOutputWindow
     h: PsppireOutputWindow
     i: PsppireOutputWindow
     fixme:win:FlashWindowEx 0xcfefdc
     wine: Unhandled page fault on write access to 0x0000001c at address
     0x1239590 (thread 0009), starting debugger...
     Unhandled exception: page fault on write access to 0x0000001c in 32-bit
     code (0x01239590).
     Register dump:
      CS:0073 SS:007b DS:007b ES:007b FS:0033 GS:003b
      EIP:01239590 ESP:00cff004 EBP:00000001 EFLAGS:00010202(  R- --  I   - - - 
)
      EAX:00000001 EBX:011e12d8 ECX:00000000 EDX:00000000
      ESI:00f01e5c EDI:00000000
     Stack dump:
     0x00cff004:  00000001 01239dd0 6c3685f5 00171038
     0x00cff014:  010cc050 00000013 010e1528 011e11b8
     0x00cff024:  010cc050 00cff088 00425b33 011e11b8
     0x00cff034:  00000001 00000039 010dad58 00000001
     0x00cff044:  010a1940 00000002 00000006 ffffffff
     0x00cff054:  00cff2ac 00000006 004ed0e4 00000006
     Backtrace:
     0x01239590: addb        %bh,0x1b(%eax)
     Modules:
     Module  Address                 Debug info      Name (126 modules)
     PE        230000-  271000       Deferred        libgdk_pixbuf-2.0-0
     PE        400000-  af7000       Deferred        psppire
     PE        d00000- 109e000       Deferred        libgtk-win32-2.0-0
     PE      617c0000-6180d000       Deferred        libjasper-1
     PE      61cc0000-61ce2000       Deferred        libintl-8
     [...]
     ==============
     
     2012/1/15 John Darrington <address@hidden>
     
     > On Sun, Jan 15, 2012 at 01:41:59PM +0100, Harry Thijssen wrote:
     >     2012/1/15 John Darrington <address@hidden>
     >
     >     >     My GTK2 version is  2.24.8-1.7
     >     >
     >     > Did your old tool chain use a different version?
     >     >
     >
     >     Yes. It is really old.  2.20.1-5.3
     >     BTW with version between these 2 I had problems that the output was 
not
     >     correctly displayed. Now it looks good when the problem line is
     > removed.
     >
     >
     >
     >     > I presume pod->viewer points to a valid GtkWindow.  If it didn't 
then
     >     > lots of other things would be going wrong.
     >     >
     >
     >     How can I check this pointer?
     >
     > Try adding the line g_print ("%s\n", G_OBJECT_TYPE_NAME (pod->viewer));
     >
     >     >
     >     > Make sure that everything else works ok.
     >     >
     >
     >     Everything opening an output window crashes. So there is not much I 
can
     >     use.  With the latest replacement I could also use the other
     >     functionality.
     >
     > I meant when you remove this problem line, does everything else work ok?
     >
     >
     > --
     > PGP Public key ID: 1024D/2DE827B3
     > fingerprint = 8797 A26D 0854 2EAB 0285  A290 8A67 719C 2DE8 27B3
     > See http://keys.gnupg.net or any PGP keyserver for public key.
     >
     >
     > -----BEGIN PGP SIGNATURE-----
     > Version: GnuPG v1.4.9 (GNU/Linux)
     >
     > iD8DBQFPEuFjimdxnC3oJ7MRAtvVAKCKE/IDJKtyfTrZop2h4c/8ax3lTgCeOa5A
     > 5uBrlckTI9O+Fl99u4RPMLQ=
     > =KOTU
     > -----END PGP SIGNATURE-----
     >
     >

     /* PSPPIRE - a graphical user interface for PSPP.
        Copyright (C) 2008, 2009, 2010, 2011, 2012  Free Software Foundation
     
        This program is free software: you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
     
        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
     
        You should have received a copy of the GNU General Public License
        along with this program.  If not, see <http://www.gnu.org/licenses/>. */
     
     #include <config.h>
     
     #include <errno.h>
     #include <gtk/gtk.h>
     #include <stdlib.h>
     #include <sys/stat.h>
     #include <sys/types.h>
     #include <unistd.h>
     
     #include "libpspp/cast.h"
     #include "libpspp/message.h"
     #include "libpspp/string-map.h"
     #include "output/cairo.h"
     #include "output/chart-item.h"
     #include "output/driver-provider.h"
     #include "output/message-item.h"
     #include "output/output-item.h"
     #include "output/tab.h"
     #include "output/table-item.h"
     #include "output/text-item.h"
     #include "ui/gui/help-menu.h"
     #include "ui/gui/builder-wrapper.h"
     #include "ui/gui/psppire-output-window.h"
     
     #include "gl/error.h"
     #include "gl/tmpdir.h"
     #include "gl/xalloc.h"
     
     #include "helper.h"
     
     #include <gettext.h>
     #define _(msgid) gettext (msgid)
     #define N_(msgid) msgid
     
     enum
       {
         COL_TITLE,                  /* Table title. */
         COL_ADDR,                   /* Pointer to the table */
         COL_Y,                      /* Y position of top of title. */
         N_COLS
       };
     
     static void psppire_output_window_base_finalize (PsppireOutputWindowClass 
*, gpointer);
     static void psppire_output_window_base_init     (PsppireOutputWindowClass 
*class);
     static void psppire_output_window_class_init    (PsppireOutputWindowClass 
*class);
     static void psppire_output_window_init          (PsppireOutputWindow      
*window);
     
     static void psppire_output_window_style_set (GtkWidget *window, GtkStyle 
*prev);
     
     
     GType
     psppire_output_window_get_type (void)
     {
       static GType psppire_output_window_type = 0;
     
       if (!psppire_output_window_type)
         {
           static const GTypeInfo psppire_output_window_info =
           {
        sizeof (PsppireOutputWindowClass),
        (GBaseInitFunc) psppire_output_window_base_init,
             (GBaseFinalizeFunc) psppire_output_window_base_finalize,
        (GClassInitFunc)psppire_output_window_class_init,
        (GClassFinalizeFunc) NULL,
        NULL,
             sizeof (PsppireOutputWindow),
        0,
        (GInstanceInitFunc) psppire_output_window_init,
           };
     
           psppire_output_window_type =
        g_type_register_static (PSPPIRE_TYPE_WINDOW, "PsppireOutputWindow",
                                &psppire_output_window_info, 0);
         }
     
       return psppire_output_window_type;
     }
     
     static GObjectClass *parent_class;
     
     static void
     psppire_output_window_finalize (GObject *object)
     {
       string_map_destroy (&PSPPIRE_OUTPUT_WINDOW(object)->render_opts);
     
     
       if (G_OBJECT_CLASS (parent_class)->finalize)
         (*G_OBJECT_CLASS (parent_class)->finalize) (object);
     }
     
     
     static void
     psppire_output_window_dispose (GObject *obj)
     {
       PsppireOutputWindow *viewer = PSPPIRE_OUTPUT_WINDOW (obj);
       size_t i;
     
       for (i = 0; i < viewer->n_items; i++)
         output_item_unref (viewer->items[i]);
       free (viewer->items);
       viewer->items = NULL;
       viewer->n_items = viewer->allocated_items = 0;
     
       if (viewer->print_settings != NULL)
         g_object_unref (viewer->print_settings);
     
       /* Chain up to the parent class */
       G_OBJECT_CLASS (parent_class)->dispose (obj);
     }
     
     static void
     psppire_output_window_class_init (PsppireOutputWindowClass *class)
     {
       GObjectClass *object_class = G_OBJECT_CLASS (class);
     
       parent_class = g_type_class_peek_parent (class);
       object_class->dispose = psppire_output_window_dispose;
       
       GTK_WIDGET_CLASS (object_class)->style_set = 
psppire_output_window_style_set;
     }
     
     
     static void
     psppire_output_window_base_init (PsppireOutputWindowClass *class)
     {
       GObjectClass *object_class = G_OBJECT_CLASS (class);
     
       object_class->finalize = psppire_output_window_finalize;
     }
     
     
     
     static void
     psppire_output_window_base_finalize (PsppireOutputWindowClass *class,
                                     gpointer class_data)
     {
     }
     
     /* Output driver class. */
     
     struct psppire_output_driver
       {
         struct output_driver driver;
         PsppireOutputWindow *viewer;
         struct xr_driver *xr;
         int font_height;
       };
     
     static struct output_driver_class psppire_output_class;
     
     static struct psppire_output_driver *
     psppire_output_cast (struct output_driver *driver)
     {
       assert (driver->class == &psppire_output_class);
       return UP_CAST (driver, struct psppire_output_driver, driver);
     }
     
     static void on_dwgarea_realize (GtkWidget *widget, gpointer data);
     
     static gboolean
     expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer 
data)
     {
       PsppireOutputWindow *viewer = PSPPIRE_OUTPUT_WINDOW (data);
       struct xr_rendering *r = g_object_get_data (G_OBJECT (widget), 
"rendering");
       cairo_t *cr = gdk_cairo_create (widget->window);
     
       const GtkStyle *style = gtk_widget_get_style (GTK_WIDGET (viewer));
     
       PangoFontDescription *font_desc;
       char *font_name;
       
       gchar *fgc =
         gdk_color_to_string (&style->text[gtk_widget_get_state (GTK_WIDGET 
(widget))]);
     
       string_map_replace (&viewer->render_opts, "foreground-color", fgc);
     
       free (fgc);
     
       /* Use GTK+ default font as proportional font. */
       font_name = pango_font_description_to_string (style->font_desc);
       string_map_replace (&viewer->render_opts, "prop-font", font_name);
       g_free (font_name);
     
       /* Derived emphasized font from proportional font. */
       font_desc = pango_font_description_copy (style->font_desc);
       pango_font_description_set_style (font_desc, PANGO_STYLE_ITALIC);
       font_name = pango_font_description_to_string (font_desc);
       string_map_replace (&viewer->render_opts, "emph-font", font_name);
       g_free (font_name);
       pango_font_description_free (font_desc);
     
       xr_rendering_apply_options (r, &viewer->render_opts);
     
       xr_rendering_draw (r, cr, event->area.x, event->area.y,
                          event->area.width, event->area.height);
       cairo_destroy (cr);
     
       return TRUE;
     }
     
     static void
     psppire_output_submit (struct output_driver *this,
                            const struct output_item *item)
     {
       struct psppire_output_driver *pod = psppire_output_cast (this);
       PsppireOutputWindow *viewer;
       GtkWidget *drawing_area;
       struct xr_rendering *r;
       struct string title;
       GtkTreeStore *store;
       GtkTreePath *path;
       GtkTreeIter iter;
       cairo_t *cr;
       int tw, th;
     
     /*  g_print ("a: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
     */
             g_print ("<1>\n");
       
       if (pod->viewer == NULL)
         {
             g_print ("<1a>\n");
           pod->viewer = PSPPIRE_OUTPUT_WINDOW (psppire_output_window_new ());
           gtk_widget_show_all (GTK_WIDGET (pod->viewer));
           pod->viewer->driver = pod;
         }
       viewer = pod->viewer;
       g_print ("b: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));  
             g_print ("<2>\n");
       if (viewer->n_items >= viewer->allocated_items)
         viewer->items = x2nrealloc (viewer->items, &viewer->allocated_items,
                                     sizeof *viewer->items);
       viewer->items[viewer->n_items++] = output_item_ref (item);
             g_print ("<3>\n");
       if (is_text_item (item))
         {
                 
           const struct text_item *text_item = to_text_item (item);
           enum text_item_type type = text_item_get_type (text_item);
           const char *text = text_item_get_text (text_item);
     
           if (type == TEXT_ITEM_COMMAND_CLOSE)
             {
               viewer->in_command = false;
               return;
             }
           else if (text[0] == '\0')
             return;
         }
       g_print ("c: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
       cr = gdk_cairo_create (GTK_WIDGET (pod->viewer)->window);
       if (pod->xr == NULL)
         {
           const GtkStyle *style = gtk_widget_get_style (GTK_WIDGET (viewer));
           struct text_item *text_item;
           PangoFontDescription *font_desc;
           char *font_name;
           int font_width;
           
           gchar *fgc = gdk_color_to_string (&style->text[gtk_widget_get_state 
(GTK_WIDGET (viewer))]);
     
           string_map_insert (&pod->viewer->render_opts, "foreground-color", 
fgc);
           g_free (fgc);
     
           font_name = pango_font_description_to_string (style->font_desc);
           string_map_insert (&pod->viewer->render_opts, "prop-font", 
font_name);
           g_free (font_name);
     
       
           font_desc = pango_font_description_copy (style->font_desc);
           pango_font_description_set_style (font_desc, PANGO_STYLE_ITALIC);
           font_name = pango_font_description_to_string (font_desc);
           string_map_insert (&pod->viewer->render_opts, "emph-font", 
font_name);
           g_free (font_name);
           pango_font_description_free (font_desc);
     
       
           string_map_insert (&pod->viewer->render_opts, "paper-size", 
"300x200000mm");
           string_map_insert (&pod->viewer->render_opts, "left-margin", "0");
           string_map_insert (&pod->viewer->render_opts, "right-margin", "0");
           string_map_insert (&pod->viewer->render_opts, "top-margin", "0");
           string_map_insert (&pod->viewer->render_opts, "bottom-margin", "0");
       g_print ("d: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
           pod->xr = xr_driver_create (cr, &pod->viewer->render_opts);
     
     
           text_item = text_item_create (TEXT_ITEM_PARAGRAPH, "X");
           r = xr_rendering_create (pod->xr, text_item_super (text_item), cr);
           xr_rendering_measure (r, &font_width, &pod->font_height);
           text_item_unref (text_item);
         }
       else
       g_print ("d: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));    
         pod->viewer->y += pod->font_height / 2;
     
       r = xr_rendering_create (pod->xr, item, cr);
       g_print ("e: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
       if (r == NULL)
         goto done;
     
       xr_rendering_measure (r, &tw, &th);
     
       drawing_area = gtk_drawing_area_new ();
     
       g_object_set_data (G_OBJECT (drawing_area), "rendering", r);
       g_signal_connect (drawing_area, "realize",
                          G_CALLBACK (on_dwgarea_realize), pod->viewer);
     
       g_signal_connect (drawing_area, "expose_event",
                          G_CALLBACK (expose_event_callback), pod->viewer);
     
       gtk_widget_set_size_request (drawing_area, tw, th);
     g_print ("f: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
       gtk_layout_put (pod->viewer->output, drawing_area, 0, pod->viewer->y);
     
       gtk_widget_show (drawing_area);
     
       if (!is_text_item (item)
           || text_item_get_type (to_text_item (item)) != TEXT_ITEM_SYNTAX
           || !viewer->in_command)
         {
           store = GTK_TREE_STORE (gtk_tree_view_get_model (viewer->overview));
     
           ds_init_empty (&title);
           if (is_text_item (item)
               && text_item_get_type (to_text_item (item)) == 
TEXT_ITEM_COMMAND_OPEN)
             {
               gtk_tree_store_append (store, &iter, NULL);
               viewer->cur_command = iter; 
               viewer->in_command = true;
             }
           else
             {
               GtkTreeIter *p = viewer->in_command ? &viewer->cur_command : 
NULL;
               gtk_tree_store_append (store, &iter, p);
             }
     
           ds_clear (&title);
           if (is_text_item (item))
             ds_put_cstr (&title, text_item_get_text (to_text_item (item)));
           else if (is_message_item (item))
             {
               const struct message_item *msg_item = to_message_item (item);
               const struct msg *msg = message_item_get_msg (msg_item);
               ds_put_format (&title, "%s: %s", _("Message"),
                              msg_severity_to_string (msg->severity));
             }
           else if (is_table_item (item))
             {
               const char *caption = table_item_get_caption (to_table_item 
(item));
               if (caption != NULL)
                 ds_put_format (&title, "Table: %s", caption);
               else
                 ds_put_cstr (&title, "Table");
             }
           else if (is_chart_item (item))
             {
               const char *s = chart_item_get_title (to_chart_item (item));
               if (s != NULL)
                 ds_put_format (&title, "Chart: %s", s);
               else
                 ds_put_cstr (&title, "Chart");
             }
           gtk_tree_store_set (store, &iter,
                               COL_TITLE, ds_cstr (&title),
                          COL_ADDR, item, 
                               COL_Y, viewer->y,
                               -1);
           ds_destroy (&title);
     
           path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
           gtk_tree_view_expand_row (viewer->overview, path, TRUE);
           gtk_tree_path_free (path);
         }
     
     g_print ("g: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
       if (pod->viewer->max_width < tw)
         pod->viewer->max_width = tw;
       pod->viewer->y += th;
     g_print ("h: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
       gtk_layout_set_size (pod->viewer->output,
                            pod->viewer->max_width, pod->viewer->y);
       
     g_print ("i: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
     
       gtk_window_set_urgency_hint (GTK_WINDOW (pod->viewer), TRUE);
       
     g_print ("j: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));  
     /*
     gtk_window_set_urgency_hint (NULL, TRUE);
     */
     done:
       cairo_destroy (cr); 
     }
     
     static struct output_driver_class psppire_output_class =
       {
         "PSPPIRE",                  /* name */
         NULL,                       /* destroy */
         psppire_output_submit,      /* submit */
         NULL,                       /* flush */
       };
     
     void
     psppire_output_window_setup (void)
     {
       struct psppire_output_driver *pod;
       struct output_driver *d;
     
       pod = xzalloc (sizeof *pod);
       d = &pod->driver;
       output_driver_init (d, &psppire_output_class, "PSPPIRE",
                           SETTINGS_DEVICE_UNFILTERED);
       output_driver_register (d);
     }
     
     
     
     /* Callback for the "delete" action (clicking the x on the top right
        hand corner of the window) */
     static gboolean
     on_delete (GtkWidget *w, GdkEvent *event, gpointer user_data)
     {
       PsppireOutputWindow *ow = PSPPIRE_OUTPUT_WINDOW (user_data);
     
       gtk_widget_destroy (GTK_WIDGET (ow));
     
       ow->driver->viewer = NULL;
     
       return FALSE;
     }
     
     
     
     static void
     cancel_urgency (GtkWindow *window,  gpointer data)
     {
       gtk_window_set_urgency_hint (window, FALSE);
     }
     
     static void
     on_row_activate (GtkTreeView *overview,
                      GtkTreePath *path,
                      GtkTreeViewColumn *column,
                      PsppireOutputWindow *window)
     {
       GtkTreeModel *model;
       GtkTreeIter iter;
       GtkAdjustment *vadj;
       GValue value = {0};
       double y, min, max;
     
       model = gtk_tree_view_get_model (overview);
       if (!gtk_tree_model_get_iter (model, &iter, path))
         return;
     
       gtk_tree_model_get_value (model, &iter, COL_Y, &value);
       y = g_value_get_long (&value);
       g_value_unset (&value);
     
       vadj = gtk_layout_get_vadjustment (window->output);
       min = vadj->lower;
       max = vadj->upper - vadj->page_size;
       if (y < min)
         y = min;
       else if (y > max)
         y = max;
       gtk_adjustment_set_value (vadj, y);
     }
     
     static void psppire_output_window_print (PsppireOutputWindow *window);
     
     
     static void
     export_output (PsppireOutputWindow *window, struct string_map *options,
                    const char *format)
     {
       struct output_driver *driver;
       size_t i;
     
       string_map_insert (options, "format", format);
       driver = output_driver_create (options);
       if (driver == NULL)
         return;
     
       for (i = 0; i < window->n_items; i++)
         driver->class->submit (driver, window->items[i]);
       output_driver_destroy (driver);
     }
     
     
     struct file_types
     {
       const gchar *label;
       const gchar *ext;
     };
     
     enum 
       {
         FT_AUTO = 0,
         FT_PDF,
         FT_HTML,
         FT_ODT,
         FT_TXT,
         FT_PS,
         FT_CSV,
         n_FT
       };
     
     #define N_EXTENSIONS (n_FT - 1)
     
     struct file_types ft[n_FT] = {
       {N_("Infer file type from extension"),  NULL},
       {N_("PDF (*.pdf)"),                     ".pdf"},
       {N_("HTML (*.html)"),                   ".html"},
       {N_("OpenDocument (*.odt)"),            ".odt"},
       {N_("Text (*.txt)"),                    ".txt"},
       {N_("PostScript (*.ps)"),               ".ps"},
       {N_("Comma-Separated Values (*.csv)"),  ".csv"}
     };
     
     
     static void
     on_combo_change (GtkFileChooser *chooser)
     {
       gboolean sensitive = FALSE;
       GtkWidget *combo = gtk_file_chooser_get_extra_widget (chooser);
     
       int x = 0; 
       gchar *fn = gtk_file_chooser_get_filename (chooser);
     
       if (combo &&  gtk_widget_get_realized (combo))
         x = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
     
       if (fn == NULL)
         {
           sensitive = FALSE;
         }
       else
         {
           gint i;
           if ( x != 0 )
        sensitive = TRUE;
     
           for (i = 1 ; i < N_EXTENSIONS ; ++i)
        {
          if ( g_str_has_suffix (fn, ft[i].ext))
            {
              sensitive = TRUE;
              break;
            }
        }
         }
     
       g_free (fn);
     
       gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser), 
GTK_RESPONSE_ACCEPT, sensitive);
     }
     
     
     static void
     on_file_chooser_change (GObject *w, GParamSpec *pspec, gpointer data)
     {
     
       GtkFileChooser *chooser = data;
       const gchar *name = g_param_spec_get_name (pspec);
     
       if ( ! gtk_widget_get_realized (GTK_WIDGET (chooser)))
         return;
     
       /* Ignore this one.  It causes recursion. */
       if ( 0 == strcmp ("tooltip-text", name))
         return;
     
       on_combo_change (chooser);
     }
     
     
     /* Recursively descend all the children of W, connecting
        to their "notify" signal */
     static void
     iterate_widgets (GtkWidget *w, gpointer data)
     {
       if ( GTK_IS_CONTAINER (w))
         gtk_container_forall (GTK_CONTAINER (w), iterate_widgets, data);
       else
         g_signal_connect (w, "notify",  G_CALLBACK (on_file_chooser_change), 
data);
     }
     
     
     
     static GtkListStore *
     create_file_type_list (void)
     {
       int i;
       GtkTreeIter iter;
       GtkListStore *list = gtk_list_store_new (2, G_TYPE_STRING, 
G_TYPE_STRING);
       
       for (i = 0 ; i < n_FT ; ++i)
         {
           gtk_list_store_append (list, &iter);
           gtk_list_store_set (list, &iter,
                          0,  gettext (ft[i].label),
                          1,  ft[i].ext,
                          -1);
         }
       
       return list;
     }
     
     static void
     psppire_output_window_export (PsppireOutputWindow *window)
     {
       gint response;
       GtkWidget *combo;
       GtkListStore *list;
     
       GtkFileChooser *chooser;
       
       GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Export Output"),
                                             GTK_WINDOW (window),
                                             GTK_FILE_CHOOSER_ACTION_SAVE,
                                             GTK_STOCK_CANCEL, 
GTK_RESPONSE_CANCEL,
                                             GTK_STOCK_SAVE,   
GTK_RESPONSE_ACCEPT,
                                             NULL);
     
       g_object_set (dialog, "local-only", FALSE, NULL);
     
       chooser = GTK_FILE_CHOOSER (dialog);
     
       list = create_file_type_list ();
     
       combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (list));
     
     
       {
         /* Create text cell renderer */
         GtkCellRenderer *cell = gtk_cell_renderer_text_new();
         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE );
     
         gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell,  "text", 
0);
       }
     
       g_signal_connect_swapped (combo, "changed", G_CALLBACK 
(on_combo_change), chooser);
     
       gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
     
       gtk_file_chooser_set_extra_widget (chooser, combo);
     
       /* This kludge is necessary because there is no signal to tell us
          when the candidate filename of a GtkFileChooser has changed */
       gtk_container_forall (GTK_CONTAINER (dialog), iterate_widgets, dialog);
     
     
       gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE);
     
       response = gtk_dialog_run (GTK_DIALOG (dialog));
     
       if ( response == GTK_RESPONSE_ACCEPT )
         {
           int file_type = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
           char *filename = gtk_file_chooser_get_filename (chooser);
           struct string_map options;
     
           g_return_if_fail (filename);
     
           if (file_type == FT_AUTO)
        {
          gint i;
          for (i = 1 ; i < N_EXTENSIONS ; ++i)
            {
              if ( g_str_has_suffix (filename, ft[i].ext))
                {
                  file_type = i;
                  break;
                }
            }
        }
     
           
           string_map_init (&options);
           string_map_insert (&options, "output-file", filename);
     
           switch (file_type)
        {
        case FT_PDF:
               export_output (window, &options, "pdf");
          break;
        case FT_HTML:
               export_output (window, &options, "html");
          break;
        case FT_ODT:
               export_output (window, &options, "odt");
          break;
        case FT_PS:
               export_output (window, &options, "ps");
          break;
        case FT_CSV:
               export_output (window, &options, "csv");
          break;
     
        case FT_TXT:
               string_map_insert (&options, "headers", "false");
               string_map_insert (&options, "paginate", "false");
               string_map_insert (&options, "squeeze", "true");
               string_map_insert (&options, "emphasis", "none");
               string_map_insert (&options, "charts", "none");
               string_map_insert (&options, "top-margin", "0");
               string_map_insert (&options, "bottom-margin", "0");
               export_output (window, &options, "txt");
          break;
        default:
          g_assert_not_reached ();
        }
     
           string_map_destroy (&options);
     
           free (filename);
         }
     
       gtk_widget_destroy (dialog);
     }
     
     
     enum {
       SELECT_FMT_NULL,
       SELECT_FMT_TEXT,
       SELECT_FMT_UTF8,
       SELECT_FMT_HTML,
       SELECT_FMT_ODT
     };
     
     static void
     clipboard_get_cb (GtkClipboard     *clipboard,
                  GtkSelectionData *selection_data,
                  guint             info,
                  gpointer          data)
     {
       PsppireOutputWindow *window = data;
     
       gsize length;
       gchar *text = NULL;
       struct output_driver *driver = NULL;
       char dirname[PATH_MAX], *filename;
       struct string_map options;
     
       GtkTreeSelection *sel = gtk_tree_view_get_selection (window->overview);
       GtkTreeModel *model = gtk_tree_view_get_model (window->overview);
     
       GList *rows = gtk_tree_selection_get_selected_rows (sel, &model);
       GList *n = rows;
     
       if ( n == NULL)
         return;
     
       if (path_search (dirname, sizeof dirname, NULL, NULL, true)
           || mkdtemp (dirname) == NULL)
         {
           error (0, errno, _("failed to create temporary directory"));
           return;
         }
       filename = xasprintf ("%s/clip.tmp", dirname);
     
       string_map_init (&options);
       string_map_insert (&options, "output-file", filename);
     
       switch (info)
         {
         case SELECT_FMT_UTF8:
           string_map_insert (&options, "box", "unicode");
           /* fall-through */
     
         case SELECT_FMT_TEXT:
           string_map_insert (&options, "format", "txt");
           break;
     
         case SELECT_FMT_HTML:
           string_map_insert (&options, "format", "html");
           string_map_insert (&options, "borders", "false");
           string_map_insert (&options, "css", "false");
           break;
     
         case SELECT_FMT_ODT:
           string_map_insert (&options, "format", "odt");
           break;
     
         default:
           g_warning ("unsupported clip target\n");
           goto finish;
           break;
         }
     
       driver = output_driver_create (&options);
       if (driver == NULL)
         goto finish;
     
       while (n)
         {
           GtkTreePath *path = n->data ; 
           GtkTreeIter iter;
           struct output_item *item ;
     
           gtk_tree_model_get_iter (model, &iter, path);
           gtk_tree_model_get (model, &iter, COL_ADDR, &item, -1);
     
           driver->class->submit (driver, item);
     
           n = n->next;
         }
     
       if ( driver->class->flush)
         driver->class->flush (driver);
     
     
       /* Some drivers (eg: the odt one) don't write anything until they
          are closed */
       output_driver_destroy (driver);
       driver = NULL;
     
       if ( g_file_get_contents (filename, &text, &length, NULL) )
         {
           gtk_selection_data_set (selection_data, selection_data->target,
                              8,
                              (const guchar *) text, length);
         }
     
      finish:
     
       if (driver != NULL)
         output_driver_destroy (driver);
     
       g_free (text);
     
       unlink (filename);
       free (filename);
       rmdir (dirname);
     
       g_list_free (rows);
     }
     
     static void
     clipboard_clear_cb (GtkClipboard *clipboard,
                    gpointer data)
     {
     }
     
     static const GtkTargetEntry targets[] = {
     
       { "STRING",        0, SELECT_FMT_TEXT },
       { "TEXT",          0, SELECT_FMT_TEXT },
       { "COMPOUND_TEXT", 0, SELECT_FMT_TEXT },
       { "text/plain",    0, SELECT_FMT_TEXT },
     
       { "UTF8_STRING",   0, SELECT_FMT_UTF8 },
       { "text/plain;charset=utf-8", 0, SELECT_FMT_UTF8 },
     
       { "text/html",     0, SELECT_FMT_HTML },
     
       { "application/vnd.oasis.opendocument.text", 0, SELECT_FMT_ODT }
     };
     
     static void
     on_copy (PsppireOutputWindow *window)
     {
       {
         GtkClipboard *clipboard =
           gtk_widget_get_clipboard (GTK_WIDGET (window),
                                GDK_SELECTION_CLIPBOARD);
     
         if (!gtk_clipboard_set_with_data (clipboard, targets,
                                       G_N_ELEMENTS (targets),
                                       clipboard_get_cb, clipboard_clear_cb,
                                      window))
     
           clipboard_clear_cb (clipboard, window);
       }
     }
     
     static void
     on_selection_change (GtkTreeSelection *sel, GtkAction *copy_action)
     {
       /* The Copy action is available only if there is something selected */
       gtk_action_set_sensitive (copy_action, 
gtk_tree_selection_count_selected_rows (sel) > 0);
     }
     
     static void
     on_select_all (PsppireOutputWindow *window)
     {
       GtkTreeSelection *sel = gtk_tree_view_get_selection (window->overview);
       gtk_tree_view_expand_all (window->overview);
       gtk_tree_selection_select_all (sel);
     }
     
     
     static void
     copy_base_to_bg (GtkWidget *dest, GtkWidget *src)
     {
       int i;
       for (i = 0; i < 5; ++i)
         {
           GdkColor *col = &gtk_widget_get_style (src)->base[i];
           gtk_widget_modify_bg (dest, i, col);
     
           col = &gtk_widget_get_style (src)->text[i];
           gtk_widget_modify_fg (dest, i, col);
         }
     }
     
     static void 
     on_dwgarea_realize (GtkWidget *dwg_area, gpointer data)
     {
       GtkWidget *viewer = GTK_WIDGET (data);
     
       copy_base_to_bg (dwg_area, viewer);
     }
     
     
     static void
     psppire_output_window_style_set (GtkWidget *w, GtkStyle *prev)
     {
       GtkWidget *op = GTK_WIDGET (PSPPIRE_OUTPUT_WINDOW (w)->output);
     
       /* Copy the base style from the parent widget to the container and 
          all its children.
          We do this, because the container's primary purpose is to 
          display text.  This way psppire appears to follow the chosen
          gnome theme.
        */
       copy_base_to_bg (op, w);
       gtk_container_foreach (GTK_CONTAINER (op), (GtkCallback) copy_base_to_bg,
                         PSPPIRE_OUTPUT_WINDOW (w)->output);
     
         /* Chain up to the parent class */
       GTK_WIDGET_CLASS (parent_class)->style_set (w, prev);
     }
     
     static void
     psppire_output_window_init (PsppireOutputWindow *window)
     {
       GtkTreeViewColumn *column;
       GtkCellRenderer *renderer;
       GtkBuilder *xml;
       GtkAction *copy_action;
       GtkAction *select_all_action;
       GtkTreeSelection *sel;
     
       string_map_init (&window->render_opts);
     
       xml = builder_new ("output-viewer.ui");
     
       copy_action = get_action_assert (xml, "edit_copy");
       select_all_action = get_action_assert (xml, "edit_select-all");
     
       gtk_action_set_sensitive (copy_action, FALSE);
     
       g_signal_connect_swapped (copy_action, "activate", G_CALLBACK (on_copy), 
window);
     
       g_signal_connect_swapped (select_all_action, "activate", G_CALLBACK 
(on_select_all), window);
     
       gtk_widget_reparent (get_widget_assert (xml, "vbox1"), GTK_WIDGET 
(window));
     
       window->output = GTK_LAYOUT (get_widget_assert (xml, "output"));
       window->y = 0;
     
       window->overview = GTK_TREE_VIEW (get_widget_assert (xml, "overview"));
     
       sel = gtk_tree_view_get_selection (window->overview);
     
       gtk_tree_selection_set_mode (sel, GTK_SELECTION_MULTIPLE);
     
       g_signal_connect (sel, "changed", G_CALLBACK (on_selection_change), 
copy_action);
     
       gtk_tree_view_set_model (window->overview,
                                GTK_TREE_MODEL (gtk_tree_store_new (
                                                  N_COLS,
                                                  G_TYPE_STRING,  /* COL_TITLE 
*/
                                             G_TYPE_POINTER, /* COL_ADDR */
                                                  G_TYPE_LONG))); /* COL_Y */
     
       window->in_command = false;
     
       window->items = NULL;
       window->n_items = window->allocated_items = 0;
     
       column = gtk_tree_view_column_new ();
       gtk_tree_view_append_column (GTK_TREE_VIEW (window->overview), column);
       renderer = gtk_cell_renderer_text_new ();
       gtk_tree_view_column_pack_start (column, renderer, TRUE);
       gtk_tree_view_column_add_attribute (column, renderer, "text", COL_TITLE);
     
       g_signal_connect (GTK_TREE_VIEW (window->overview),
                         "row-activated", G_CALLBACK (on_row_activate), window);
     
       connect_help (xml);
     
       g_signal_connect (window,
                    "focus-in-event",
                    G_CALLBACK (cancel_urgency),
                    NULL);
     
       g_signal_connect (get_action_assert (xml,"windows_minimise-all"),
                    "activate",
                    G_CALLBACK (psppire_window_minimise_all),
                    NULL);
     
       {
         GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (xml, 
"uimanager1", GTK_TYPE_UI_MANAGER));
         merge_help_menu (uim);
     
         PSPPIRE_WINDOW (window)->menu =
           GTK_MENU_SHELL (gtk_ui_manager_get_widget 
(uim,"/ui/menubar/windows_menuitem/windows_minimise-all")->parent);
       }
     
       g_signal_connect_swapped (get_action_assert (xml, "file_export"), 
"activate",
                                 G_CALLBACK (psppire_output_window_export), 
window);
     
     
       g_signal_connect_swapped (get_action_assert (xml, "file_print"), 
"activate",
                                 G_CALLBACK (psppire_output_window_print), 
window);
     
       g_object_unref (xml);
     
       g_signal_connect (window, "delete-event",
                    G_CALLBACK (on_delete), window);
     }
     
     
     GtkWidget*
     psppire_output_window_new (void)
     {
       return GTK_WIDGET (g_object_new (psppire_output_window_get_type (),
                                   /* TRANSLATORS: This will form a filename.  
Please avoid whitespace. */
                                   "filename", _("Output"),
                                   "description", _("Output Viewer"),
                                   NULL));
     }
     
     
     
     static void
     create_xr_print_driver (GtkPrintContext *context, PsppireOutputWindow 
*window)
     {
       struct string_map options;
       GtkPageSetup *page_setup;
       double width, height;
       double left_margin;
       double right_margin;
       double top_margin;
       double bottom_margin;
     
       page_setup = gtk_print_context_get_page_setup (context);
       width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
       height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
       left_margin = gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM);
       right_margin = gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM);
       top_margin = gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM);
       bottom_margin = gtk_page_setup_get_bottom_margin (page_setup, 
GTK_UNIT_MM);
     
       string_map_init (&options);
       string_map_insert_nocopy (&options, xstrdup ("paper-size"),
                                 xasprintf("%.2fx%.2fmm", width, height));
       string_map_insert_nocopy (&options, xstrdup ("left-margin"),
                                 xasprintf ("%.2fmm", left_margin));
       string_map_insert_nocopy (&options, xstrdup ("right-margin"),
                                 xasprintf ("%.2fmm", right_margin));
       string_map_insert_nocopy (&options, xstrdup ("top-margin"),
                                 xasprintf ("%.2fmm", top_margin));
       string_map_insert_nocopy (&options, xstrdup ("bottom-margin"),
                                 xasprintf ("%.2fmm", bottom_margin));
     
       window->print_xrd =
         xr_driver_create (gtk_print_context_get_cairo_context (context), 
&options);
     
       string_map_destroy (&options);
     }
     
     static gboolean
     paginate (GtkPrintOperation *operation,
          GtkPrintContext   *context,
          PsppireOutputWindow *window)
     {
       if (window->paginated)
         {
           /* Sometimes GTK+ emits this signal again even after pagination is
              complete.  Don't let that screw up printing. */
           return TRUE;
         }
       else if ( window->print_item < window->n_items )
         {
           xr_driver_output_item (window->print_xrd, 
window->items[window->print_item++]);
           while (xr_driver_need_new_page (window->print_xrd))
        {
          xr_driver_next_page (window->print_xrd, NULL);
          window->print_n_pages ++;
        }
           return FALSE;
         }
       else
         {
           gtk_print_operation_set_n_pages (operation, window->print_n_pages);
     
           /* Re-create the driver to do the real printing. */
           xr_driver_destroy (window->print_xrd);
           create_xr_print_driver (context, window);
           window->print_item = 0;
           window->paginated = TRUE;
     
           return TRUE;
         }
     }
     
     static void
     begin_print (GtkPrintOperation *operation,
             GtkPrintContext   *context,
             PsppireOutputWindow *window)
     {
       create_xr_print_driver (context, window);
     
       window->print_item = 0;
       window->print_n_pages = 1;
       window->paginated = FALSE;
     }
     
     static void
     end_print (GtkPrintOperation *operation,
           GtkPrintContext   *context,
           PsppireOutputWindow *window)
     {
       xr_driver_destroy (window->print_xrd);
     }
     
     
     static void
     draw_page (GtkPrintOperation *operation,
           GtkPrintContext   *context,
           gint               page_number,
           PsppireOutputWindow *window)
     {
       xr_driver_next_page (window->print_xrd, 
gtk_print_context_get_cairo_context (context));
       while (!xr_driver_need_new_page (window->print_xrd)
              && window->print_item < window->n_items)
         xr_driver_output_item (window->print_xrd, window->items 
[window->print_item++]);
     }
     
     
     static void
     psppire_output_window_print (PsppireOutputWindow *window)
     {
       GtkPrintOperationResult res;
     
       GtkPrintOperation *print = gtk_print_operation_new ();
     
       if (window->print_settings != NULL) 
         gtk_print_operation_set_print_settings (print, window->print_settings);
     
       g_signal_connect (print, "begin_print", G_CALLBACK (begin_print), 
window);
       g_signal_connect (print, "end_print", G_CALLBACK (end_print),     
window);
       g_signal_connect (print, "paginate", G_CALLBACK (paginate),       
window);
       g_signal_connect (print, "draw_page", G_CALLBACK (draw_page),     
window);
     
       res = gtk_print_operation_run (print, 
GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
                                      GTK_WINDOW (window), NULL);
     
       if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
         {
           if (window->print_settings != NULL)
             g_object_unref (window->print_settings);
           window->print_settings = g_object_ref 
(gtk_print_operation_get_print_settings (print));
           
         }
     
       g_object_unref (print);
     }


-- 
PGP Public key ID: 1024D/2DE827B3 
fingerprint = 8797 A26D 0854 2EAB 0285  A290 8A67 719C 2DE8 27B3
See http://keys.gnupg.net or any PGP keyserver for public key.

Attachment: signature.asc
Description: Digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]