Index: wp-includes/taxonomy.php
===================================================================
--- wp-includes/taxonomy.php	(revision 15691)
+++ wp-includes/taxonomy.php	(working copy)
@@ -2828,46 +2828,3 @@

 	return apply_filters('get_ancestors', $ancestors, $object_id, $object_type);
 }
-
-
-/**
- * {@internal Missing Short Description}}
- *
- * @since unknown
- *
- * @param unknown_type $post_id
- * @return unknown
- */
-function get_tags_to_edit( $post_id, $taxonomy = 'post_tag' ) {
-	return get_terms_to_edit( $post_id, $taxonomy);
-}
-
-/**
- * {@internal Missing Short Description}}
- *
- * @since unknown
- *
- * @param unknown_type $post_id
- * @return unknown
- */
-function get_terms_to_edit( $post_id, $taxonomy = 'post_tag' ) {
-	$post_id = (int) $post_id;
-	if ( !$post_id )
-		return false;
-
-	$tags = wp_get_post_terms($post_id, $taxonomy, array());
-
-	if ( !$tags )
-		return false;
-
-	if ( is_wp_error($tags) )
-		return $tags;
-
-	foreach ( $tags as $tag )
-		$tag_names[] = $tag->name;
-	$tags_to_edit = join( ',', $tag_names );
-	$tags_to_edit = esc_attr( $tags_to_edit );
-	$tags_to_edit = apply_filters( 'terms_to_edit', $tags_to_edit, $taxonomy );
-
-	return $tags_to_edit;
-}
Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 15691)
+++ wp-includes/post.php	(working copy)
@@ -4716,202 +4716,233 @@


 /**
- * Default post information to use when populating the "Write Post" form.
+ * Returns or echos a form containing a post box.
  *
- * @since unknown
+ * Used for the QuickPress dashboard module.
  *
- *@param string A post type string, defaults to 'post'.
- * @return object stdClass object containing all the default post data as attributes
+ * @since 3.1.0
+ *
+ * @param array $args Arguments.
  */
