<commit_before>/* gtkextendedlayout.c
 * Copyright (C) 2007 Openismus GmbH
 *
 * Author:
 *      <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */


#include <config.h>
#include "gtkextendedlayout.h"
#include "gtksizegroup.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkalias.h"

/* With extended layout, a widget may be requested
 * its width for 2 or maximum 3 heights in one resize
 */
#define N_CACHED_SIZES 3

typedef struct 
{
  guint  age;
  gint   for_size;
  gint   minimum_size;
  gint   natural_size;
} DesiredSize;

typedef struct {
  DesiredSize desired_widths[N_CACHED_SIZES];
  DesiredSize desired_heights[N_CACHED_SIZES];
  guint cached_width_age;
  guint cached_height_age;
} ExtendedLayoutCache;

static GQuark quark_cache = 0;


GType
gtk_extended_layout_get_type (void)
{
  static GType extended_layout_type = 0;

  if (G_UNLIKELY(!extended_layout_type))
    {
      extended_layout_type =
	g_type_register_static_simple (G_TYPE_INTERFACE, I_("GtkExtendedLayout"),
				       sizeof (GtkExtendedLayoutIface),
				       NULL, 0, NULL, 0);

      g_type_interface_add_prerequisite (extended_layout_type, GTK_TYPE_WIDGET);

      quark_cache = g_quark_from_static_string ("gtk-extended-layout-cache");
    }

  return extended_layout_type;
}

/* looks for a cached size request for this for_size. If not
 * found, returns the oldest entry so it can be overwritten */
static gboolean
get_cached_desired_size (gfloat         for_size,
			 DesiredSize   *cached_sizes,
			 DesiredSize  **result)
{
  guint i;

  *result = &cached_sizes[0];

  for (i = 0; i < N_CACHED_SIZES; i++)
    {
      DesiredSize *cs;

      cs = &cached_sizes[i];

      if (cs->age > 0 &&
          cs->for_size == for_size)
        {
          *result = cs;
          return TRUE;
        }
      else if (cs->age < (*result)->age)
        {
          *result = cs;
        }
    }

  return FALSE;
}

static void 
destroy_cache (ExtendedLayoutCache *cache)
{
  g_slice_free (ExtendedLayoutCache, cache);
}

ExtendedLayoutCache *
get_cache (GtkExtendedLayout *layout, gboolean create)
{
  ExtendedLayoutCache *cache;
  
  cache = g_object_get_qdata (G_OBJECT (layout), quark_cache);
  if (!cache && create)
    {
      cache = g_slice_new0 (ExtendedLayoutCache);

      cache->cached_width_age  = 1;
      cache->cached_height_age = 1;

      g_object_set_qdata_full (G_OBJECT (layout), quark_cache, cache, 
			       (GDestroyNotify)destroy_cache);
    }
  
  return cache;
}


static void
do_size_request (GtkWidget *widget)
{
  if (GTK_WIDGET_REQUEST_NEEDED (widget))
    {
      gtk_widget_ensure_style (widget);      
      GTK_PRIVATE_UNSET_FLAG (widget, GTK_REQUEST_NEEDED);
      g_signal_emit_by_name (widget,
			     "size-request",
			     &widget->requisition);
    }
}

