/* Copyright (c) 1999, Red Hat Software, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 * X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 * Except as contained in this notice, the name of the Red Hat Software shall not be
 * used in advertising or otherwise to promote the sale, use or other dealings
 * in this Software without prior written authorization from Red Hat Software
*/

#include "gtkglyphlabel.h"
#include <gdk/gdkx.h>

#include <string.h>

#define GDK_FONT_XFONTSTRUCT(font) ((XFontStruct *)GDK_FONT_XFONT(font))
#define GDK_FONT_IS_16(font) ((GDK_FONT_XFONTSTRUCT(font)->min_byte1 != 0) || \
			      (GDK_FONT_XFONTSTRUCT(font)->max_byte1 != 0))

static void gtk_glyph_label_class_init   (GtkGlyphLabelClass *klass);
static void gtk_glyph_label_init         (GtkGlyphLabel      *glabel);
static void gtk_glyph_label_destroy      (GtkObject           *object);
static void gtk_glyph_label_size_request (GtkWidget           *widget,
					  GtkRequisition      *requisition);
static gint gtk_glyph_label_expose_event (GtkWidget           *widget,
					  GdkEventExpose      *event);

GtkType
gtk_glyph_label_get_type ()
{
  static GtkType glyph_label_type = 0;

  if (!glyph_label_type)
    {
      static const GtkTypeInfo glyph_label_info =
      {
	"GtkGlyphLabel",
	sizeof (GtkGlyphLabel),
	sizeof (GtkGlyphLabelClass),
	(GtkClassInitFunc) gtk_glyph_label_class_init,
	(GtkObjectInitFunc) gtk_glyph_label_init,
	NULL, /* reserved */
	NULL, /* reserved */
	(GtkClassInitFunc) NULL
      };

      glyph_label_type = gtk_type_unique (GTK_TYPE_MISC, &glyph_label_info);
    }

  return glyph_label_type;
}

static void
gtk_glyph_label_class_init (GtkGlyphLabelClass *klass)
{
  GtkObjectClass *object_class = (GtkObjectClass *)klass;
  GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;

  object_class->destroy = gtk_glyph_label_destroy;
  
  widget_class->size_request = gtk_glyph_label_size_request;
  widget_class->expose_event = gtk_glyph_label_expose_event;
}

static void
gtk_glyph_label_init (GtkGlyphLabel *glabel)
{
  GTK_WIDGET_SET_FLAGS (GTK_WIDGET (glabel), GTK_NO_WINDOW);
  
  glabel->font = NULL;
  glabel->wide = FALSE;
  glabel->u.glyphs = NULL;
}

static void
gtk_glyph_label_destroy (GtkObject *object)
{
  GtkGlyphLabel *glabel;

  g_return_if_fail (GTK_IS_GLYPH_LABEL (object));

  glabel = GTK_GLYPH_LABEL (object);

  if (glabel->font)
    gdk_font_unref (glabel->font);

  if (glabel->u.glyphs)
    g_free (glabel->u.glyphs);
}

GtkWidget *
gtk_glyph_label_new (GdkFont *font)
{
  GtkWidget *result;
  
  g_return_val_if_fail (font != NULL, NULL);

  result = gtk_type_new (GTK_TYPE_GLYPH_LABEL);
  gtk_glyph_label_set_font (GTK_GLYPH_LABEL (result), font);

  return result;
}

void
gtk_glyph_label_set_string (GtkGlyphLabel *glabel,
			    const gchar    *string)
{
  g_return_if_fail (glabel != NULL);
  g_return_if_fail (!glabel->wide);

  if (glabel->u.glyphs)
    g_free (glabel->u.glyphs);

  glabel->length = strlen (string);
  glabel->u.glyphs = g_strdup (string);
}

