/* Modified by Yen-Ju Chen <yjchenx at hotmail dot com> */
/*
   CEViewLayoutManager.m

   Copyright (C) 2002, 2003 Free Software Foundation, Inc.

   Author: Alexander Malmberg <alexander@malmberg.org>
   Date: November 2002 - February 2003

   This file is part of the GNUstep GUI Library.

   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; see the file COPYING.LIB.
   If not, write to the Free Software Foundation,
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include <AppKit/AppKit.h>

#include "CEViewTypesetter.h"
#include "CEViewLayoutManager.h"
#include <GNUstepGUI/GSLayoutManager_internal.h>
#include <GNUstepBase/Unicode.h>

/***** Glyph handling *****/
@implementation CEViewLayoutManager (backend)

/* Remove ligature support (backart) */
-(unsigned int) _findSafeBreakMovingBackwardFrom: (unsigned int)ch
{
  return ch;
}

-(unsigned int) _findSafeBreakMovingForwardFrom: (unsigned int)ch
{
  return ch;
}
-(void) _generateGlyphsForRun: (glyph_run_t *)run  at: (unsigned int)pos
{
  run->ligature = 0;
  [super _generateGlyphsForRun: run at: pos];
}

@end

/***** Layout handling *****/

@implementation CEViewLayoutManager (layout)

- (void) setTextContainer: (NSTextContainer *)aTextContainer 
            forGlyphRange: (NSRange)glyphRange
{
  textcontainer_t *tc;
  int i;

  tc = textcontainers;
  i = 0;

  /* FIXME: Only set text container once for whole glyphs*/
  tc->pos = 0;
  tc->length = glyphRange.length;

  layout_glyph = tc->pos + tc->length;
  if (layout_glyph == glyphs->glyph_length)
    layout_char = glyphs->char_length;
  else
    layout_char = [self characterIndexForGlyphAtIndex: layout_glyph];
}

- (void) setLineFragmentRect: (NSRect)fragmentRect 
	       forGlyphRange: (NSRange)glyphRange
		    usedRect: (NSRect)usedRect
{
  textcontainer_t *tc;
  int i;
  linefrag_t *lf;

  tc = textcontainers;
  i = 0;

  lf = &tc->linefrags[tc->num_linefrags - 1];

  if (!(tc->num_linefrags + tc->num_soft))
    {
      if (!tc->size_linefrags)
	{
	  tc->size_linefrags = 16;
	  tc->linefrags = malloc(sizeof(linefrag_t) * tc->size_linefrags);
	}
      tc->num_linefrags = 1;
      lf = tc->linefrags;
    }
  else if (!tc->num_soft)
    {
      if (tc->size_linefrags <= tc->num_linefrags)
	{
	  tc->size_linefrags += tc->size_linefrags / 2;
	  tc->linefrags = realloc(tc->linefrags, sizeof(linefrag_t) * tc->size_linefrags);
	}
      tc->num_linefrags++;
      lf = &tc->linefrags[tc->num_linefrags - 1];
    }
  else
    {
      int i;
      for (i = tc->num_linefrags, lf = tc->linefrags + i; i < tc->num_linefrags + tc->num_soft; i++, lf++)
	{
	  if (lf->pos >= NSMaxRange(glyphRange))
	    break;
	  if (lf->points)
	    {
	      free(lf->points);
	      lf->points = NULL;
	    }
	}

      if (i == tc->num_linefrags)
	{
	  /*
	  If we should keep all soft frags, we need to enlarge the array
	  to fit the new line frag.
	  */
	  if (tc->size_linefrags <= tc->num_linefrags + tc->num_soft)
	    {
	      tc->size_linefrags += tc->size_linefrags / 2;
	      tc->linefrags = realloc(tc->linefrags, sizeof(linefrag_t) * tc->size_linefrags);
	    }
	  memmove(&tc->linefrags[tc->num_linefrags + 1], &tc->linefrags[tc->num_linefrags], tc->num_soft * sizeof(linefrag_t));
	}
      else if (i > tc->num_linefrags + 1)
	{
	  tc->num_soft -= i - tc->num_linefrags;
	  memmove(&tc->linefrags[tc->num_linefrags + 1], &tc->linefrags[i], tc->num_soft * sizeof(linefrag_t));
	}
      else
	{
	  /*
	  If i == tc->num_linefrags + 1, we're lucky and everything already
	  lines up, so no moving is necessary.
	  */
	  tc->num_soft--;
	}

      tc->num_linefrags++;
      lf = &tc->linefrags[tc->num_linefrags - 1];
    }

  memset(lf, 0, sizeof(linefrag_t));
  lf->rect = fragmentRect;
  lf->used_rect = usedRect;
  lf->pos = glyphRange.location;
  lf->length = glyphRange.length;
}

- (void) setLocation: (NSPoint)location 
forStartOfGlyphRange: (NSRange)glyphRange
{
  textcontainer_t *tc;
  int i;
  linefrag_t *lf;
  linefrag_point_t *lp;

  i = 0;
  tc = textcontainers;

  for (i = tc->num_linefrags - 1, lf = tc->linefrags + i; i >= 0; i--, lf--)
    {
      if (lf->pos <= glyphRange.location &&
	  lf->pos + lf->length >= glyphRange.location + glyphRange.length)
	break;
    }
  if (!lf->num_points)
    {
      lp = lf->points = malloc(sizeof(linefrag_point_t));
      lf->num_points++;
    }
  else
    {
      lp = &lf->points[lf->num_points - 1];
      lf->num_points++;
      lf->points = realloc(lf->points, sizeof(linefrag_point_t) * lf->num_points);
      lp = &lf->points[lf->num_points - 1];
    }
  lp->pos = glyphRange.location;
  lp->length = glyphRange.length;
  lp->p = location;
}

@end


/***** The rest *****/

@implementation CEViewLayoutManager

- (id) init
{
  if (!(self = [super init]))
    return nil;

  typesetter = [[CEViewTypesetter sharedSystemTypesetter] retain];

  return self;
}


-(void) dealloc
{
  DESTROY(typesetter);
  [super dealloc];
}

@end

