/* SentenceBreakIterator.java - Default sentence BreakIterator.
   Copyright (C) 1999, 2001, 2002, 2004 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath 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
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.text;

import java.text.CharacterIterator;

/**
 * @author Tom Tromey <tromey@cygnus.com>
 * @date March 23, 1999
 * Written using The Unicode Standard, Version 2.0.
 */

public class SentenceBreakIterator extends BaseBreakIterator
{
  public Object clone ()
  {
    return new SentenceBreakIterator (this);
  }

  public SentenceBreakIterator ()
  {
  }

  private SentenceBreakIterator (SentenceBreakIterator other)
  {
    iter = (CharacterIterator) other.iter.clone();
  }

  public int next ()
  {
    int end = iter.getEndIndex();
    if (iter.getIndex() == end)
      return DONE;

    while (iter.getIndex() < end)
      {
	char c = iter.current();
	if (c == CharacterIterator.DONE)
	  break;
	int type = Character.getType(c);

	char n = iter.next();
	if (n == CharacterIterator.DONE)
	  break;

	// Always break after paragraph separator.
	if (type == Character.PARAGRAPH_SEPARATOR)
	  break;

	if (c == '!' || c == '?')
	  {
	    // Skip close punctuation.
	    while (n != CharacterIterator.DONE
		   && Character.getType(n) == Character.END_PUNCTUATION)
	      n = iter.next();
	    // Skip (java) space, line and paragraph separators.
	    while (n != CharacterIterator.DONE && Character.isWhitespace(n))
	      n = iter.next();

	    // There's always a break somewhere after `!' or `?'.
	    break;
	  }

	if (c == '.')
	  {
	    int save = iter.getIndex();
	    // Skip close punctuation.
	    while (n != CharacterIterator.DONE
		   && Character.getType(n) == Character.END_PUNCTUATION)
	      n = iter.next();
	    // Skip (java) space, line and paragraph separators.
	    // We keep count because we need at least one for this period to
	    // represent a terminator.
	    int spcount = 0;
	    while (n != CharacterIterator.DONE && Character.isWhitespace(n))
	      {
		n = iter.next();
		++spcount;
	      }
	    if (spcount > 0)
	      {
		int save2 = iter.getIndex();
		// Skip over open puncutation.
		while (n != CharacterIterator.DONE
		       && Character.getType(n) == Character.START_PUNCTUATION)
		  n = iter.next();
		// Next character must not be lower case.
		if (n == CharacterIterator.DONE
		    || ! Character.isLowerCase(n))
		  {
		    iter.setIndex(save2);
		    break;
		  }
	      }
	    iter.setIndex(save);
	  }
      }

    return iter.getIndex();
  }

  private final int previous_internal ()
  {
    int start = iter.getBeginIndex();
    if (iter.getIndex() == start)
      return DONE;

    while (iter.getIndex() >= start)
      {
	char c = iter.previous();
	if (c == CharacterIterator.DONE)
	  break;

	char n = iter.previous();
	if (n == CharacterIterator.DONE)
	  break;
	iter.next();
	int nt = Character.getType(n);

	if (! Character.isLowerCase(c)
	    && (nt == Character.START_PUNCTUATION
		|| Character.isWhitespace(n)))
	  {
	    int save = iter.getIndex();
	    int save_nt = nt;
	    char save_n = n;
	    // Skip open punctuation.
	    while (n != CharacterIterator.DONE
		   && Character.getType(n) == Character.START_PUNCTUATION)
	      n = iter.previous();
	    if (n == CharacterIterator.DONE)
	      break;
	    if (Character.isWhitespace(n))
	      {
		// Must have at least one (java) space after the `.'.
		int save2 = iter.getIndex();
		while (n != CharacterIterator.DONE
		       && Character.isWhitespace(n))
		  n = iter.previous();
		// Skip close punctuation.
		while (n != CharacterIterator.DONE
		       && Character.getType(n) == Character.END_PUNCTUATION)
		  n = iter.previous();
		if (n == CharacterIterator.DONE || n == '.')
		  {
		    // Communicate location of actual end.
		    period = iter.getIndex();
		    iter.setIndex(save2);
		    break;
		  }
	      }
	    iter.setIndex(save);
	    nt = save_nt;
	    n = save_n;
	  }

	if (nt == Character.PARAGRAPH_SEPARATOR)
	  {
	    // Communicate location of actual end.
	    period = iter.getIndex();
	    break;
	  }
	else if (Character.isWhitespace(n)
		 || nt == Character.END_PUNCTUATION)
	  {
	    int save = iter.getIndex();
	    // Skip (java) space, line and paragraph separators.
	    while (n != CharacterIterator.DONE
		   && Character.isWhitespace(n))
	      n = iter.previous();
	    // Skip close punctuation.
	    while (n != CharacterIterator.DONE
		   && Character.getType(n) == Character.END_PUNCTUATION)
	      n = iter.previous();
	    int here = iter.getIndex();
	    iter.setIndex(save);
	    if (n == CharacterIterator.DONE || n == '!' || n == '?')
	      {
		// Communicate location of actual end.
		period = here;
		break;
	      }
	  }
	else if (n == '!' || n == '?')
	  {
	    // Communicate location of actual end.
	    period = iter.getIndex();
	    break;
	  }
      }

    return iter.getIndex();
  }

  public int previous ()
  {
    // We want to skip over the first sentence end to the second one.
    // However, at the end of the string we want the first end.
    int here = iter.getIndex();
    period = here;
    int first = previous_internal ();
    if (here == iter.getEndIndex() || first == DONE)
      return first;
    iter.setIndex(period);
    return previous_internal ();
  }

  // This is used for communication between previous and
  // previous_internal.
  private int period;
}
