[Swfdec-commits] 21 commits - swfdec/swfdec_movie.c swfdec/swfdec_player.c swfdec/swfdec_sandbox.c swfdec/swfdec_selection.c swfdec/swfdec_sprite_movie_as.c swfdec/swfdec_text_buffer.c swfdec/swfdec_text_field_movie_as.c swfdec/swfdec_text_field_movie.c swfdec/swfdec_text_layout.c swfdec/swfdec_text_layout.h test/swfdec_test_plugin.c test/trace

Benjamin Otte company at kemper.freedesktop.org
Tue May 20 13:33:17 PDT 2008


 swfdec/swfdec_movie.c                                |   19 +
 swfdec/swfdec_player.c                               |    7 
 swfdec/swfdec_sandbox.c                              |    8 
 swfdec/swfdec_selection.c                            |   80 ++++++-
 swfdec/swfdec_sprite_movie_as.c                      |   14 +
 swfdec/swfdec_text_buffer.c                          |    2 
 swfdec/swfdec_text_field_movie.c                     |  116 ++++++----
 swfdec/swfdec_text_field_movie_as.c                  |   27 +-
 swfdec/swfdec_text_layout.c                          |  209 ++++++++++++++++++-
 swfdec/swfdec_text_layout.h                          |   10 
 test/swfdec_test_plugin.c                            |    8 
 test/trace/Makefile.am                               |    9 
 test/trace/selection-setFocus-textfields-5.swf       |binary
 test/trace/selection-setFocus-textfields-5.swf.trace |    9 
 test/trace/selection-setFocus-textfields-6.swf       |binary
 test/trace/selection-setFocus-textfields-6.swf.trace |    9 
 test/trace/selection-setFocus-textfields-7.swf       |binary
 test/trace/selection-setFocus-textfields-7.swf.trace |    9 
 test/trace/selection-setFocus-textfields-8.swf       |binary
 test/trace/selection-setFocus-textfields-8.swf.trace |    9 
 test/trace/selection-setFocus-textfields.as          |   45 ++++
 21 files changed, 501 insertions(+), 89 deletions(-)

New commits:
commit a9ae6f1a56b94cd209e6362c96adf82de72452d4
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue May 20 22:28:40 2008 +0200

    fixes to attachMovie init object property copying
    
    - The constructor is set in advance
    - Don't copy hidden properties

diff --git a/swfdec/swfdec_sprite_movie_as.c b/swfdec/swfdec_sprite_movie_as.c
index 1b50643..2c57c74 100644
--- a/swfdec/swfdec_sprite_movie_as.c
+++ b/swfdec/swfdec_sprite_movie_as.c
@@ -672,6 +672,11 @@ swfdec_sprite_movie_foreach_copy_properties (SwfdecAsObject *object,
 
   g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (target), FALSE);
 
+  /* FIXME: We likely need better flag handling here.
+   * We might even want to fix swfdec_as_object_foreach() */
+  if (flags & SWFDEC_AS_VARIABLE_HIDDEN)
+    return TRUE;
+
   swfdec_as_object_set_variable (target, variable, value);
 
   return TRUE;
@@ -710,12 +715,12 @@ swfdec_sprite_movie_attachMovie (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   SwfdecMovie *movie;
   SwfdecMovie *ret;
-  SwfdecAsObject *initObject;
+  SwfdecAsObject *initObject, *constructor;
   const char *name, *export;
   int depth;
   SwfdecGraphic *sprite;
 
-  SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, (gpointer)&movie, "ssi", &export, &name, &depth);
+  SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, &movie, "ssi", &export, &name, &depth);
 
   if (argc > 3 && SWFDEC_AS_VALUE_IS_OBJECT (&argv[3])) {
     initObject = SWFDEC_AS_VALUE_GET_OBJECT ((&argv[3]));
@@ -740,6 +745,11 @@ swfdec_sprite_movie_attachMovie (SwfdecAsContext *cx, SwfdecAsObject *object,
   SWFDEC_LOG ("attached %s (%u) as %s to depth %u", export, SWFDEC_CHARACTER (sprite)->id,
       ret->name, ret->depth);
   /* run init and construct */
+  constructor = swfdec_player_get_export_class (SWFDEC_PLAYER (cx), export);
+  if (constructor == NULL)
+    constructor = movie->resource->sandbox->MovieClip;
+  swfdec_as_object_set_constructor (SWFDEC_AS_OBJECT (ret), constructor);
+
   swfdec_sprite_movie_init_from_object (ret, initObject);
   SWFDEC_AS_VALUE_SET_OBJECT (rval, SWFDEC_AS_OBJECT (ret));
 }
commit ddb764561f7780bccb2625f9093e0d4eaacd710e
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue May 20 14:58:06 2008 +0200

    fix docs

diff --git a/swfdec/swfdec_sandbox.c b/swfdec/swfdec_sandbox.c
index 9832f63..8842251 100644
--- a/swfdec/swfdec_sandbox.c
+++ b/swfdec/swfdec_sandbox.c
@@ -117,11 +117,14 @@ swfdec_sandbox_initialize (SwfdecSandbox *sandbox, guint version)
     context->state = SWFDEC_AS_CONTEXT_RUNNING;
   swfdec_sandbox_unuse (sandbox);
 }
