Index: wp-admin/includes/media.php
===================================================================
--- wp-admin/includes/media.php	(revision 9036)
+++ wp-admin/includes/media.php	(working copy)
@@ -58,7 +58,7 @@
 	$rel = $rel ? ' rel="attachment wp-att-'.attribute_escape($id).'"' : '';
 
 	if ( $url )
-		$html = '<a href="' . clean_url($url) . "\"$rel>$html</a>";
+		$html = '<a href="' . clean_url($url) . "\" title=\"". attribute_escape($title) ."\"$rel>$html</a>";
 
 	$html = apply_filters( 'image_send_to_editor', $html, $id, $alt, $title, $align, $url, $size );
 
@@ -274,8 +274,19 @@
 				wp_set_object_terms($attachment_id, array_map('trim', preg_split('/,+/', $attachment[$t])), $t, false);
 	}
 
-	if ( isset($_POST['insert-gallery']) )
-		return media_send_to_editor('[gallery]');
+	if ( isset($_POST['insert-gallery']) ) { 
+		if ( ( isset($_POST['gallery_insert']) ) && ( $_POST['gallery_insert'] > 0 ) ) { 
+			return media_send_to_editor('[gallery group="'.$_POST['gallery_insert'].'"]'); 
+		} else { 
+			return media_send_to_editor('[gallery]'); 
+		} 
+	}
+	
+	if ( isset($_POST['new-gallery']) )
+		wp_new_gallery($post['post_parent']);
+		
+	if ( isset($_POST['gallery_delete']) && !is_null($_POST['gallery_delete']) && ($_POST['gallery_delete'] > 0) ) 
+		wp_delete_gallery($post['post_parent'], $_POST['gallery_delete']); 
 
 	if ( isset($_POST['send']) ) {
 		$keys = array_keys($_POST['send']);
@@ -317,8 +328,11 @@
 			$align = attribute_escape($_POST['insertonly']['align']);
 			$class = " class='align$align'";
 		}
+		if ( isset($_POST['insertonly']['title']) ) { 
+			$title = " title='".attribute_escape($_POST['insertonly']['title'])."'"; 
+		} 
 		if ( !empty($src) )
-			$html = "<img src='$src' alt='$alt'$class />";
+			$html = "<img src='$src' alt='$alt'$title$class />";
 		return media_send_to_editor($html);
 	}
 
@@ -732,13 +746,18 @@
 	return $form_fields;
 }
 