static void
compute_size_for_orientation (GtkExtendedLayout *layout,
			      GtkSizeGroupMode   orientation,
			      gint               for_size,
			      gint              *minimum_size,
			      gint              *natural_size)
{
  ExtendedLayoutCache *cache;
  DesiredSize         *cached_size;
  GtkWidget           *widget;
  gboolean             found_in_cache = FALSE;

  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
  g_return_if_fail (minimum_size != NULL || natural_size != NULL);

  widget = GTK_WIDGET (layout);
  cache  = get_cache (layout, TRUE);

  if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
    {
      cached_size = &cache->desired_widths[0];
      
      if (GTK_WIDGET_WIDTH_REQUEST_NEEDED (layout) == FALSE)
	found_in_cache = get_cached_desired_size (for_size, cache->desired_widths, &cached_size);
      else
	memset (cache->desired_widths, 0x0, N_CACHED_SIZES * sizeof (DesiredSize));
    }
  else
    {
      cached_size = &cache->desired_heights[0];
      
      if (GTK_WIDGET_WIDTH_REQUEST_NEEDED (layout) == FALSE)<commit_msg>Fixed another caching bug in extended layout<commit_after>/* gtkextendedlayout.c
 * Copyright (C) 2007 Openismus GmbH
 *
 * Author:
 *      <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */


#include <config.h>
#include "gtkextendedlayout.h"
#include "gtksizegroup.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkalias.h"

/* With extended layout, a widget may be requested
 * its width for 2 or maximum 3 heights in one resize
 */
#define N_CACHED_SIZES 3

typedef struct 
{
  guint  age;
  gint   for_size;
  gint   minimum_size;
  gint   natural_size;
} DesiredSize;

typedef struct {
  DesiredSize desired_widths[N_CACHED_SIZES];
  DesiredSize desired_heights[N_CACHED_SIZES];
  guint cached_width_age;
  guint cached_height_age;
} ExtendedLayoutCache;

static GQuark quark_cache = 0;


GType
gtk_extended_layout_get_type (void)
{
  static GType extended_layout_type = 0;

  if (G_UNLIKELY(!extended_layout_type))
    {
      extended_layout_type =
	g_type_register_static_simple (G_TYPE_INTERFACE, I_("GtkExtendedLayout"),
				       sizeof (GtkExtendedLayoutIface),
				       NULL, 0, NULL, 0);

      g_type_interface_add_prerequisite (extended_layout_type, GTK_TYPE_WIDGET);

      quark_cache = g_quark_from_static_string ("gtk-extended-layout-cache");
    }

  return extended_layout_type;
}

/* looks for a cached size request for this for_size. If not
 * found, returns the oldest entry so it can be overwritten */
static gboolean
get_cached_desired_size (gfloat         for_size,
			 DesiredSize   *cached_sizes,
			 DesiredSize  **result)
{
  guint i;

  *result = &cached_sizes[0];

  for (i = 0; i < N_CACHED_SIZES; i++)
    {
      DesiredSize *cs;

      cs = &cached_sizes[i];

      if (cs->age > 0 &&
          cs->for_size == for_size)
        {
          *result = cs;
          return TRUE;
        }
      else if (cs->age < (*result)->age)
        {
          *result = cs;
        }
    }

  return FALSE;
}

static void 
destroy_cache (ExtendedLayoutCache *cache)
{
  g_slice_free (ExtendedLayoutCache, cache);
}

ExtendedLayoutCache *
get_cache (GtkExtendedLayout *layout, gboolean create)
{
  ExtendedLayoutCache *cache;
  
  cache = g_object_get_qdata (G_OBJECT (layout), quark_cache);
  if (!cache && create)
    {
      cache = g_slice_new0 (ExtendedLayoutCache);

      cache->cached_width_age  = 1;
      cache->cached_height_age = 1;

      g_object_set_qdata_full (G_OBJECT (layout), quark_cache, cache, 
			       (GDestroyNotify)destroy_cache);
    }
  
  return cache;
}


static void
do_size_request (GtkWidget *widget)
{
  if (GTK_WIDGET_REQUEST_NEEDED (widget))
    {
      gtk_widget_ensure_style (widget);      
      GTK_PRIVATE_UNSET_FLAG (widget, GTK_REQUEST_NEEDED);
      g_signal_emit_by_name (widget,
			     "size-request",
			     &widget->requisition);
    }
}

static void
compute_size_for_orientation (GtkExtendedLayout *layout,
			      GtkSizeGroupMode   orientation,
			      gint               for_size,
			      gint              *minimum_size,
			      gint              *natural_size)
{
  ExtendedLayoutCache *cache;
  DesiredSize         *cached_size;
  GtkWidget           *widget;
  gboolean             found_in_cache = FALSE;

  g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (layout));
  g_return_if_fail (minimum_size != NULL || natural_size != NULL);

  widget = GTK_WIDGET (layout);
  cache  = get_cache (layout, TRUE);

  if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
    {
      cached_size = &cache->desired_widths[0];
      
      if (GTK_WIDGET_WIDTH_REQUEST_NEEDED (layout) == FALSE)
	found_in_cache = get_cached_desired_size (for_size, cache->desired_widths, &cached_size);
      else
	memset (cache->desired_widths, 0x0, N_CACHED_SIZES * sizeof (DesiredSize));
    }
  else
    {
      cached_size = &cache->desired_heights[0];
      
      if (GTK_WIDGET_HEIGHT_REQUEST_NEEDED (layout) == FALSE)
{'fraction_non_alphanumeric': 0.08767720828789531, 'fraction_numerical': 0.007851690294438387, 'mean_word_length': 3.2088113813676, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3589879', 'n_tokens_mistral': 3233, 'n_tokens_neox': 3012, 'n_words': 795}