/*
**  CEView+Indentation.m
**
**  Copyright (c) 2002, 2003
**
**  Author: Yen-Ju Chen <yjchenx@hotmail.com>
**          Bjoern Giesler <bjoern@giesler.de>
**
**  This program 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 of the License, or
**  (at your option) any later version.
**
**  This program 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 this program; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "CEView+Indentation.h"
#include "CEView+TextUtils.h"
#include "BundleLoader.h"
#include "CodeParser.h"
#include "FontificationHandler.h"
#include "IndentationHandler.h"
#include <AppKit/AppKit.h>

@interface NSString (Indentation)
- (NSString *)stringByRemovingWhitespace;
@end

@implementation NSString (ndentation)
- (NSString *)stringByRemovingWhitespace
{
  //FIXME: it assume string is ASCII

  int begin, end, len;
  char *cstr;
  
  cstr = (char *)[self lossyCString];
  len = strlen(cstr);
  
  for(begin=0; begin<len; begin++)
    if(!isspace(cstr[begin]))
      break;
  if(begin == len)
    return @"";
  for(end=len-1; end>=begin; end--)
    if(!isspace(cstr[end]))
      break;
  if(end < begin)
    return @"";
  return [self substringWithRange: NSMakeRange(begin, end-begin+1)];
}
@end

@implementation CodeEditorView (Indentation)

- (int)lengthOfWhitespaceStartingAt: (int)position
{
  int i, wsp;
  char *str;
  str = (char *)[[self string] lossyCString];
  wsp = 0;
  for(i=position; i<strlen(str); i++)
    {
      if(!((str[i] == ' ') || (str[i] == '\t')))
        break;
      wsp ++;
    }
  
  return wsp;
}

// this auto-indents the line containing <position>.
- (int)syntacticallyIndentLineAtIndex: (int)position
{
  NSRange lineRange;
  NSString *lineBefore; NSRange lineBeforeRange;
  char cstr[255];  
  unsigned int delta, whitespace;
  BOOL found;
  CodeParser *parser;
  id <IndentationHandler> handler;

  lineRange = [self rangeOfLineAtPosition: position];
  delta = 0;
  
  // first, delete all whitespace.
  whitespace = [self lengthOfWhitespaceStartingAt: lineRange.location];

  if(whitespace)
    {
      [[self textStorage]
       deleteCharactersInRange: NSMakeRange(lineRange.location,
					     whitespace)];
      lineRange.length -= whitespace;
      delta -= whitespace;
    }

  found = NO;
  whitespace = 0;
  
  // Check for oneline block delimiters
  if(lineRange.location != 0)
    {
      int index;
      NSString *firstWord;

      lineBeforeRange = [self rangeOfLineAtPosition: lineRange.location-1];
      whitespace = [self lengthOfWhitespaceStartingAt: lineBeforeRange.location];
      lineBefore = [[[self string] substringWithRange: lineBeforeRange] stringByTrimmingSpaces];
      firstWord = [self wordAtPosition: lineBeforeRange.location+whitespace+1];

      /* use CodeParser */
      index = [bundleLanguages indexOfObject: languageName];
      if (index == NSNotFound)
        return 0;

      if (indentationHandlerClass)
        {
          handler = [[indentationHandlerClass alloc] init];
          if (handler == nil) 
            {
              NSLog(@"Can't load block handler");
              return whitespace;
            }
        }
      else
        {
          return whitespace;
        }

      parser = [[CodeParser alloc] initWithCodeHandler: handler
                                   withString: lineBefore];
      NSLog(@"Indentation parse begin");
      [parser parse];
      NSLog(@"indentation parse end");
      whitespace += [handler spaces];
      RELEASE(handler);
      RELEASE(parser);
    }

  if(whitespace)
    {
      sprintf(cstr, "%*s", whitespace, " ");
      [[[self textStorage] mutableString]
       insertString: [NSString stringWithCString: cstr]
       atIndex: lineRange.location];
      delta += whitespace;
    }

  return delta;
}

@end
