Blame pango/pango-tabs.c

Packit 0ec9dd
/* Pango
Packit 0ec9dd
 * pango-tabs.c: Tab-related stuff
Packit 0ec9dd
 *
Packit 0ec9dd
 * Copyright (C) 2000 Red Hat Software
Packit 0ec9dd
 *
Packit 0ec9dd
 * This library is free software; you can redistribute it and/or
Packit 0ec9dd
 * modify it under the terms of the GNU Library General Public
Packit 0ec9dd
 * License as published by the Free Software Foundation; either
Packit 0ec9dd
 * version 2 of the License, or (at your option) any later version.
Packit 0ec9dd
 *
Packit 0ec9dd
 * This library is distributed in the hope that it will be useful,
Packit 0ec9dd
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 0ec9dd
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
Packit 0ec9dd
 * Library General Public License for more details.
Packit 0ec9dd
 *
Packit 0ec9dd
 * You should have received a copy of the GNU Library General Public
Packit 0ec9dd
 * License along with this library; if not, write to the
Packit 0ec9dd
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 0ec9dd
 * Boston, MA 02111-1307, USA.
Packit 0ec9dd
 */
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * SECTION:tab-stops
Packit 0ec9dd
 * @short_description:Structures for storing tab stops
Packit 0ec9dd
 * @title:Tab Stops
Packit 0ec9dd
 *
Packit 0ec9dd
 * Functions in this section are used to deal with #PangoTabArray objects
Packit 0ec9dd
 * that can be used to set tab stop positions in a #PangoLayout.
Packit 0ec9dd
 */
Packit 0ec9dd
#include "config.h"
Packit 0ec9dd
#include "pango-tabs.h"
Packit 0ec9dd
#include "pango-impl-utils.h"
Packit 0ec9dd
#include <string.h>
Packit 0ec9dd
Packit 0ec9dd
typedef struct _PangoTab PangoTab;
Packit 0ec9dd
Packit 0ec9dd
struct _PangoTab
Packit 0ec9dd
{
Packit 0ec9dd
  gint location;	        /* Offset in pixels of this tab stop
Packit 0ec9dd
				 * from the left margin of the text.
Packit 0ec9dd
				 */
Packit 0ec9dd
  PangoTabAlign alignment;      /* Where the tab stop appears relative
Packit 0ec9dd
				 * to the text.
Packit 0ec9dd
				 */
Packit 0ec9dd
};
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * PangoTabArray:
Packit 0ec9dd
 *
Packit 0ec9dd
 * A #PangoTabArray struct contains an array
Packit 0ec9dd
 * of tab stops. Each tab stop has an alignment and a position.
Packit 0ec9dd
 */
