diff --git a/docs/intro.rst b/docs/intro.rst
index 97b0a68c..7a863819 100644
--- a/docs/intro.rst
+++ b/docs/intro.rst
@@ -218,7 +218,7 @@ This is the current list of error and warning codes:
 +============+======================================================================+
 | **E1**     | *Indentation*                                                        |
 +------------+----------------------------------------------------------------------+
-| E101       | indentation contains mixed spaces and tabs                           |
+| E101       | non matching indentation levels                                      |
 +------------+----------------------------------------------------------------------+
 | E111       | indentation is not a multiple of four                                |
 +------------+----------------------------------------------------------------------+
@@ -232,6 +232,9 @@ This is the current list of error and warning codes:
 +------------+----------------------------------------------------------------------+
 | E116       | unexpected indentation (comment)                                     |
 +------------+----------------------------------------------------------------------+
+| E117       | expected tab, used space                                             |
++------------+----------------------------------------------------------------------+
+| E118       | expecting space, used tab                                            |
 +------------+----------------------------------------------------------------------+
 | E121 (\*^) | continuation line under-indented for hanging indent                  |
 +------------+----------------------------------------------------------------------+
diff --git a/pep8.py b/pep8.py
old mode 100755
new mode 100644
index b1916cce..7356453a
--- a/pep8.py
+++ b/pep8.py
@@ -138,8 +138,8 @@ def tabs_or_spaces(physical_line, indent_char):
     warnings about code that illegally mixes tabs and spaces.  When using -tt
     these warnings become errors.  These options are highly recommended!
 
-    Okay: if a == 0:\n        a = 1\n        b = 1
-    E101: if a == 0:\n        a = 1\n\tb = 1
+    Okay: if a == 0:\n    a = 1
+    E101: if a == 0:\n  \ta = 1
     """
     indent = INDENT_REGEX.match(physical_line).group(1)
     for offset, char in enumerate(indent):
@@ -351,8 +351,8 @@ def missing_whitespace(logical_line):
             yield index, "E231 missing whitespace after '%s'" % char
 
 
-def indentation(logical_line, previous_logical, indent_char,
-                indent_level, previous_indent_level):
+def indentation(logical_line, previous_logical, indent_char, initial_indent,
+                indent_level, previous_indent_level, physical_line):
     r"""Use 4 spaces per indentation level.
 
     For really old code that you don't want to mess up, you can continue to
@@ -370,14 +370,53 @@ def indentation(logical_line, previous_logical, indent_char,
     Okay: a = 1\nb = 2
     E113: a = 1\n    b = 2
     E116: a = 1\n    # b = 2
+
+    Okay: if a == 0:\n    a = 1\nif a == 1:\n    a = 1
+    W191: if a == 0:\n\ta = 1\nif a == 1:\n\ta = 1
+
+    E117: if a == 0:\n\ta = 1\nif a == 1:\n    a = 1
+
+    E118: # if a == 0:\n    a = 1\nif a == 1:\n\ta = 1
+
     """
+
     c = 0 if logical_line else 3
+    indent = INDENT_REGEX.match(physical_line).group(1)
+    tab = "\t"
     tmpl = "E11%d %s" if logical_line else "E11%d %s (comment)"
-    if indent_level % 4:
-        yield 0, tmpl % (1 + c, "indentation is not a multiple of four")
     indent_expect = previous_logical.endswith(':')
+
+    expectedTabs = previous_indent_level // 4 + 1
+    expectedSpaces = previous_indent_level + 4
+    numTabs = indent.count("\t")
+    numSpaces = sum(a.isspace() for a in indent) - numTabs
+
+    if indent_level % 4:
+        yield 0, tmpl % (1 + c, "indentation is not a multiple of 4")
+
     if indent_expect and indent_level <= previous_indent_level:
         yield 0, tmpl % (2 + c, "expected an indented block")
+    elif indent_expect and indent_level > previous_indent_level:
+        if initial_indent == tab:
+            if ' ' in indent:
+                yield 0, tmpl % (7, "TAB ERROR: %d tabs indentation "
+                                 "expected; indentation was %d tabs and "
+                                 "%d spaces" %
+                                 (expectedTabs, numTabs, numSpaces))
+            elif indent_level != previous_indent_level + 4:
+                yield 0, tmpl % (7, "TAB ERROR: %d tabs indentation "
+                                 "expected; indentation was %d tabs" %
+                                 (expectedTabs, numTabs))
+        else:
+            if tab in indent:
+                yield 0, tmpl % (8, "SPACE ERROR: %d spaces indentation "
+                                 "expected; indentation was %d tabs and "
+                                 "%d spaces" %
+                                 (expectedSpaces, numTabs, numSpaces))
+            elif indent_level != previous_indent_level + 4:
+                yield 0, tmpl % (8, "SPACE ERROR: %d SPACES indentation "
+                                 "expected; indentation was %d spaces" %
+                                 (expectedSpaces, indent_level))
     elif not indent_expect and indent_level > previous_indent_level:
         yield 0, tmpl % (3 + c, "unexpected indentation")
 
@@ -1207,18 +1246,18 @@ def expand_indent(line):
     >>> expand_indent('    ')
     4
     >>> expand_indent('\t')
-    8
+    4
     >>> expand_indent('       \t')
     8
     >>> expand_indent('        \t')
-    16
+    12
     """
     if '\t' not in line:
         return len(line) - len(line.lstrip())
     result = 0
     for char in line:
         if char == '\t':
-            result = result // 8 * 8 + 8
+            result = result // 4 * 4 + 4
         elif char == ' ':
             result += 1
         else:
@@ -1419,6 +1458,7 @@ def readline(self):
         self.line_number += 1
         if self.indent_char is None and line[:1] in WHITESPACE:
             self.indent_char = line[0]
+            self.initial_indent = line[0]
         return line
 
     def run_check(self, check, argument_names):
@@ -1574,6 +1614,7 @@ def check_all(self, expected=None, line_offset=0):
             self.check_ast()
         self.line_number = 0
         self.indent_char = None
+        self.initial_indent = None
         self.indent_level = self.previous_indent_level = 0
         self.previous_logical = ''
         self.tokens = []
diff --git a/testsuite/E11.py b/testsuite/E11.py
index 4ed10963..c2f29788 100644
--- a/testsuite/E11.py
+++ b/testsuite/E11.py
@@ -1,7 +1,7 @@
-#: E111
+#: E111 E118
 if x > 2:
   print x
-#: E111
+#: E111 E118
 if True:
      print
 #: E112
@@ -14,6 +14,26 @@
 mimetype = 'application/x-directory'
      # 'httpd/unix-directory'
 create_date = False
+#: E117 W191
+if True:
+		print
+#: E111 E118
+for a in 'abc':
+    for b in 'xyz':
+         print
+#: E101 E118 W191
+for a in 'abc':
+    for b in 'xyz':
+		print
+#: E101 E111 E117 W191 W191 W191
+for a in 'abc':
+	print
+	for b in 'xyz':
+	     print
+#: E101 E111 E117 W191 W191
+for a in 'abc':
+	for b in 'xyz':
+	     print
 #: E116 E116 E116
 def start(self):
     if True: