Index: wp-includes/category-template.php
===================================================================
--- wp-includes/category-template.php	(revision 8666)
+++ wp-includes/category-template.php	(working copy)
@@ -350,11 +350,17 @@
 	if ( empty( $tags ) )
 		return;
 
+	foreach ( $tags as $key => $tag ) {
+		$link = get_tag_link( $tag->term_id );
+		if ( is_wp_error( $link ) )
+			return false;
+
+		$tags[ $key ]->link = $link;
+		$tags[ $key ]->id = $tag->term_id;
+	}
+
 	$return = wp_generate_tag_cloud( $tags, $args ); // Here's where those top tags get sorted according to $args
 
-	if ( is_wp_error( $return ) )
-		return false;
-
 	$return = apply_filters( 'wp_tag_cloud', $return, $args );
 
 	if ( 'array' == $args['format'] )
@@ -377,23 +383,39 @@
 function wp_generate_tag_cloud( $tags, $args = '' ) {
 	global $wp_rewrite;
 	$defaults = array(
-		'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
-		'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC'
+		'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 0,
+		'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC',
+		'single_text' => '%d topic', 'multiple_text' => '%d topics'
 	);
 	$args = wp_parse_args( $args, $defaults );
 	extract( $args );
 
 	if ( empty( $tags ) )
 		return;
-	$counts = $tag_links = array();
-	foreach ( (array) $tags as $tag ) {
-		$counts[$tag->name] = $tag->count;
-		$tag_links[$tag->name] = get_tag_link( $tag->term_id );
-		if ( is_wp_error( $tag_links[$tag->name] ) )
-			return $tag_links[$tag->name];
-		$tag_ids[$tag->name] = $tag->term_id;
+
+	// SQL cannot save you; this is a second (potentially different) sort on a subset of data.
+	if ( 'name' == $orderby )
+		uasort( $tags, create_function('$a, $b', 'return strnatcasecmp($a->name, $b->name);') );
+	else
+		uasort( $tags, create_function('$a, $b', 'return ($a->count < $b->count);') );
+
+	if ( 'DESC' == $order )
+		$tags = array_reverse( $tags, true );
+	elseif ( 'RAND' == $order ) {
+		$keys = array_rand( $tags, count( $tags ) );
+		foreach ( $keys as $key )
+			$temp[$key] = $tags[$key];
+		$tags = $temp;
+		unset( $temp );
 	}
 
+	if ( $number > 0 )
+		$tags = array_slice($tags, 0, $number);
+
+	$counts = array();
+	foreach ( (array) $tags as $key => $tag )
+		$counts[ $key ] = $tag->count;
+
 	$min_count = min( $counts );
 	$spread = max( $counts ) - $min_count;
 	if ( $spread <= 0 )
@@ -403,32 +425,18 @@
 		$font_spread = 1;
 	$font_step = $font_spread / $spread;
 
-	// SQL cannot save you; this is a second (potentially different) sort on a subset of data.
-	if ( 'name' == $orderby )
-		uksort( $counts, 'strnatcasecmp' );
-	else
-		asort( $counts );
-
-	if ( 'DESC' == $order )
-		$counts = array_reverse( $counts, true );
-	elseif ( 'RAND' == $order ) {
-		$keys = array_rand( $counts, count( $counts ) );
-		foreach ( $keys as $key )
-			$temp[$key] = $counts[$key];
-		$counts = $temp;
-		unset( $temp );
-	}
-
 	$a = array();
 
 	$rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? ' rel="tag"' : '';
 
-	foreach ( $counts as $tag => $count ) {
-		$tag_id = $tag_ids[$tag];
-		$tag_link = clean_url($tag_links[$tag]);
-		$a[] = "<a href='$tag_link' class='tag-link-$tag_id' title='" . attribute_escape( sprintf( __ngettext('%d topic','%d topics',$count), $count ) ) . "'$rel style='font-size: " .
+	foreach ( $tags as $key => $tag ) {
+		$count = $counts[ $key ];
+		$tag_link = clean_url( $tag->link );
+		$tag_id = isset($tags[ $key ]->id) ? $tags[ $key ]->id : $key;
+		$tag_name = $tags[ $key ]->name;
+		$a[] = "<a href='$tag_link' class='tag-link-$tag_id' title='" . attribute_escape( sprintf( __ngettext( $single_text, $multiple_text, $count ), $count ) ) . "'$rel style='font-size: " .
 			( $smallest + ( ( $count - $min_count ) * $font_step ) )
-			. "$unit;'>$tag</a>";
+			. "$unit;'>$tag_name</a>";
 	}
 
 	switch ( $format ) :