+
 /**
  * swfdec_sandbox_set_allow_network:
  * @sandbox: a #SwfdecSandbox
- * finished, by giving the sandbox network or local file access. This function
- * should be called on all return values of swfdec_sandbox_get_for_url().
+ * @network: %TRUE if network access is possible
+ *
+ * Checks if the given sandbox may be loaded and if so initializes its type. 
+ * This function should be called on every new sandbox.
  *
  * Returns: %TRUE if the sandbox initialization could be finished as requested,
  *          %FALSE if not and it shouldn't be used.
@@ -165,7 +168,6 @@ swfdec_sandbox_set_allow_network (SwfdecSandbox *sandbox, gboolean network)
  *                 file access. See the documentation of the use_network flag 
  *                 of the SWF FileAttributes tag for what that means.
  *
- *
  * Checks if a sandbox is already in use for a given URL and if so, returns it.
  * Otherwise a new sandbox is created, initialized and returned.
  * Note that the given url must be a HTTP, HTTPS or a FILE url.
commit 2d7bc4018ec680a43303fa2022eb289247224c3f
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue May 20 14:52:14 2008 +0200

    fix uninitialized variable

diff --git a/swfdec/swfdec_text_field_movie_as.c b/swfdec/swfdec_text_field_movie_as.c
index 0f33e92..c23be82 100644
--- a/swfdec/swfdec_text_field_movie_as.c
+++ b/swfdec/swfdec_text_field_movie_as.c
@@ -743,6 +743,7 @@ swfdec_text_field_movie_set_autoSize (SwfdecAsContext *cx,
   if (argc < 1)
     return;
 
+  old = text->auto_size;
   if (SWFDEC_AS_VALUE_IS_BOOLEAN (&argv[0])) {
     if (SWFDEC_AS_VALUE_GET_BOOLEAN (&argv[0])) {
       text->auto_size = SWFDEC_AUTO_SIZE_LEFT;
@@ -753,7 +754,6 @@ swfdec_text_field_movie_set_autoSize (SwfdecAsContext *cx,
     swfdec_as_value_to_number (cx, &argv[0]);
     s = swfdec_as_value_to_string (cx, &argv[0]);
 
-    old = text->auto_size;
     if (!g_ascii_strcasecmp (s, "none")) {
       text->auto_size = SWFDEC_AUTO_SIZE_NONE;
     } else if (!g_ascii_strcasecmp (s, "left")) {
commit 8c5e0584038b736781c824f6f73eef504e7249a9
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 15:04:27 2008 +0200

    reimplement mouse position querying
    
    It's still somewhat broken as it doesn't offset the coordinates properly, but
    it works with identity matrices :(

diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index c867409..1f7bc4b 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -495,14 +495,28 @@ swfdec_text_field_movie_letter_clicked (SwfdecTextFieldMovie *text,
   }
 }
 
-static gboolean
+static void
 swfdec_text_field_movie_xy_to_index (SwfdecTextFieldMovie *text, double x,
-    double y, gsize *index_)
+    double y, gsize *index_, gboolean *hit)
 {
-  SWFDEC_STUB ("swfdec_text_field_movie_xy_to_index");
+  SwfdecRectangle area;
+  int trailing;
+  int stage_x, stage_y;
+
+  stage_x = x * text->xscale / SWFDEC_TWIPS_SCALE_FACTOR;
+  stage_y = y * text->yscale / SWFDEC_TWIPS_SCALE_FACTOR;
+  swfdec_text_field_movie_get_visible_area (text, &area);
+#if 0
+  g_print ("@ %g,%g => %d,%d => %d, %d\n", x, y, stage_x, stage_y,
+      stage_x - area.x, stage_y - area.y);
+#endif
+  swfdec_text_layout_query_position (text->layout, text->scroll,
+      stage_x, stage_y, index_, hit, &trailing);
+
   if (index_)
-    *index_ = 0;
-  return FALSE;
+    *index_ += trailing;
+
+  //g_print ("found %u %s\n", index_ ? *index_ : (guint) -1, hit ? *hit ? "HIT" : "" : "???");
 }
 
 static SwfdecMouseCursor
@@ -512,10 +526,12 @@ swfdec_text_field_movie_mouse_cursor (SwfdecActor *actor)
   double x, y;
   guint index_;
   const SwfdecTextAttributes *attr;
+  gboolean hit;
 
   swfdec_movie_get_mouse (SWFDEC_MOVIE (actor), &x, &y);
 
-  if (swfdec_text_field_movie_xy_to_index (text, x, y, &index_)) {
+  swfdec_text_field_movie_xy_to_index (text, x, y, &index_, &hit);
+  if (hit) {
     attr = swfdec_text_buffer_get_attributes (text->text, index_);
   } else {
     attr = NULL;
@@ -544,7 +560,7 @@ swfdec_text_field_movie_mouse_press (SwfdecActor *actor, guint button)
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
   double x, y;
   guint index_;
-  gboolean direct;
+  gboolean hit;
 
   if (!text->selectable)
     return;
@@ -556,18 +572,18 @@ swfdec_text_field_movie_mouse_press (SwfdecActor *actor, guint button)
 
   swfdec_movie_get_mouse (SWFDEC_MOVIE (actor), &x, &y);
 
-  direct = swfdec_text_field_movie_xy_to_index (text, x, y, &index_);
-
-  text->mouse_pressed = TRUE;
-  swfdec_text_buffer_set_cursor (text->text, index_, index_);
+  swfdec_text_field_movie_xy_to_index (text, x, y, &index_, &hit);
 
-  if (direct) {
+  if (hit) {
     text->character_pressed = index_;
   } else {
-    text->character_pressed = 0;
+    text->character_pressed = -1;
   }
 
   swfdec_player_grab_focus (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (text)->context), actor);
+
+  text->mouse_pressed = TRUE;
+  swfdec_text_buffer_set_cursor (text->text, index_, index_);
 }
 
 static void
@@ -575,6 +591,7 @@ swfdec_text_field_movie_mouse_move (SwfdecActor *actor, double x, double y)
 {
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
   guint index_;
+  gsize start, end;
 
   if (!text->selectable)
     return;
@@ -582,9 +599,13 @@ swfdec_text_field_movie_mouse_move (SwfdecActor *actor, double x, double y)
   if (!text->mouse_pressed)
     return;
 
-  swfdec_text_field_movie_xy_to_index (text, x, y, &index_);
+  swfdec_text_field_movie_xy_to_index (text, x, y, &index_, NULL);
 
-  swfdec_text_buffer_set_cursor (text->text, swfdec_text_buffer_get_cursor (text->text), index_);
+  swfdec_text_buffer_get_selection (text->text, &start, &end);
+  swfdec_text_buffer_set_cursor (text->text, 
+      swfdec_text_buffer_get_cursor (text->text) == start ? end : start, index_);
+  g_print ("setting cursor to %u %u\n", 
+      swfdec_text_buffer_get_cursor (text->text) == start ? end : start, index_);
 }
 
 static void
@@ -593,7 +614,7 @@ swfdec_text_field_movie_mouse_release (SwfdecActor *actor, guint button)
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
   double x, y;
   guint index_;
-  gboolean direct;
+  gboolean hit;
 
   if (!text->selectable)
     return;
@@ -607,15 +628,11 @@ swfdec_text_field_movie_mouse_release (SwfdecActor *actor, guint button)
 
   text->mouse_pressed = FALSE;
 
-  direct = swfdec_text_field_movie_xy_to_index (text, x, y, &index_);
-
-  if (text->character_pressed != 0) {
-    if (direct && text->character_pressed == index_ + 1) {
-      swfdec_text_field_movie_letter_clicked (text,
-	  text->character_pressed - 1);
-    }
+  swfdec_text_field_movie_xy_to_index (text, x, y, &index_, &hit);
 
-    text->character_pressed = 0;
+  if (hit && text->character_pressed == index_) {
+    swfdec_text_field_movie_letter_clicked (text, text->character_pressed);
+    text->character_pressed = -1;
   }
 }
 
@@ -772,6 +789,7 @@ swfdec_text_field_movie_init (SwfdecTextFieldMovie *text)
       G_CALLBACK (swfdec_text_field_movie_layout_changed), text);
 
   text->mouse_wheel_enabled = TRUE;
+  text->character_pressed = -1;
 
   swfdec_text_attributes_reset (&text->default_attributes);
 }
diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index 67db9d0..c359824 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -1009,3 +1009,79 @@ swfdec_text_layout_render (SwfdecTextLayout *layout, cairo_t *cr,
   } while (!g_sequence_iter_is_end (iter));
 }
 
+/**
+ * swfdec_text_layout_query_position:
+ * @layout: the layout to query
+ * @row: the start of this row indicates the (0,0) position to which @x and @y 
+ *       are relative
+ * @x: x offset
+ * @y: y offset
+ * @index_: %NULL or variable that will be set to the index in the layout's 
+ *          buffer that corresponds to the position of the pressed grapheme.
+ * @hit: %NULL or variable that will be set to %TRUE if the coordinate is inside
+ *	 the glyhs's extents and %FALSE otherwise
+ * @trailing: %NULL or variable that will be set to thenumber of characters 
+ *            inside the grapheme that have been passed.
+ *
+ * Magic function to query everything of interest about the string at a current 
+ * position inisde the @layout.
+ **/
+void
+swfdec_text_layout_query_position (SwfdecTextLayout *layout, guint row,
+    int x, int y, gsize *index_, gboolean *hit, int *trailing)
+{
+  GSequenceIter *iter;
+  SwfdecTextBlock *block;
+  PangoRectangle extents;
+
+  g_return_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout));
+  g_return_if_fail (row < swfdec_text_layout_get_n_rows (layout));
+
+  swfdec_text_layout_ensure (layout);
+
+  iter = swfdec_text_layout_find_row (layout, row); 
+  block = g_sequence_get (iter);
+  row -= block->row;
+
+  do {
+    block = g_sequence_get (iter);
+    if (y < 0) {
+      if (index_)
+	*index_ = block->start;
+      if (hit)
+	*hit = FALSE;
+      if (trailing)
+	*trailing = 0;
+      return;
+    }
+
+    for (;row < (guint) pango_layout_get_line_count (block->layout); row++) {
+      PangoLayoutLine *line = pango_layout_get_line_readonly (block->layout, row);
+      
+      pango_layout_line_get_pixel_extents (line, NULL, &extents);
+      if (extents.height > y) {
+	gboolean tmp;
+	int ind;
+	x -= swfdec_text_layout_get_line_offset (layout, block, line);
+	tmp = pango_layout_line_x_to_index (line, x * PANGO_SCALE, &ind, trailing);
+	if (hit)
+	  *hit = tmp;
+	if (index_)
+	  *index_ = block->start + ind;
+	return;
+      }
+      y -= extents.height;
+    }
+    y -= pango_layout_get_spacing (block->layout) / PANGO_SCALE;
+    row = 0;
+    iter = g_sequence_iter_next (iter);
+  } while (!g_sequence_iter_is_end (iter));
+
+  if (index_)
+    *index_ = swfdec_text_buffer_get_length (layout->text);
+  if (hit)
+    *hit = FALSE;
+  if (trailing)
+    *trailing = 0;
+}
+
diff --git a/swfdec/swfdec_text_layout.h b/swfdec/swfdec_text_layout.h
index 7695c13..3ad0e7f 100644
--- a/swfdec/swfdec_text_layout.h
+++ b/swfdec/swfdec_text_layout.h
@@ -92,6 +92,13 @@ void			swfdec_text_layout_render		(SwfdecTextLayout *	layout,
 								 guint			row,
 								 guint			height,
 								 SwfdecColor		focus);