-function get_media_items( $post_id, $errors ) {
+function get_media_items( $post_id, $group_num = null, $errors ) {
 	if ( $post_id ) {
 		$post = get_post($post_id);
-		if ( $post && $post->post_type == 'attachment' )
+		if ( $post && $post->post_type == 'attachment' ) {
+			// @todo This section has not been tested to see if it's working at all.
 			$attachments = array($post->ID => $post);
-		else
-			$attachments = get_children( array( 'post_parent' => $post_id, 'post_type' => 'attachment', 'orderby' => 'menu_order ASC, ID', 'order' => 'DESC') );
+		} else {
+			$attachments = get_attachments( $post_id, $group_num );
+			
+			if ( ! count($attachments) ) 
+				return "\n<div class='media-item media-no-items child-of-$post_id preloaded'><div class='progress'><div class='bar'></div></div><div id='media-upload-error-$id'></div><div class='filename'></div><div class='filename new'>". __("No images in this group. Move items to this group.") ."</div></div>"; 
+		}
 	} else {
 		if ( is_array($GLOBALS['wp_the_query']->posts) )
 			foreach ( $GLOBALS['wp_the_query']->posts as $attachment )
@@ -748,10 +767,11 @@
 	if ( empty($attachments) )
 		return '';
 
-	foreach ( $attachments as $id => $attachment )
+	foreach ( $attachments as $id => $attachment ) {	
 		if ( $item = get_media_item( $id, array( 'errors' => isset($errors[$id]) ? $errors[$id] : null) ) )
 			$output .= "\n<div id='media-item-$id' class='media-item child-of-$attachment->post_parent preloaded'><div class='progress'><div class='bar'></div></div><div id='media-upload-error-$id'></div><div class='filename'></div>$item\n</div>";
-
+	}
+	
 	return $output;
 }
 
@@ -780,6 +800,7 @@
 	$filename = basename($post->guid);
 	$title = attribute_escape($post->post_title);
 	$description = attribute_escape($post->post_content);
+	$group_number = attribute_escape($post->group_number);
 	if ( $_tags = get_the_tags($attachment_id) ) {
 		foreach ( $_tags as $tag )
 			$tags[] = $tag->name;
@@ -810,6 +831,8 @@
 	$gallery = ( (isset($_REQUEST['tab']) && 'gallery' == $_REQUEST['tab']) || (isset($redir_tab) && 'gallery' == $redir_tab) ) ? true : false;
 	$order = '';
 
+	$groupnum = '<input type="hidden" class="group-value" name="attachments['.$attachment_id.'][group_number]" value="'.$group_number.'" />';
+
 	foreach ( $form_fields as $key => $val ) {
 		if ( 'menu_order' == $key ) {
 			if ( $gallery )
@@ -826,6 +849,7 @@
 	$type
 	$toggle_links
 	$order
+	$groupnum
 	$display_title
 	<table class='slidetoggle describe $class'>
 		<thead class='media-item-info'>
@@ -1088,7 +1112,7 @@
 		html = '<img alt="'+alt+'" src="'+f.src.value+'"'+title+cls+' width="'+t.width+'" height="'+t.height+'" />';
 
 		if ( f.url.value )
-			html = '<a href="'+f.url.value+'">'+html+'</a>';
+			html = '<a href="'+f.url.value+'"'+title+'>'+html+'</a>';
 
 		if ( caption )
 			html = '[caption id="" align="'+t.align+'" width="'+t.width+'" caption="'+caption+'"]'+html+'[/caption]';
@@ -1151,6 +1175,9 @@
 	media_upload_header();
 
 	$post_id = intval($_REQUEST['post_id']);
+	$group_num = intval(get_attachment_groups( $post_id ));
+	$_group_name = get_attachments_groupsname( $post_id );
+	
 	$form_action_url = admin_url("media-upload.php?type={$GLOBALS['type']}&tab=gallery&post_id=$post_id");
 ?>
 
@@ -1160,8 +1187,26 @@
 	var preloaded = $(".media-item.preloaded");
 	if ( preloaded.length > 0 ) {
 		preloaded.each(function(){prepareMediaItem({id:this.id.replace(/[^0-9]/g, '')},'');});
-		updateMediaForm();
 	}
+	jQuery("a.del-group").click(function () { 
+		var deleteConfirmation = confirm('<?php _e("Are you sure you want to delete this gallery group?"); ?>'); 
+		
+		if (!deleteConfirmation) { return; } 
+		
+		if (jQuery("#media-group-" + jQuery(this).attr('value') + " .media-item input.group-value").length)
+		{ 
+			jQuery.each(jQuery("#media-group-delete-" + jQuery(this).attr('value') + " .media-item input.group-value"), function(i, id) { 
+				jQuery(id)[0].value = 0;        //      we are going to set all the items to group 0             
+			}); 
+		} 
+		jQuery("#gallery-delete").val( jQuery(this).attr('value') );    //      set the gallery we are deleting 
+		jQuery("#media-group-" + jQuery(this).attr('value')).hide();    //      hide the gallery and then... 
+		jQuery(".savebutton").click(); 
+	}); 
+	jQuery("a.insert-group").click(function () {
+		jQuery("#gallery-insert").val( jQuery(this).attr('value') );    //      set the gallery we are inserting 
+		jQuery(".insert-gallery").click();               
+	});
 });
 -->
 </script>
@@ -1169,23 +1214,58 @@
 <form enctype="multipart/form-data" method="post" action="<?php echo attribute_escape($form_action_url); ?>" class="media-upload-form validate" id="gallery-form">
 <?php wp_nonce_field('media-form'); ?>
 <?php //media_upload_form( $errors ); ?>
+<div id="media-items"> 
+<?php 
+for ( $i = 0; $i < $group_num; $i++ ) 
+{ 
+?> 
+<div id="media-group-<?php echo $i; ?>" class="media-groups"> 
+<input type="hidden" id="media-group-value-<?php echo $i; ?>" value="<?php echo $i; ?>" /> 
 <table class="widefat">
 <thead><tr>
-<th><?php _e('Media'); ?></th>
+<th> 
+<?php  
+if ($i > 0) {
+	
+	$delete = "<a href=\"#media-group-delete-value-".$i."\" value=\"".$i."\" class=\"del-group\">" . __('Delete') . "</a>"; 
+	$insert = "<a href=\"#media-group-insert-value-".$i."\" value=\"".$i."\" class=\"insert-group\">" . __('Insert') . "</a>"; 
+	$group_link = "<small>[".$delete." | " .$insert."]</small>";
+	$group_name = "<input type=\"text\" name=\"\" value=\"" . $_group_name[$i] . "\" size=\"20\" />";
+	
+	_e('Group (' . $i . ') ' . $group_name . ' ' . $group_link);
+		
+} else { 
+
+	_e('Media: Non-grouped items.'); 
+	
+}
+?> 
+</th>
 <th class="order-head"><?php _e('Order'); ?></th>
 </tr></thead>
 </table>
-<div id="media-items">
-<?php echo get_media_items($post_id, $errors); ?>
+<?php echo get_media_items($post_id, $i, $errors); ?>
 </div>
+<?php 
+}
+?> 
+</div>
 <p class="ml-submit">
 <input type="submit" class="button savebutton" name="save" value="<?php echo attribute_escape( __( 'Save all changes' ) ); ?>" />
-<input type="submit" class="button insert-gallery" name="insert-gallery" value="<?php echo attribute_escape( __( 'Insert gallery into post' ) ); ?>" />
+<input type="submit" class="button new-gallery" name="new-gallery" value="<?php echo attribute_escape( __( 'Create new gallery' ) ); ?>" /> 
+<input type="submit" class="button insert-gallery" name="insert-gallery" value="<?php echo attribute_escape( __( 'Insert full gallery into post' ) ); ?>" /> 
+<input type="hidden" name="gallery_delete" id="gallery-delete" value="" /> 
+<input type="hidden" name="gallery_insert" id="gallery-insert" value="" /> 
 <input type="hidden" name="post_id" id="post_id" value="<?php echo (int) $post_id; ?>" />
 <input type="hidden" name="type" value="<?php echo attribute_escape( $GLOBALS['type'] ); ?>" />
 <input type="hidden" name="tab" value="<?php echo attribute_escape( $GLOBALS['tab'] ); ?>" />
 </p>
 </form>
+<script type="text/javascript"> 
+<!-- 
+	updateMediaForm(); 
+--> 
+</script> 
 <?php
 }
 
@@ -1325,7 +1405,7 @@
 </script>
 
 <div id="media-items">
-<?php echo get_media_items(null, $errors); ?>
+<?php echo get_media_items(null, null, $errors); ?> 
 </div>
 <p class="ml-submit">
 <input type="submit" class="button savebutton" name="save" value="<?php echo attribute_escape( __( 'Save all changes' ) ); ?>" />
Index: wp-admin/js/gallery.js
===================================================================
--- wp-admin/js/gallery.js	(revision 9036)
+++ wp-admin/js/gallery.js	(working copy)
@@ -1,22 +1,44 @@
 jQuery(function($) {
 	var gallerySortable;
+
 	var gallerySortableInit = function() {
 		gallerySortable = $('#media-items').sortable( {
 			items: '.media-item',
 			placeholder: 'sorthelper',
 			axis: 'y',
 			distance: 2,
-			update: galleryReorder
+			update: galleryHandle,
 		} );
 	}
-
-	// When an update has occurred, adjust the order for each item
+	
+	var galleryHandle = function (e, sort) {
+		galleryReorder(e, sort); 
+		gallerySortGroups();
+	}
+	
+	// @todo: fix me!
+	// When an update has occurred, adjust the order for each item.. 
 	var galleryReorder = function(e, sort) {
+		var o = 0;
 		jQuery.each(sort['element'].sortable('toArray'), function(i, id) {
-			jQuery('#' + id + ' .menu_order input')[0].value = (1+i);
+			if (id)
+			{
+				o++;
+				jQuery('#' + id + ' .menu_order input')[0].value = o;
+			}
 		});
 	}
-
+	
+	var gallerySortGroups = function () {
+		var mediaGroups = jQuery(".media-groups").length;
+		for (g = 0; g < mediaGroups; g++)
+		{
+			jQuery.each(jQuery("#media-group-" + g + " .media-item input.group-value"), function(i, id) {
+				jQuery(id)[0].value = g;		
+			});
+		}
+	}
+	
 	// initialize sortable
 	gallerySortableInit();
 });
Index: wp-includes/js/swfupload/handlers.js
===================================================================
--- wp-includes/js/swfupload/handlers.js	(revision 9036)
+++ wp-includes/js/swfupload/handlers.js	(working copy)
@@ -126,16 +126,23 @@
 	}
 
 	// Only show Save buttons when there is at least one file.
-	if ( jQuery('#media-items>*').not('.media-blank').length > 0 )
+	if ( jQuery('#media-items .media-item').not('.media-no-items').length > 0 )
 		jQuery('.savebutton').show();
 	else
 		jQuery('.savebutton').hide();
 
+	// Only show new Gallery button when there are at least two files.
+	if ( jQuery('#media-items .media-item').not('.media-no-items').length > 1 )
+		jQuery('.new-gallery').show();
+	else
+		jQuery('.new-gallery').hide();
+
 	// Only show Gallery button when there are at least two files.
-	if ( jQuery('#media-items>*').length > 1 )
+	if ( jQuery('#media-items .media-groups').length > 1 )
 		jQuery('.insert-gallery').show();
 	else
 		jQuery('.insert-gallery').hide();
+		
 }
 
 function uploadSuccess(fileObj, serverData) {
Index: wp-includes/media.php
===================================================================
--- wp-includes/media.php	(revision 9036)
+++ wp-includes/media.php	(working copy)
@@ -617,12 +617,13 @@
 		'icontag'    => 'dt',
 		'captiontag' => 'dd',
 		'columns'    => 3,
+		'group'		 => null,
 		'size'       => 'thumbnail',
 	), $attr));
 
 	$id = intval($id);
