Index: wp-admin/categories.php
===================================================================
--- wp-admin/categories.php	(revision 12659)
+++ wp-admin/categories.php	(working copy)
@@ -11,8 +11,26 @@
 
 $title = __('Categories');
 
-wp_reset_vars( array('action') );
+wp_reset_vars( array('action', 'taxonomy', 'post_type') );
 
+if ( empty($taxonomy) )
+	$taxonomy = 'category';
+
+if ( !is_taxonomy($taxonomy) )
+	wp_die(__('Invalid taxonomy'));
+
+if ( empty($post_type) || !in_array( $post_type, get_post_types( array('_show' => true) ) ) )
+	$post_type = 'post';
+
+if ( 'post' != $post_type ) {
+	$parent_file = "edit.php?post_type=$post_type";
+	$submenu_file = "categories.php?taxonomy=$taxonomy&amp;post_type=$post_type";
+} else {
+	$parent_file = 'edit.php';
+	$submenu_file = "categories.php?taxonomy=$taxonomy";	
+}
+
+
 if ( isset( $_GET['action'] ) && isset($_GET['delete']) && ( 'delete' == $_GET['action'] || 'delete' == $_GET['action2'] ) )
 	$action = 'bulk-delete';
 
@@ -135,7 +153,7 @@
 <div class="wrap nosubsub">
 <?php screen_icon(); ?>
 <h2><?php echo esc_html( $title );
-if ( isset($_GET['s']) && $_GET['s'] )
+if ( !empty($_GET['s']) )
 	printf( '<span class="subtitle">' . __('Search results for &#8220;%s&#8221;') . '</span>', esc_html( stripslashes($_GET['s']) ) ); ?>
 </h2>
 
@@ -146,6 +164,8 @@
 endif; ?>
 
 <form class="search-form topmargin" action="" method="get">
+<input type="hidden" name="taxonomy" value="<?php echo esc_attr($taxonomy); ?>" />
+<input type="hidden" name="post_type" value="<?php echo esc_attr($post_type); ?>" />
 <p class="search-box">
 	<label class="screen-reader-text" for="category-search-input"><?php _e('Search Categories'); ?>:</label>
 	<input type="text" id="category-search-input" name="s" value="<?php _admin_search_query(); ?>" />
@@ -159,6 +179,8 @@
 <div id="col-right">
 <div class="col-wrap">
 <form id="posts-filter" action="" method="get">
+<input type="hidden" name="taxonomy" value="<?php echo esc_attr($taxonomy); ?>" />
+<input type="hidden" name="post_type" value="<?php echo esc_attr($post_type); ?>" />
 <div class="tablenav">
 
 <?php
@@ -172,9 +194,9 @@
 $cats_per_page = apply_filters( 'edit_categories_per_page', $cats_per_page );
 
 if ( !empty($_GET['s']) )
-	$num_cats = count(get_categories(array('hide_empty' => 0, 'search' => $_GET['s'])));
+	$num_cats = count(get_categories(array('taxonomy' => $taxonomy, 'hide_empty' => 0, 'search' => $_GET['s'])));
 else
