Index: wp-includes/default-widgets.php
===================================================================
--- wp-includes/default-widgets.php	(revision 32594)
+++ wp-includes/default-widgets.php	(working copy)
@@ -254,19 +254,9 @@
 	 * @param array $args
 	 * @param array $instance
 	 */
-	public function widget( $args, $instance ) {
-		/** This filter is documented in wp-includes/default-widgets.php */
-		$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
-
-		echo $args['before_widget'];
-		if ( $title ) {
-			echo $args['before_title'] . $title . $args['after_title'];
-		}
-
+	public function widget_markup( $args, $instance ) {
 		// Use current theme search form if it exists
 		get_search_form();
-
-		echo $args['after_widget'];
 	}
 
 	/**
@@ -444,14 +434,7 @@
 	 * @param array $args
 	 * @param array $instance
 	 */
-	public function widget( $args, $instance ) {
-		/** This filter is documented in wp-includes/default-widgets.php */
-		$title = apply_filters( 'widget_title', empty($instance['title']) ? __( 'Meta' ) : $instance['title'], $instance, $this->id_base );
-
-		echo $args['before_widget'];
-		if ( $title ) {
-			echo $args['before_title'] . $title . $args['after_title'];
-		}
+	public function widget_markup( $args, $instance ) {
 ?>
 			<ul>
 			<?php wp_register(); ?>
@@ -476,7 +459,6 @@
 ?>
 			</ul>
 <?php
-		echo $args['after_widget'];
 	}
 
 	/**
@@ -519,18 +501,10 @@
 	 * @param array $args
 	 * @param array $instance
 	 */
-	public function widget( $args, $instance ) {
-		/** This filter is documented in wp-includes/default-widgets.php */
-		$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
-
-		echo $args['before_widget'];
-		if ( $title ) {
-			echo $args['before_title'] . $title . $args['after_title'];
-		}
+	public function widget_markup( $args, $instance ) {
 		echo '<div id="calendar_wrap">';
 		get_calendar();
 		echo '</div>';
-		echo $args['after_widget'];
 	}
 
 	/**
@@ -575,9 +549,7 @@
 	 * @param array $args
 	 * @param array $instance
 	 */
-	public function widget( $args, $instance ) {
-		/** This filter is documented in wp-includes/default-widgets.php */
-		$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
+	public function widget_markup( $args, $instance ) {
 
 		/**
 		 * Filter the content of the Text widget.
@@ -588,13 +560,9 @@
 		 * @param WP_Widget $instance    WP_Widget instance.
 		 */
 		$text = apply_filters( 'widget_text', empty( $instance['text'] ) ? '' : $instance['text'], $instance );
-		echo $args['before_widget'];
-		if ( ! empty( $title ) ) {
-			echo $args['before_title'] . $title . $args['after_title'];
-		} ?>
+		?>
 			<div class="textwidget"><?php echo !empty( $instance['filter'] ) ? wpautop( $text ) : $text; ?></div>
 		<?php
-		echo $args['after_widget'];
 	}
 
 	/**
@@ -1392,7 +1360,7 @@
 	 * @param array $args
 	 * @param array $instance
 	 */
-	public function widget( $args, $instance ) {
+	public function widget_markup( $args, $instance ) {
 		$current_taxonomy = $this->_get_current_taxonomy($instance);
 		if ( !empty($instance['title']) ) {
 			$title = $instance['title'];
@@ -1405,13 +1373,6 @@
 			}
 		}
 
-		/** This filter is documented in wp-includes/default-widgets.php */
-		$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
-
-		echo $args['before_widget'];
-		if ( $title ) {
-			echo $args['before_title'] . $title . $args['after_title'];
-		}
 		echo '<div class="tagcloud">';
 
 		/**
@@ -1429,7 +1390,6 @@
 		) ) );
 
 		echo "</div>\n";
-		echo $args['after_widget'];
 	}
 
 	/**
Index: wp-includes/widgets.php
===================================================================
--- wp-includes/widgets.php	(revision 32594)
+++ wp-includes/widgets.php	(working copy)
@@ -104,10 +104,43 @@
 	 * @param array $instance The settings for the particular instance of the widget.
 	 */
 	public function widget( $args, $instance ) {
-		die('function WP_Widget::widget() must be over-ridden in a sub-class.');
+		$this->before_widget( $args, $instance );
+		$this->widget_markup( $args, $instance );
+		$this->after_widget( $args, $instance );
 	}
 
 	/**
+	 * Default treatment of before widget markup
+	 *
+	 * @param $args
+	 * @param $instance
+	 */
+	public function before_widget( $args, $instance ) {
+		$title = apply_filters( 'widget_title', ! isset($instance['title']  ) || empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
+		echo $args['before_widget'];
+		if ( $title ) {
+			echo $args['before_title'] . $title . $args['after_title'];
+		}
+	}
+
+	/**
+	 * Output the custom markup content for the widget
+	 *
+	 * Subclasses will override this to create their output
+	 */
+	public function widget_markup( $args, $instance ) {}
+
+	/**
+	 * Default treatment of after widget markup
+	 *
+	 * @param $args
+	 * @param $instance
+	 */
+	public function after_widget( $args, $instance ) {
+		echo $args['after_widget'];
+	}
+
+	/**
 	 * Update a particular instance.
 	 *
 	 * This function should check that $new_instance is set correctly. The newly-calculated
