Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 23386)
+++ wp-includes/post.php	(working copy)
@@ -5245,6 +5245,13 @@
 
 	$preview = wp_get_post_autosave($post->ID);
 
+	$preview_id = (int) $_GET['preview_id'];
+	if ( $preview->ID != $preview_id ) {
+		$actual_preview = get_post( $preview_id );
+		if ( 'revision' == $actual_preview->post_type )
+			$preview = $actual_preview;
+	}
+
 	if ( ! is_object($preview) )
 		return $post;
 
Index: wp-admin/includes/post.php
===================================================================
--- wp-admin/includes/post.php	(revision 23386)
+++ wp-admin/includes/post.php	(working copy)
@@ -243,8 +243,33 @@
 
 	update_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID );
 
-	wp_update_post( $post_data );
+	if ( ! empty( $_POST['save-as-draft'] ) ) {
+		unset( $post_data['post_ID'], $post_data['ID'] );
+		$post_data['post_type'] = 'revision';
+		$post_data['post_parent'] = $post_ID;
+		$post_data['post_status'] = 'draft';
+	}
 
+	if ( ! empty( $_POST['publish'] ) && 'revision' == $post->post_type && current_user_can( 'publish_posts' ) ) {
+		$parent = get_post( $post->post_parent );
+		if ( ! current_user_can( 'edit_post', $parent->ID ) )
+			wp_die( __( 'You are not allowed to edit this post.' ) );
+
+		unset( $post_data['post_parent'] );
+		$post_data['post_type'] = $parent->post_type;
+		$post_data['post_status'] = $parent->post_status;
+		$post_data['post_ID'] = $parent->ID;
+		$post_data['ID'] = $parent->ID;
+
+		// Discard the draft
+		wp_delete_post( $post->ID, true );
+	}
+
+	if ( ! empty( $post_data['post_ID'] ) )
+		$post_ID = wp_update_post( $post_data );
+	else
+		$post_ID = wp_insert_post( $post_data );
+
 	// Now that we have an ID we can fix any attachment anchor hrefs
 	_fix_attachment_links( $post_ID );
 
@@ -1298,11 +1323,21 @@
 	if ( is_wp_error($id) )
 		wp_die( $id->get_error_message() );
 
-	if ( $_POST['post_status'] == 'draft'  ) {
+	$post_status = $_POST['post_status'];
+	$preview_id = $id;
+
+	if ( 'revision' == $post->post_type ) {
+		$parent = get_post( $post->post_parent );
+		$post_status = $parent->post_status;
+		$id = $parent->ID;
+		$preview_id = $post->ID;
+	}
+
+	if ( $post_status == 'draft'  ) {
 		$url = add_query_arg( 'preview', 'true', get_permalink($id) );
 	} else {
-		$nonce = wp_create_nonce('post_preview_' . $id);
-		$url = add_query_arg( array( 'preview' => 'true', 'preview_id' => $id, 'preview_nonce' => $nonce ), get_permalink($id) );
+		$nonce = wp_create_nonce('post_preview_' . $preview_id);
+		$url = add_query_arg( array( 'preview' => 'true', 'preview_id' => $preview_id, 'preview_nonce' => $nonce ), get_permalink($id) );
 	}
 
 	return $url;
Index: wp-admin/includes/meta-boxes.php
===================================================================
--- wp-admin/includes/meta-boxes.php	(revision 23386)
+++ wp-admin/includes/meta-boxes.php	(working copy)
@@ -13,8 +13,29 @@
 	global $action;
 
 	$post_type = $post->post_type;
+
+	if ( 'revision' == $post_type ) {
+		$parent = get_post( $post->post_parent );
+		$post_type = $parent->post_type;
+	}
+
 	$post_type_object = get_post_type_object($post_type);
 	$can_publish = current_user_can($post_type_object->cap->publish_posts);
+
+	$revision = null;
+	if ( 'publish' == $post->post_status ) {
+		$revisions = get_posts( array(
+			'post_parent'    => $post->ID,
+			'post_type'      => 'revision',
+			'post_status'    => array( 'draft' ),
+			'posts_per_page' => 1,
+		) );
+
+		if ( ! empty( $revisions ) && is_array( $revisions ) ) {
+			$revision = $revisions[0];
+			$edit_revision_link = add_query_arg( 'post', $revision->ID, get_edit_post_link( $post->ID ) );
+		}
+	}
 ?>
 <div class="submitbox" id="submitpost">
 
@@ -31,6 +52,8 @@
 <input <?php if ( 'private' == $post->post_status ) { ?>style="display:none"<?php } ?> type="submit" name="save" id="save-post" value="<?php esc_attr_e('Save Draft'); ?>" class="button" />
 <?php } elseif ( 'pending' == $post->post_status && $can_publish ) { ?>
 <input type="submit" name="save" id="save-post" value="<?php esc_attr_e('Save as Pending'); ?>" class="button" />
+<?php } elseif ( 'publish' == $post->post_status && ( ! $revision || ! current_user_can( 'edit_post', $revision ) ) ) { ?>
+<input type="submit" name="save-as-draft" id="save-post" value="<?php esc_attr_e('Save as Draft'); ?>" class="button" />
 <?php } ?>
 <span class="spinner"></span>
 </div>
