# FreeRIDE Ruby Integrated Development Environment
#
# Author: Rich Kilmer
# Copyright (c) 2001, Richard Kilmer, rich@infoether.com
# Licensed under the Ruby License

module AutoIndent
  NO_INDENT = 0
  START_INDENT = 1
  START_END_INDENT = 2
  END_INDENT = 3
  
  def automatic_indentation(ch)
    if (ch==10 or ch==13)
      sel_start = @model.selection_start
      sel_end = @model.selection_end
      current_line = @model.line_from_position(@model.current_pos)
      indent = current_line > 0 ? @model.get_line_indentation(current_line - 1) : 0
      set_line_indentation(current_line, indent)
    end
  end

=begin
  def automatic_indentation(ch)
    sel_start = @model.selection_start
    sel_end = @model.selection_end
    current_line = @model.line_from_position(@model.current_pos)
    indent_size = @model.properties["indent.size"]
    if (ch==10 or ch==13)
      indent, state = get_indent_state(current_line - 1)
      #fold_level = (current_line > 0 ? @model.get_fold_level(current_line - 1) & Scintilla::SC_FOLDLEVELNUMBERMASK : Scintilla::Scintilla::SC_FOLDLEVELBASE)
      case state
        when START_INDENT
          indent = indent + indent_size
          #@model.set_fold_level(current_line - 1, foldLevel|Scintilla::SC_FOLDLEVELHEADERFLAG)
          #fold_level = fold_level + 1
        when END_INDENT
          back_line = current_line - 2
          while back_line > -1
            indent2, state2 = get_indent_state(back_line)
            if state2==START_INDENT
              set_line_indentation(current_line-1, indent2)
              indent = indent2
              break;
            elsif state2==END_INDENT
              indent2 = indent2 - indent_size
              set_line_indentation(current_line-1, indent2)
              indent=indent2
              break;
            end
            back_line = back_line - 1
          end
        when START_END_INDENT
          back_line = current_line-2
          while back_line > -1
            indent2, state2 = get_indent_state(back_line)
            if state2==START_INDENT or state2==START_END_INDENT
              set_line_indentation(current_line-1, indent2)
              indent=indent2 + indent_size
              #@model.set_fold_level(current_line - 1, @model.get_fold_level(back_line)|Scintilla::SC_FOLDLEVELHEADERFLAG)
              #fold_level = fold_level + 1
              break;
            end
            back_line = back_line - 1
          end
      end
      #@model.set_fold_level(current_line, fold_level)
      #puts "fold: #{@model.get_fold_level(current_line)} prev: #{@model.get_fold_level(current_line-1) if current_line > 0}"
      set_line_indentation(current_line, indent)
    end
  end
=end
  
  
  def get_indent_state(line)
    state = NO_INDENT
    indent = line > 0 ? @model.get_line_indentation(line) : 0
    text = @model.get_line(line)
    each_indent_token(text) do |token|
      case token[0..((token.index(/[\s(]/).nil? ? 0 : token.index(/[\s(]/) )-1)]
      when "def", "case", "class", "while", "until", "module", "catch"
        state=START_INDENT
      when "unless", "if","begin"
        state=START_INDENT unless token[-3..-1] == "end"
      when "when", "else", "elsif","rescue","ensure"
        state = START_END_INDENT
      when "end", "}"
        if state==START_INDENT
         state = NO_INDENT
        else
         state = END_INDENT
        end
      else
         state = START_INDENT if (token[-2..-1]=="do" && token[-3..-1]!="end") or token[-1..-1]=="{" or token[-1..-1]=="|"
      end
    end

    return indent, state
  end

  def each_indent_token(line)
    in_str = false
    str_chr = nil
    result = ""
    line.each_byte do |c|
      case c
      when 35 #  35=#
        unless in_str
          yield result.strip
          return
        end
      when 39 # 39='
        if in_str
          if str_chr==c
            in_str=false
          end
        else
          in_str = true
          str_chr = c
        end
      when 34 # 34="
        if in_str
          if str_chr==c
            in_str=false unless result[-1]==92
          end
        else
          in_str = true
          str_chr = c
        end
      when 59 #  59=;
        yield result.strip
        result=""
      end
      result += c.chr if c!=59
    end
    yield result.strip
  end

  def set_line_indentation(line, indent)
    #puts "line: #{line} indent: #{indent}"
    return if indent < 0
    sel_start = @model.selection_start
    sel_end = @model.selection_end
    pos_before = @model.get_line_indent_position(line)
    @model.set_line_indentation(line, indent)
    pos_after = @model.get_line_indent_position(line)
    pos_diff = pos_after - pos_before
    if pos_after > pos_before
      if sel_start >= pos_before
        sel_start = sel_start + pos_diff
      end
      if sel_end >= pos_before
        sel_end = sel_end + pos_diff
      end
    elsif pos_after < pos_before
      if sel_start >= pos_after
        if sel_start >= pos_before
          sel_start = sel_start + pos_diff
        else
          sel_start = pos_after
        end
      end
      if sel_end >= pos_after
        if sel_end >= pos_before
          sel_end = sel_end + pos_diff
        else
          sel_end = pos_after
        end
      end
    end
    @model.set_sel(sel_start, sel_end)
  end

end

syntax highlighted by Code2HTML, v. 0.9.1