Improve extended slicing support in builtin types and classes. Specifically:

 - Specialcase extended slices that amount to a shallow copy the same way as
   is done for simple slices, in the tuple, string and unicode case.

 - Specialcase step-1 extended slices to optimize the common case for all
   involved types.

 - For lists, allow extended slice assignment of differing lengths as long
   as the step is 1. (Previously, 'l[:2:1] = []' failed even though
   'l[:2] = []' and 'l[:2:None] = []' do not.)

 - Implement extended slicing for buffer, array, structseq, mmap and
   UserString.UserString.

 - Implement slice-object support (but not non-step-1 slice assignment) for
   UserString.MutableString.

 - Add tests for all new functionality.
diff --git a/Objects/listobject.c b/Objects/listobject.c
index ac0d018..c0621dc 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2473,6 +2473,9 @@
 		if (slicelength <= 0) {
 			return PyList_New(0);
 		}
+		else if (step == 1) {
+			return list_slice(self, start, stop);
+		}
 		else {
 			result = PyList_New(slicelength);
 			if (!result) return NULL;
@@ -2516,10 +2519,15 @@
 			return -1;
 		}
 
-		/* treat L[slice(a,b)] = v _exactly_ like L[a:b] = v */
-		if (step == 1 && ((PySliceObject*)item)->step == Py_None)
+		if (step == 1)
 			return list_ass_slice(self, start, stop, value);
 
+		/* Make sure s[5:2] = [..] inserts at the right place:
+		   before 5, not before 2. */
+		if ((step < 0 && start < stop) ||
+		    (step > 0 && start > stop))
+			stop = start;
+
 		if (value == NULL) {
 			/* delete slice */
 			PyObject **garbage;
@@ -2541,12 +2549,16 @@
 				return -1;
 			}
 
-			/* drawing pictures might help
-			   understand these for loops */
+			/* drawing pictures might help understand these for
+			   loops. Basically, we memmove the parts of the
+			   list that are *not* part of the slice: step-1
+			   items for each item that is part of the slice,
+			   and then tail end of the list that was not
+			   covered by the slice */
 			for (cur = start, i = 0;
 			     cur < stop;
 			     cur += step, i++) {
-				Py_ssize_t lim = step;
+				Py_ssize_t lim = step - 1;
 
 				garbage[i] = PyList_GET_ITEM(self, cur);
 
@@ -2558,11 +2570,12 @@
 					self->ob_item + cur + 1,
 					lim * sizeof(PyObject *));
 			}
-
-			for (cur = start + slicelength*step + 1;
-			     cur < Py_Size(self); cur++) {
-				PyList_SET_ITEM(self, cur - slicelength,
-						PyList_GET_ITEM(self, cur));
+			cur = start + slicelength*step;
+			if (cur < Py_Size(self)) {
+				memmove(self->ob_item + cur - slicelength,
+					self->ob_item + cur,
+					(Py_Size(self) - cur) * 
+					 sizeof(PyObject *));
 			}
 
 			Py_Size(self) -= slicelength;
@@ -2577,7 +2590,8 @@
 		}
 		else {
 			/* assign slice */
-			PyObject **garbage, *ins, *seq, **seqitems, **selfitems;
+			PyObject *ins, *seq;
+			PyObject **garbage, **seqitems, **selfitems;
 			Py_ssize_t cur, i;
 
 			/* protect against a[::-1] = a */
@@ -2587,14 +2601,17 @@
 			}
 			else {
 				seq = PySequence_Fast(value,
-					"must assign iterable to extended slice");
+						      "must assign iterable "
+						      "to extended slice");
 			}
 			if (!seq)
 				return -1;
 
 			if (PySequence_Fast_GET_SIZE(seq) != slicelength) {
 				PyErr_Format(PyExc_ValueError,
-            "attempt to assign sequence of size %zd to extended slice of size %zd",
+					"attempt to assign sequence of "
+					"size %zd to extended slice of "
+					"size %zd",
 					     PySequence_Fast_GET_SIZE(seq),
 					     slicelength);
 				Py_DECREF(seq);