@@ -45,6 +68,9 @@
 	$preview_link = esc_url( apply_filters( 'preview_post_link', add_query_arg( 'preview', 'true', $preview_link ) ) );
 	$preview_button = __( 'Preview' );
 }
+
+if ( 'revision' == $post->post_type )
+	$preview_button = __( 'Preview Changes' );
 ?>
 <a class="preview button" href="<?php echo $preview_link; ?>" target="wp-preview" id="post-preview"><?php echo $preview_button; ?></a>
 <input type="hidden" name="wp-preview" id="wp-preview" value="" />
@@ -55,6 +81,8 @@
 
 <div id="misc-publishing-actions">
 
+<?php if ( 'revision' == $post->post_type ) : ?>
+<?php else : ?>
 <div class="misc-pub-section"><label for="post_status"><?php _e('Status:') ?></label>
 <span id="post-status-display">
 <?php
@@ -180,6 +208,8 @@
 </div><?php // /misc-pub-section ?>
 <?php endif; ?>
 
+<?php endif; // !revision ?>
+
 <?php do_action('post_submitbox_misc_actions'); ?>
 </div>
 <div class="clear"></div>
@@ -194,8 +224,15 @@
 		$delete_text = __('Delete Permanently');
 	else
 		$delete_text = __('Move to Trash');
+
+	$delete_link = get_delete_post_link( $post->ID );
+	if ( 'revision' == $post->post_type ) {
+		$delete_text = __( 'Discard Changes' );
+		$delete_link = add_query_arg( 'post', $post->ID, get_delete_post_link( $post->post_parent, '', true ) );
+		$delete_link = wp_nonce_url( $delete_link, "delete-post_{$post->ID}" );
+	}
 	?>
-<a class="submitdelete deletion" href="<?php echo get_delete_post_link($post->ID); ?>"><?php echo $delete_text; ?></a><?php
+<a class="submitdelete deletion" href="<?php echo esc_url( $delete_link ); ?>"><?php echo $delete_text; ?></a><?php
 } ?>
 </div>
 
@@ -208,8 +245,12 @@
 		<input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Schedule') ?>" />
 		<?php submit_button( __( 'Schedule' ), 'primary button-large', 'publish', false, array( 'accesskey' => 'p' ) ); ?>
 <?php	else : ?>
+		<?php $publish_label = ( 'revision' == $post->post_type ) ? __( 'Publish Changes' ) : __( 'Publish' ); ?>
+		<?php if ( 'revision' == $post->post_type ) : ?>
+		<input type="hidden" name="publish-revision" value="1" />
+		<?php endif; ?>
 		<input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Publish') ?>" />
-		<?php submit_button( __( 'Publish' ), 'primary button-large', 'publish', false, array( 'accesskey' => 'p' ) ); ?>
+		<?php submit_button( $publish_label, 'primary button-large', 'publish', false, array( 'accesskey' => 'p' ) ); ?>
 <?php	endif;
 	else : ?>
 		<input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Submit for Review') ?>" />
Index: wp-admin/post.php
===================================================================
--- wp-admin/post.php	(revision 23386)
+++ wp-admin/post.php	(working copy)
@@ -31,6 +31,19 @@
 if ( $post ) {
 	$post_type = $post->post_type;
 	$post_type_object = get_post_type_object( $post_type );
+
+	$revisions = get_posts( array(
+		'post_parent' => $post->ID,
+		'post_type' => 'revision',
+		'post_status' => array( 'draft' ),
+	) );
+
+	if ( ! empty( $revisions ) && is_array( $revisions ) ) {
+		$revision = $revisions[0];
+		if ( current_user_can( 'edit_post', $revision->ID ) ) {
+			redirect_post( $revision->ID );
+		}
+	}
 }
 
 /**
@@ -39,6 +52,11 @@
  * @param int $post_id Optional. Post ID.
  */
 function redirect_post($post_id = '') {
+
+	$post = get_post( $post_id );
+	if ( 'revision' == $post->post_type )
+		$post_id = $post->post_parent;
+
 	if ( isset($_POST['save']) || isset($_POST['publish']) ) {
 		$status = get_post_status( $post_id );
 
@@ -53,6 +71,9 @@
 				default:
 					$message = 6;
 			}
+
+			if ( ! empty( $_POST['publish-revision'] ) )
+				$message = 12;
 		} else {
 				$message = 'draft' == $status ? 10 : 1;
 		}
@@ -72,6 +93,16 @@
 		$location = add_query_arg( 'message', 4, get_edit_post_link( $post_id, 'url' ) );
 	}
 