-	$attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
-
+	$attachments = get_attachments( $post->ID, $group, array('post_status' => 'inherit', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
+	
 	if ( empty($attachments) )
 		return '';
 
Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 9036)
+++ wp-includes/post.php	(working copy)
@@ -69,6 +69,143 @@
 }
 
 /**
+ * Get the posts attachments data.
+ *
+ * @since 2.7.0
+ *
+ * @param int $post_id Post ID
+ */
+function _get_attachment_data ( $post_id ) {
+	global $wpdb;
+
+	$_attchments = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = '_wp_post_attachments' LIMIT 1", $post_id));
+	return unserialize($_attchments->meta_value);
+}
+/**
+ * Get the posts attachments.
+ *
+ * @since 2.7.0
+ *
+ * @param int $post_id Post ID
+ * @param int $group_num Group Number
+ * @param mixed $args Optional. User defined arguments for replacing the defaults.
+ */
+function &get_attachments( $post_id, $group_num = null, $args = '' ) {
+
+	$attachment = _get_attachment_data ( $post_id );
+	
+	foreach ( $attachment as $key => $group ) {
+		
+		if (!is_null($group_num))
+			if ($key != $group_num) { continue; }
+		
+		if ( !is_array($group['items']) )
+			break;
+			
+		foreach ( $group['items'] as $item => $attachment_id ) {
+			$p = get_post( $attachment_id );
+			$p->group_number = $key;
+			
+			$attach[$attachment_id] = $p;
+		}
+	} 
+	
+	// @todo Orginize items based on the settings either default or user
+	
+	return $attach;
+}
+
+/**
+ * Get the gallery groups names.
+ *
+ * @since 2.7.0
+ *
+ * @param int $post_id Post ID
+ */
+function &get_attachments_groupsname( $post_id ) {
+
+	$attachment = _get_attachment_data ( $post_id );
+	
+	if ( !is_array($attachment) )
+		return '';
+	
+	foreach ( $attachment as $key => $group ) {
+		$groups[$key] = $group['name'];
+	} 
+	
+	return $groups;
+}
+
+/**
+ * Get the number of groups attached to this post.
+ *
+ * @since 2.7.0
+ *
+ * @param int $post_id Post ID
+ */
+function get_attachment_groups( $post_id ) {
+	
+	return count(_get_attachment_data ( $post_id ));
+}
+
+/**
+ * Insert a new gallery into the post. 
+ * 
+ * @since 2.7.0 
+ * 
+ * @param int $post_id post data 
+*/ 
+function wp_new_gallery ( $post_id ) { 
+
+	$attachment = _get_attachment_data ( $post_id );
+	
+	foreach ( $attachment as $key => $group )
+		$_group[$key] = array ('name' => $group['name'], 'items' => $group['items']);
+
+	$_group[] = array ('name' => null, 'items' => null);
+	
+	update_post_meta( $post_id, '_wp_post_attachments', $_group );
+	
+}
+
+/**
+ * We are deleting a gallery and moving 
+ * 
+ * @since 2.7.0 
+ * 
+ * @param int $post_id Post ID
+ * @param int $group_number Group Number
+*/ 
+function wp_delete_gallery ( $post_id, $group_num ) {
+	 
+	$attachment = _get_attachment_data ( $post_id );
+	
+	foreach ( $attachment as $key => $group ) {
+		if ($key != $group_num) {
+			$_group[$key] = array ('name' => $group['name'], 'items' => $group['items']);
+			continue;						
+		}	
+		
+		if ( !is_array($group['items']) )
+			break;
+		
+		foreach ( $group['items'] as $item => $attachment_id ) {
+			$_attach[] = $attachment_id;	
+		}
+	}
+	
+	if ( is_array($_group[0]['items']) && is_array($_attach) )  {
+		$i = array_merge($_group[0]['items'], $_attach);	
+		$_group[0] = array ('name' => null, 'items' => $i);	
+	} else {
+		$_group[0] = array ('name' => null, 'items' => $_group[0]['items']);
+	}
+
+	update_post_meta( $post_id, '_wp_post_attachments', $_group );
+
+}
+
+/**
  * Retrieve all children of the post parent ID.
  *
  * Normally, without any enhancements, the children would apply to pages. In the