+void			swfdec_text_layout_query_position	(SwfdecTextLayout *	layout,
+								 guint			row,
+								 int			x,
+								 int			y,
+								 gsize *		index_,
+								 gboolean *		hit,
+								 int *			trailing);
 
 
 G_END_DECLS
commit 4aec1ccfb5b950ee7f7018dacb38fde2bd70ad63
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 15:03:45 2008 +0200

    compute selection offset correctly
    
    Fixes wrong areas being selected

diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index d7d581b..67db9d0 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -849,6 +849,14 @@ swfdec_text_layout_modify_attributes (SwfdecTextLayout *layout,
       sel_start = sel_end = 0;
     }
   }
+  if (sel_start <= block->start)
+    sel_start = 0;
+  else
+    sel_start -= block->start;
+  if (sel_end <= block->start)
+    sel_end = 0;
+  else
+    sel_end -= block->start;
 
   old = pango_layout_get_attributes (block->layout);
   pango_attr_list_ref (old);
commit c44a079b5cb826547bca1c06ae679afeb135df6b
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 13:49:13 2008 +0200

    remove useless argument from _xy_to_index()

diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 5f97881..c867409 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -497,13 +497,11 @@ swfdec_text_field_movie_letter_clicked (SwfdecTextFieldMovie *text,
 
 static gboolean
 swfdec_text_field_movie_xy_to_index (SwfdecTextFieldMovie *text, double x,
-    double y, guint *index_, gboolean *before)
+    double y, gsize *index_)
 {
   SWFDEC_STUB ("swfdec_text_field_movie_xy_to_index");
   if (index_)
     *index_ = 0;
-  if (before)
-    *before = FALSE;
   return FALSE;
 }
 
@@ -517,7 +515,7 @@ swfdec_text_field_movie_mouse_cursor (SwfdecActor *actor)
 
   swfdec_movie_get_mouse (SWFDEC_MOVIE (actor), &x, &y);
 