+	if ( 'revision' == $post->post_type ) {
+		$post_id = $post->ID;
+		$location = add_query_arg( 'post', $post->ID, $location );
+
+		if ( ! empty( $_POST['save-as-draft'] ) || ! empty( $_POST['save'] ) )
+			$location = add_query_arg( 'message', 13, $location );
+		else
+			$location = remove_query_arg( 'message', $location );
+	}
+
 	wp_redirect( apply_filters( 'redirect_post_location', $location, $post_id ) );
 	exit;
 }
@@ -135,6 +166,13 @@
 
 	$p = $post_id;
 
+	$post_type = $post->post_type;
+	if ( 'revision' == $post_type && ! empty( $post->post_parent ) ) {
+		$parent = get_post( $post->post_parent );
+		$post_type = $parent->post_type;
+		$post_type_object = get_post_type_object( $post_type );
+	}
+
 	if ( empty($post->ID) )
 		wp_die( __('You attempted to edit an item that doesn&#8217;t exist. Perhaps it was deleted?') );
 
@@ -147,7 +185,6 @@
 	if ( 'trash' == $post->post_status )
 		wp_die( __('You can&#8217;t edit this item because it is in the Trash. Please restore it and try again.') );
 
-	$post_type = $post->post_type;
 	if ( 'post' == $post_type ) {
 		$parent_file = "edit.php";
 		$submenu_file = "edit.php";
@@ -182,6 +219,8 @@
 		enqueue_comment_hotkeys_js();
 	}
 
+	set_current_screen( $post_type );
+
 	include('./edit-form-advanced.php');
 
 	break;
@@ -243,6 +282,10 @@
 	if ( !current_user_can($post_type_object->cap->delete_post, $post_id) )
 		wp_die( __('You are not allowed to delete this item.') );
 
+	if ( 'revision' == $post->post_type ) {
+		$sendback = add_query_arg( 'message', 11, get_edit_post_link( $post->post_parent, 'raw' ) );
+	}
+
 	$force = !EMPTY_TRASH_DAYS;
 	if ( $post->post_type == 'attachment' ) {
 		$force = ( $force || !MEDIA_TRASH );
@@ -259,7 +302,6 @@
 
 case 'preview':
 	check_admin_referer( 'autosave', 'autosavenonce' );
-
 	$url = post_preview();
 
 	wp_redirect($url);
Index: wp-admin/edit-form-advanced.php
===================================================================
--- wp-admin/edit-form-advanced.php	(revision 23386)
+++ wp-admin/edit-form-advanced.php	(working copy)
@@ -45,6 +45,9 @@
 		// translators: Publish box date format, see http://php.net/date
 		date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ),
 	10 => sprintf( __('Post draft updated. <a target="_blank" href="%s">Preview post</a>'), esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
+	11 => __( 'Your changes have been discarded.' ),
+	12 => sprintf( __( 'Your changes have been saved and published. <a href="%s">View post</a>' ), esc_url( get_permalink( $post_ID ) ) ),
+	13 => __( 'Your changes have been saved, but not published.' ),
 );
 $messages['page'] = array(
 	 0 => '', // Unused. Messages start at index 1.
@@ -296,6 +299,24 @@
 <?php if ( $message ) : ?>
 <div id="message" class="updated"><p><?php echo $message; ?></p></div>
 <?php endif; ?>
+<?php
+	$revision = null;
+	$revisions = get_posts( array(
+		'post_parent' => $post->ID,
+		'post_type' => 'revision',
+		'post_status' => array( 'draft' ),
+	) );
+
+	if ( ! empty( $revisions ) && is_array( $revisions ) ) {
+		$revision = $revisions[0];
+		$edit_revision_link = add_query_arg( 'post', $revision->ID, get_edit_post_link( $post->ID ) );
+	}
+?>
+<?php if ( 'revision' == $post->post_type ) : ?>
+<div class="updated">
+	<p>These changes are not published. <a href="<?php echo esc_url( get_permalink( $post->post_parent ) ); ?>">View published post</a>.</p>
+</div>
+<?php endif; ?>
 <form name="post" action="post.php" method="post" id="post"<?php do_action('post_edit_form_tag'); ?>>
 <?php wp_nonce_field($nonce_action); ?>
 <input type="hidden" id="user-id" name="user_ID" value="<?php echo (int) $user_ID ?>" />
@@ -336,7 +357,7 @@
 if ( !empty($shortlink) )
     $sample_permalink_html .= '<input id="shortlink" type="hidden" value="' . esc_attr($shortlink) . '" /><a href="#" class="button button-small" onclick="prompt(&#39;URL:&#39;, jQuery(\'#shortlink\').val()); return false;">' . __('Get Shortlink') . '</a>';
 
-if ( $post_type_object->public && ! ( 'pending' == get_post_status( $post ) && !current_user_can( $post_type_object->cap->publish_posts ) ) ) { ?>
+if ( $post_type_object->public && ! ( 'pending' == get_post_status( $post ) && !current_user_can( $post_type_object->cap->publish_posts ) ) && 'revision' != $post->post_type ) { ?>
 	<div id="edit-slug-box" class="hide-if-no-js">
 	<?php
 		if ( $sample_permalink_html && 'auto-draft' != $post->post_status )
