diff --git a/src/plugins/qtscripteditor/qtscripteditor.cpp b/src/plugins/qtscripteditor/qtscripteditor.cpp
index d751a87d39560e9290ac29ccb7ed58840819dbda..4a2c9cd489d3ee7f2df523eb88a0f55904d05774 100644
--- a/src/plugins/qtscripteditor/qtscripteditor.cpp
+++ b/src/plugins/qtscripteditor/qtscripteditor.cpp
@@ -31,6 +31,7 @@
 #include "qtscripteditorconstants.h"
 #include "qtscripthighlighter.h"
 #include "qtscripteditorplugin.h"
+#include "qtscriptindenter.h"
 
 #include "parser/javascriptengine_p.h"
 #include "parser/javascriptparser_p.h"
@@ -39,7 +40,6 @@
 #include "parser/javascriptastvisitor_p.h"
 #include "parser/javascriptast_p.h"
 
-#include <indenter.h>
 #include <utils/uncommentselection.h>
 
 #include <coreplugin/icore.h>
@@ -338,29 +338,18 @@ bool ScriptEditor::isElectricCharacter(const QChar &ch) const
     return false;
 }
 
-    // Indent a code line based on previous
-template <class Iterator>
-static void indentScriptBlock(const TextEditor::TabSettings &ts,
-                              const QTextBlock &block,
-                              const Iterator &programBegin,
-                              const Iterator &programEnd,
-                              QChar typedChar)
-{
-    typedef typename SharedTools::Indenter<Iterator> Indenter ;
-    Indenter &indenter = Indenter::instance();
-    indenter.setTabSize(ts.m_tabSize);
-    indenter.setIndentSize(ts.m_indentSize);
-    const TextEditor::TextBlockIterator current(block);
-    const int indent = indenter.indentForBottomLine(current, programBegin,
-                                                    programEnd, typedChar);
-    ts.indentLine(block, indent);
-}
-
 void ScriptEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar)
 {
     const TextEditor::TextBlockIterator begin(doc->begin());
     const TextEditor::TextBlockIterator end(block.next());
-    indentScriptBlock(tabSettings(), block, begin, end, typedChar);
+
+    TextEditor::TabSettings ts = tabSettings();
+    QtScriptIndenter indenter;
+    indenter.setTabSize(ts.m_tabSize);
+    indenter.setIndentSize(ts.m_indentSize);
+
+    const int indent = indenter.indentForBottomLine(begin, end, typedChar);
+    ts.indentLine(block, indent);
 }
 
 TextEditor::BaseTextEditorEditable *ScriptEditor::createEditableInterface()
diff --git a/src/plugins/qtscripteditor/qtscripteditor.pro b/src/plugins/qtscripteditor/qtscripteditor.pro
index 2ff0c5699e75db66a4d99252dcacf114e2cf597a..f3257a52a778dc18b18416d68c7f3a37fd2e718f 100644
--- a/src/plugins/qtscripteditor/qtscripteditor.pro
+++ b/src/plugins/qtscripteditor/qtscripteditor.pro
@@ -13,12 +13,14 @@ HEADERS += qtscripteditor.h \
 qtscripteditorfactory.h \
 qtscripteditorplugin.h \
 qtscripthighlighter.h \
+qtscriptindenter.h \
 qtscriptcodecompletion.h
 
 SOURCES += qtscripteditor.cpp \
 qtscripteditorfactory.cpp \
 qtscripteditorplugin.cpp \
 qtscripthighlighter.cpp \
+qtscriptindenter.cpp \
 qtscriptcodecompletion.cpp
 
 RESOURCES += qtscripteditor.qrc