-	$num_cats = wp_count_terms('category');
+	$num_cats = wp_count_terms($taxonomy);
 
 $page_links = paginate_links( array(
 	'base' => add_query_arg( 'pagenum', '%#%' ),
@@ -218,7 +240,7 @@
 
 	<tbody id="the-list" class="list:cat">
 <?php
-cat_rows(0, 0, 0, $pagenum, $cats_per_page);
+cat_rows(0, 0, 0, $pagenum, $cats_per_page, $taxonomy);
 ?>
 	</tbody>
 </table>
@@ -244,8 +266,12 @@
 </form>
 
 <div class="form-wrap">
-<p><?php printf(__('<strong>Note:</strong><br />Deleting a category does not delete the posts in that category. Instead, posts that were only assigned to the deleted category are set to the category <strong>%s</strong>.'), apply_filters('the_category', get_cat_name(get_option('default_category')))) ?></p>
+<?php if ( get_option('default_' . $taxonomy) ) : ?>
+<p><?php printf(__('<strong>Note:</strong><br />Deleting a %1$s does not delete the objects in that %1$s. Instead, objects that were only assigned to the deleted %1$s are set to the %1$s <strong>%2$s</strong>.'), $tax->label, apply_filters('the_category', get_cat_name(get_option('default_' . $taxonomy)))) ?></p>
+<?php endif; ?>
+<?php if ( 'category' == $taxonomy ) : ?>
 <p><?php printf(__('Categories can be selectively converted to tags using the <a href="%s">category to tag converter</a>.'), 'admin.php?import=wp-cat2tag') ?></p>
+<?php endif; ?>
 </div>
 
 </div>
@@ -261,6 +287,8 @@
 <h3><?php _e('Add Category'); ?></h3>
 <div id="ajax-response"></div>
 <form name="addcat" id="addcat" method="post" action="categories.php" class="add:the-list: validate">
+<input type="hidden" name="taxonomy" value="<?php echo esc_attr($taxonomy); ?>" />
+<input type="hidden" name="post_type" value="<?php echo esc_attr($post_type); ?>" />
 <input type="hidden" name="action" value="addcat" />
 <?php wp_original_referer_field(true, 'previous'); wp_nonce_field('add-category'); ?>
 
@@ -278,7 +306,7 @@
 
 <div class="form-field">
 	<label for="category_parent"><?php _e('Category Parent') ?></label>
-	<?php wp_dropdown_categories(array('hide_empty' => 0, 'name' => 'category_parent', 'orderby' => 'name', 'selected' => $category->parent, 'hierarchical' => true, 'show_option_none' => __('None'))); ?>
+	<?php wp_dropdown_categories(array('hide_empty' => 0, 'hide_if_empty' => false, 'taxonomy' => $taxonomy, 'name' => 'category_parent', 'orderby' => 'name', 'selected' => $category->parent, 'hierarchical' => true, 'show_option_none' => __('None'))); ?>
     <p><?php _e('Categories, unlike tags, can have a hierarchy. You might have a Jazz category, and under that have children categories for Bebop and Big Band. Totally optional.'); ?></p>
 </div>
 
Index: wp-admin/includes/taxonomy.php
===================================================================
--- wp-admin/includes/taxonomy.php	(revision 12659)
+++ wp-admin/includes/taxonomy.php	(working copy)
@@ -108,7 +108,7 @@
  * @return unknown
  */
 function wp_insert_category($catarr, $wp_error = false) {
-	$cat_defaults = array('cat_ID' => 0, 'cat_name' => '', 'category_description' => '', 'category_nicename' => '', 'category_parent' => '');
+	$cat_defaults = array('cat_ID' => 0, 'taxonomy' => 'category', 'cat_name' => '', 'category_description' => '', 'category_nicename' => '', 'category_parent' => '');
 	$catarr = wp_parse_args($catarr, $cat_defaults);
 	extract($catarr, EXTR_SKIP);
 
@@ -142,9 +142,9 @@
 	$args = compact('name', 'slug', 'parent', 'description');
 
 	if ( $update )
-		$cat_ID = wp_update_term($cat_ID, 'category', $args);
+		$cat_ID = wp_update_term($cat_ID, $taxonomy, $args);
 	else
-		$cat_ID = wp_insert_term($cat_name, 'category', $args);
+		$cat_ID = wp_insert_term($cat_name, $taxonomy, $args);
 
 	if ( is_wp_error($cat_ID) ) {
 		if ( $wp_error )
Index: wp-admin/includes/template.php
===================================================================
--- wp-admin/includes/template.php	(revision 12659)
+++ wp-admin/includes/template.php	(working copy)
@@ -20,13 +20,13 @@
  * @param unknown_type $page
  * @param unknown_type $per_page
  */
-function cat_rows( $parent = 0, $level = 0, $categories = 0, $page = 1, $per_page = 20 ) {
+function cat_rows( $parent = 0, $level = 0, $categories = 0, $page = 1, $per_page = 20, $taxonomy = 'category' ) {
 
 	$count = 0;
 
 	if ( empty($categories) ) {
 
-		$args = array('hide_empty' => 0);
+		$args = array('hide_empty' => 0, 'taxonomy' => $taxonomy);
 		if ( !empty($_GET['s']) )
 			$args['search'] = $_GET['s'];
 
@@ -36,7 +36,7 @@
 			return false;
 	}
 
-	$children = _get_term_hierarchy('category');
+	$children = _get_term_hierarchy($taxonomy);
 
 	_cat_rows( $parent, $level, $categories, $children, $page, $per_page, $count );
 
@@ -59,8 +59,8 @@
 
 	$start = ($page - 1) * $per_page;
 	$end = $start + $per_page;
-	ob_start();
 
+	$output = '';
 	foreach ( $categories as $key => $category ) {
 		if ( $count >= $end )
 			break;
@@ -83,25 +83,22 @@
 
 			$num_parents = count($my_parents);
 			while( $my_parent = array_pop($my_parents) ) {
-				echo "\t" . _cat_row( $my_parent, $level - $num_parents );
+				$output .=  "\t" . _cat_row( $my_parent, $level - $num_parents );
 				$num_parents--;
 			}
 		}
 
 		if ( $count >= $start )
-			echo "\t" . _cat_row( $category, $level );
+			$output .= "\t" . _cat_row( $category, $level );
 
 		unset( $categories[ $key ] );
 
 		$count++;
 
 		if ( isset($children[$category->term_id]) )
-			_cat_rows( $category->term_id, $level + 1, $categories, $children, $page, $per_page, $count );
+			$output .= _cat_rows( $category->term_id, $level + 1, $categories, $children, $page, $per_page, $count );
 	}
 
-	$output = ob_get_contents();
-	ob_end_clean();
-
 	echo $output;
 }
 
@@ -2568,7 +2565,7 @@
 ?>
 </select>
 <input class="hide-if-js" type="text" id="metakeyinput" name="metakeyinput" tabindex="7" value="" />
-<a href="#postcustomstuff" class="hide-if-no-js" onClick="jQuery('#metakeyinput, #metakeyselect, #enternew, #cancelnew').toggle();return false;">
+<a href="#postcustomstuff" class="hide-if-no-js" onclick="jQuery('#metakeyinput, #metakeyselect, #enternew, #cancelnew').toggle();return false;">
 <span id="enternew"><?php _e('Enter new'); ?></span>
 <span id="cancelnew" class="hidden"><?php _e('Cancel'); ?></span></a>
 <?php } else { ?>
@@ -3239,7 +3236,7 @@
 				<?php wp_nonce_field( 'find-posts', '_ajax_nonce', false ); ?>
 				<label class="screen-reader-text" for="find-posts-input"><?php _e( 'Search' ); ?></label>
 				<input type="text" id="find-posts-input" name="ps" value="" />
-				<input type="button" onClick="findPosts.send();" value="<?php esc_attr_e( 'Search' ); ?>" class="button" /><br />
+				<input type="button" onclick="findPosts.send();" value="<?php esc_attr_e( 'Search' ); ?>" class="button" /><br />
 
 				<input type="radio" name="find-posts-what" id="find-posts-posts" checked="checked" value="posts" />
 				<label for="find-posts-posts"><?php _e( 'Posts' ); ?></label>
@@ -3249,7 +3246,7 @@
 			<div id="find-posts-response"></div>
 		</div>
 		<div class="find-box-buttons">
-			<input type="button" class="button alignleft" onClick="findPosts.close();" value="<?php esc_attr_e('Close'); ?>" />
+			<input type="button" class="button alignleft" onclick="findPosts.close();" value="<?php esc_attr_e('Close'); ?>" />
 			<input id="find-posts-submit" type="submit" class="button-primary alignright" value="<?php esc_attr_e('Select'); ?>" />
 		</div>
 	</div>
Index: wp-admin/menu.php
===================================================================
--- wp-admin/menu.php	(revision 12659)
+++ wp-admin/menu.php	(working copy)
@@ -47,15 +47,16 @@
 
 	$i = 15;
 	foreach ( $wp_taxonomies as $tax ) {
-		if ( $tax->hierarchical || ! in_array('post', (array) $tax->object_type, true) )
+		if ( ! in_array('post', (array) $tax->object_type, true) )
 			continue;
 
-		$submenu['edit.php'][$i] = array( esc_attr($tax->label), 'manage_categories', 'edit-tags.php?taxonomy=' . $tax->name );
+		if ( $tax->hierarchical )
+			$submenu['edit.php'][$i] = array( esc_attr($tax->label), 'manage_categories', 'categories.php?taxonomy=' . $tax->name );
+		else
+			$submenu['edit.php'][$i] = array( esc_attr($tax->label), 'manage_categories', 'edit-tags.php?taxonomy=' . $tax->name );
 		++$i;
 	}
 
-	$submenu['edit.php'][50] = array( __('Categories'), 'manage_categories', 'categories.php' );
-
 $menu[10] = array( __('Media'), 'upload_files', 'upload.php', '', 'menu-top', 'menu-media', 'div' );
 	$submenu['upload.php'][5] = array( __('Library'), 'upload_files', 'upload.php');
 	/* translators: add new file */
@@ -86,10 +87,13 @@
 
 	$i = 15;
 	foreach ( $wp_taxonomies as $tax ) {
-		if ( $tax->hierarchical || ! in_array($ptype, (array) $tax->object_type, true) )
+		if ( ! in_array($ptype, (array) $tax->object_type, true) )
 			continue;
 
-		$submenu["edit.php?post_type=$ptype"][$i] = array( esc_attr($tax->label), 'manage_categories', "edit-tags.php?taxonomy=$tax->name&amp;post_type=$ptype" );
+		if ( $tax->hierarchical )
+			$submenu["edit.php?post_type=$ptype"][$i] = array( esc_attr($tax->label), 'manage_categories', "categories.php?taxonomy=$tax->name&amp;post_type=$ptype" );
+		else
+			$submenu["edit.php?post_type=$ptype"][$i] = array( esc_attr($tax->label), 'manage_categories', "edit-tags.php?taxonomy=$tax->name&amp;post_type=$ptype" );
 		++$i;
 	}
 }
Index: wp-includes/category-template.php
===================================================================
--- wp-includes/category-template.php	(revision 12659)
+++ wp-includes/category-template.php	(working copy)
@@ -337,7 +337,8 @@
 		'exclude' => '', 'echo' => 1,
 		'selected' => 0, 'hierarchical' => 0,
 		'name' => 'cat', 'class' => 'postform',
-		'depth' => 0, 'tab_index' => 0
+		'depth' => 0, 'tab_index' => 0,
+		'taxonomy' => 'category', 'hide_if_empty' => false
 	);
 
 	$defaults['selected'] = ( is_category() ) ? get_query_var( 'cat' ) : 0;
@@ -359,9 +360,11 @@
 	$name = esc_attr($name);
 	$class = esc_attr($class);
 
-	$output = '';
+	if ( ! $r['hide_if_empty'] || ! empty($categories) )
+		$output = "<select name='$name' id='$name' class='$class' $tab_index_attribute>\n";
+	else
+		$output = '';
 	if ( ! empty( $categories ) ) {
-		$output = "<select name='$name' id='$name' class='$class' $tab_index_attribute>\n";
 
 		if ( $show_option_all ) {
 			$show_option_all = apply_filters( 'list_cats', $show_option_all );
@@ -381,9 +384,11 @@
 			$depth = -1; // Flat.
 
 		$output .= walk_category_dropdown_tree( $categories, $depth, $r );
+	}
+	if ( ! $r['hide_if_empty'] || ! empty($categories) )
 		$output .= "</select>\n";
-	}
 
+
 	$output = apply_filters( 'wp_dropdown_cats', $output );
 
 	if ( $echo )
Index: wp-includes/category.php
===================================================================
--- wp-includes/category.php	(revision 12659)
+++ wp-includes/category.php	(working copy)
@@ -37,12 +37,13 @@
  * @return array List of categories.
  */
 function &get_categories( $args = '' ) {
-	$defaults = array( 'type' => 'category' );
+	$defaults = array( 'taxonomy' => 'category' );
 	$args = wp_parse_args( $args, $defaults );
 
-	$taxonomy = apply_filters( 'get_categories_taxonomy', 'category', $args );
-	if ( 'link' == $args['type'] )
-		$taxonomy = 'link_category';
+	if ( isset($args['type']) && 'link' == $args['type'] ) //Back compat
+		$args['taxonomy'] = 'link_category';
+
+	$taxonomy = apply_filters( 'get_categories_taxonomy', $args['taxonomy'], $args );
 	$categories = (array) get_terms( $taxonomy, $args );
 
 	foreach ( array_keys( $categories ) as $k )
