Index: wp-includes/theme.php
===================================================================
--- wp-includes/theme.php	(revision 7943)
+++ wp-includes/theme.php	(working copy)
@@ -479,6 +479,44 @@
 	echo '<link rel="stylesheet" href="' . $stylesheet . '" type="text/css" media="screen" />';
 }
 
+function preview_theme() {
+	if ( ! (isset($_GET['template']) && isset($_GET['preview'])) )
+		return;
+
+	if ( !current_user_can( 'switch_themes' ) )
+		return;
+
+	add_filter('template', create_function('', "return '$_GET[template]';") );
+
+	if ( isset($_GET['stylesheet']) )
+		add_filter('stylesheet', create_function('', "return '$_GET[stylesheet]';") );
+
+	ob_start( 'preview_theme_ob_filter' );
+}
+add_action('setup_theme', 'preview_theme');
+
+function preview_theme_ob_filter( $content ) {
+	return preg_replace_callback( "|(<a.*?href=([\"']))(.*?)([\"'].*?>)|", 'preview_theme_ob_filter_callback', $content );
+}
+
+function preview_theme_ob_filter_callback( $matches ) {
+	if (
+	    ( false !== strpos($matches[3], '/wp-admin/') )
+	||
+	    ( false !== strpos($matches[3], '://') && 0 !== strpos($matches[3], get_option('home')) )
+	||
+	    ( false !== strpos($matches[3], '/feed/') )
+	||
+	    ( false !== strpos($matches[3], '/trackback/') )
+	)
+		return $matches[1] . "#$matches[2] onclick=$matches[2]return false;" . $matches[4];
+
+	$link = add_query_arg( array('preview' => 1, 'template' => $_GET['template'], 'stylesheet' => @$_GET['stylesheet'] ), $matches[3] );
+	if ( 0 === strpos($link, 'preview=1') )
+		$link = "?$link";
+	return $matches[1] . attribute_escape( $link ) . $matches[4];
+}
+
 function switch_theme($template, $stylesheet) {
 	update_option('template', $template);
 	update_option('stylesheet', $stylesheet);
Index: wp-settings.php
===================================================================
--- wp-settings.php	(revision 7943)
+++ wp-settings.php	(working copy)
@@ -425,19 +425,8 @@
  */
 $wp           =& new WP();
 
+$wp->init();  // Sets up current user.
 
-/**
- * Web Path to the current active template directory
- * @since 1.5
- */
-define('TEMPLATEPATH', get_template_directory());
-
-/**
- * Web Path to the current active template stylesheet directory
- * @since 2.1
- */
-define('STYLESHEETPATH', get_stylesheet_directory());
-
 // Load the default text localization domain.
 load_default_textdomain();
 
@@ -460,6 +449,20 @@
  */
 $wp_locale =& new WP_Locale();
 
+do_action('setup_theme');
+
+/**
+ * Web Path to the current active template directory
+ * @since 1.5
+ */
+define('TEMPLATEPATH', get_template_directory());
+
+/**
+ * Web Path to the current active template stylesheet directory
+ * @since 2.1
+ */
+define('STYLESHEETPATH', get_stylesheet_directory());
+
 // Load functions for active theme.
 if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists(STYLESHEETPATH . '/functions.php') )
 	include(STYLESHEETPATH . '/functions.php');
@@ -478,8 +481,6 @@
 }
 register_shutdown_function('shutdown_action_hook');
 
-$wp->init();  // Sets up current user.
-
 // Everything is loaded and initialized.
 do_action('init');
 
Index: wp-admin/wp-admin.css
===================================================================
--- wp-admin/wp-admin.css	(revision 7943)
+++ wp-admin/wp-admin.css	(working copy)
@@ -52,30 +52,80 @@
 	margin: 10px 20px 10px 20px;
 }
 
-.available-theme {
-	width: 30%;
-	margin: 0 1em;
-	float: left;
-	text-align: center;
-	height: 28em;
-	overflow: hidden;
+table#availablethemes {
+	border-spacing: 0px;
+	border: none;
+	border-top: 1px solid #ccc;
+	border-bottom: 1px solid #ccc;
+	margin: 10px auto;
 }