diff --git a/src/plugins/qtscripteditor/qtscriptindenter.cpp b/src/plugins/qtscripteditor/qtscriptindenter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7f6bb1ae601c98b80348f5cb2b81b975d11d182e
--- /dev/null
+++ b/src/plugins/qtscripteditor/qtscriptindenter.cpp
@@ -0,0 +1,1064 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+/*
+    This file is a self-contained interactive indenter for Qt Script.
+
+    The general problem of indenting a program is ill posed. On
+    the one hand, an indenter has to analyze programs written in a
+    free-form formal language that is best described in terms of
+    tokens, not characters, not lines. On the other hand, indentation
+    applies to lines and white space characters matter, and otherwise
+    the programs to indent are formally invalid in general, as they
+    are begin edited.
+
+    The approach taken here works line by line. We receive a program
+    consisting of N lines or more, and we want to compute the
+    indentation appropriate for the Nth line. Lines beyond the Nth
+    lines are of no concern to us, so for simplicity we pretend the
+    program has exactly N lines and we call the Nth line the "bottom
+    line". Typically, we have to indent the bottom line when it's
+    still empty, so we concentrate our analysis on the N - 1 lines
+    that precede.
+
+    By inspecting the (N - 1)-th line, the (N - 2)-th line, ...
+    backwards, we determine the kind of the bottom line and indent it
+    accordingly.
+
+      * The bottom line is a comment line. See
+        bottomLineStartsInCComment() and
+        indentWhenBottomLineStartsInCComment().
+      * The bottom line is a continuation line. See isContinuationLine()
+        and indentForContinuationLine().
+      * The bottom line is a standalone line. See
+        indentForStandaloneLine().
+
+    Certain tokens that influence the indentation, notably braces,
+    are looked for in the lines. This is done by simple string
+    comparison, without a real tokenizer. Confusing constructs such
+    as comments and string literals are removed beforehand.
+*/
+
+#include "qtscriptindenter.h"
+
+using namespace QtScriptEditor::Internal;
+
+/*
+    The indenter avoids getting stuck in almost infinite loops by
+    imposing arbitrary limits on the number of lines it analyzes when
+    looking for a construct.
+
+    For example, the indenter never considers more than BigRoof lines
+    backwards when looking for the start of a C-style comment.
+*/
+const int QtScriptIndenter::SmallRoof = 40;
+const int QtScriptIndenter::BigRoof = 400;
+
+QtScriptIndenter::QtScriptIndenter()
+    : literal(QRegExp(QLatin1String("([\"'])(?:\\\\.|[^\\\\])*\\1"))),
+      label(QRegExp(QLatin1String("^\\s*((?:case\\b([^:]|::)+|[a-zA-Z_0-9]+)(?:\\s+slots)?:)(?!:)"))),
+      inlineCComment(QRegExp(QLatin1String("/\\*.*\\*/"))),
+      braceX(QRegExp(QLatin1String("^\\s*\\}\\s*(?:else|catch)\\b"))),
+      iflikeKeyword(QRegExp(QLatin1String("\\b(?:catch|do|for|if|while|with)\\b")))
+{
+
+    /*
+        The indenter supports a few parameters:
+
+          * ppHardwareTabSize is the size of a '\t' in your favorite editor.
+          * ppIndentSize is the size of an indentation, or software tab
+            size.
+          * ppContinuationIndentSize is the extra indent for a continuation
+            line, when there is nothing to align against on the previous
+            line.
+          * ppCommentOffset is the indentation within a C-style comment,
+            when it cannot be picked up.
+    */
+
+    ppHardwareTabSize = 8;
+    ppIndentSize = 4;
+    ppContinuationIndentSize = 8;
+    ppCommentOffset = 2;
+
+    /*
+        The "linizer" is a group of functions and variables to iterate
+        through the source code of the program to indent. The program is
+        given as a list of strings, with the bottom line being the line
+        to indent. The actual program might contain extra lines, but
+        those are uninteresting and not passed over to us.
+    */
+
+    // shorthands
+    yyLine = 0;
+    yyBraceDepth = 0;
+    yyLeftBraceFollows = 0;
+
+    literal.setMinimal(true);
+    inlineCComment.setMinimal(true);
+}
+
+QtScriptIndenter::~QtScriptIndenter()
+{
+}
+
+void QtScriptIndenter::setTabSize(int size)
+{
+    ppHardwareTabSize = size;
+}
+
+void QtScriptIndenter::setIndentSize(int size)
+{
+    ppIndentSize = size;
+    ppContinuationIndentSize = 2 * size;
+}
+
+/*
+    Returns the first non-space character in the string t, or
+    QChar() if the string is made only of white space.
+*/
+QChar QtScriptIndenter::firstNonWhiteSpace(const QString &t)
+{
+    int i = 0;
+    while (i < t.length()) {
+        if (!t.at(i).isSpace())
+            return t.at(i);
+        i++;
+    }
+    return QChar();
+}
+
+/*
+    Returns true if string t is made only of white space; otherwise
+    returns false.
+*/
+bool QtScriptIndenter::isOnlyWhiteSpace(const QString &t)
+{
+    return firstNonWhiteSpace(t).isNull();
+}
+
+/*
+    Assuming string t is a line, returns the column number of a given
+    index. Column numbers and index are identical for strings that don't
+    contain '\t's.
+*/
+int QtScriptIndenter::columnForIndex(const QString &t, int index)
+{
+    int col = 0;
+    if (index > t.length())
+        index = t.length();
+
+    for (int i = 0; i < index; i++) {
+        if (t.at(i) == QLatin1Char('\t')) {
+            col = ((col / ppHardwareTabSize) + 1) * ppHardwareTabSize;
+        } else {
+            col++;
+        }
+    }
+    return col;
+}
+
+/*
+    Returns the indentation size of string t.
+*/
+int QtScriptIndenter::indentOfLine(const QString &t)
+{
+    return columnForIndex(t, t.indexOf(firstNonWhiteSpace(t)));
+}
+
+/*
+    Replaces t[k] by ch, unless t[k] is '\t'. Tab characters are better
+    left alone since they break the "index equals column" rule. No
+    provisions are taken against '\n' or '\r', which shouldn't occur in
+    t anyway.
+*/
+inline void QtScriptIndenter::eraseChar(QString &t, int k, QChar ch)
+{
+    if (t.at(k) != QLatin1Char('\t'))
+        t[k] = ch;
+}
+
+/*
+   Removes some nefast constructs from a code line and returns the
+   resulting line.
+*/
+QString QtScriptIndenter::trimmedCodeLine(const QString &t)
+{
+    QString trimmed = t;
+    int k;
+
+    /*
+        Replace character and string literals by X's, since they may
+        contain confusing characters (such as '{' and ';'). "Hello!" is
+        replaced by XXXXXXXX. The literals are rigourously of the same
+        length before and after; otherwise, we would break alignment of
+        continuation lines.
+    */
+    k = 0;
+    while ((k = trimmed.indexOf(literal, k)) != -1) {
+        for (int i = 0; i < literal.matchedLength(); i++)
+            eraseChar(trimmed, k + i, QLatin1Char('X'));
+        k += literal.matchedLength();
+    }
+
+    /*
+        Replace inline C-style comments by spaces. Other comments are
+        handled elsewhere.
+    */
+    k = 0;
+    while ((k = trimmed.indexOf(inlineCComment, k)) != -1) {
+        for (int i = 0; i < inlineCComment.matchedLength(); i++)
+            eraseChar(trimmed, k + i, QLatin1Char(' '));
+        k += inlineCComment.matchedLength();
+    }
+
+    /*
+        Replace goto and switch labels by whitespace, but be careful
+        with this case:
+
+        foo1: bar1;
+                bar2;
+    */
+    while (trimmed.lastIndexOf(QLatin1Char(':')) != -1 && trimmed.indexOf(label) != -1) {
+        const QString cap1 = label.cap(1);
+        int pos1 = label.pos(1);
+        int stop = cap1.length();
+
+        if (pos1 + stop < trimmed.length() && ppIndentSize < stop)
+            stop = ppIndentSize;
+
+        int i = 0;
+        while (i < stop) {
+            eraseChar(trimmed, pos1 + i, QLatin1Char(' '));
+            i++;
+        }
+        while (i < cap1.length()) {
+            eraseChar(trimmed, pos1 + i, QLatin1Char(';'));
+            i++;
+        }
+    }
+
+    /*
+        Remove C++-style comments.
+    */
+    k = trimmed.indexOf(QLatin1String("//"));
+    if (k != -1)
+        trimmed.truncate(k);
+
+    return trimmed;
+}
+
+/*
+    Returns '(' if the last parenthesis is opening, ')' if it is
+    closing, and QChar() if there are no parentheses in t.
+*/
+inline QChar QtScriptIndenter::lastParen(const QString &t)
+{
+    int i = t.length();
+    while (i > 0) {
+        i--;
+        if (t.at(i) == QLatin1Char('(') || t.at(i) == QLatin1Char(')'))
+            return t.at(i);
+    }
+    return QChar();
+}
+
+/*
+    Returns true if typedIn the same as okayCh or is null; otherwise
+    returns false.
+*/
+inline bool QtScriptIndenter::okay(QChar typedIn, QChar okayCh)
+{
+    return typedIn == QChar() || typedIn == okayCh;
+}
+
+/*
+    Saves and restores the state of the global linizer. This enables
+    backtracking.
+*/
+#define YY_SAVE() LinizerState savedState = yyLinizerState
+#define YY_RESTORE() yyLinizerState = savedState
+
+/*
+    Advances to the previous line in yyProgram and update yyLine
+    accordingly. yyLine is cleaned from comments and other damageable
+    constructs. Empty lines are skipped.
+*/
+bool QtScriptIndenter::readLine()
+{
+    int k;
+
+    yyLinizerState.leftBraceFollows =
+            (firstNonWhiteSpace(yyLinizerState.line) == QLatin1Char('{'));
+
+    do {
+        if (yyLinizerState.iter == yyProgram.constBegin()) {
+            yyLinizerState.line.clear();
+            return false;
+        }
+
+        --yyLinizerState.iter;
+        yyLinizerState.line = *yyLinizerState.iter;
+
+        yyLinizerState.line = trimmedCodeLine(yyLinizerState.line);
+
+        /*
+            Remove C-style comments that span multiple lines. If the
+            bottom line starts in a C-style comment, we are not aware
+            of that and eventually yyLine will contain a slash-aster.
+
+            Notice that both if's can be executed, since
+            yyLinizerState.inCComment is potentially set to false in
+            the first if. The order of the if's is also important.
+        */
+
+        if (yyLinizerState.inCComment) {
+            const QLatin1String slashAster("/*");
+
+            k = yyLinizerState.line.indexOf(slashAster);
+            if (k == -1) {
+                yyLinizerState.line.clear();
+            } else {
+                yyLinizerState.line.truncate(k);
+                yyLinizerState.inCComment = false;
+            }
+        }
+
+        if (!yyLinizerState.inCComment) {
+            const QLatin1String asterSlash("*/");
+
+            k = yyLinizerState.line.indexOf(asterSlash);
+            if (k != -1) {
+                for (int i = 0; i < k + 2; i++)
+                    eraseChar(yyLinizerState.line, i, QLatin1Char(' '));
+                yyLinizerState.inCComment = true;
+            }
+        }
+
+        /*
+            Remove preprocessor directives.
+        */
+        k = 0;
+        while (k < yyLinizerState.line.length()) {
+            const QChar ch = yyLinizerState.line.at(k);
+            if (ch == QLatin1Char('#')) {
+                yyLinizerState.line.clear();
+            } else if (!ch.isSpace()) {
+                break;
+            }
+            k++;
+        }
+
+        /*
+            Remove trailing spaces.
+        */
+        k = yyLinizerState.line.length();
+        while (k > 0 && yyLinizerState.line.at(k - 1).isSpace())
+            k--;
+        yyLinizerState.line.truncate(k);
+
+        /*
+            '}' increment the brace depth and '{' decrements it and not
+            the other way around, as we are parsing backwards.
+        */
+        yyLinizerState.braceDepth +=
+                yyLinizerState.line.count('}') -
+                yyLinizerState.line.count('{');
+
+        /*
+            We use a dirty trick for
+
+                } else ...
+
+            We don't count the '}' yet, so that it's more or less
+            equivalent to the friendly construct
+
+                }
+                else ...
+        */
+        if (yyLinizerState.pendingRightBrace)
+            yyLinizerState.braceDepth++;
+        yyLinizerState.pendingRightBrace =
+                (yyLinizerState.line.indexOf(braceX) == 0);
+        if (yyLinizerState.pendingRightBrace)
+            yyLinizerState.braceDepth--;
+    } while (yyLinizerState.line.isEmpty());
+
+    return true;
+}
+
+/*
+    Resets the linizer to its initial state, with yyLine containing the
+    line above the bottom line of the program.
+*/
+void QtScriptIndenter::startLinizer()
+{
+    yyLinizerState.braceDepth = 0;
+    yyLinizerState.inCComment = false;
+    yyLinizerState.pendingRightBrace = false;
+
+    yyLine = &yyLinizerState.line;
+    yyBraceDepth = &yyLinizerState.braceDepth;
+    yyLeftBraceFollows = &yyLinizerState.leftBraceFollows;
+
+    yyLinizerState.iter = yyProgram.constEnd();
+    --yyLinizerState.iter;
+    yyLinizerState.line = *yyLinizerState.iter;
+    readLine();
+}
+
+/*
+    Returns true if the start of the bottom line of yyProgram (and
+    potentially the whole line) is part of a C-style comment;
+    otherwise returns false.
+*/
+bool QtScriptIndenter::bottomLineStartsInCComment()
+{
+    const QLatin1String slashAster("/*");
+    const QLatin1String asterSlash("*/");
+
+    /*
+        We could use the linizer here, but that would slow us down
+        terribly. We are better to trim only the code lines we need.
+    */
+    Program::const_iterator p = yyProgram.constEnd();
+    --p; // skip bottom line
+
+    for (int i = 0; i < BigRoof; i++) {
+        if (p == yyProgram.constBegin())
+            return false;
+        --p;
+
+        const QString blockText = *p;
+
+        if (blockText.indexOf(slashAster) != -1 || blockText.indexOf(asterSlash) != -1) {
+            const QString trimmed = trimmedCodeLine(blockText);
+
+            if (trimmed.indexOf(slashAster) != -1) {
+                return true;
+            } else if (trimmed.indexOf(asterSlash) != -1) {
+                return false;
+            }
+        }
+    }
+    return false;
+}
+
+/*
+    Returns the recommended indent for the bottom line of yyProgram
+    assuming that it starts in a C-style comment, a condition that is
+    tested elsewhere.
+
+    Essentially, we're trying to align against some text on the
+    previous line.
+*/
+int QtScriptIndenter::indentWhenBottomLineStartsInCComment()
+{
+    int k = yyLine->lastIndexOf(QLatin1String("/*"));
+    if (k == -1) {
+        /*
+          We found a normal text line in a comment. Align the
+          bottom line with the text on this line.
+        */
+        return indentOfLine(*yyLine);
+    } else {
+        /*
+          The C-style comment starts on this line. If there is
+          text on the same line, align with it. Otherwise, align
+          with the slash-aster plus a given offset.
+        */
+        int indent = columnForIndex(*yyLine, k);
+        k += 2;
+        while (k < yyLine->length()) {
+            if (!yyLine->at(k).isSpace())
+                return columnForIndex(*yyLine, k);
+            k++;
+        }
+        return indent + ppCommentOffset;
+    }
+}
+
+/*
+    A function called match...() modifies the linizer state. If it
+    returns true, yyLine is the top line of the matched construct;
+    otherwise, the linizer is left in an unknown state.
+
+    A function called is...() keeps the linizer state intact.
+*/
+
+/*
+    Returns true if the current line (and upwards) forms a braceless
+    control statement; otherwise returns false.
+
+    The first line of the following example is a "braceless control
+    statement":
+
+        if (x)
+            y;
+*/
+bool QtScriptIndenter::matchBracelessControlStatement()
+{
+    int delimDepth = 0;
+
+    if (yyLine->endsWith(QLatin1String("else")))
+        return true;
+
+    if (!yyLine->endsWith(QLatin1String(")")))
+        return false;
+
+    for (int i = 0; i < SmallRoof; i++) {
+        int j = yyLine->length();
+        while (j > 0) {
+            j--;
+            QChar ch = yyLine->at(j);
+
+            switch (ch.unicode()) {
+            case ')':
+                delimDepth++;
+                break;
+            case '(':
+                delimDepth--;
+                if (delimDepth == 0) {
+                    if (yyLine->indexOf(iflikeKeyword) != -1) {
+                        /*
+                            We have
+
+                                if (x)
+                                    y
+
+                            "if (x)" is not part of the statement
+                            "y".
+                        */
+                        return true;
+                    }
+                }
+                if (delimDepth == -1) {
+                    /*
+                      We have
+
+                          if ((1 +
+                                2)
+
+                      and not
+
+                          if (1 +
+                               2)
+                    */
+                    return false;
+                }
+                break;
+            case '{':
+            case '}':
+            case ';':
+                /*
+                    We met a statement separator, but not where we
+                    expected it. What follows is probably a weird
+                    continuation line. Be careful with ';' in for,
+                    though.
+                */
+                if (ch != QLatin1Char(';') || delimDepth == 0)
+                    return false;
+            }
+        }
+
+        if (!readLine())
+            break;
+    }
+    return false;
+}
+
+/*
+    Returns true if yyLine is an unfinished line; otherwise returns
+    false.
+
+    In many places we'll use the terms "standalone line", "unfinished
+    line" and "continuation line". The meaning of these should be
+    evident from this code example:
+
+        a = b;    // standalone line
+        c = d +   // unfinished line
+            e +   // unfinished continuation line
+            f +   // unfinished continuation line
+            g;    // continuation line
+*/
+bool QtScriptIndenter::isUnfinishedLine()
+{
+    bool unf = false;
+
+    YY_SAVE();
+
+    if (yyLine->isEmpty())
+        return false;
+
+    QChar lastCh = yyLine->at(yyLine->length() - 1);
+    if (QString::fromLatin1("{};").indexOf(lastCh) == -1 && !yyLine->endsWith("...")) {
+        /*
+          It doesn't end with ';' or similar. If it's neither
+          "Q_OBJECT" nor "if (x)", it must be an unfinished line.
+        */
+        unf = (yyLine->indexOf(QLatin1String("Q_OBJECT")) == -1 &&
+                !matchBracelessControlStatement());
+    } else if (lastCh == QLatin1Char(';')) {
+        if (lastParen(*yyLine) == QLatin1Char('(')) {
+            /*
+              Exception:
+
+                  for (int i = 1; i < 10;
+            */
+            unf = true;
+        } else if (readLine() && yyLine->endsWith(QLatin1String(";")) &&
+                    lastParen(*yyLine) == QLatin1Char('(')) {
+            /*
+              Exception:
+
+                  for (int i = 1;
+                        i < 10;
+            */
+            unf = true;
+        }
+    }
+
+    YY_RESTORE();
+    return unf;
+}
+
+/*
+    Returns true if yyLine is a continuation line; otherwise returns
+    false.
+*/
+bool QtScriptIndenter::isContinuationLine()
+{
+    bool cont = false;
+
+    YY_SAVE();
+    if (readLine())
+        cont = isUnfinishedLine();
+    YY_RESTORE();
+    return cont;
+}
+
+/*
+    Returns the recommended indent for the bottom line of yyProgram,
+    assuming it's a continuation line.
+
+    We're trying to align the continuation line against some parenthesis
+    or other bracked left opened on a previous line, or some interesting
+    operator such as '='.
+*/
+int QtScriptIndenter::indentForContinuationLine()
+{
+    int braceDepth = 0;
+    int delimDepth = 0;
+
+    bool leftBraceFollowed = *yyLeftBraceFollows;
+
+    for (int i = 0; i < SmallRoof; i++) {
+        int hook = -1;
+
+        int j = yyLine->length();
+        while (j > 0 && hook < 0) {
+            j--;
+            QChar ch = yyLine->at(j);
+
+            switch (ch.unicode()) {
+            case ')':
+            case ']':
+                delimDepth++;
+                break;
+            case '}':
+                braceDepth++;
+                break;
+            case '(':
+            case '[':
+                delimDepth--;
+                /*
+                    An unclosed delimiter is a good place to align at,
+                    at least for some styles (including Qt's).
+                */
+                if (delimDepth == -1)
+                    hook = j;
+                break;
+            case '{':
+                braceDepth--;
+                /*
+                    A left brace followed by other stuff on the same
+                    line is typically for an enum or an initializer.
+                    Such a brace must be treated just like the other
+                    delimiters.
+                */
+                if (braceDepth == -1) {
+                    if (j < yyLine->length() - 1) {
+                        hook = j;
+                    } else {
+                        return 0; // shouldn't happen
+                    }
+                }
+                break;
+            case '=':
+                /*
+                    An equal sign is a very natural alignment hook
+                    because it's usually the operator with the lowest
+                    precedence in statements it appears in. Case in
+                    point:
+
+                        int x = 1 +
+                                2;
+
+                    However, we have to beware of constructs such as
+                    default arguments and explicit enum constant
+                    values:
+
+                        void foo(int x = 0,
+                                  int y = 0);
+
+                    And not
+
+                        void foo(int x = 0,
+                                        int y = 0);
+
+                    These constructs are caracterized by a ',' at the
+                    end of the unfinished lines or by unbalanced
+                    parentheses.
+                */
+                Q_ASSERT(j - 1 >= 0);
+
+                if (QString::fromLatin1("!=<>").indexOf(yyLine->at(j - 1)) == -1 &&
+                     j + 1 < yyLine->length() && yyLine->at(j + 1) != '=') {
+                    if (braceDepth == 0 && delimDepth == 0 &&
+                         j < yyLine->length() - 1 &&
+                         !yyLine->endsWith(QLatin1String(",")) &&
+                         (yyLine->contains('(') == yyLine->contains(')')))
+                        hook = j;
+                }
+            }
+        }
+
+        if (hook >= 0) {
+            /*
+                Yes, we have a delimiter or an operator to align
+                against! We don't really align against it, but rather
+                against the following token, if any. In this example,
+                the following token is "11":
+
+                    int x = (11 +
+                              2);
+
+                If there is no such token, we use a continuation indent:
+
+                    static QRegExp foo(QString(
+                            "foo foo foo foo foo foo foo foo foo"));
+            */
+            hook++;
+            while (hook < yyLine->length()) {
+                if (!yyLine->at(hook).isSpace())
+                    return columnForIndex(*yyLine, hook);
+                hook++;
+            }
+            return indentOfLine(*yyLine) + ppContinuationIndentSize;
+        }
+
+        if (braceDepth != 0)
+            break;
+
+        /*
+            The line's delimiters are balanced. It looks like a
+            continuation line or something.
+        */
+        if (delimDepth == 0) {
+            if (leftBraceFollowed) {
+                /*
+                    We have
+
+                        int main()
+                        {
+
+                    or
+
+                        Bar::Bar()
+                            : Foo(x)
+                        {
+
+                    The "{" should be flush left.
+                */
+                if (!isContinuationLine())
+                    return indentOfLine(*yyLine);
+            } else if (isContinuationLine() || yyLine->endsWith(QLatin1String(","))) {
+                /*
+                    We have
+
+                        x = a +
+                            b +
+                            c;
+
+                    or
+
+                        int t[] = {
+                            1, 2, 3,
+                            4, 5, 6
+
+                    The "c;" should fall right under the "b +", and the
+                    "4, 5, 6" right under the "1, 2, 3,".
+                */
+                return indentOfLine(*yyLine);
+            } else {
+                /*
+                    We have
+
+                        stream << 1 +
+                                2;
+
+                    We could, but we don't, try to analyze which
+                    operator has precedence over which and so on, to
+                    obtain the excellent result
+
+                        stream << 1 +
+                                  2;
+
+                    We do have a special trick above for the assignment
+                    operator above, though.
+                */
+                return indentOfLine(*yyLine) + ppContinuationIndentSize;
+            }
+        }
+
+        if (!readLine())
+            break;
+    }
+    return 0;
+}
+
+/*
+    Returns the recommended indent for the bottom line of yyProgram if
+    that line is standalone (or should be indented likewise).
+
+    Indenting a standalone line is tricky, mostly because of braceless
+    control statements. Grossly, we are looking backwards for a special
+    line, a "hook line", that we can use as a starting point to indent,
+    and then modify the indentation level according to the braces met
+    along the way to that hook.
+
+    Let's consider a few examples. In all cases, we want to indent the
+    bottom line.
+
+    Example 1:
+
+        x = 1;
+        y = 2;
+
+    The hook line is "x = 1;". We met 0 opening braces and 0 closing
+    braces. Therefore, "y = 2;" inherits the indent of "x = 1;".
+
+    Example 2:
+
+        if (x) {
+            y;
+
+    The hook line is "if (x) {". No matter what precedes it, "y;" has
+    to be indented one level deeper than the hook line, since we met one
+    opening brace along the way.
+
+    Example 3:
+
+        if (a)
+            while (b) {
+                c;
+            }
+        d;
+
+    To indent "d;" correctly, we have to go as far as the "if (a)".
+    Compare with
+
+        if (a) {
+            while (b) {
+                c;
+            }
+            d;
+
+    Still, we're striving to go back as little as possible to
+    accommodate people with irregular indentation schemes. A hook line
+    near at hand is much more reliable than a remote one.
+*/
+int QtScriptIndenter::indentForStandaloneLine()
+{
+    for (int i = 0; i < SmallRoof; i++) {
+        if (!*yyLeftBraceFollows) {
+            YY_SAVE();
+
+            if (matchBracelessControlStatement()) {
+                /*
+                    The situation is this, and we want to indent "z;":
+
+                        if (x &&
+                             y)
+                            z;
+
+                    yyLine is "if (x &&".
+                */
+                return indentOfLine(*yyLine) + ppIndentSize;
+            }
+            YY_RESTORE();
+        }
+
+        if (yyLine->endsWith(QLatin1Char(';')) || yyLine->contains(QLatin1Char('{'))) {
+            /*
+                The situation is possibly this, and we want to indent
+                "z;":
+
+                    while (x)
+                        y;
+                    z;
+
+                We return the indent of "while (x)". In place of "y;",
+                any arbitrarily complex compound statement can appear.
+            */
+
+            if (*yyBraceDepth > 0) {
+                do {
+                    if (!readLine())
+                        break;
+                } while (*yyBraceDepth > 0);
+            }
+
+            LinizerState hookState;
+
+            while (isContinuationLine())
+                readLine();
+            hookState = yyLinizerState;
+
+            readLine();
+            if (*yyBraceDepth <= 0) {
+                do {
+                    if (!matchBracelessControlStatement())
+                        break;
+                    hookState = yyLinizerState;
+                } while (readLine());
+            }
+
+            yyLinizerState = hookState;
+
+            while (isContinuationLine())
+                readLine();
+
+            /*
+              Never trust lines containing only '{' or '}', as some
+              people (Richard M. Stallman) format them weirdly.
+            */
+            if (yyLine->trimmed().length() > 1)
+                return indentOfLine(*yyLine) - *yyBraceDepth * ppIndentSize;
+        }
+
+        if (!readLine())
+            return -*yyBraceDepth * ppIndentSize;
+    }
+    return 0;
+}
+
+/*
+    Returns the recommended indent for the bottom line of program.
+    Unless null, typedIn stores the character of yyProgram that
+    triggered reindentation.
+
+    This function works better if typedIn is set properly; it is
+    slightly more conservative if typedIn is completely wild, and
+    slighly more liberal if typedIn is always null. The user might be
+    annoyed by the liberal behavior.
+*/
+int QtScriptIndenter::indentForBottomLine(TextEditor::TextBlockIterator begin, TextEditor::TextBlockIterator end, QChar typedIn)
+{
+    if (begin == end)
+        return 0;
+
+    yyProgram = Program(begin, end);
+    startLinizer();
+
+    TextEditor::TextBlockIterator last = end;
+    --last;
+
+    const QString &bottomLine = *last;
+    QChar firstCh = firstNonWhiteSpace(bottomLine);
+    int indent;
+
+    if (bottomLineStartsInCComment()) {
+        /*
+            The bottom line starts in a C-style comment. Indent it
+            smartly, unless the user has already played around with it,
+            in which case it's better to leave her stuff alone.
+        */
+        if (isOnlyWhiteSpace(bottomLine)) {
+            indent = indentWhenBottomLineStartsInCComment();
+        } else {
+            indent = indentOfLine(bottomLine);
+        }
+    } else if (okay(typedIn, QLatin1Char('#')) && firstCh == QLatin1Char('#')) {
+        /*
+            Preprocessor directives go flush left.
+        */
+        indent = 0;
+    } else {
+        if (isUnfinishedLine()) {
+            indent = indentForContinuationLine();
+        } else {
+            indent = indentForStandaloneLine();
+        }
+
+        if (okay(typedIn, QLatin1Char('}')) && firstCh == QLatin1Char('}')) {
+            /*
+                A closing brace is one level more to the left than the
+                code it follows.
+            */
+            indent -= ppIndentSize;
+        } else if (okay(typedIn, QLatin1Char(':'))) {
+            QRegExp caseLabel(
+                "\\s*(?:case\\b(?:[^:]|::)+"
+                "|(?:default)\\s*"
+                ")?:.*");
+
+            if (caseLabel.exactMatch(bottomLine)) {
+                /*
+                    Move a case label (or the ':' in front of a
+                    constructor initialization list) one level to the
+                    left, but only if the user did not play around with
+                    it yet. Some users have exotic tastes in the
+                    matter, and most users probably are not patient
+                    enough to wait for the final ':' to format their
+                    code properly.
+
+                    We don't attempt the same for goto labels, as the
+                    user is probably the middle of "foo::bar". (Who
+                    uses goto, anyway?)
+                */
+                if (indentOfLine(bottomLine) <= indent)
+                    indent -= ppIndentSize;
+                else
+                    indent = indentOfLine(bottomLine);
+            }
+        }
+    }
+
+    return qMax(0, indent);
+}
diff --git a/src/plugins/qtscripteditor/qtscriptindenter.h b/src/plugins/qtscripteditor/qtscriptindenter.h
new file mode 100644
index 0000000000000000000000000000000000000000..215d15152b086098303bb330453efbdfddb6ef6d
--- /dev/null
+++ b/src/plugins/qtscripteditor/qtscriptindenter.h
@@ -0,0 +1,144 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QTSCRIPTINDENTER_H
+#define QTSCRIPTINDENTER_H
+
+#include <QtCore/QRegExp>
+#include <QtCore/QStringList>
+#include <texteditor/textblockiterator.h>
+
+namespace QtScriptEditor {
+namespace Internal {
+
+class QtScriptIndenter
+{
+    Q_DISABLE_COPY(QtScriptIndenter)
+
+public:
+    QtScriptIndenter();
+    ~QtScriptIndenter();
+
+    void setTabSize(int size);
+    void setIndentSize(int size);
+
+    int indentForBottomLine(TextEditor::TextBlockIterator begin, TextEditor::TextBlockIterator end, QChar typedIn);
+    QChar firstNonWhiteSpace(const QString &t);
+
+private:
+    static const int SmallRoof;
+    static const int BigRoof;
+
+    bool isOnlyWhiteSpace(const QString &t);
+    int columnForIndex(const QString &t, int index);
+    int indentOfLine(const QString &t);
+    QString trimmedCodeLine(const QString &t);
+
+    inline void eraseChar(QString &t, int k, QChar ch);
+    inline QChar lastParen(const QString &t);
+    inline bool okay(QChar typedIn, QChar okayCh);
+
+    /*
+        The "linizer" is a group of functions and variables to iterate
+        through the source code of the program to indent. The program is
+        given as a list of strings, with the bottom line being the line
+        to indent. The actual program might contain extra lines, but
+        those are uninteresting and not passed over to us.
+    */
+
+    bool readLine();
+    void startLinizer();
+    bool bottomLineStartsInCComment();
+    int indentWhenBottomLineStartsInCComment();
+    bool matchBracelessControlStatement();
+    bool isUnfinishedLine();
+    bool isContinuationLine();
+    int indentForContinuationLine();
+    int indentForStandaloneLine();
+
+private:
+    int ppHardwareTabSize;
+    int ppIndentSize;
+    int ppContinuationIndentSize;
+    int ppCommentOffset;
+
+private:
+    struct LinizerState
+    {
+        LinizerState()
+            : braceDepth(0),
+              leftBraceFollows(false),
+              inCComment(false),
+              pendingRightBrace(false)
+        { }
+
+        int braceDepth;
+        bool leftBraceFollows;
+        bool inCComment;
+        bool pendingRightBrace;
+        QString line;
+        TextEditor::TextBlockIterator iter;
+    };
+
+    struct Program {
+        TextEditor::TextBlockIterator b, e;
+        typedef TextEditor::TextBlockIterator iterator;
+        typedef TextEditor::TextBlockIterator const_iterator;
+
+        Program() {}
+        Program(TextEditor::TextBlockIterator begin, TextEditor::TextBlockIterator end)
+            : b(begin), e(end) {}
+
+        iterator begin() const { return b; }
+        iterator end() const { return e; }
+
+        const_iterator constBegin() const { return b; }
+        const_iterator constEnd() const { return e; }
+    };
+
+    Program yyProgram;
+    LinizerState yyLinizerState;
+
+    // shorthands
+    const QString *yyLine;
+    const int *yyBraceDepth;
+    const bool *yyLeftBraceFollows;
+
+    QRegExp literal;
+    QRegExp label;
+    QRegExp inlineCComment;
+    QRegExp braceX;
+    QRegExp iflikeKeyword;
+};
+
+} // namespace Internal
+} // namespace QtScriptEditor
+
+#endif // QTSCRIPTINDENTER_H
+