Index: django/utils/text.py
===================================================================
--- django/utils/text.py	(revision 7141)
+++ django/utils/text.py	(working copy)
@@ -10,29 +10,33 @@
 
 def wrap(text, width):
     """
-    A word-wrap function that preserves existing line breaks and most spaces in
-    the text. Expects that existing line breaks are posix newlines.
+    A word-wrap function that preserves existing line breaks. Expects that
+    existing line breaks are posix newlines.
+
+    All white space is preserved except added line breaks consume the space on
+    which they break the line.
+
+    Long words are not wrapped, so the output text may have lines longer than
+    ``width``.
     """
     text = force_unicode(text)
     def _generator():
-        it = iter(text.split(' '))
-        word = it.next()
-        yield word
-        pos = len(word) - word.rfind('\n') - 1
-        for word in it:
-            if "\n" in word:
-                lines = word.split('\n')
-            else:
-                lines = (word,)
-            pos += len(lines[0]) + 1
-            if pos > width:
-                yield '\n'
-                pos = len(lines[-1])
-            else:
-                yield ' '
-                if len(lines) > 1:
-                    pos = len(lines[-1])
-            yield word
+        for line in text.splitlines(True):   # True keeps trailing linebreaks
+            quote = ''
+            max_width = (line.endswith('\n') and width + 1 or width)
+            while len(line) > max_width:
+                space = line[:max_width+1].rfind(' ') + 1
+                if space == 0:
+                    space = line.find(' ') + 1
+                    if space == 0:
+                        yield line
+                        line = ''
+                        break
+                yield '%s\n' % line[:space-1]
+                line = line[space:]
+                max_width = (line.endswith('\n') and width + 1 or width)
+            if line:
+                yield line
     return u''.join(_generator())
 wrap = allow_lazy(wrap, unicode)
 
Index: tests/regressiontests/utils/tests.py
===================================================================
--- tests/regressiontests/utils/tests.py	(revision 7141)
+++ tests/regressiontests/utils/tests.py	(working copy)
@@ -8,11 +8,13 @@
 
 import timesince
 import datastructures
+import text
 
 # Extra tests
 __test__ = {
     'timesince': timesince,
     'datastructures': datastructures,
+    'text': text,
 }
 
 class TestUtilsHtml(TestCase):
Index: tests/regressiontests/utils/text.py
===================================================================
--- tests/regressiontests/utils/text.py	(revision 0)
+++ tests/regressiontests/utils/text.py	(revision 0)
@@ -0,0 +1,23 @@
+r"""
+>>> from django.utils.text import wrap
+
+>>> wrap('1234 67 9', 100)
+u'1234 67 9'
+>>> wrap('1234 67 9', 9)
+u'1234 67 9'
+>>> wrap('1234 67 9', 8)
+u'1234 67\n9'
+
+>>> wrap('short\na long line', 7)
+u'short\na long\nline'
+
+>>> wrap('do-not-break-long-words please? ok', 8)
+u'do-not-break-long-words\nplease?\nok'
+
+>>> long_word = 'l%sng' % ('0123456789'*100)
+>>> wrap(long_word, 50) == long_word
+True
+>>> out = wrap('a %s word' % long_word, 10)
+>>> '%s...%s' % (out[:20], out[-20:])
+u'a\nl01234567890123456...7890123456789ng\nword'
+"""