+td.available-theme {
+	vertical-align: top;
+	width: 240px;
+	margin: 0;
+	padding: 20px;
+	text-align: left;
+}
+table#availablethemes td {
+	border: 1px solid #eee;
+	border-top: none;
+}
+table#availablethemes td.top {
+	border-top: none;
+}
+table#availablethemes td.right {
+	border-right: none;
+	border-left: none;
+}
+table#availablethemes td.bottom {
+	border-bottom: none;
+}
+table#availablethemes td.left {
+	border-right: none;
+	border-left: none;
+}
 
 .available-theme a.screenshot {
-	width: 250px;
-	height: 200px;
+	width: 240px;
+	height: 180px;
 	display: block;
-	margin: auto;
+	border: 1px solid #efefef;
 	margin-bottom: 10px;
 	overflow: hidden;
-	border-width: 1px;
-	border-style: solid;
 }
-
 .available-theme img {
-	width: 100%;
+	width: 240px;
 }
+.available-theme h3 {
+	margin: 15px 0 5px;
+}
 
+#current-theme {
+	margin-top: 1em;
+}
+
+#current-theme a {
+	border-bottom: none;
+}
+
+#current-theme h3 {
+	font-size: 17px;
+	font-weight: normal;
+	margin: 0;
+}
+
+#current-theme .description {
+	margin-top: 5px;
+}
+
+#current-theme img {
+	float: left;
+	border: 1px solid #666;
+	margin-right: 1em;
+	margin-bottom: 1.5em;
+	width: 150px;
+}
+
 .checkbox {
 	border: none;
 	margin: 0;
@@ -249,15 +299,6 @@
 	border-collapse: separate;
 }
 
-#currenttheme img {
-	float: left;
-	margin-right: 1em;
-	margin-bottom: 1.5em;
-	width: 300px;
-	border-width: 1px;
-	border-style: solid;
-}
-
 #quicktags {
 	padding: 0;
 	border: 0 none;
Index: wp-admin/includes/media.php
===================================================================
--- wp-admin/includes/media.php	(revision 7943)
+++ wp-admin/includes/media.php	(working copy)
@@ -194,7 +194,10 @@
 </style>\n";
 }
 
