// Aspell check functions
// Copyright 1998 by Kevin Atkinson under the terms of the LGPL

#ifndef as_check_t__
#define as_check_t__

#include <functional>

#include "check.hh"
#include "language.hh"
#include "token-t.hh"


#define tl template <class Itr, class ItrEnd>
#define tld template <class Itr, class ItrEnd = Itr>
#define tt Itr,ItrEnd

tl void url_skip_iterator<tt>::scan_ahead() {
  enum {slash, who_cares} prev_char = who_cares;
  enum {wbegin, wmiddle, wend} word_pos = wbegin;
  blank_out_ = false;
  int point_chars = 0;
  Itr next;
  if (cur_ == end_) return;
  for (;;) {
    if (word_pos == wend) break;
    next = cur_; ++next;
    if (next == end_ || *next == ' ' || *next == '\n' || *next == '\t')
      word_pos = wend;
    if (word_pos == wmiddle) {
      switch (*cur_) {
      case '@':
	blank_out_ = true;
	prev_char = who_cares;
	break;
      case '.':
	++point_chars;
	prev_char = who_cares;
	break;
      case '/':
	if (prev_char == slash) blank_out_ = true;
	prev_char = slash;
	break;
      default:
	prev_char = who_cares;
      }
    }
    ++cur_;
    if (word_pos == wbegin) word_pos = wmiddle;
  }
  if (point_chars > 1) blank_out_ = true;
}

#undef tl
#undef tt
#undef tld

template <class ForItr, class Enditr>
class region_skipper_iterator_nv {
public:
  typedef region_skipper_iterator<ForItr, Enditr> v_iterator;
  typedef v_iterator::value_type                  value_type;
  v_iterator * itr;
  ~region_skipper_iterator_nv() {delete itr;}
  region_skipper_iterator_nv(const region_skipper_iterator_nv & i) {
    itr = i.itr->clone();
  }
  region_skipper_iterator_nv& operator= (const region_skipper_iterator_nv & i){
    if (!itr) itr = i.itr->clone();
    else *itr = *i.itr;
    return *this;
  }
  region_skipper_iterator_nv() : itr(0) {}
  region_skipper_iterator_nv(v_iterator * i) : itr(i->clone()) {}
  v_iterator::value_type operator* () const {return **itr;}
  region_skipper_iterator_nv& operator++ () {++*itr; return *this;}
};

template <class ForItr, class EndItr>
inline bool operator== (const region_skipper_iterator_nv<ForItr, EndItr> & rhs,  
			const region_skipper_iterator_nv<ForItr, EndItr> & lhs) 
{
  return *rhs.itr == *lhs.itr;
}



template <class ForwardIterator, class EndIterator>
class region_skipper_iterator_nv_end {
public:
  bool operator() (const region_skipper_iterator_nv<ForwardIterator,EndIterator> & i) const
  {return i.itr->is_end();}
};

template <class ForItr> 
inline void copy2str (string &str, ForItr i, ForItr e) {
  for(;i != e; ++i) {
    str += *i;
  }
}

template <class ForItr, class EndItr, class StatusFunc>
bool check (const aspell & sc, 
	    aspell_check_state<ForItr, EndItr> & state,
	    const StatusFunc & print_status)
{
  *state.word_end_ = *state.word_begin_;

  tok<region_skipper_iterator_nv<ForItr,EndItr>, 
    region_skipper_iterator_nv_end<ForItr,EndItr> > 
    i(region_skipper_iterator_nv<ForItr,EndItr>(state.word_end_),
      region_skipper_iterator_nv_end<ForItr,EndItr>(),
      sc.lang());

  string word;
  for (; !i.at_end(); ++i) {
    if ((*i).is_word) {
      word.resize(0);
      copy2str(word, (*i).begin, (*i).end);
      if (sc.check(word)) {
	print_status();
      } else {
	*state.word_begin_ = *(*i).begin.itr;
	*state.word_end_   = *(*i).end.itr;
	state.save_state();
	return true;
      } 
    }
  }
  
  *state.word_begin_ = *(*i).begin.itr;
  return false;
}

#endif
