Commit 741c71eb authored by Jonathan Blandford's avatar Jonathan Blandford Committed by Havoc Pennington

Initial stab at getting the focus code to work.

Fri Jun  1 18:54:47 2001  Jonathan Blandford  <jrb@redhat.com>

	* gtk/gtktreeview.c: (gtk_tree_view_focus): Initial stab at
	getting the focus code to work.
	(gtk_tree_view_class_init): Add a bunch of keybindings.

	* gtk/gtktreeviewcolumn.c
	(gtk_tree_view_column_set_cell_data_func):
	s/GtkCellDataFunc/GtkTreeCellDataFunc.
	(_gtk_tree_view_column_set_tree_view): Use "notify::model" instead
	of "properties_changed" to help justify the death of the latter
	signal. (-:

	* tests/testtreefocus.c (main): Let some columns be focussable to
	test focus better.
parent 11043de6
......@@ -495,6 +495,7 @@ This can later be composited together with other
#GtkRcStyle structures to form a #GtkStyle.
</para>
@parent_instance:
@name:
@bg_pixmap_name:
@font_desc:
......
2001-06-01 Havoc Pennington <hp@redhat.com>
Apply patch from sandmann@daimi.au.dk, with some tweaks.
Makes things a bit more robust, and adds test-loaders.c
which is good for finding further robustness bugs to fix.
* io-tiff.c: Try to work around libtiff suckiness a bit;
put a giant thread lock on the whole loader,
paranoically check both whether error handlers were called and
also whether functions return false. Handle case where width or
height is 0. Various cleanups.
* io-png.c (gdk_pixbuf__png_image_stop_load): only unref pixbuf
if it existed
(png_error_callback): apparently libpng expects you to longjmp out
of this thing?
* io-gif.c (struct _GifContext): remove unused "pixbuf" field
(lzw_read_byte): change "Mail jrb if this fails" g_warning
to a g_set_error()
(gif_get_lzw): check for out-of-memory
(gif_prepare_lzw): catch/report an error
(new_context): use try_malloc, since GifContext is nearly 70K
(gdk_pixbuf__gif_image_load_increment): set context->buf to NULL
so we don't crash later.
* Makefile.am: Add test-loaders
* gdk-pixbuf-loader.c (gdk_pixbuf_loader_close): handle context ==
NULL due to errors
2001-05-29 Darin Adler <darin@eazel.com>
* gdk-pixbuf.h: Fix prototype to use "(void)" instead of "()".
......
......@@ -160,8 +160,8 @@ builtin_objs = @INCLUDED_LOADER_OBJ@
endif
noinst_PROGRAMS = test-gdk-pixbuf
TESTS = test-gdk-pixbuf
TESTS = test-gdk-pixbuf test-loaders
noinst_PROGRAMS = $(TESTS)
DEPS = libgdk_pixbuf-1.3.la
INCLUDES = -I$(top_srcdir) -I$(top_builddir) \
......@@ -170,11 +170,14 @@ INCLUDES = -I$(top_srcdir) -I$(top_builddir) \
@INCLUDED_LOADER_DEFINE@ \
@GTK_DEBUG_FLAGS@ \
@GDK_PIXBUF_DEP_CFLAGS@
AM_CPPFLAGS = "-DPIXBUF_LIBDIR=\"$(loaderdir)\""
AM_CPPFLAGS = "-DPIXBUF_LIBDIR=\"$(loaderdir)\"" "-DBUILT_MODULES_DIR=\"$(srcdir)/.libs\""
LDADDS = libgdk_pixbuf-1.3.la
test_gdk_pixbuf_LDADD = $(LDADDS)
test_loaders_LDADD = $(LDADDS)
test_loaders_SOURCES = test-loaders.c test-images.h
bin_PROGRAMS=make-inline-pixbuf
......@@ -182,6 +185,8 @@ make_inline_pixbuf_SOURCES=make-inline-pixbuf.c
make_inline_pixbuf_LDADD = $(LDADDS)
#
# The GdkPixBuf library
#
......
......@@ -345,7 +345,7 @@ gdk_pixbuf_loader_write (GdkPixbufLoader *loader,
g_return_val_if_fail (count >= 0, FALSE);
priv = loader->priv;
/* we expect it's not to be closed */
g_return_val_if_fail (priv->closed == FALSE, FALSE);
......@@ -532,7 +532,7 @@ gdk_pixbuf_loader_close (GdkPixbufLoader *loader,
if (priv->image_module == NULL)
gdk_pixbuf_loader_load_module (loader, NULL, NULL);
if (priv->image_module && priv->image_module->stop_load)
if (priv->image_module && priv->image_module->stop_load && priv->context)
retval = priv->image_module->stop_load (priv->context, error);
priv->closed = TRUE;
......
......@@ -123,7 +123,6 @@ struct _GifContext
unsigned int frame_bit_pixel;
unsigned int aspect_ratio;
GdkPixbuf *pixbuf;
GdkPixbufGifAnim *animation;
GdkPixbufFrame *frame;
Gif89 gif89;
......@@ -198,10 +197,10 @@ static int count = 0;
/* Returns TRUE if read is OK,
* FALSE if more memory is needed. */
static int
static gboolean
gif_read (GifContext *context, guchar *buffer, size_t len)
{
gint retval;
gboolean retval;
#ifdef IO_GIFDEBUG
gint i;
#endif
......@@ -586,9 +585,13 @@ lzw_read_byte (GifContext *context)
int count;
unsigned char buf[260];
/*g_error (" DID WE EVER EVER GET HERE\n");*/
g_warning ("Unhandled Case. If you have an image that causes this, let me <jrb@redhat.com> know.\n");
/* FIXME - we should handle this case */
g_set_error (context->error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_FAILED,
_("GIF image loader can't understand this image."));
return -2;
if (ZeroDataBlock) {
return -2;
}
......@@ -735,7 +738,15 @@ gif_get_lzw (GifContext *context)
8,
context->frame_len,
context->frame_height);
if (!context->frame->pixbuf) {
g_free (context->frame);
g_set_error (context->error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
_("Not enough memory to load GIF file"));
return -2;
}
context->frame->x_offset = context->x_offset;
context->frame->y_offset = context->y_offset;
context->frame->need_recomposite = TRUE;
......@@ -962,6 +973,14 @@ gif_prepare_lzw (GifContext *context)
/*g_message (_("GIF: EOF / read error on image data\n"));*/
return -1;
}
if (context->lzw_set_code_size > MAX_LZW_BITS) {
g_set_error (context->error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
_("GIF image is corrupt (incorrect LZW compression)"));
return -2;
}
context->lzw_code_size = context->lzw_set_code_size + 1;
context->lzw_clear_code = 1 << context->lzw_set_code_size;
......@@ -974,6 +993,9 @@ gif_prepare_lzw (GifContext *context)
context->code_last_byte = 0;
context->code_done = FALSE;
g_assert (context->lzw_clear_code <=
G_N_ELEMENTS (context->lzw_table[0]));
for (i = 0; i < context->lzw_clear_code; ++i) {
context->lzw_table[0][i] = 0;
context->lzw_table[1][i] = i;
......@@ -1188,7 +1210,7 @@ gif_get_next_step (GifContext *context)
}
#define LOG(x)
#define LOG(x) /* g_print ("%d: %s\n", __LINE__, x); */
static gint
gif_main_loop (GifContext *context)
......@@ -1269,8 +1291,12 @@ new_context (void)
{
GifContext *context;
context = g_new0 (GifContext, 1);
context = g_try_malloc (sizeof (GifContext));
if (context == NULL)
return NULL;
memset (context, 0, sizeof (GifContext));
context->animation = g_object_new (GDK_TYPE_PIXBUF_GIF_ANIM, NULL);
context->frame = NULL;
context->file = NULL;
......@@ -1297,6 +1323,15 @@ gdk_pixbuf__gif_image_load (FILE *file, GError **error)
g_return_val_if_fail (file != NULL, NULL);
context = new_context ();
if (context == NULL) {
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
_("Not enough memory to load GIF file"));
return NULL;
}
context->file = file;
context->error = error;
......@@ -1333,6 +1368,15 @@ gdk_pixbuf__gif_image_begin_load (ModulePreparedNotifyFunc prepare_func,
count = 0;
#endif
context = new_context ();
if (context == NULL) {
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
_("Not enough memory to load GIF file"));
return NULL;
}
context->error = error;
context->prepare_func = prepare_func;
context->update_func = update_func;
......@@ -1401,8 +1445,10 @@ gdk_pixbuf__gif_image_load_increment (gpointer data,
retval = gif_main_loop (context);
if (retval == -2)
if (retval == -2) {
context->buf = NULL;
return FALSE;
}
if (retval == -1) {
/* we didn't have enough memory */
/* prepare for the next image_load_increment */
......@@ -1437,6 +1483,14 @@ gdk_pixbuf__gif_image_load_animation (FILE *file,
context = new_context ();
if (context == NULL) {
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
_("Not enough memory to load GIF file"));
return NULL;
}
context->error = error;
context->file = file;
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/* GdkPixbuf library - PNG image loader
*
* Copyright (C) 1999 Mark Crichton
......@@ -403,7 +404,8 @@ gdk_pixbuf__png_image_stop_load (gpointer context, GError **error)
* we have unused image data
*/
gdk_pixbuf_unref(lc->pixbuf);
if (lc->pixbuf)
gdk_pixbuf_unref (lc->pixbuf);
png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL);
g_free(lc);
......@@ -606,6 +608,8 @@ png_error_callback(png_structp png_read_ptr,
_("Fatal error reading PNG image file: %s"),
error_msg);
}
longjmp (png_read_ptr->jmpbuf, 1);
}
static void
......@@ -639,7 +643,8 @@ gdk_pixbuf__png_image_save (FILE *f,
guchar *ptr;
guchar *pixels;
int x, y, j;
png_bytep row_ptr, data = NULL;
png_bytep row_ptr;
png_bytep data;
png_color_8 sig_bit;
int w, h, rowstride;
int has_alpha;
......@@ -661,6 +666,7 @@ gdk_pixbuf__png_image_save (FILE *f,
}
#endif
}
data = NULL;
bpc = gdk_pixbuf_get_bits_per_sample (pixbuf);
w = gdk_pixbuf_get_width (pixbuf);
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/* GdkPixbuf library - TIFF image loader
*
* Copyright (C) 1999 Mark Crichton
......@@ -6,6 +7,7 @@
* Authors: Mark Crichton <crichton@gimp.org>
* Federico Mena-Quintero <federico@gimp.org>
* Jonathan Blandford <jrb@redhat.com>
* Sren Sandmann <sandmann@daimi.au.dk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -42,103 +44,197 @@
#endif
typedef struct _TiffData TiffData;
struct _TiffData
typedef struct _TiffContext TiffContext;
struct _TiffContext
{
ModulePreparedNotifyFunc prepare_func;
ModuleUpdatedNotifyFunc update_func;
gpointer user_data;
gchar *tempname;
FILE *file;
gboolean all_okay;
guchar *buffer;
guint allocated;
guint used;
guint pos;
};
/* There's no user data for the error handlers, so we just have to
* put a big-ass lock on the whole TIFF loader
*/
G_LOCK_DEFINE_STATIC (tiff_loader);
static char *global_error = NULL;
static TIFFErrorHandler orig_error_handler = NULL;
static TIFFErrorHandler orig_warning_handler = NULL;
static void
tiff_warning_handler (const char *mod, const char *fmt, va_list ap)
{
/* Don't print anything; we should not be dumping junk to
* stderr, since that may be bad for some apps.
*/
/* libTIFF seems to occasionally warn about things that
* are really errors, so maybe we should just call tiff_error_handler
* here.
*/
}
static void
tiff_error_handler (const char *mod, const char *fmt, va_list ap)
{
if (global_error) {
/* Blah, loader called us twice */
return;
}
global_error = g_strdup_vprintf (fmt, ap);
}
static void
tiff_push_handlers (void)
{
if (global_error)
g_warning ("TIFF loader left crufty global_error around, FIXME");
orig_error_handler = TIFFSetErrorHandler (tiff_error_handler);
orig_warning_handler = TIFFSetWarningHandler (tiff_warning_handler);
}
static void
tiff_pop_handlers (void)
{
if (global_error)
g_warning ("TIFF loader left crufty global_error around, FIXME");
TIFFSetErrorHandler (orig_error_handler);
TIFFSetWarningHandler (orig_warning_handler);
}
static void
tiff_set_error (GError **error,
int error_code,
const char *msg)
{
/* Take the error message from libtiff and merge it with
* some context we provide.
*/
g_set_error (error,
GDK_PIXBUF_ERROR,
error_code,
"%s%s%s",
msg, global_error ? ": " : "", global_error);
if (global_error) {
g_free (global_error);
global_error = NULL;
}
}
static GdkPixbuf *
gdk_pixbuf__tiff_image_load_real (FILE *f, TiffData *context, GError **error)
tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error)
{
TIFF *tiff;
guchar *pixels = NULL;
guchar *tmppix;
gint w, h, x, y, num_pixs, fd;
uint32 *rast, *tmp_rast;
gint w, h, x, y, num_pixs;
GdkPixbuf *pixbuf;
fd = fileno (f);
tiff = TIFFFdOpen (fd, "libpixbuf-tiff", "r");
if (!tiff) {
/* We're called with the lock held. */
g_return_val_if_fail (global_error == NULL, NULL);
if (!TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &w) || global_error) {
tiff_set_error (error,
GDK_PIXBUF_ERROR_FAILED,
_("Could not get image width (bad TIFF file)"));
return NULL;
}
if (!TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &h) || global_error) {
tiff_set_error (error,
GDK_PIXBUF_ERROR_FAILED,
_("Could not get image height (bad TIFF file)"));
return NULL;
}
num_pixs = w * h;
if (num_pixs == 0) {
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
_("Failed to open TIFF image"));
return NULL;
_("Width or height of TIFF image is zero"));
return NULL;
}
TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &w);
TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &h);
num_pixs = w * h;
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, w, h);
if (!pixbuf) {
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
_("Insufficient memory to open TIFF file"));
TIFFClose (tiff);
return NULL;
return NULL;
}
G_UNLOCK (tiff_loader);
if (context)
(* context->prepare_func) (pixbuf, NULL, context->user_data);
G_LOCK (tiff_loader);
/* Yes, it needs to be _TIFFMalloc... */
rast = (uint32 *) _TIFFmalloc (num_pixs * sizeof (uint32));
rast = (uint32 *) _TIFFmalloc (num_pixs * sizeof (uint32));
if (!rast) {
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
_("Insufficient memory to open TIFF file"));
TIFFClose (tiff);
return NULL;
return NULL;
}
if (!TIFFReadRGBAImage (tiff, w, h, rast, 0) || global_error) {
tiff_set_error (error,
GDK_PIXBUF_ERROR_FAILED,
_("Failed to load RGB data from TIFF file"));
_TIFFfree (rast);
if (TIFFReadRGBAImage (tiff, w, h, rast, 0)) {
pixels = gdk_pixbuf_get_pixels (pixbuf);
return NULL;
}
pixels = gdk_pixbuf_get_pixels (pixbuf);
g_assert (pixels);
tmppix = pixels;
for (y = 0; y < h; y++) {
/* Unexplainable...are tiffs backwards? */
/* Also looking at the GIMP plugin, this
* whole reading thing can be a bit more
* robust.
*/
tmp_rast = rast + ((h - y - 1) * w);
for (x = 0; x < w; x++) {
tmppix[0] = TIFFGetR (*tmp_rast);
tmppix[1] = TIFFGetG (*tmp_rast);
tmppix[2] = TIFFGetB (*tmp_rast);
tmppix[3] = TIFFGetA (*tmp_rast);
tmp_rast++;
tmppix += 4;
}
}
g_assert (pixels);
tmppix = pixels;
for (y = 0; y < h; y++) {
/* Unexplainable...are tiffs backwards? */
/* Also looking at the GIMP plugin, this
* whole reading thing can be a bit more
* robust.
*/
tmp_rast = rast + ((h - y - 1) * w);
for (x = 0; x < w; x++) {
tmppix[0] = TIFFGetR (*tmp_rast);
tmppix[1] = TIFFGetG (*tmp_rast);
tmppix[2] = TIFFGetB (*tmp_rast);
tmppix[3] = TIFFGetA (*tmp_rast);
tmp_rast++;
tmppix += 4;
}
}
}
_TIFFfree (rast);
TIFFClose (tiff);
_TIFFfree (rast);
if (context) {
G_UNLOCK (tiff_loader);
if (context)
(* context->update_func) (pixbuf, 0, 0, w, h, context->user_data);
gdk_pixbuf_unref (pixbuf);
}
return pixbuf;
G_LOCK (tiff_loader);
return pixbuf;
}
......@@ -148,17 +244,49 @@ gdk_pixbuf__tiff_image_load_real (FILE *f, TiffData *context, GError **error)
static GdkPixbuf *
gdk_pixbuf__tiff_image_load (FILE *f, GError **error)
{
return gdk_pixbuf__tiff_image_load_real (f, NULL, error);
TIFF *tiff;
int fd;
GdkPixbuf *pixbuf;
g_return_val_if_fail (f != NULL, NULL);
G_LOCK (tiff_loader);
tiff_push_handlers ();
fd = fileno (f);
tiff = TIFFFdOpen (fd, "libpixbuf-tiff", "r");
if (!tiff) {
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
_("Failed to open TIFF image"));
tiff_pop_handlers ();
G_UNLOCK (tiff_loader);
return NULL;
}
pixbuf = tiff_image_parse (tiff, NULL, error);
TIFFClose (tiff);
if (global_error) {
tiff_set_error (error,
GDK_PIXBUF_ERROR_FAILED,
_("TIFFClose operation failed"));
}
tiff_pop_handlers ();
G_UNLOCK (tiff_loader);
return pixbuf;
}
/* Progressive loader */
/*
* Tiff loading progressively cannot be done. We write it to a file, then load
* the file when it's done. It's not pretty.
*/
static gpointer
gdk_pixbuf__tiff_image_begin_load (ModulePreparedNotifyFunc prepare_func,
......@@ -166,54 +294,165 @@ gdk_pixbuf__tiff_image_begin_load (ModulePreparedNotifyFunc prepare_func,
gpointer user_data,
GError **error)
{
TiffData *context;
gint fd;
context = g_new (TiffData, 1);
TiffContext *context;
context = g_new0 (TiffContext, 1);
context->prepare_func = prepare_func;
context->update_func = update_func;
context->user_data = user_data;
context->all_okay = TRUE;
fd = g_file_open_tmp ("gdkpixbuf-tif-tmp.XXXXXX", &context->tempname,
NULL);
if (fd < 0) {
g_free (context);
return NULL;
}
context->buffer = NULL;
context->allocated = 0;
context->used = 0;
context->pos = 0;
return context;
}
context->file = fdopen (fd, "w");
if (context->file == NULL) {
g_free (context->tempname);
g_free (context);
return NULL;
}
static tsize_t
tiff_read (thandle_t handle, tdata_t buf, tsize_t size)
{
TiffContext *context = (TiffContext *)handle;
if (context->pos + size > context->used)
return 0;
memcpy (buf, context->buffer + context->pos, size);
context->pos += size;
return size;
}
return context;
static tsize_t
tiff_write (thandle_t handle, tdata_t buf, tsize_t size)
{
return -1;
}
static toff_t
tiff_seek (thandle_t handle, toff_t offset, int whence)
{
TiffContext *context = (TiffContext *)handle;
switch (whence) {
case SEEK_SET:
if (offset > context->used || offset < 0)
return -1;
context->pos = offset;
break;
case SEEK_CUR:
if (offset + context->pos >= context->used)
return -1;
context->pos += offset;
break;
case SEEK_END:
if (offset + context->used > context->used)
return -1;
context->pos = context->used + offset;
break;
default:
return -1;
break;
}