-add_action( 'admin_print_scripts', 'media_buttons_head' );
+add_action( 'admin_head-post-new.php', 'media_buttons_head' );
+add_action( 'admin_head-post.php', 'media_buttons_head' );
+add_action( 'admin_head-page-new.php', 'media_buttons_head' );
+add_action( 'admin_head-page.php', 'media_buttons_head' );
 
 function media_admin_css() {
 	wp_admin_css('css/media');
Index: wp-admin/js/theme-preview.js
===================================================================
--- wp-admin/js/theme-preview.js	(revision 0)
+++ wp-admin/js/theme-preview.js	(revision 0)
@@ -0,0 +1,46 @@
+jQuery(function($) {
+	if ( 'undefined' == typeof $.fn.pngFix )
+		$.fn.pngFix = function() { return this; }
+
+	var thickDims = function() {
+		var width = $(window).width();
+		var height = $(window).height();
+
+		var tbWindow = $('#TB_window');
+		if ( tbWindow.size() ) {
+			tbWindow.width( width - 100 ).height( height - 60 );
+			tb_position( width - 70, height - 60 );
+			$('#TB_iframeContent').height( height - 88 );
+		}
+
+		return $('a.thickbox').each( function() {
+			var href = $(this).parents('.available-theme').find('.previewlink').attr('href');
+			if ( !href )
+				return;
+			href = href.replace(/&width=[0-9]+/g, '');
+			href = href.replace(/&height=[0-9]+/g, '');
+			$(this).attr( 'href', href + '&width=' + ( width - 100 ) + '&height=' + ( height - 100 ) );
+		} );
+	}
+
+	thickDims()
+	.click( function() {
+		var alink = $(this).parents('.available-theme').find('.activatelink');
+		var url = alink.attr('href');
+		var text = alink.html();
+
+		var img = $('<img id="TB-close-png" src="wp-includes/js/thickbox/tb-close.png" alt="close" title="close" />')
+			.wrap('<a href="#" id="TB-close-link" style="float: left; border-bottom: none;" onclick="tb_remove(); return false;"></a>')
+			.css( { width: 28, height: 28 } )
+			.parent().pngFix();
+
+		$('#TB_ajaxWindowTitle')
+			.before(img)
+			.append('&nbsp;<a href="' + url + '" target="_top" style="position: absolute; right: 1ex; font-weight: bold;">' + text + ' &raquo;</a>');
+
+		$('#TB_iframeContent').width('100%');
+		return false;
+	} );
+
+	$(window).resize( function() { thickDims() } );
+});
Index: wp-admin/admin-header.php
===================================================================
--- wp-admin/admin-header.php	(revision 7943)
+++ wp-admin/admin-header.php	(working copy)
@@ -48,12 +48,16 @@
 	do_action('admin_print_scripts-' . $page_hook);
 else if ( isset($plugin_page) )
 	do_action('admin_print_scripts-' . $plugin_page);
+else if ( isset($pagenow) )
+	do_action('admin_print_scripts-' . $pagenow);
 do_action('admin_print_scripts');
 
 if ( isset($page_hook) )
 	do_action('admin_head-' . $page_hook);
 else if ( isset($plugin_page) )
 	do_action('admin_head-' . $plugin_page);
+else if ( isset($pagenow) )
+	do_action('admin_head-' . $pagenow);
 do_action('admin_head');
 ?>
 </head>
Index: wp-admin/css/theme-tb.css
===================================================================
--- wp-admin/css/theme-tb.css	(revision 0)
+++ wp-admin/css/theme-tb.css	(revision 0)
@@ -0,0 +1,169 @@
+/* ----------------------------------------------------------------------------------------------------------------*/
+/* ---------->>> global settings needed for thickbox <<<-----------------------------------------------------------*/
+/* ----------------------------------------------------------------------------------------------------------------*/
+/* * {padding: 0; margin: 0;} */
+
+/* ----------------------------------------------------------------------------------------------------------------*/
+/* ---------->>> thickbox specific link and font settings <<<------------------------------------------------------*/
+/* ----------------------------------------------------------------------------------------------------------------*/
+#TB_window {
+	font: 12px Arial, Helvetica, sans-serif;
+	color: #333333;
+}
+
+#TB_secondLine {
+	font: 10px Arial, Helvetica, sans-serif;
+	color:#666666;
+}
+/*
+#TB_window a:link {color: #666666;}
+#TB_window a:visited {color: #666666;}
+#TB_window a:hover {color: #000;}
+#TB_window a:active {color: #666666;}
+#TB_window a:focus{color: #666666;}
+*/
+/* ----------------------------------------------------------------------------------------------------------------*/
+/* ---------->>> thickbox settings <<<-----------------------------------------------------------------------------*/
+/* ----------------------------------------------------------------------------------------------------------------*/
+#TB_overlay {
+	position: fixed;
+	z-index:100;
+	top: 0px;
+	left: 0px;
+	background-color:#000;
+	filter:alpha(opacity=75);
+	-moz-opacity: 0.75;
+	opacity: 0.75;
+	height:100%;
+	width:100%;
+}
+
+* html #TB_overlay { /* ie6 hack */
+     position: absolute;
+     height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
+}
+
+#TB_window {
+	position: fixed;
+	background: #ffffff;
+	z-index: 102;
+	color:#000000;
+	display:none;
+	border: 4px solid #525252;
+	text-align:left;
+	top:50%;
+	left:50%;
+}
+
+* html #TB_window { /* ie6 hack */
+position: absolute;
+margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');
+}
+
+#TB_window img#TB_Image {
+	display:block;
+	margin: 15px 0 0 15px;
+	border-right: 1px solid #ccc;
+	border-bottom: 1px solid #ccc;
+	border-top: 1px solid #666;
+	border-left: 1px solid #666;
+}
+
+#TB_caption{
+	height:25px;
+	padding:7px 30px 10px 25px;
+	float:left;
+}
+
+#TB_closeWindow{
+	height:25px;
+	padding:11px 25px 10px 0;
+	float:right;
+}
+
+#TB_closeAjaxWindow{
+	padding:7px 10px 5px 0;
+	margin-bottom:1px;
+	text-align:right;
+	float:right;
+}
+
+#TB_ajaxWindowTitle{
+	float:left;
+	padding:7px 0 5px;
+	margin-bottom:1px;
+}
+
+#TB_title{
+	background-color:#e8e8e8;
+	height:27px;
+}
+
+#TB_ajaxContent{
+	clear:both;
+	padding:2px 15px 15px 15px;
+	overflow:auto;
+	text-align:left;
+	line-height:1.4em;
+}
+
+#TB_ajaxContent.TB_modal{
+	padding:15px;
+}
+
+#TB_ajaxContent p{
+	padding:5px 0px 5px 0px;
+}
+
+#TB_load{ /* WP */
+	background-color: #E8E8E8;
+	border: 4px solid #525252;
+	position: fixed;
+	display:none;
+	height:50px;
+	width:250px;
+	z-index:103;
+	top: 50%;
+	left: 50%;
+	margin: -25px 0 0 -125px; /* -height/2 0 0 -width/2 */
+	padding: 1ex;
+}
+
+* html #TB_load { /* ie6 hack */
+position: absolute;
+margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');
+}
+
+#TB_load img { /* WP */
+	position: absolute;
+	bottom: 2ex;
+	left: 21px; /* (width(TB_load) - width(img))/2 */
+	padding-left: 1ex;
+}
+
+#TB_HideSelect{
+	z-index:99;
+	position:fixed;
+	top: 0;
+	left: 0;
+	background-color:#fff;
+	border:none;
+	filter:alpha(opacity=0);
+	-moz-opacity: 0;
+	opacity: 0;
+	height:100%;
+	width:100%;
+}
+
+* html #TB_HideSelect { /* ie6 hack */
+     position: absolute;
+     height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
+}
+
+#TB_iframeContent{
+	clear:both;
+	border:none;
+	margin-bottom:-1px;
+	margin-top:1px;
+	_margin-bottom:1px;
+}
Index: wp-admin/themes.php
===================================================================
--- wp-admin/themes.php	(revision 7943)
+++ wp-admin/themes.php	(working copy)
@@ -1,6 +1,13 @@
 <?php
 require_once('admin.php');
 