Packit 0ec9dd
struct _PangoTabArray
Packit 0ec9dd
{
Packit 0ec9dd
  gint size;
Packit 0ec9dd
  gint allocated;
Packit 0ec9dd
  gboolean positions_in_pixels;
Packit 0ec9dd
  PangoTab *tabs;
Packit 0ec9dd
};
Packit 0ec9dd
Packit 0ec9dd
static void
Packit 0ec9dd
init_tabs (PangoTabArray *array, gint start, gint end)
Packit 0ec9dd
{
Packit 0ec9dd
  while (start < end)
Packit 0ec9dd
    {
Packit 0ec9dd
      array->tabs[start].location = 0;
Packit 0ec9dd
      array->tabs[start].alignment = PANGO_TAB_LEFT;
Packit 0ec9dd
      ++start;
Packit 0ec9dd
    }
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_tab_array_new:
Packit 0ec9dd
 * @initial_size: Initial number of tab stops to allocate, can be 0
Packit 0ec9dd
 * @positions_in_pixels: whether positions are in pixel units
Packit 0ec9dd
 *
Packit 0ec9dd
 * Creates an array of @initial_size tab stops. Tab stops are specified in
Packit 0ec9dd
 * pixel units if @positions_in_pixels is %TRUE, otherwise in Pango
Packit 0ec9dd
 * units. All stops are initially at position 0.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Return value: the newly allocated #PangoTabArray, which should
Packit 0ec9dd
 *               be freed with pango_tab_array_free().
Packit 0ec9dd
 **/
Packit 0ec9dd
PangoTabArray*
Packit 0ec9dd
pango_tab_array_new (gint initial_size,
Packit 0ec9dd
		     gboolean positions_in_pixels)
Packit 0ec9dd
{
Packit 0ec9dd
  PangoTabArray *array;
Packit 0ec9dd
Packit 0ec9dd
  g_return_val_if_fail (initial_size >= 0, NULL);
Packit 0ec9dd
Packit 0ec9dd
  /* alloc enough to treat array->tabs as an array of length
Packit 0ec9dd
   * size, though it's declared as an array of length 1.
Packit 0ec9dd
   * If we allowed tab array resizing we'd need to drop this
Packit 0ec9dd
   * optimization.
Packit 0ec9dd
   */
Packit 0ec9dd
  array = g_slice_new (PangoTabArray);
Packit 0ec9dd
  array->size = initial_size;
Packit 0ec9dd
  array->allocated = initial_size;
Packit 0ec9dd
Packit 0ec9dd
  if (array->allocated > 0)
Packit 0ec9dd
    {
Packit 0ec9dd
      array->tabs = g_new (PangoTab, array->allocated);
Packit 0ec9dd
      init_tabs (array, 0, array->allocated);
Packit 0ec9dd
    }
Packit 0ec9dd
  else
Packit 0ec9dd
    array->tabs = NULL;
Packit 0ec9dd
Packit 0ec9dd
  array->positions_in_pixels = positions_in_pixels;
Packit 0ec9dd
Packit 0ec9dd
  return array;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_tab_array_new_with_positions:
Packit 0ec9dd
 * @size: number of tab stops in the array
Packit 0ec9dd
 * @positions_in_pixels: whether positions are in pixel units
Packit 0ec9dd
 * @first_alignment: alignment of first tab stop
Packit 0ec9dd
 * @first_position: position of first tab stop
Packit 0ec9dd
 * @...: additional alignment/position pairs
Packit 0ec9dd
 *
Packit 0ec9dd
 * This is a convenience function that creates a #PangoTabArray
Packit 0ec9dd
 * and allows you to specify the alignment and position of each
Packit 0ec9dd
 * tab stop. You <emphasis>must</emphasis> provide an alignment
Packit 0ec9dd
 * and position for @size tab stops.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Return value: the newly allocated #PangoTabArray, which should
Packit 0ec9dd
 *               be freed with pango_tab_array_free().
Packit 0ec9dd
 **/
Packit 0ec9dd
PangoTabArray  *
Packit 0ec9dd
pango_tab_array_new_with_positions (gint           size,
Packit 0ec9dd
				    gboolean       positions_in_pixels,
Packit 0ec9dd
				    PangoTabAlign  first_alignment,
Packit 0ec9dd
				    gint           first_position,
Packit 0ec9dd
				    ...)
Packit 0ec9dd
{
Packit 0ec9dd
  PangoTabArray *array;
Packit 0ec9dd
  va_list args;
Packit 0ec9dd
  int i;
Packit 0ec9dd
Packit 0ec9dd
  g_return_val_if_fail (size >= 0, NULL);
Packit 0ec9dd
Packit 0ec9dd
  array = pango_tab_array_new (size, positions_in_pixels);
Packit 0ec9dd
Packit 0ec9dd
  if (size == 0)
Packit 0ec9dd
    return array;
Packit 0ec9dd
Packit 0ec9dd
  array->tabs[0].alignment = first_alignment;
Packit 0ec9dd
  array->tabs[0].location = first_position;
Packit 0ec9dd
Packit 0ec9dd
  if (size == 1)
Packit 0ec9dd
    return array;
Packit 0ec9dd
Packit 0ec9dd
  va_start (args, first_position);
Packit 0ec9dd
Packit 0ec9dd
  i = 1;
Packit 0ec9dd
  while (i < size)
Packit 0ec9dd
    {
Packit 0ec9dd
      PangoTabAlign align = va_arg (args, PangoTabAlign);
Packit 0ec9dd
      int pos = va_arg (args, int);
Packit 0ec9dd
Packit 0ec9dd
      array->tabs[i].alignment = align;
Packit 0ec9dd
      array->tabs[i].location = pos;
Packit 0ec9dd
Packit 0ec9dd
      ++i;
Packit 0ec9dd
    }
Packit 0ec9dd
Packit 0ec9dd
  va_end (args);
Packit 0ec9dd
Packit 0ec9dd
  return array;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
G_DEFINE_BOXED_TYPE (PangoTabArray, pango_tab_array,
Packit 0ec9dd
                     pango_tab_array_copy,
Packit 0ec9dd
                     pango_tab_array_free);
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_tab_array_copy:
Packit 0ec9dd
 * @src: #PangoTabArray to copy
Packit 0ec9dd
 *
Packit 0ec9dd
 * Copies a #PangoTabArray
Packit 0ec9dd
 *
Packit 0ec9dd
 * Return value: the newly allocated #PangoTabArray, which should
Packit 0ec9dd
 *               be freed with pango_tab_array_free().
Packit 0ec9dd
 **/
Packit 0ec9dd
PangoTabArray*
Packit 0ec9dd
pango_tab_array_copy (PangoTabArray *src)
Packit 0ec9dd
{
Packit 0ec9dd
  PangoTabArray *copy;
Packit 0ec9dd
Packit 0ec9dd
  g_return_val_if_fail (src != NULL, NULL);
Packit 0ec9dd
Packit 0ec9dd
  copy = pango_tab_array_new (src->size, src->positions_in_pixels);
Packit 0ec9dd
Packit 0ec9dd
  memcpy (copy->tabs, src->tabs, sizeof(PangoTab)*src->size);
Packit 0ec9dd
Packit 0ec9dd
  return copy;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_tab_array_free:
Packit 0ec9dd
 * @tab_array: a #PangoTabArray
Packit 0ec9dd
 *
Packit 0ec9dd
 * Frees a tab array and associated resources.
Packit 0ec9dd
 *
Packit 0ec9dd
 **/
Packit 0ec9dd
void
Packit 0ec9dd
pango_tab_array_free   (PangoTabArray *tab_array)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_if_fail (tab_array != NULL);
Packit 0ec9dd
Packit 0ec9dd
  g_free (tab_array->tabs);
Packit 0ec9dd
Packit 0ec9dd
  g_slice_free (PangoTabArray, tab_array);
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_tab_array_get_size:
Packit 0ec9dd
 * @tab_array: a #PangoTabArray
Packit 0ec9dd
 *
Packit 0ec9dd
 * Gets the number of tab stops in @tab_array.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Return value: the number of tab stops in the array.
Packit 0ec9dd
 **/
Packit 0ec9dd
gint
Packit 0ec9dd
pango_tab_array_get_size (PangoTabArray *tab_array)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_val_if_fail (tab_array != NULL, 0);
Packit 0ec9dd
Packit 0ec9dd
  return tab_array->size;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_tab_array_resize:
Packit 0ec9dd
 * @tab_array: a #PangoTabArray
Packit 0ec9dd
 * @new_size: new size of the array
Packit 0ec9dd
 *
Packit 0ec9dd
 * Resizes a tab array. You must subsequently initialize any tabs that
Packit 0ec9dd
 * were added as a result of growing the array.
Packit 0ec9dd
 *
Packit 0ec9dd
 **/
Packit 0ec9dd
void
Packit 0ec9dd
pango_tab_array_resize (PangoTabArray *tab_array,
Packit 0ec9dd
			gint           new_size)
Packit 0ec9dd
{
Packit 0ec9dd
  if (new_size > tab_array->allocated)
Packit 0ec9dd
    {
Packit 0ec9dd
      gint current_end = tab_array->allocated;
Packit 0ec9dd
Packit 0ec9dd
      /* Ratchet allocated size up above the index. */
Packit 0ec9dd
      if (tab_array->allocated == 0)
Packit 0ec9dd
	tab_array->allocated = 2;
Packit 0ec9dd
Packit 0ec9dd
      while (new_size > tab_array->allocated)
Packit 0ec9dd
	tab_array->allocated = tab_array->allocated * 2;
Packit 0ec9dd
Packit 0ec9dd
      tab_array->tabs = g_renew (PangoTab, tab_array->tabs,
Packit 0ec9dd
				 tab_array->allocated);
Packit 0ec9dd
Packit 0ec9dd
      init_tabs (tab_array, current_end, tab_array->allocated);
Packit 0ec9dd
    }
Packit 0ec9dd
Packit 0ec9dd
  tab_array->size = new_size;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_tab_array_set_tab:
Packit 0ec9dd
 * @tab_array: a #PangoTabArray
Packit 0ec9dd
 * @tab_index: the index of a tab stop
Packit 0ec9dd
 * @alignment: tab alignment
Packit 0ec9dd
 * @location: tab location in Pango units
Packit 0ec9dd
 *
Packit 0ec9dd
 * Sets the alignment and location of a tab stop.
Packit 0ec9dd
 * @alignment must always be #PANGO_TAB_LEFT in the current
Packit 0ec9dd
 * implementation.
Packit 0ec9dd
 *
Packit 0ec9dd
 **/
Packit 0ec9dd
void
Packit 0ec9dd
pango_tab_array_set_tab  (PangoTabArray *tab_array,
Packit 0ec9dd
			  gint           tab_index,
Packit 0ec9dd
			  PangoTabAlign  alignment,
Packit 0ec9dd
			  gint           location)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_if_fail (tab_array != NULL);
Packit 0ec9dd
  g_return_if_fail (tab_index >= 0);
Packit 0ec9dd
  g_return_if_fail (alignment == PANGO_TAB_LEFT);
Packit 0ec9dd
  g_return_if_fail (location >= 0);
Packit 0ec9dd
Packit 0ec9dd
  if (tab_index >= tab_array->size)
Packit 0ec9dd
    pango_tab_array_resize (tab_array, tab_index + 1);
Packit 0ec9dd
Packit 0ec9dd
  tab_array->tabs[tab_index].alignment = alignment;
Packit 0ec9dd
  tab_array->tabs[tab_index].location = location;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_tab_array_get_tab:
Packit 0ec9dd
 * @tab_array: a #PangoTabArray
Packit 0ec9dd
 * @tab_index: tab stop index
Packit 0ec9dd
 * @alignment: (out) (allow-none): location to store alignment, or %NULL
Packit 0ec9dd
 * @location: (out) (allow-none): location to store tab position, or %NULL
Packit 0ec9dd
 *
Packit 0ec9dd
 * Gets the alignment and position of a tab stop.
Packit 0ec9dd
 *
Packit 0ec9dd
 **/
Packit 0ec9dd
void
Packit 0ec9dd
pango_tab_array_get_tab  (PangoTabArray *tab_array,
Packit 0ec9dd
			  gint           tab_index,
Packit 0ec9dd
			  PangoTabAlign *alignment,
Packit 0ec9dd
			  gint          *location)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_if_fail (tab_array != NULL);
Packit 0ec9dd
  g_return_if_fail (tab_index < tab_array->size);
Packit 0ec9dd
  g_return_if_fail (tab_index >= 0);
Packit 0ec9dd
Packit 0ec9dd
  if (alignment)
Packit 0ec9dd
    *alignment = tab_array->tabs[tab_index].alignment;
Packit 0ec9dd
Packit 0ec9dd
  if (location)
Packit 0ec9dd
    *location = tab_array->tabs[tab_index].location;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_tab_array_get_tabs:
Packit 0ec9dd
 * @tab_array: a #PangoTabArray
Packit 0ec9dd
 * @alignments: (out) (allow-none): location to store an array of tab
Packit 0ec9dd
 *   stop alignments, or %NULL
Packit 0ec9dd
 * @locations: (out) (allow-none) (array): location to store an array
Packit 0ec9dd
 *   of tab positions, or %NULL
Packit 0ec9dd
 *
Packit 0ec9dd
 * If non-%NULL, @alignments and @locations are filled with allocated
Packit 0ec9dd
 * arrays of length pango_tab_array_get_size(). You must free the
Packit 0ec9dd
 * returned array.
Packit 0ec9dd
 *
Packit 0ec9dd
 **/
Packit 0ec9dd
void
Packit 0ec9dd
pango_tab_array_get_tabs (PangoTabArray *tab_array,
Packit 0ec9dd
			  PangoTabAlign **alignments,
Packit 0ec9dd
			  gint          **locations)
Packit 0ec9dd
{
Packit 0ec9dd
  gint i;
Packit 0ec9dd
Packit 0ec9dd
  g_return_if_fail (tab_array != NULL);
Packit 0ec9dd
Packit 0ec9dd
  if (alignments)
Packit 0ec9dd
    *alignments = g_new (PangoTabAlign, tab_array->size);
Packit 0ec9dd
Packit 0ec9dd
  if (locations)
Packit 0ec9dd
    *locations = g_new (gint, tab_array->size);
Packit 0ec9dd
Packit 0ec9dd
  i = 0;
Packit 0ec9dd
  while (i < tab_array->size)
Packit 0ec9dd
    {
Packit 0ec9dd
      if (alignments)
Packit 0ec9dd
	(*alignments)[i] = tab_array->tabs[i].alignment;
Packit 0ec9dd
      if (locations)
Packit 0ec9dd
	(*locations)[i] = tab_array->tabs[i].location;
Packit 0ec9dd
Packit 0ec9dd
      ++i;
Packit 0ec9dd
    }
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_tab_array_get_positions_in_pixels:
Packit 0ec9dd
 * @tab_array: a #PangoTabArray
Packit 0ec9dd
 *
Packit 0ec9dd
 * Returns %TRUE if the tab positions are in pixels, %FALSE if they are
Packit 0ec9dd
 * in Pango units.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Return value: whether positions are in pixels.
Packit 0ec9dd
 **/
Packit 0ec9dd
gboolean
Packit 0ec9dd
pango_tab_array_get_positions_in_pixels (PangoTabArray *tab_array)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_val_if_fail (tab_array != NULL, FALSE);
Packit 0ec9dd
Packit 0ec9dd
  return tab_array->positions_in_pixels;
Packit 0ec9dd
}