void
gtk_glyph_label_set_string16 (GtkGlyphLabel *glabel,
			      const guint16  *string16)
{
  gint i;

  g_return_if_fail (glabel != NULL);
  g_return_if_fail (glabel->wide);

  if (glabel->u.glyphs16)
    g_free (glabel->u.glyphs16);

  glabel->length = 0;
  while (string16[glabel->length])
    glabel->length++;
  
  glabel->u.glyphs16 = g_new (guint16, glabel->length+1);
  for (i = 0; i<glabel->length; i++)
    glabel->u.glyphs16[i] = string16[0];
  glabel->u.glyphs16[i] = 0;
}

void
gtk_glyph_label_set_font (GtkGlyphLabel *glabel,
			  GdkFont        *font)
{
  g_return_if_fail (glabel != NULL);
  g_return_if_fail (font != NULL);
  g_return_if_fail (font->type == GDK_FONT_FONT);
  
  if (GDK_FONT_IS_16(font) && !glabel->wide)
    {
      glabel->wide = TRUE;
      g_free (glabel->u.glyphs);
      glabel->length = 0;
    }
  else if (!GDK_FONT_IS_16(font) && glabel->wide)
    {
      glabel->wide = FALSE;
      g_free (glabel->u.glyphs16);
      glabel->length = 0;
    }

  if (glabel->font)
    gdk_font_unref (glabel->font);

  glabel->font = font;
  gdk_font_ref (font);
}

static void
gtk_glyph_label_size_request (GtkWidget      *widget,
			      GtkRequisition *requisition)
{
  GtkGlyphLabel *glabel;
  GtkMisc *misc;
  
  g_return_if_fail (GTK_IS_GLYPH_LABEL (widget));
  g_return_if_fail (requisition != NULL);

  glabel = GTK_GLYPH_LABEL (widget);
  misc = GTK_MISC (widget);
  
  if (glabel->font)
    {
      widget->requisition.height = glabel->font->ascent + glabel->font->descent;
      if (glabel->u.glyphs)
	widget->requisition.width = gdk_text_width (glabel->font,
						    glabel->u.glyphs,
						    glabel->wide ? glabel->length * 2 : glabel->length);
      else
	widget->requisition.height = 0;
    }

  widget->requisition.width += 2 * misc->xpad;
  widget->requisition.width += 2 * misc->ypad;
}

static gint
gtk_glyph_label_expose_event (GtkWidget      *widget,
			      GdkEventExpose *event)
{
  GtkGlyphLabel *glabel;
  GtkMisc *misc;
  gint xpos, ypos;
  GdkRectangle clip_rect;

  g_return_val_if_fail (GTK_IS_GLYPH_LABEL (widget), FALSE);
  g_return_val_if_fail (event != NULL, FALSE);

  glabel = GTK_GLYPH_LABEL (widget);
  misc = GTK_MISC (widget);

  if (glabel->font == NULL || glabel->u.glyphs == NULL)
    return TRUE;
  
  xpos = widget->allocation.x + (gint)misc->xpad +
    ((gint)widget->allocation.width - (gint)widget->requisition.width) *
    misc->xalign;
  ypos = widget->allocation.y + (gint)misc->ypad +
    ((gint)widget->allocation.height - (gint)widget->requisition.height) *
    misc->yalign;

  clip_rect.x = widget->allocation.x;
  clip_rect.y = widget->allocation.y;
  clip_rect.width = widget->allocation.width;
  clip_rect.height = widget->allocation.height;

  gdk_gc_set_clip_origin (widget->style->fg_gc[widget->state], 0, 0);
  gdk_gc_set_clip_rectangle (widget->style->fg_gc[widget->state], &clip_rect);
  
  gdk_draw_text (widget->window, glabel->font, widget->style->fg_gc[widget->state],
		 xpos, ypos + glabel->font->ascent,
		 glabel->u.glyphs,
		 glabel->wide ? glabel->length * 2 : glabel->length);

  gdk_gc_set_clip_rectangle (widget->style->fg_gc[widget->state], NULL);

  return TRUE;
}