+function switch_themes_css() {
+	echo "<style type='text/css' media='all'>
+		@import 'css/theme-tb.css?1';
+		#TB_closeWindow, #TB_closeAjaxWindow { display: none; }
+		</style>\n";
+}
+
 if ( isset($_GET['action']) ) {
 	check_admin_referer('switch-theme_' . $_GET['template']);
 
@@ -13,6 +20,11 @@
 
 $title = __('Manage Themes');
 $parent_file = 'themes.php';
+
+wp_enqueue_script( 'theme-preview', '/wp-admin/js/theme-preview.js', array( 'thickbox', 'dimensions' ), 5 );
+
+add_action( 'admin_head', 'switch_themes_css' );
+
 require_once('admin-header.php');
 ?>
 
@@ -29,12 +41,12 @@
 
 <div class="wrap">
 <h2><?php _e('Current Theme'); ?></h2>
-<div id="currenttheme">
+<div id="current-theme">
 <?php if ( $ct->screenshot ) : ?>
 <img src="<?php echo get_option('siteurl') . '/' . $ct->stylesheet_dir . '/' . $ct->screenshot; ?>" alt="<?php _e('Current theme preview'); ?>" />
 <?php endif; ?>
 <h3><?php printf(_c('%1$s %2$s by %3$s|1: theme title, 2: theme version, 3: theme author'), $ct->title, $ct->version, $ct->author) ; ?></h3>
-<p><?php echo $ct->description; ?></p>
+<p class="description"><?php echo $ct->description; ?></p>
 <?php if ($ct->parent_theme) { ?>
 	<p><?php printf(__('The template files are located in <code>%2$s</code>.  The stylesheet files are located in <code>%3$s</code>.  <strong>%4$s</strong> uses templates from <strong>%5$s</strong>.  Changes made to the templates will affect both themes.'), $ct->title, $ct->template_dir, $ct->stylesheet_dir, $ct->title, $ct->parent_theme); ?></p>
 <?php } else { ?>
@@ -47,16 +59,31 @@
 
 <h2><?php _e('Available Themes'); ?></h2>
 <?php if ( 1 < count($themes) ) { ?>
-
+<table id="availablethemes" cellspacing="0" cellpadding="0">
 <?php
 $style = '';
 
 $theme_names = array_keys($themes);
 natcasesort($theme_names);
 
-foreach ($theme_names as $theme_name) {
-	if ( $theme_name == $ct->name )
-		continue;
+$rows = ceil(count($theme_names) / 3);
+for ( $row = 1; $row <= $rows; $row++ )
+	for ( $col = 1; $col <= 3; $col++ )
+		$table[$row][$col] = array_shift($theme_names);
+
+foreach ( $table as $row => $cols ) {
+?>
+<tr>
+<?php
+foreach ( $cols as $col => $theme_name ) {
+	$class = array('available-theme');
+	if ( $row == 1 ) $class[] = 'top';
+	if ( $col == 1 ) $class[] = 'left';
+	if ( $row == $rows ) $class[] = 'bottom';
+	if ( $col == 3 ) $class[] = 'right';
+?>
+	<td class="<?php echo join(' ', $class); ?>">
+<?php if ( !empty($theme_name) ) :
 	$template = $themes[$theme_name]['Template'];
 	$stylesheet = $themes[$theme_name]['Stylesheet'];
 	$title = $themes[$theme_name]['Title'];
@@ -65,25 +92,32 @@
 	$author = $themes[$theme_name]['Author'];
 	$screenshot = $themes[$theme_name]['Screenshot'];
 	$stylesheet_dir = $themes[$theme_name]['Stylesheet Dir'];
+	$preview_link = clean_url( get_option('home') . '/');
+	$preview_link = add_query_arg( array('preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'TB_iframe' => 'true', 'width' => 600, 'height' => 400 ), $preview_link );
+	$preview_text = attribute_escape( sprintf( __('Preview of "%s"'), $title ) );
 	$tags = $themes[$theme_name]['Tags'];
+	$thickbox_class = 'thickbox';
 	$activate_link = wp_nonce_url("themes.php?action=activate&amp;template=".urlencode($template)."&amp;stylesheet=".urlencode($stylesheet), 'switch-theme_' . $template);
+	$activate_text = attribute_escape( sprintf( __('Activate "%s"'), $title ) );
 ?>
-<div class="available-theme">
-<h3><a href="<?php echo $activate_link; ?>"><?php echo $title; ?></a></h3>
-
-<a href="<?php echo $activate_link; ?>" class="screenshot">
+		<a href="<?php echo $activate_link; ?>" class="<?php echo $thickbox_class; ?> screenshot">
 <?php if ( $screenshot ) : ?>
-<img src="<?php echo get_option('siteurl') . '/' . $stylesheet_dir . '/' . $screenshot; ?>" alt="" />
+			<img src="<?php echo ( $tpage == 'stage' ) ? $screenshot : get_option('siteurl') . '/' . $stylesheet_dir . '/' . $screenshot; ?>" alt="" />
 <?php endif; ?>
-</a>
-
-<p><?php echo $description; ?></p>
+		</a>
+		<h3><a class="<?php echo $thickbox_class; ?>" href="<?php echo $activate_link; ?>"><?php echo $title; ?></a></h3>
+		<p><?php echo $description; ?></p>
 <?php if ( $tags ) : ?>
-<p><?php _e('Tags:'); ?> <?php echo join(', ', $tags); ?></p>
+		<p><?php _e('Tags:'); ?> <?php echo join(', ', $tags); ?></p>
+		<noscript><p class="themeactions"><a href="<?php echo $preview_link; ?>" title="<?php echo $preview_text; ?>"><?php _e('Preview'); ?></a> <a href="<?php echo $activate_link; ?>" title="<?php echo $activate_text; ?>"><?php _e('Activate'); ?></a></p></noscript>
 <?php endif; ?>
-</div>
-<?php } // end foreach theme_names ?>
-
+		<div style="display:none;"><a class="previewlink" href="<?php echo $preview_link; ?>"><?php echo $preview_text; ?></a> <a class="activatelink" href="<?php echo $activate_link; ?>"><?php echo $activate_text; ?></a></div>
+<?php endif; // end if not empty theme_name ?>
+	</td>
+<?php } // end foreach $cols ?>
+</tr>
+<?php } // end foreach $table ?>
+</table>
 <?php } ?>
 
 <?php