-function get_default_post_to_edit( $post_type = 'post', $create_in_db = false ) {
-	global $wpdb;
+function wp_quickpress_form( $args = array() ) {
+	$defaults = array(
+		'form_id' => '',
+		'action' => admin_url( 'post.php' ),
+		'post' => null, // Post object, ID, or null.
+		'post_type' => null, // Post type. Optional. Overridden if 'post' parameter is specified.
+		'fields' => null, // Array of fields.
+		'submit_fields' => null, // Array of submit, hidden, and publishing inputs.
+		'tabindex' => false, // @todo Can we just kill tabindex?
+		'capability' => 'edit_posts',
+		'submit_class' => 'submit',
+		'publish_action_container' => 'span',
+		'publish_action_id' => 'publishing-action',
+		'submit_fields_container' => 'p',
+		'submit_fields_container_class' => 'submit',
+	);

-	$post_title = '';
-	if ( !empty( $_REQUEST['post_title'] ) )
-		$post_title = esc_html( stripslashes( $_REQUEST['post_title'] ));
+	$args = wp_parse_args( $args, $defaults );

-	$post_content = '';
-	if ( !empty( $_REQUEST['content'] ) )
-		$post_content = esc_html( stripslashes( $_REQUEST['content'] ));
+	// @todo Kill the cap check and arg. Stick to pure presentation only.
+	// We can still handle them on a field-by-field basis.
+	if ( ! current_user_can( $args['capability'] ) ) {
+		do_action( 'quickpress_form_no_form', $args );
+		return;
+	}

-	$post_excerpt = '';
-	if ( !empty( $_REQUEST['excerpt'] ) )
-		$post_excerpt = esc_html( stripslashes( $_REQUEST['excerpt'] ));
+	if (! function_exists('get_terms_to_edit') )
+		require_once (ABSPATH . 'wp-admin/includes/taxonomy.php');

-	if ( $create_in_db ) {
-		// Cleanup old auto-drafts more than 7 days old
-		$old_posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_status = 'auto-draft' AND DATE_SUB( NOW(), INTERVAL 7 DAY ) > post_date" );
-		foreach ( (array) $old_posts as $delete )
-			wp_delete_post( $delete, true ); // Force delete
-		$post_id = wp_insert_post( array( 'post_title' => __( 'Auto Draft' ), 'post_type' => $post_type, 'post_status' => 'auto-draft' ) );
-		$post = get_post( $post_id );
+	if (! function_exists('get_default_post_to_edit') )
+		require_once (ABSPATH . 'wp-admin/includes/post.php');
+
+	if ( empty( $args['post'] ) ) {
+		if ( null === $args['post_type'] )
+			$args['post_type'] = 'post';
+		$args['post'] = 0;
 	} else {
-		$post->ID = 0;
-		$post->post_author = '';
-		$post->post_date = '';
-		$post->post_date_gmt = '';
-		$post->post_password = '';
-		$post->post_type = $post_type;
-		$post->post_status = 'draft';
-		$post->to_ping = '';
-		$post->pinged = '';
-		$post->comment_status = get_option( 'default_comment_status' );
-		$post->ping_status = get_option( 'default_ping_status' );
-		$post->post_pingback = get_option( 'default_pingback_flag' );
-		$post->post_category = get_option( 'default_category' );
-		$post->page_template = 'default';
-		$post->post_parent = 0;
-		$post->menu_order = 0;
+		$post = get_post( $args['post'] );
+		$args['post_type'] = $post->post_type;
 	}

-	$post->post_content = apply_filters( 'default_content', $post_content, $post );
-	$post->post_title   = apply_filters( 'default_title',   $post_title, $post   );
-	$post->post_excerpt = apply_filters( 'default_excerpt', $post_excerpt, $post );
-	$post->post_name = '';
+	$post_type_obj = get_post_type_object( $args['post_type'] );

-	return $post;
-}
-
-/**
- * Returns or echos a form containing a post box.
- *
- * Used for the QuickPress dashboard module.
- *
- * @since 3.1.0
- *
- * @param array $args Arguments.
- * @param string $post_type Post type.
- */
-function wp_quickpress_form( $args = array(), $post_type = 'post'){
-	global $post_ID;
-
-	$fields = array(
+	// @todo Clean these up still. Arrays?
+	$default_fields = array(
 		'title' => array(
 			'capability' => '', // Capability to check before outputing field
-			'output' => '<h4 id="%s-title"><label for="title">'. __('Title') .'</label></h4>
+			'output' => '<h4 id="%1$s-title"><label for="title">'. __('Title') .'</label></h4>
 		<div class="input-text-wrap">
-			<input type="text" name="post_title" id="%s-title" tabindex="%d" autocomplete="off" value="'. esc_attr( $post->post_title ).'" />
+			<input type="text" name="post_title" id="%1$s-title" tabindex="%2$d" autocomplete="off" value="' . ( $post && esc_attr( $post->post_title ) ) . '" />
 		</div>'
 		),
+		// @todo This needs JS enqueued to work.
 		'media_buttons' => array(
 			'capability' => 'upload_files',
-			'output' => '<div id="%s-media-buttons" class="hide-if-no-js">'. get_media_buttons() .'</div>',
+			'output' => '<div id="%1$s-media-buttons" class="hide-if-no-js">'. get_media_buttons() .'</div>',
 		),
+		// @todo The TinyMCE stuff should disappear into a hook, like the ajax spinner.
 		'content' => array(
 			'capability' => '',
-			'output' => '<h4 id="%s-content-label"><label for="content">'. __('Content') .'</label></h4>
+			'output' => '<h4 id="%1$s-content-label"><label for="content">'. __('Content') .'</label></h4>
 		<div class="textarea-wrap">
-			<textarea name="content" id="%s-content" class="mceEditor" rows="3" cols="15" tabindex="%d">'. $post->post_content.'</textarea>
+			<textarea name="content" id="%1$s-content" class="mceEditor" rows="3" cols="15" tabindex="%2$d">' . ( $post && $post->post_content ) . '</textarea>
 		</div>
-			'."     <script type='text/javascript'>edCanvas = document.getElementById('content');edInsertContent = null;</script>
+			'."	<script type='text/javascript'>edCanvas = document.getElementById('%1$s-content');edInsertContent = null;</script>
 		"
-
 		),
 		'tags' => array(
 			'capability' =>'',
 			'output' => '
-			<h4><label for="%s-tags-input">'. __('Tags') .'</label></h4>
+			<h4><label for="%1$s-tags-input">'. __( 'Tags' ) .'</label></h4>
 			<div class="input-text-wrap">
-				<input type="text" name="%s-tags_input" id="tags-input" tabindex="%d" value="'. get_tags_to_edit( $post->ID ) .'" />
-			</div>
-'
+				<input type="text" name="%1$s-tags_input" id="tags-input" tabindex="%2$d" value="' . ( $post && get_tags_to_edit( $post->ID ) ) . '" />
+			</div>'
 		),
-
 	);

-	$hidden_fields = array(
-		'action' => '<input type="hidden" name="action" id="quickpost-action" value="'.$post_type.'-quickpress-save" />',
-		'post_id' => '<input type="hidden" name="quickpress_post_ID" value="'. $post_ID .'" />',
-		'post_type' => '<input type="hidden" name="post_type" value="'.$post_type.'" />',
-	);
+	if ( null === $args['fields'] ) {
+		$fields = $default_fields;
+	} else {
+		$fields = array();
+		foreach ( $args['fields'] as $key => $value ) {
+			if ( true === $value ) // i.e. tags => true
+				$fields[] = $default_fields[ $key ];
+			elseif ( is_string( $value ) ) // i.e. array( 'tags' )
+				$fields[] = $default_fields[ $value ];
+			else
+				$fields[] = $value;
+		}
+	}
+	// Sync this so filters are given correct information.
+	$args['fields'] = $fields;

-	$submit_fields = array(
-		'save' => '<input type="submit" name="save" id="save-post" class="button" tabindex="%s" value="'.  esc_attr('Save Draft') .'" />',
-		'reset' => '<input type="reset" tabindex="%s" value="'. esc_attr( 'Reset' ).'" class="button" />',
+	$publishing_action = current_user_can( $post_type_obj->cap->publish_posts ) ? __( 'Publish' ) : __( 'Submit for Review' );
+
+	// These are keyed by input name.
+	// Accepted keys: type, value, id (defaults to none).
+	// These are also accepted for non-hidden inputs:
+	// primary (defaults to false), class (defaults to 'button', except for the primary button, when it is 'button-primary'),
+	// tabindex (defaults to true), accesskey (defaults to none).
+	$default_submit_fields = array(
+		'action'    => array( 'type' => 'hidden', 'id' => 'quickpost-action', 'value' => $post_type . '-quickpress-save' ),
+		'quickpress_post_ID' => array( 'type' => 'hidden', 'value' => $post_ID ),
+		'post_type' => array( 'type' => 'hidden', 'value' => $post_type ),
+		'save'      => array( 'type' => 'submit', 'value' => __( 'Save Draft' ) ),
+		'reset'     => array( 'type' => 'reset',  'value' => __( 'Reset' ) ),
+		'submit'    => array( 'type' => 'submit', 'primary' => true, 'accesskey' => 'p', 'value' => $publishing_action ),
 	);

-	$publishing_action = current_user_can('publish_posts') ? esc_attr('Publish') : esc_attr('Submit for Review');
+	if ( null === $args['submit_fields'] ) {
+		$submit_fields = $default_submit_fields;
+	} else {
+		$submit_fields = array();
+		foreach ( $args['submit_fields'] as $key => $value ) {
+			// @todo If this is going to work like this, then the hidden/submit fields need to be split back up.
+			if ( true === $value ) // i.e. tags => true
+				$submit_fields[] = $default_submit_fields[ $key ];
+			elseif ( is_string( $value ) ) // i.e. array( 'tags' )
+				$submit_fields[] = $default_submit_fields[ $value ];
+			else
+				$submit_fields[] = $value;
+		}
+	}

-	$publishing_fields = array(
-	'submit' => '<input type="submit" name="publish" id="publish" accesskey="p" tabindex="%s" class="button-primary" value="' . $publishing_action . '" />',
-	/*'test' => '<input type="submit" name="publish" id="publish" accesskey="p" tabindex="%n" class="button-primary" value="'. esc_attr('Publish') .'" />', */
+	$primary_fields = array();
+	foreach ( $submit_fields as $key => $f ) {
+		if ( ! isset( $f['type'] ) || ! isset( $f['value'] ) )
+			continue;
+		$f['name'] = $key;
+		if ( ! isset( $f['id'] ) )
+			$f['id'] = false;

-	);
+		if ( 'hidden' == $f['type'] ) {
+			$f['primary'] = $f['accesskey'] = $f['tabindex'] = $f['class'] = false;
+		} else {
+			if ( ! isset( $f['class'] ) )
+				$f['class'] = ! empty( $f['primary'] ) ? 'button-primary' : 'button';
+			$f = wp_parse_args( $f, array( 'accesskey' => false, 'tabindex' => true, 'primary' => false, 'tabindex' => true ) );
+		}
+	}

-	$defaults = array(
-		'action' => admin_url( 'post.php' ),
-		'fields' => $fields,
-		'form_id' => '',
-		'default_cap' => 'edit_posts',
-		'tabindex_start' => '1',
-		'ajax' => true,
-		'hidden_fields' => $hidden_fields,
-		'submit_fields' => $submit_fields,
-		'publishing_fields' => $publishing_fields,
-		'submit_class' => 'submit',
-		'publish_action_container' => 'span',
-		'publish_action_id' => 'publishing-action',
-		'hidden_and_submit_fields_container' => 'p',
-		'hidden_and_submit_fields_container_class' => 'submit',
-	);
+	// Sync this so filters are given correct information.
+	$args['submit_fields'] = $submit_fields;
+	// Then we can separate the primary fields.
+	foreach ( $submit_fields as $key => $f ) {
+		if ( $f['primary'] ) {
+			$primary_fields[] = $f;
+			unset( $submit_fields[ $key ] );
+		}
+	}

-	$args = wp_parse_args($args, $defaults);
+	// @todo :(
+	$tabindex = apply_filters( 'quickpress_tabindex', $tabindex, $args );

-	$tabindex =  apply_filters( 'quickpress_tabindex_start', $args['tabindex_start'], $args['form_id']  );
+	do_action('quickpress_before_form', $args );

-	if ( current_user_can( $args['default_cap'] ) ): ?>
-		<?php do_action('quickpress_form_before_form', $args['form_id'] ); ?>
-		<form name="post" action="<?php echo $args['action'] ?>" method="post" id="<?php echo $args['form_id']; ?>">
-			<?php do_action('quickpress_form_before_fields', $args['form_id']);
+	echo '<form name="post" action="' . $args['action'] . '" method="post" id="' . $args['form_id'] . '">';

-			$fields = apply_filters( 'quickpress_fields',  $args['fields'], $args['form_id'] );
-			foreach ($fields as $title => $field){
-				if ( empty( $field['capability'] ) || current_user_can( $field['capability'] ) ){
-					printf( $field['output'], $args['form_id'], $args['form_id'], $tabindex );
-					$tabindex++;
-				}
-			}
-			//Hidden Fields
-			do_action('quickpress_form_after_fields', $args['form_id'] );
+	do_action( 'quickpress_before_fields', $args );

-			echo "<{$args['hidden_and_submit_fields_container']} class='{$args['hidden_and_submit_fields_container_class']}'>";
+	$fields = apply_filters( 'quickpress_fields', $form_fields, $args );
+	foreach ( $fields as $title => $field ) {
+		if ( empty( $field['capability'] ) || current_user_can( $field['capability'] ) )
+			printf( $field['output'], $args['form_id'], ( $tabindex ? $tabindex++ : '' ) );
+	}

-			$hidden_fields = apply_filters( 'quickpress_hidden_fields', $args['hidden_fields'] , $args['form_id'] );
+	do_action( 'quickpress_after_fields', $form_id );

-			foreach( $hidden_fields as $hidden_field )
-				echo $hidden_field;
+	echo "<{$args['submit_fields_container']} class='{$args['submit_fields_container_class']}'>";

-			// nonce
-			wp_nonce_field('add-post');
+	// nonce
+	wp_nonce_field( 'add-post' );

-			// submit
-			foreach( $args['submit_fields'] as $submit_field )
-				printf( $submit_field, $tabindex++ );
+	foreach ( array( $args['submit_fields'], $args['primary_fields'] ) as $fields ) {
+		foreach( $fields as $f ) {
+			$f['tabindex']  = $tabindex && ! empty( $f['tabindex'] ) ? ' tabindex="' . $tabindex++ . '"'  : '';
+			$f['class']     = ! empty( $f['class'] )     ? ' class="' . $f['class'] . '"' : '';
+			$f['id']        = ! empty( $f['id'] )        ? ' id="' . $f['id'] . '"'       : '';
+			$f['accesskey'] = ! empty( $f['accesskey'] ) ? ' accesskey="' . $f['accesskey'] . '"' : '';

-			// publish
-			echo "<{$args['publish_action_container']} id='{$args['publish_action_id']}'>";
+			$f['name']  = ' name="' . $f['name'] . '"';
+			$f['type']  = ' type="' . $f['type'] . '"';
+			$f['value'] = ' value="' . esc_attr( $f['value'] ) . '"';
+		}
+	}

-			$publishing_fields = apply_filters( 'quickpress_publishing_fields', $args['publishing_fields'] , $args['form_id'] );
+	// hidden fields and secondary submit buttons
+	foreach ( $args['submit_fields'] as $f )
+		echo '<input ' . $f['type'] . $f['name'] . $f['id'] . $f['class'] . $f['tabindex'] . $f['value'] . '" />';

-			foreach( $publishing_fields as $publishing_field) {
-				printf( $publishing_field, $tabindex );
-					$tabindex++;
-			}
+	// primary submit buttons
+	echo "<{$args['publish_action_container']} id='{$args['publish_action_id']}'>";

-			if ($args['ajax'] == true)
-				echo '<img class="waiting" src="'. esc_url( admin_url( 'images/wpspin_light.gif' ) ) .'" />';
+	foreach ( $args['primary_fields'] as $f )
+		echo '<input ' . $f['type'] . $f['name'] . $f['id'] . $f['class'] . $f['tabindex'] . $f['value'] . '" />';

-			echo "</{$args['publish_action_container']}>";
-			echo "<br class='clear' />";
-			do_action( 'quickpress_form_after_submit_fields', $args['form_id']);
+	do_action( 'quickpress_publish_actions', $args );

-			echo "</{$args['hidden_and_submit_fields_container']}";
-		do_action( 'quickpress_form_after_form_content', $args['form_id']);
-		echo '</form>';
-		do_action('quickpress_form_after_form', $args['form_id'] );
-	else:
-		do_action( 'quickpress_form_no_form', $args['form_id'] );
-	endif;
+	echo "</{$args['publish_action_container']}>";
+
+	echo "<br class='clear' />";
+
+	do_action( 'quickpress_after_submit_fields', $args );
+
+	echo "</{$args['submit_fields_container']}";
+
+	do_action( 'quickpress_after_form_content', $args );
+
+	echo '</form>';
+
+	do_action( 'quickpress_after_form', $args );
 }

+// @todo Move this to admin/includes/dashboard.
+function _dashboard_quickpress_publish_actions( $args ) {
+	if ( ! isset( $args['form_id'] ) || $args['form_id'] != 'dashboard_quick-press' )
+		return;
+	echo '<img class="waiting" src="'. esc_url( admin_url( 'images/wpspin_light.gif' ) ) .'" />';
+}
+add_action( 'quickpress_publish_actions', '_dashboard_quickpress_publish_actions' );
+
 ?>
\ No newline at end of file
Index: wp-admin/includes/taxonomy.php
===================================================================
--- wp-admin/includes/taxonomy.php	(revision 15691)
+++ wp-admin/includes/taxonomy.php	(working copy)
@@ -208,3 +208,47 @@

 	return wp_insert_term($tag_name, $taxonomy);
 }
+
+
+
+/**
+ * {@internal Missing Short Description}}
+ *
+ * @since unknown
+ *
+ * @param unknown_type $post_id
+ * @return unknown
+ */
+function get_tags_to_edit( $post_id, $taxonomy = 'post_tag' ) {
+	return get_terms_to_edit( $post_id, $taxonomy);
+}
+
+/**
+ * {@internal Missing Short Description}}
+ *
+ * @since unknown
+ *
+ * @param unknown_type $post_id
+ * @return unknown
+ */
+function get_terms_to_edit( $post_id, $taxonomy = 'post_tag' ) {
+	$post_id = (int) $post_id;
+	if ( !$post_id )
+		return false;
+
+	$tags = wp_get_post_terms($post_id, $taxonomy, array());
+
+	if ( !$tags )
+		return false;
+
+	if ( is_wp_error($tags) )
+		return $tags;
+
+	foreach ( $tags as $tag )
+		$tag_names[] = $tag->name;
+	$tags_to_edit = join( ',', $tag_names );
+	$tags_to_edit = esc_attr( $tags_to_edit );
+	$tags_to_edit = apply_filters( 'terms_to_edit', $tags_to_edit, $taxonomy );
+
+	return $tags_to_edit;
+}
Index: wp-admin/includes/post.php
===================================================================
--- wp-admin/includes/post.php	(revision 15691)
+++ wp-admin/includes/post.php	(working copy)
@@ -1567,3 +1567,61 @@
 </script>
 <?php
 }
+
+
+/**
+ * Default post information to use when populating the "Write Post" form.
+ *
+ * @since unknown
+ *
+ *@param string A post type string, defaults to 'post'.
+ * @return object stdClass object containing all the default post data as attributes
+ */
+function get_default_post_to_edit( $post_type = 'post', $create_in_db = false ) {
+	global $wpdb;
+
+	$post_title = '';
+	if ( !empty( $_REQUEST['post_title'] ) )
+		$post_title = esc_html( stripslashes( $_REQUEST['post_title'] ));
+
+	$post_content = '';
+	if ( !empty( $_REQUEST['content'] ) )
+		$post_content = esc_html( stripslashes( $_REQUEST['content'] ));
+
+	$post_excerpt = '';
+	if ( !empty( $_REQUEST['excerpt'] ) )
+		$post_excerpt = esc_html( stripslashes( $_REQUEST['excerpt'] ));
+
+	if ( $create_in_db ) {
+		// Cleanup old auto-drafts more than 7 days old
+		$old_posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE post_status = 'auto-draft' AND DATE_SUB( NOW(), INTERVAL 7 DAY ) > post_date" );
+		foreach ( (array) $old_posts as $delete )
+			wp_delete_post( $delete, true ); // Force delete
+		$post_id = wp_insert_post( array( 'post_title' => __( 'Auto Draft' ), 'post_type' => $post_type, 'post_status' => 'auto-draft' ) );
+		$post = get_post( $post_id );
+	} else {
+		$post->ID = 0;
+		$post->post_author = '';
+		$post->post_date = '';
+		$post->post_date_gmt = '';
+		$post->post_password = '';
+		$post->post_type = $post_type;
+		$post->post_status = 'draft';
+		$post->to_ping = '';
+		$post->pinged = '';
+		$post->comment_status = get_option( 'default_comment_status' );
+		$post->ping_status = get_option( 'default_ping_status' );
+		$post->post_pingback = get_option( 'default_pingback_flag' );
+		$post->post_category = get_option( 'default_category' );
+		$post->page_template = 'default';
+		$post->post_parent = 0;
+		$post->menu_order = 0;
+	}
+
+	$post->post_content = apply_filters( 'default_content', $post_content, $post );
+	$post->post_title   = apply_filters( 'default_title',   $post_title, $post   );
+	$post->post_excerpt = apply_filters( 'default_excerpt', $post_excerpt, $post );
+	$post->post_name = '';
+
+	return $post;
+}