-  if (swfdec_text_field_movie_xy_to_index (text, x, y, &index_, NULL)) {
+  if (swfdec_text_field_movie_xy_to_index (text, x, y, &index_)) {
     attr = swfdec_text_buffer_get_attributes (text->text, index_);
   } else {
     attr = NULL;
@@ -546,7 +544,7 @@ swfdec_text_field_movie_mouse_press (SwfdecActor *actor, guint button)
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
   double x, y;
   guint index_;
-  gboolean direct, before;
+  gboolean direct;
 
   if (!text->selectable)
     return;
@@ -558,11 +556,9 @@ swfdec_text_field_movie_mouse_press (SwfdecActor *actor, guint button)
 
   swfdec_movie_get_mouse (SWFDEC_MOVIE (actor), &x, &y);
 
-  direct = swfdec_text_field_movie_xy_to_index (text, x, y, &index_, &before);
+  direct = swfdec_text_field_movie_xy_to_index (text, x, y, &index_);
 
   text->mouse_pressed = TRUE;
-  if (!before && index_ < swfdec_text_buffer_get_length (text->text))
-    index_++;
   swfdec_text_buffer_set_cursor (text->text, index_, index_);
 
   if (direct) {
@@ -579,7 +575,6 @@ swfdec_text_field_movie_mouse_move (SwfdecActor *actor, double x, double y)
 {
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
   guint index_;
-  gboolean direct, before;
 
   if (!text->selectable)
     return;
@@ -587,10 +582,7 @@ swfdec_text_field_movie_mouse_move (SwfdecActor *actor, double x, double y)
   if (!text->mouse_pressed)
     return;
 
-  direct = swfdec_text_field_movie_xy_to_index (text, x, y, &index_, &before);
-
-  if (!before && index_ < swfdec_text_buffer_get_length (text->text))
-    index_++;
+  swfdec_text_field_movie_xy_to_index (text, x, y, &index_);
 
   swfdec_text_buffer_set_cursor (text->text, swfdec_text_buffer_get_cursor (text->text), index_);
 }
@@ -601,7 +593,7 @@ swfdec_text_field_movie_mouse_release (SwfdecActor *actor, guint button)
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
   double x, y;
   guint index_;
-  gboolean direct, before;
+  gboolean direct;
 
   if (!text->selectable)
     return;
@@ -615,10 +607,10 @@ swfdec_text_field_movie_mouse_release (SwfdecActor *actor, guint button)
 
   text->mouse_pressed = FALSE;
 
-  direct = swfdec_text_field_movie_xy_to_index (text, x, y, &index_, &before);
+  direct = swfdec_text_field_movie_xy_to_index (text, x, y, &index_);
 
   if (text->character_pressed != 0) {
-    if (direct && text->character_pressed == index_ + 1 - (before ? 1 : 0)) {
+    if (direct && text->character_pressed == index_ + 1) {
       swfdec_text_field_movie_letter_clicked (text,
 	  text->character_pressed - 1);
     }
commit ddb2927cfe9a1cab012477689698e16cb44a5745
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 13:31:26 2008 +0200

    fix behavior of selectable xor editable movies.
    
    It seems selectable means "reacts to mouse events" and editable means
    "reacts to keyboard events". And then the Flash developers tried more or less
    successful to implement that.

diff --git a/swfdec/swfdec_player.c b/swfdec/swfdec_player.c
index 1031f08..27a8ee9 100644
--- a/swfdec/swfdec_player.c
+++ b/swfdec/swfdec_player.c
@@ -48,6 +48,7 @@
 #include "swfdec_resource.h"
 #include "swfdec_script_internal.h"
 #include "swfdec_sprite_movie.h"
+#include "swfdec_text_field_movie.h"
 #include "swfdec_utils.h"
 
 /*** gtk-doc ***/
@@ -1490,7 +1491,11 @@ swfdec_player_get_tab_movies (SwfdecPlayer *player, const GList *current)
       continue;
 
     swfdec_sandbox_use (SWFDEC_MOVIE (actor)->resource->sandbox);
-    if (SWFDEC_MOVIE (actor)->parent != NULL) {
+    if (SWFDEC_IS_TEXT_FIELD_MOVIE (actor)) {
+      SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
+      if (text->editable)
+	ret = g_list_prepend (ret, actor);
+    } else if (SWFDEC_MOVIE (actor)->parent != NULL) {
       swfdec_as_object_get_variable (SWFDEC_AS_OBJECT (actor), SWFDEC_AS_STR_tabEnabled, &val);
       if (swfdec_as_value_to_boolean (SWFDEC_AS_CONTEXT (player), &val)) {
 	swfdec_as_object_get_variable (SWFDEC_AS_OBJECT (actor), SWFDEC_AS_STR_tabEnabled, &val);
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 1b8cabf..5f97881 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -230,7 +230,8 @@ swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
 
   swfdec_text_field_movie_get_visible_area (text, &area);
   if (swfdec_text_field_movie_has_focus (text) &&
-      (text->selectable || text->editable)) {
+      (text->editable ||
+       (text->selectable && swfdec_text_buffer_has_selection (text->text)))) {
     if (text->background) {
       color = swfdec_color_apply_transform (text->background_color, ctrans);
       color = SWFDEC_COLOR_OPAQUE (color);
@@ -524,7 +525,7 @@ swfdec_text_field_movie_mouse_cursor (SwfdecActor *actor)
 
   if (attr != NULL && attr->url != SWFDEC_AS_STR_EMPTY) {
     return SWFDEC_MOUSE_CURSOR_CLICK;
-  } else if (text->editable || text->selectable) {
+  } else if (text->selectable) {
     return SWFDEC_MOUSE_CURSOR_TEXT;
   } else{
     return SWFDEC_MOUSE_CURSOR_NORMAL;
@@ -534,7 +535,9 @@ swfdec_text_field_movie_mouse_cursor (SwfdecActor *actor)
 static gboolean
 swfdec_text_field_movie_mouse_events (SwfdecActor *actor)
 {
-  return TRUE;
+  SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
+
+  return text->selectable;
 }
 
 static void
@@ -545,14 +548,14 @@ swfdec_text_field_movie_mouse_press (SwfdecActor *actor, guint button)
   guint index_;
   gboolean direct, before;
 
+  if (!text->selectable)
+    return;
+
   if (button != 0) {
     SWFDEC_FIXME ("implement popup menus, scrollwheel and middle mouse paste");
     return;
   }
 
-  if (!text->selectable)
-    return;
-
   swfdec_movie_get_mouse (SWFDEC_MOVIE (actor), &x, &y);
 
   direct = swfdec_text_field_movie_xy_to_index (text, x, y, &index_, &before);
@@ -600,6 +603,9 @@ swfdec_text_field_movie_mouse_release (SwfdecActor *actor, guint button)
   guint index_;
   gboolean direct, before;
 
+  if (!text->selectable)
+    return;
+
   if (button != 0) {
     SWFDEC_FIXME ("implement popup menus, scrollwheel and middle mouse paste");
     return;
commit 31ef4cabfc52cdc1710487b22e6bb8d6ba4e1d1d
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 12:17:13 2008 +0200

    improve comment

diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index b6616e1..d7d581b 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -853,8 +853,9 @@ swfdec_text_layout_modify_attributes (SwfdecTextLayout *layout,
   old = pango_layout_get_attributes (block->layout);
   pango_attr_list_ref (old);
   new = pango_attr_list_copy (old);
-  /* we create an iterator through the old list, which means we know it
-   * never gets modified. */
+  /* we create an iterator through the old list, so we know it
+   * never gets modified. As the new list is identical to the old one, it 
+   * achieves exactly what we want. */
   iter = pango_attr_list_get_iterator (old);
   do {
     guint cur_start, cur_end;
commit 6e1ae5ae9afd1579eff10b5732292d6745433b68
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 12:06:41 2008 +0200

    remove debugging prints

diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index b2fb9ea..b6616e1 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -942,7 +942,6 @@ swfdec_text_layout_render (SwfdecTextLayout *layout, cairo_t *cr,
     cursor_color = swfdec_color_apply_transform (cursor_color, ctrans);
     cursor_color = SWFDEC_COLOR_OPAQUE (cursor_color);
     cursor = swfdec_text_buffer_get_cursor (layout->text);
-    g_print ("drawing cursor at %u\n", cursor);
   }
   iter = swfdec_text_layout_find_row (layout, row); 
   block = g_sequence_get (iter);
@@ -971,7 +970,6 @@ swfdec_text_layout_render (SwfdecTextLayout *layout, cairo_t *cr,
       first_line = FALSE;
       cairo_translate (cr, xoffset, - extents.y);
       pango_cairo_show_layout_line (cr, line);
-      g_print ("  %d [%d %d]\n", cursor_index, line->start_index, line->length);
       if (line->start_index + line->length >= cursor_index &&
 	  line->start_index <= cursor_index &&
 	  (line->start_index + line->length != cursor_index || 
commit 5e1ea688be8c5a4b32247b5c1dc056dc0c667483
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 12:03:50 2008 +0200

    new testcase for setFocus handling in textfields

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 122f378..1373375 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -2850,6 +2850,15 @@ EXTRA_DIST = \
 	selection-properties-7.swf.trace \
 	selection-properties-8.swf \
 	selection-properties-8.swf.trace \
+	selection-setFocus-textfields-5.swf \
+	selection-setFocus-textfields-5.swf.trace \
+	selection-setFocus-textfields-6.swf \
+	selection-setFocus-textfields-6.swf.trace \
+	selection-setFocus-textfields-7.swf \
+	selection-setFocus-textfields-7.swf.trace \
+	selection-setFocus-textfields-8.swf \
+	selection-setFocus-textfields-8.swf.trace \
+	selection-setFocus-textfields.as \
 	set-overwrite-global-5.swf \
 	set-overwrite-global-6.swf \
 	set-overwrite-global-7.swf \
diff --git a/test/trace/selection-setFocus-textfields-5.swf b/test/trace/selection-setFocus-textfields-5.swf
new file mode 100644
index 0000000..b5acaa7
Binary files /dev/null and b/test/trace/selection-setFocus-textfields-5.swf differ
diff --git a/test/trace/selection-setFocus-textfields-5.swf.trace b/test/trace/selection-setFocus-textfields-5.swf.trace
new file mode 100644
index 0000000..fd5321e
--- /dev/null
+++ b/test/trace/selection-setFocus-textfields-5.swf.trace
@@ -0,0 +1,9 @@
+null (-1 - -1) @ -1
+null (-1 - -1) @ -1
+null (-1 - -1) @ -1
+null (-1 - -1) @ -1
+null (-1 - -1) @ -1
+null (-1 - -1) @ -1
+null (-1 - -1) @ -1
+null (-1 - -1) @ -1
+null (-1 - -1) @ -1
diff --git a/test/trace/selection-setFocus-textfields-6.swf b/test/trace/selection-setFocus-textfields-6.swf
new file mode 100644
index 0000000..e680291
Binary files /dev/null and b/test/trace/selection-setFocus-textfields-6.swf differ
diff --git a/test/trace/selection-setFocus-textfields-6.swf.trace b/test/trace/selection-setFocus-textfields-6.swf.trace
new file mode 100644
index 0000000..e8dfce3
--- /dev/null
+++ b/test/trace/selection-setFocus-textfields-6.swf.trace
@@ -0,0 +1,9 @@
+_level0.t0 (0 - 11) @ 11
+_level0.t1 (0 - 11) @ 11
+_level0.t2 (0 - 11) @ 11
+_level0.t3 (0 - 11) @ 11
+_level0.t4 (0 - 11) @ 11
+_level0.t5 (0 - 11) @ 11
+_level0.t5 (0 - 11) @ 11
+_level0.a (-1 - -1) @ -1
+null (-1 - -1) @ -1
diff --git a/test/trace/selection-setFocus-textfields-7.swf b/test/trace/selection-setFocus-textfields-7.swf
new file mode 100644
index 0000000..7bda62f
Binary files /dev/null and b/test/trace/selection-setFocus-textfields-7.swf differ
diff --git a/test/trace/selection-setFocus-textfields-7.swf.trace b/test/trace/selection-setFocus-textfields-7.swf.trace
new file mode 100644
index 0000000..e8dfce3
--- /dev/null
+++ b/test/trace/selection-setFocus-textfields-7.swf.trace
@@ -0,0 +1,9 @@
+_level0.t0 (0 - 11) @ 11
+_level0.t1 (0 - 11) @ 11
+_level0.t2 (0 - 11) @ 11
+_level0.t3 (0 - 11) @ 11
+_level0.t4 (0 - 11) @ 11
+_level0.t5 (0 - 11) @ 11
+_level0.t5 (0 - 11) @ 11
+_level0.a (-1 - -1) @ -1
+null (-1 - -1) @ -1
diff --git a/test/trace/selection-setFocus-textfields-8.swf b/test/trace/selection-setFocus-textfields-8.swf
new file mode 100644
index 0000000..12bb27c
Binary files /dev/null and b/test/trace/selection-setFocus-textfields-8.swf differ
diff --git a/test/trace/selection-setFocus-textfields-8.swf.trace b/test/trace/selection-setFocus-textfields-8.swf.trace
new file mode 100644
index 0000000..e8dfce3
--- /dev/null
+++ b/test/trace/selection-setFocus-textfields-8.swf.trace
@@ -0,0 +1,9 @@
+_level0.t0 (0 - 11) @ 11
+_level0.t1 (0 - 11) @ 11
+_level0.t2 (0 - 11) @ 11
+_level0.t3 (0 - 11) @ 11
+_level0.t4 (0 - 11) @ 11
+_level0.t5 (0 - 11) @ 11
+_level0.t5 (0 - 11) @ 11
+_level0.a (-1 - -1) @ -1
+null (-1 - -1) @ -1
diff --git a/test/trace/selection-setFocus-textfields.as b/test/trace/selection-setFocus-textfields.as
new file mode 100644
index 0000000..cbe7208
--- /dev/null
+++ b/test/trace/selection-setFocus-textfields.as
@@ -0,0 +1,45 @@
+// makeswf -v 7 -s 200x150 -r 1 -o selection-setFocus-textfields.swf selection-setFocus-textfields.as
+
+function create (depth, selectable, type) {
+  createTextField ("t" + depth, depth, 0, depth * 25, 100, 20);
+  var t = this["t" + depth];
+  var tf = new TextFormat ();
+  tf.font = "Bitstream Vera Sans";
+  tf.align = "right";
+  t.setNewTextFormat (tf);
+  t.border = true;
+  t.text = "Hello World";
+
+  t.selectable = selectable;
+  t.type = type;
+  if (arguments.length > 3)
+    t.focusEnabled = arguments[3];
+}
+
+create (0, false, "dynamic");
+create (1, true, "dynamic");
+create (2, false, "input");
+create (3, true, "input");
+create (4, true, "input", true);
+create (5, true, "input", false);
+
+function check (x) {
+  Selection.setFocus (x);
+  trace (Selection.getFocus () + " (" + Selection.getBeginIndex () + " - " + 
+    Selection.getEndIndex () + ") @ " + Selection.getCaretIndex ());
+}
+check (t0);
+check (t1);
+check (t2);
+check (t3);
+check (t4);
+check (t5);
+
+createEmptyMovieClip ("a", 100);
+check (a);
+a.onPress = function () { trace ("press"); };
+check (a);
+
+check (undefined);
+
+getURL ("fscommand:quit", "");
commit 4332a7511e36da8ca4e019899f03b68f04c7eb68
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 12:03:05 2008 +0200

    if focusEnabled isn't set on MovieClips, check if it handles events instead

diff --git a/swfdec/swfdec_selection.c b/swfdec/swfdec_selection.c
index a6427c2..4772b1a 100644
--- a/swfdec/swfdec_selection.c
+++ b/swfdec/swfdec_selection.c
@@ -119,7 +119,7 @@ swfdec_actor_can_grab_focus (SwfdecActor *actor)
       return FALSE;
     if (!swfdec_as_object_get_variable (SWFDEC_AS_OBJECT (actor),
 	SWFDEC_AS_STR_focusEnabled, &val))
-      return FALSE;
+      return swfdec_actor_get_mouse_events (actor);
     return swfdec_as_value_to_boolean (SWFDEC_AS_OBJECT (actor)->context, &val);
   } else if (SWFDEC_IS_TEXT_FIELD_MOVIE (actor)) {
     /* cool that you can select all textfields, eh? */
commit 6b67fab081b9a51721a0f408e20c59feacd55a99
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 11:49:13 2008 +0200

    render the cursor again

diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index 218766e..b2fb9ea 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -921,6 +921,9 @@ swfdec_text_layout_render (SwfdecTextLayout *layout, cairo_t *cr,
   SwfdecTextBlock *block;
   PangoRectangle extents;
   PangoAttrList *attr;
+  SwfdecColor cursor_color;
+  gsize cursor;
+  int cursor_index; /* Pango neds proper types... */
   gboolean first_line = TRUE;
 
   g_return_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout));
@@ -930,11 +933,23 @@ swfdec_text_layout_render (SwfdecTextLayout *layout, cairo_t *cr,
   
   swfdec_text_layout_ensure (layout);
 
+  if (!focus || swfdec_text_buffer_has_selection (layout->text)) {
+    cursor_color = 0;
+    cursor = G_MAXSIZE;
+  } else {
+    cursor_color = swfdec_text_buffer_get_attributes (layout->text,
+	swfdec_text_buffer_get_length (layout->text))->color;
+    cursor_color = swfdec_color_apply_transform (cursor_color, ctrans);
+    cursor_color = SWFDEC_COLOR_OPAQUE (cursor_color);
+    cursor = swfdec_text_buffer_get_cursor (layout->text);
+    g_print ("drawing cursor at %u\n", cursor);
+  }
   iter = swfdec_text_layout_find_row (layout, row); 
   block = g_sequence_get (iter);
   row -= block->row;
   do {
     block = g_sequence_get (iter);
+    cursor_index = cursor - block->start;
     pango_cairo_update_layout (cr, block->layout);
     cairo_translate (cr, block->rect.x, 0);
     if (block->bullet && row == 0) {
@@ -956,6 +971,21 @@ swfdec_text_layout_render (SwfdecTextLayout *layout, cairo_t *cr,
       first_line = FALSE;
       cairo_translate (cr, xoffset, - extents.y);
       pango_cairo_show_layout_line (cr, line);
+      g_print ("  %d [%d %d]\n", cursor_index, line->start_index, line->length);
+      if (line->start_index + line->length >= cursor_index &&
+	  line->start_index <= cursor_index &&
+	  (line->start_index + line->length != cursor_index || 
+	   (gsize) line->start_index + line->length == block->end - block->start)) {
+	int x_index;
+	/* FIXME: implement (trailing for) RTL */
+	pango_layout_line_index_to_x (line, cursor_index, FALSE, &x_index);
+	x_index = PANGO_PIXELS (x_index);
+	swfdec_color_set_source (cr, cursor_color);
+	cairo_set_line_width (cr, 1.0);
+	cairo_move_to (cr, x_index + 0.5, extents.y);
+	cairo_rel_line_to (cr, 0, extents.height);
+	cairo_stroke (cr);
+      }
       height -= extents.height;
       cairo_translate (cr, - xoffset, extents.height + extents.y);
     }
commit 40dd0c7aeb6220c948d4665b3122a278746e591f
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 10:32:50 2008 +0200

    implement coloring of the selected area

diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index de00ec6..1b8cabf 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -186,7 +186,6 @@ swfdec_text_field_movie_invalidate (SwfdecMovie *movie, const cairo_matrix_t *ma
       SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), &rect);
 }
 
-#if 0
 static gboolean
 swfdec_text_field_movie_has_focus (SwfdecTextFieldMovie *text)
 {
@@ -194,7 +193,6 @@ swfdec_text_field_movie_has_focus (SwfdecTextFieldMovie *text)
 
   return swfdec_player_has_focus (player, SWFDEC_ACTOR (text));
 }
-#endif
 
 static void
 swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
@@ -231,13 +229,24 @@ swfdec_text_field_movie_render (SwfdecMovie *movie, cairo_t *cr,
   }
 
   swfdec_text_field_movie_get_visible_area (text, &area);
+  if (swfdec_text_field_movie_has_focus (text) &&
+      (text->selectable || text->editable)) {
+    if (text->background) {
+      color = swfdec_color_apply_transform (text->background_color, ctrans);
+      color = SWFDEC_COLOR_OPAQUE (color);
+    } else {
+      color = SWFDEC_COLOR_WHITE;
+    }
+  } else {
+    color = 0;
+  }
 
   /* render the layout */
   cairo_rectangle (cr, area.x, area.y, area.width, area.height);
   cairo_clip (cr);
   cairo_translate (cr, (double) area.x - text->hscroll, area.y);
   swfdec_text_layout_render (text->layout, cr, ctrans,
-      text->scroll, area.height);
+      text->scroll, area.height, color);
 }
 
 static void
@@ -617,7 +626,9 @@ swfdec_text_field_movie_focus_in (SwfdecActor *actor)
 {
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
   
-  if (text->editable)
+  swfdec_text_buffer_set_cursor (text->text, 0,
+      swfdec_text_buffer_get_length (text->text));
+  if (text->editable || text->selectable)
     swfdec_movie_invalidate_last (SWFDEC_MOVIE (actor));
 }
 
@@ -626,7 +637,7 @@ swfdec_text_field_movie_focus_out (SwfdecActor *actor)
 {
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
   
-  if (text->editable)
+  if (text->editable || text->selectable)
     swfdec_movie_invalidate_last (SWFDEC_MOVIE (actor));
 }
 
diff --git a/swfdec/swfdec_text_layout.c b/swfdec/swfdec_text_layout.c
index 505d41c..218766e 100644
--- a/swfdec/swfdec_text_layout.c
+++ b/swfdec/swfdec_text_layout.c
@@ -386,6 +386,7 @@ swfdec_text_layout_create_paragraph (SwfdecTextLayout *layout, PangoContext *con
       /* check that we have found a line */
       g_assert (i < pango_layout_get_line_count (block->layout));
     }
+    block->end = new_block;
 
     start = new_block;
     pango_layout_get_pixel_size (block->layout, &block->rect.width, &block->rect.height);
@@ -410,7 +411,6 @@ swfdec_text_layout_create (SwfdecTextLayout *layout)
   context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (map));
 
   p = string = swfdec_text_buffer_get_text (layout->text);
-  //g_print ("=====>\n %s\n<======\n", string);
   for (;;) {
     end = strpbrk (p, "\r\n");
     if (end == NULL) {
@@ -823,6 +823,84 @@ swfdec_text_layout_get_line_offset (SwfdecTextLayout *layout,
   return diff;
 }
 
+static PangoAttrList *
+swfdec_text_layout_modify_attributes (SwfdecTextLayout *layout, 
+    SwfdecTextBlock *block, const SwfdecColorTransform *ctrans, SwfdecColor focus)
+{
+  gsize sel_start, sel_end;
+  PangoAttrList *old, *new;
+  PangoAttrIterator *iter;
+
+  if (swfdec_color_transform_is_identity (ctrans)) {
+    /* if we're not focused, there's no need to draw a selection */
+    if (!focus)
+      return NULL;
+    swfdec_text_buffer_get_selection (layout->text, &sel_start, &sel_end);
+    /* no selection, we draw a cursor instead */
+    if (sel_start == sel_end)
+      return NULL;
+    /* selection outside of block's range */
+    if (sel_start >= block->end || sel_end <= block->start)
+      return NULL;
+  } else {
+    if (focus) {
+      swfdec_text_buffer_get_selection (layout->text, &sel_start, &sel_end);
+    } else {
+      sel_start = sel_end = 0;
+    }
+  }
+
+  old = pango_layout_get_attributes (block->layout);
+  pango_attr_list_ref (old);
+  new = pango_attr_list_copy (old);
+  /* we create an iterator through the old list, which means we know it
+   * never gets modified. */
+  iter = pango_attr_list_get_iterator (old);
+  do {
+    guint cur_start, cur_end;
+    PangoAttrColor *color_attr;
+    SwfdecColor color;
+    pango_attr_iterator_range (iter, (int *) &cur_start, (int *) &cur_end);
+    if (cur_end == G_MAXINT)
+      break;
+    color_attr = (PangoAttrColor *) pango_attr_iterator_get (iter, PANGO_ATTR_FOREGROUND);
+    /* must hold as we explicitly set color attributes when creating 
+     * the list initially */
+    g_assert (color_attr);
+    color = SWFDEC_COLOR_COMBINE (color_attr->color.red >> 8, 
+	color_attr->color.green >> 8, color_attr->color.blue >> 8, 0xFF);
+    color = swfdec_color_apply_transform (color, ctrans);
+    /* We differentiate three ranges: before selection, in selection and after selection */
+    if (cur_start < sel_start) {
+      PangoAttribute *fg = pango_attr_foreground_new (SWFDEC_COLOR_R (color) * 0x101,
+	  SWFDEC_COLOR_G (color) * 0x101, SWFDEC_COLOR_B (color) * 0x101);
+      fg->start_index = cur_start;
+      fg->end_index = MIN (cur_end, sel_start);
+      pango_attr_list_change (new, fg);
+    }
+    if (sel_start < cur_end && sel_end > cur_start) {
+      PangoAttribute *fg = pango_attr_foreground_new (SWFDEC_COLOR_R (focus) * 0x101,
+	  SWFDEC_COLOR_G (focus) * 0x101, SWFDEC_COLOR_B (focus) * 0x101);
+      PangoAttribute *bg = pango_attr_background_new (SWFDEC_COLOR_R (color) * 0x101,
+	  SWFDEC_COLOR_G (color) * 0x101, SWFDEC_COLOR_B (color) * 0x101);
+      fg->start_index = bg->start_index = MAX (cur_start, sel_start);
+      fg->end_index = bg->end_index = MIN (cur_end, sel_end);
+      pango_attr_list_change (new, fg);
+      pango_attr_list_change (new, bg);
+    }
+    if (cur_end > sel_end) {
+      PangoAttribute *fg = pango_attr_foreground_new (SWFDEC_COLOR_R (color) * 0x101,
+	  SWFDEC_COLOR_G (color) * 0x101, SWFDEC_COLOR_B (color) * 0x101);
+      fg->start_index = MAX (sel_end, cur_start);
+      fg->end_index = cur_end;
+      pango_attr_list_change (new, fg);
+    }
+  } while (pango_attr_iterator_next (iter));
+  pango_layout_set_attributes (block->layout, new);
+  pango_attr_list_unref (new);
+  return old;
+}
+
 /**
  * swfdec_text_layout_render:
  * @layout: the layout to render
@@ -831,16 +909,18 @@ swfdec_text_layout_get_line_offset (SwfdecTextLayout *layout,
  * @ctrans: The color transform to apply.
  * @row: index of the first row to render.
  * @height: The height in pixels of the visible area.
+ * @focus: color to invert the selection with, 0 if no focus
  *
  * Renders the contents of the layout into the given Cairo context.
  **/
 void
 swfdec_text_layout_render (SwfdecTextLayout *layout, cairo_t *cr, 
-    const SwfdecColorTransform *ctrans, guint row, guint height)
+    const SwfdecColorTransform *ctrans, guint row, guint height, SwfdecColor focus)
 {
   GSequenceIter *iter;
   SwfdecTextBlock *block;
   PangoRectangle extents;
+  PangoAttrList *attr;
   gboolean first_line = TRUE;
 
   g_return_if_fail (SWFDEC_IS_TEXT_LAYOUT (layout));
@@ -860,19 +940,29 @@ swfdec_text_layout_render (SwfdecTextLayout *layout, cairo_t *cr,
     if (block->bullet && row == 0) {
       SWFDEC_FIXME ("render bullet");
     }
+    attr = swfdec_text_layout_modify_attributes (layout, block, ctrans, focus);
     for (;row < (guint) pango_layout_get_line_count (block->layout); row++) {
       PangoLayoutLine *line = pango_layout_get_line_readonly (block->layout, row);
       int xoffset = swfdec_text_layout_get_line_offset (layout, block, line);
       
       pango_layout_line_get_pixel_extents (line, NULL, &extents);
-      if (extents.height > (int) height && !first_line)
+      if (extents.height > (int) height && !first_line) {
+	if (attr) {
+	  pango_layout_set_attributes (block->layout, attr);
+	  pango_attr_list_unref (attr);
+	}
 	return;
+      }
       first_line = FALSE;
       cairo_translate (cr, xoffset, - extents.y);
       pango_cairo_show_layout_line (cr, line);
       height -= extents.height;
       cairo_translate (cr, - xoffset, extents.height + extents.y);
     }
+    if (attr) {
+      pango_layout_set_attributes (block->layout, attr);
+      pango_attr_list_unref (attr);
+    }
     if ((int) height <= pango_layout_get_spacing (block->layout) / PANGO_SCALE)
       return;
     height -= pango_layout_get_spacing (block->layout) / PANGO_SCALE;
diff --git a/swfdec/swfdec_text_layout.h b/swfdec/swfdec_text_layout.h
index dccd79c..7695c13 100644
--- a/swfdec/swfdec_text_layout.h
+++ b/swfdec/swfdec_text_layout.h
@@ -90,7 +90,8 @@ void			swfdec_text_layout_render		(SwfdecTextLayout *	layout,
 								 cairo_t *		cr, 
 								 const SwfdecColorTransform *ctrans,
 								 guint			row,
-								 guint			height);
+								 guint			height,
+								 SwfdecColor		focus);
 
 
 G_END_DECLS
commit 79e22067b26eaac50ad2284fe796e60bcc232fa4
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 10:30:49 2008 +0200

    implement Selection.get*Index()

diff --git a/swfdec/swfdec_selection.c b/swfdec/swfdec_selection.c
index 1f9dee9..a6427c2 100644
--- a/swfdec/swfdec_selection.c
+++ b/swfdec/swfdec_selection.c
@@ -31,13 +31,26 @@
 #include "swfdec_button_movie.h"
 #include "swfdec_sprite_movie.h"
 #include "swfdec_text_field_movie.h"
+#include "swfdec_text_buffer.h"
 
 SWFDEC_AS_NATIVE (600, 0, swfdec_selection_getBeginIndex)
 void
 swfdec_selection_getBeginIndex (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SWFDEC_STUB ("Selection.getBeginIndex (static)");
+  SwfdecPlayerPrivate *priv = SWFDEC_PLAYER (cx)->priv;
+  SwfdecTextFieldMovie *text;
+  gsize start, end;
+  const char *s;
+
+  if (!SWFDEC_IS_TEXT_FIELD_MOVIE (priv->focus)) {
+    SWFDEC_AS_VALUE_SET_INT (ret, -1);
+    return;
+  }
+  text = SWFDEC_TEXT_FIELD_MOVIE (priv->focus);
+  swfdec_text_buffer_get_selection (text->text, &start, &end);
+  s = swfdec_text_buffer_get_text (text->text);
+  SWFDEC_AS_VALUE_SET_INT (ret, g_utf8_pointer_to_offset (s, s + start));
 }
 
 SWFDEC_AS_NATIVE (600, 1, swfdec_selection_getEndIndex)
@@ -45,7 +58,19 @@ void
 swfdec_selection_getEndIndex (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SWFDEC_STUB ("Selection.getEndIndex (static)");
+  SwfdecPlayerPrivate *priv = SWFDEC_PLAYER (cx)->priv;
+  SwfdecTextFieldMovie *text;
+  gsize start, end;
+  const char *s;
+
+  if (!SWFDEC_IS_TEXT_FIELD_MOVIE (priv->focus)) {
+    SWFDEC_AS_VALUE_SET_INT (ret, -1);
+    return;
+  }
+  text = SWFDEC_TEXT_FIELD_MOVIE (priv->focus);
+  swfdec_text_buffer_get_selection (text->text, &start, &end);
+  s = swfdec_text_buffer_get_text (text->text);
+  SWFDEC_AS_VALUE_SET_INT (ret, g_utf8_pointer_to_offset (s, s + end));
 }
 
 SWFDEC_AS_NATIVE (600, 2, swfdec_selection_getCaretIndex)
@@ -53,7 +78,18 @@ void
 swfdec_selection_getCaretIndex (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SWFDEC_STUB ("Selection.getCaretIndex (static)");
+  SwfdecPlayerPrivate *priv = SWFDEC_PLAYER (cx)->priv;
+  SwfdecTextFieldMovie *text;
+  const char *s;
+
+  if (!SWFDEC_IS_TEXT_FIELD_MOVIE (priv->focus)) {
+    SWFDEC_AS_VALUE_SET_INT (ret, -1);
+    return;
+  }
+  text = SWFDEC_TEXT_FIELD_MOVIE (priv->focus);
+  s = swfdec_text_buffer_get_text (text->text);
+  SWFDEC_AS_VALUE_SET_INT (ret, g_utf8_pointer_to_offset (s, 
+	s + swfdec_text_buffer_get_cursor (text->text)));
 }
 
 SWFDEC_AS_NATIVE (600, 3, swfdec_selection_getFocus)
commit 5cd10a4472d0f7f8ca50444b6b85f1d8bcd42b7f
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun May 18 10:29:11 2008 +0200

    The end of the selection is the current cursor

diff --git a/swfdec/swfdec_text_buffer.c b/swfdec/swfdec_text_buffer.c
index afd0af7..536b446 100644
--- a/swfdec/swfdec_text_buffer.c
+++ b/swfdec/swfdec_text_buffer.c
@@ -422,7 +422,7 @@ swfdec_text_buffer_get_cursor (SwfdecTextBuffer *buffer)
 {
   g_return_val_if_fail (SWFDEC_IS_TEXT_BUFFER (buffer), 0);
 
-  return buffer->cursor_start;
+  return buffer->cursor_end;
 }
 
 gboolean
commit 75e4c10301c516e9084eafa3b73cb916881ea5eb
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu May 15 18:19:21 2008 +0200

    fix Selection.setFocus() for textfields
    
    And of course, I had to make it nicer while at it...

diff --git a/swfdec/swfdec_selection.c b/swfdec/swfdec_selection.c
index 8eabe2e..1f9dee9 100644
--- a/swfdec/swfdec_selection.c
+++ b/swfdec/swfdec_selection.c
@@ -28,6 +28,9 @@
 #include "swfdec_movie.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_sandbox.h"
+#include "swfdec_button_movie.h"
+#include "swfdec_sprite_movie.h"
+#include "swfdec_text_field_movie.h"
 
 SWFDEC_AS_NATIVE (600, 0, swfdec_selection_getBeginIndex)
 void
@@ -68,25 +71,44 @@ swfdec_selection_getFocus (SwfdecAsContext *cx, SwfdecAsObject *object,
   }
 }
 
+static gboolean
+swfdec_actor_can_grab_focus (SwfdecActor *actor)
+{
+  SwfdecAsValue val;
+
+  /* Functions like this just make me love Flash */
+  if (SWFDEC_IS_SPRITE_MOVIE (actor) ||
+      SWFDEC_IS_BUTTON_MOVIE (actor)) {
+    if (SWFDEC_MOVIE (actor)->parent == NULL)
+      return FALSE;
+    if (!swfdec_as_object_get_variable (SWFDEC_AS_OBJECT (actor),
+	SWFDEC_AS_STR_focusEnabled, &val))
+      return FALSE;
+    return swfdec_as_value_to_boolean (SWFDEC_AS_OBJECT (actor)->context, &val);
+  } else if (SWFDEC_IS_TEXT_FIELD_MOVIE (actor)) {
+    /* cool that you can select all textfields, eh? */
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
 SWFDEC_AS_NATIVE (600, 4, swfdec_selection_setFocus)
 void
 swfdec_selection_setFocus (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SwfdecAsValue val;
   SwfdecActor *actor;
   SwfdecSandbox *sandbox;
 
   SWFDEC_AS_VALUE_SET_BOOLEAN (ret, FALSE);
   SWFDEC_AS_CHECK (0, NULL, "O", &actor);
 
-  if (actor != NULL &&
-      (!SWFDEC_IS_MOVIE (actor) ||
-       SWFDEC_MOVIE (actor)->parent == NULL ||
-       !swfdec_as_object_get_variable (SWFDEC_AS_OBJECT (actor),
-	  SWFDEC_AS_STR_focusEnabled, &val) ||
-       swfdec_as_value_to_boolean (SWFDEC_AS_OBJECT (actor)->context, &val) == FALSE))
-    return;
+  if (actor != NULL) {
+    if (!SWFDEC_IS_ACTOR (actor) ||
+	!swfdec_actor_can_grab_focus (actor))
+      return;
+  }
 
   /* FIXME: how is security handled here? */
   sandbox = SWFDEC_SANDBOX (cx->global);
commit 3eef13f5b570b3f32e2cdeebc5f808c02f2898a1
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed May 14 23:01:54 2008 +0200

    also queue an update when setting autoSize to a boolean value

diff --git a/swfdec/swfdec_text_field_movie_as.c b/swfdec/swfdec_text_field_movie_as.c
index 3bab7e7..0f33e92 100644
--- a/swfdec/swfdec_text_field_movie_as.c
+++ b/swfdec/swfdec_text_field_movie_as.c
@@ -749,21 +749,20 @@ swfdec_text_field_movie_set_autoSize (SwfdecAsContext *cx,
     } else {
       text->auto_size = SWFDEC_AUTO_SIZE_NONE;
     }
-    return;
-  }
+  } else {
+    swfdec_as_value_to_number (cx, &argv[0]);
+    s = swfdec_as_value_to_string (cx, &argv[0]);
 
-  swfdec_as_value_to_number (cx, &argv[0]);
-  s = swfdec_as_value_to_string (cx, &argv[0]);
-
-  old = text->auto_size;
-  if (!g_ascii_strcasecmp (s, "none")) {
-    text->auto_size = SWFDEC_AUTO_SIZE_NONE;
-  } else if (!g_ascii_strcasecmp (s, "left")) {
-    text->auto_size = SWFDEC_AUTO_SIZE_LEFT;
-  } else if (!g_ascii_strcasecmp (s, "right")) {
-    text->auto_size = SWFDEC_AUTO_SIZE_RIGHT;
-  } else if (!g_ascii_strcasecmp (s, "center")) {
-    text->auto_size = SWFDEC_AUTO_SIZE_CENTER;
+    old = text->auto_size;
+    if (!g_ascii_strcasecmp (s, "none")) {
+      text->auto_size = SWFDEC_AUTO_SIZE_NONE;
+    } else if (!g_ascii_strcasecmp (s, "left")) {
+      text->auto_size = SWFDEC_AUTO_SIZE_LEFT;
+    } else if (!g_ascii_strcasecmp (s, "right")) {
+      text->auto_size = SWFDEC_AUTO_SIZE_RIGHT;
+    } else if (!g_ascii_strcasecmp (s, "center")) {
+      text->auto_size = SWFDEC_AUTO_SIZE_CENTER;
+    }
   }
 
   if (text->auto_size != old) {
commit 523f782df97b3abd0cf13ff331be6669a560ce47
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed May 14 21:58:18 2008 +0200

    x0 must be moved negative coordinates when auto-sizing
    
    Fixes weird size increases/decreases on center/right autoSize mode

diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index a738a3a..de00ec6 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -118,11 +118,12 @@ swfdec_text_field_movie_auto_size (SwfdecTextFieldMovie *text)
       x0 = 0;
       break;
     case SWFDEC_AUTO_SIZE_RIGHT:
-      x0 = x1;
+      x0 = -x1;
       x1 = 0;
       break;
     case SWFDEC_AUTO_SIZE_CENTER:
-      x0 = x1 = x1 / 2;
+      x1 = x1 / 2;
+      x0 = -x1;
       break;
     case SWFDEC_AUTO_SIZE_NONE:
     default:
commit 9bb247eee69fcaa7d34981e564c4a4f646b5d12b
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed May 14 21:53:44 2008 +0200

    save/restore only the vfunc call, not the whole render() function
    
    This ensures clip regions etc set up by the render vfunc get properly removed
    for mask() etc call - fixes test/image/mask-textfield test

diff --git a/swfdec/swfdec_movie.c b/swfdec/swfdec_movie.c
index fafbd04..19c43fe 100644
--- a/swfdec/swfdec_movie.c
+++ b/swfdec/swfdec_movie.c
@@ -789,7 +789,6 @@ swfdec_movie_render (SwfdecMovie *movie, cairo_t *cr,
     return;
   }
 
-  cairo_save (cr);
   if (movie->masked_by != NULL) {
     cairo_push_group (cr);
   }
@@ -798,6 +797,7 @@ swfdec_movie_render (SwfdecMovie *movie, cairo_t *cr,
     SWFDEC_DEBUG ("pushing group for blend mode %u", movie->blend_mode);
     cairo_push_group (cr);
   }
+  cairo_save (cr);
 
   SWFDEC_LOG ("transforming movie, transform: %g %g  %g %g   %g %g",
       movie->matrix.xx, movie->matrix.yy,
@@ -830,6 +830,7 @@ swfdec_movie_render (SwfdecMovie *movie, cairo_t *cr,
   if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
     g_warning ("error rendering with cairo: %s", cairo_status_to_string (cairo_status (cr)));
   }
+  cairo_restore (cr);
   if (group) {
     cairo_pattern_t *pattern;
 
@@ -864,7 +865,6 @@ swfdec_movie_render (SwfdecMovie *movie, cairo_t *cr,
     cairo_mask (cr, mask);
     cairo_pattern_destroy (mask);
   }
-  cairo_restore (cr);
 }
 
 static void
commit 488bf1b0b020ec3e2687502363c8c64936731f66
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed May 14 21:43:31 2008 +0200

    make background colors work again
    
    Why does noone notice this is broken? I guess we need a buildbot :o

diff --git a/test/swfdec_test_plugin.c b/test/swfdec_test_plugin.c
index 5bf5794..9ee07e5 100644
--- a/test/swfdec_test_plugin.c
+++ b/test/swfdec_test_plugin.c
@@ -47,12 +47,16 @@ swfdec_test_plugin_swfdec_screenshot (SwfdecTestPlugin *plugin, unsigned char *d
 {
   cairo_surface_t *surface;
   cairo_t *cr;
+  guint background;
 
   surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32, 
       width, height, width * 4);
   cr = cairo_create (surface);
-  /* use a white background */
-  cairo_set_source_rgb (cr, 1, 1, 1);
+  background  = swfdec_player_get_background_color (plugin->data);
+  cairo_set_source_rgb (cr, 
+      ((background >> 16) & 0xFF) / 255.0,
+      ((background >> 8) & 0xFF) / 255.0,
+      (background & 0xFF) / 255.0);
   cairo_paint (cr);
 
   cairo_translate (cr, -x, -y);
commit 6ed6a7f6e93f25275f98b6af99c1f2fbb59594e9
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed May 14 20:27:52 2008 +0200

    don't return non-scriptable objects from swfdec_movie_get_by_name()
    
    fixes a testsuite failure

diff --git a/swfdec/swfdec_movie.c b/swfdec/swfdec_movie.c
index e4d1ed4..fafbd04 100644
--- a/swfdec/swfdec_movie.c
+++ b/swfdec/swfdec_movie.c
@@ -953,6 +953,10 @@ swfdec_movie_mark (SwfdecAsObject *object)
   SWFDEC_AS_OBJECT_CLASS (swfdec_movie_parent_class)->mark (object);
 }
 
+#define swfdec_movie_is_scriptable(mov) \
+  ((SWFDEC_IS_ACTOR (mov) || SWFDEC_IS_VIDEO_MOVIE (mov)) && \
+   (swfdec_movie_get_version (mov) > 5 || !SWFDEC_IS_TEXT_FIELD_MOVIE (mov)))
+
 /* FIXME: This function can definitely be implemented easier */
 SwfdecMovie *
 swfdec_movie_get_by_name (SwfdecMovie *movie, const char *name, gboolean unnamed)
@@ -985,8 +989,12 @@ swfdec_movie_get_by_name (SwfdecMovie *movie, const char *name, gboolean unnamed
     SwfdecMovie *cur = walk->data;
     if (cur->original_name == SWFDEC_AS_STR_EMPTY && !unnamed)
       continue;
-    if (swfdec_strcmp (version, cur->name, name) == 0)
-      return cur;
+    if (swfdec_strcmp (version, cur->name, name) == 0) {
+      if (swfdec_movie_is_scriptable (cur))
+	return cur;
+      else
+	return movie;
+    }
   }
   return NULL;
 }
@@ -1040,9 +1048,6 @@ swfdec_movie_get_variable (SwfdecAsObject *object, SwfdecAsObject *orig,
   
   ret = swfdec_movie_get_by_name (movie, variable, FALSE);
   if (ret) {
-    if ((!SWFDEC_IS_ACTOR (ret) && !SWFDEC_IS_VIDEO_MOVIE (ret)) ||
-	(swfdec_movie_get_version (movie) <= 5 && SWFDEC_IS_TEXT_FIELD_MOVIE (ret)))
-      ret = movie;
     SWFDEC_AS_VALUE_SET_OBJECT (val, SWFDEC_AS_OBJECT (ret));
     *flags = 0;
     return TRUE;


More information about the Swfdec-commits mailing list