Index: bp-xprofile/bp-xprofile-classes.php
===================================================================
--- bp-xprofile/bp-xprofile-classes.php	(revision 9037)
+++ bp-xprofile/bp-xprofile-classes.php	(working copy)
@@ -2440,13 +2440,39 @@
 	 * @since BuddyPress (2.0.0)
  	 */
 	public function __construct() {
+	
 		parent::__construct();
 
 		$this->category = _x( 'Single Fields', 'xprofile field type category', 'buddypress' );
 		$this->name     = _x( 'Multi-line Text Area', 'xprofile field type', 'buddypress' );
+		$this->type     = 'textarea';
 
+		// use this for options but not as intended!
+		$this->supports_options = true;
+		
+		// save options when field is saved
+		add_action( 'xprofile_fields_saved_field', array( $this, 'save_options' ), 10, 1 );
+		
 		$this->set_format( '/^.*$/m', 'replace' );
+		
+		// create custom filters that mirror 'the_content' for formatting output
+		add_filter( 'bp_xprofile_field_type_textarea_content', 'wptexturize'        );
+		add_filter( 'bp_xprofile_field_type_textarea_content', 'convert_smilies'    );
+		add_filter( 'bp_xprofile_field_type_textarea_content', 'convert_chars'      );
+		add_filter( 'bp_xprofile_field_type_textarea_content', 'wpautop'            );
+		add_filter( 'bp_xprofile_field_type_textarea_content', 'shortcode_unautop'  );
+
+		// override and augment allowed tags
+		add_filter( 'xprofile_allowed_tags', array( $this, 'allowed_tags' ), 30, 2 );
+		
+		// we need to parse the edit value
+		add_filter( 'bp_get_the_profile_field_edit_value', array( $this, 'get_field_value' ), 30, 3 );
+		
+		// filter for those who use xprofile_get_field_data instead of get_field_value
+		add_filter( 'xprofile_get_field_data', array( $this, 'get_field_data' ), 15, 3 );
+		
 		do_action( 'bp_xprofile_field_type_textarea', $this );
+		
 	}
 
 	/**
@@ -2464,24 +2490,78 @@
 		if ( isset( $raw_properties['user_id'] ) ) {
 			unset( $raw_properties['user_id'] );
 		}
+		
+		global $field;
+		
+		// sanity checks
+		if ( ! is_object( $field ) ) return;
+		if ( $field->type !== $this->type ) return;
+		
+		// get enabled and default to enabled if not yet present
+		$richtext_enabled = bp_xprofile_get_meta( $field->id, 'field', 'richtext_enabled', true );
+		if ( $richtext_enabled === false ) $richtext_enabled = 1;
+		$richtext_enabled = ( $richtext_enabled == 1 ) ? true : false;
+		
+		if ( ! $richtext_enabled ) {
 
-		$r = bp_parse_args( $raw_properties, array(
-			'cols' => 40,
-			'rows' => 5,
-		) ); ?>
+			$r = bp_parse_args( $raw_properties, array(
+				'cols' => 40,
+				'rows' => 5,
+			) ); ?>
 
-		<label for="<?php bp_the_profile_field_input_name(); ?>">
-			<?php bp_the_profile_field_name(); ?>
-			<?php if ( bp_get_the_profile_field_is_required() ) : ?>
-				<?php esc_html_e( '(required)', 'buddypress' ); ?>
-			<?php endif; ?>
-		</label>
+			<label for="<?php bp_the_profile_field_input_name(); ?>">
+				<?php bp_the_profile_field_name(); ?>
+				<?php if ( bp_get_the_profile_field_is_required() ) : ?>
+					<?php esc_html_e( '(required)', 'buddypress' ); ?>
+				<?php endif; ?>
+			</label>
 
-		<?php do_action( bp_get_the_profile_field_errors_action() ); ?>
+			<?php do_action( bp_get_the_profile_field_errors_action() ); ?>
 
-		<textarea <?php echo $this->get_edit_field_html_elements( $r ); ?>><?php bp_the_profile_field_edit_value(); ?></textarea>
+			<textarea <?php echo $this->get_edit_field_html_elements( $r ); ?>><?php bp_the_profile_field_edit_value(); ?></textarea>
 
-		<?php
+			<?php
+			
+		} else {
+
+			// get quicktags and default to off if not yet present
+			$richtext_quicktags = bp_xprofile_get_meta( $field->id, 'field', 'richtext_quicktags', true );
+			if ( $richtext_quicktags === false ) $richtext_quicktags = 0;
+			$richtext_quicktags = ( $richtext_quicktags == 1 ) ? true : false;
+			
+			// get quicktags and default to off if not yet present
+			$richtext_media = bp_xprofile_get_meta( $field->id, 'field', 'richtext_media', true );
+			if ( $richtext_media === false ) $richtext_media = 0;
+			$richtext_media = ( $richtext_media == 1 ) ? true : false;
+			
+			?>
+			<label for="<?php bp_the_profile_field_input_name(); ?>"><?php bp_the_profile_field_name(); ?> <?php if ( bp_get_the_profile_field_is_required() ) : ?><?php esc_html_e( '(required)', 'buddypress' ); ?><?php endif; ?></label>
+			<?php do_action( bp_get_the_profile_field_errors_action() ); ?>
+			<?php
+			
+			// define some default buttons for cases where teeny TInyMCE is set to false
+			$buttons = array(
+				'theme_advanced_buttons1' => 'bold,italic,underline,blockquote,strikethrough,|,link,unlink,|,spellchecker,removeformat,fullscreen',
+				'theme_advanced_buttons2' => '',
+				'theme_advanced_buttons3' => ''
+			);
+			
+			// define our editor
+			wp_editor(
+				
+				bp_get_the_profile_field_edit_value(),
+				bp_get_the_profile_field_input_name(),
+				array(
+					'media_buttons' => apply_filters( 'bp_xprofile_field_type_textarea_addmedia', $richtext_media ), 
+					'teeny' => apply_filters( 'bp_xprofile_field_type_textarea_teeny', true ), 
+					'quicktags' => apply_filters( 'bp_xprofile_field_type_textarea_quicktags', $richtext_quicktags ),
+					'tinymce' => apply_filters( 'bp_xprofile_field_type_textarea_buttons', $buttons )
+				)
+				
+			);
+			
+		}
+	
 	}
 
 	/**
@@ -2493,25 +2573,312 @@
 	 * @since BuddyPress (2.0.0)
 	 */
 	public function admin_field_html( array $raw_properties = array() ) {
+		
 		$r = bp_parse_args( $raw_properties, array(
 			'cols' => 40,
 			'rows' => 5,
-		) ); ?>
+		) );
+		
+		global $field;
+		
+		// sanity checks
+		if ( ! is_object( $field ) ) return;
+		if ( $field->type !== $this->type ) return;
+		
+		// get enabled and default to enabled if not yet present
+		$richtext_enabled = bp_xprofile_get_meta( $field->id, 'field', 'richtext_enabled', true );
+		if ( $richtext_enabled === false ) $richtext_enabled = 1;
+		$richtext_enabled = ( $richtext_enabled == 1 ) ? true : false;
+		
+		if ( ! $richtext_enabled ) {
+		
+			?>
 
-		<textarea <?php echo $this->get_edit_field_html_elements( $r ); ?>></textarea>
+			<textarea <?php echo $this->get_edit_field_html_elements( $r ); ?>></textarea>
 
-		<?php
+			<?php
+			
+		} else {
+
+			// get quicktags and default to off if not yet present
+			$richtext_quicktags = bp_xprofile_get_meta( $field->id, 'field', 'richtext_quicktags', true );
+			if ( $richtext_quicktags === false ) $richtext_quicktags = 0;
+			$richtext_quicktags = ( $richtext_quicktags == 1 ) ? true : false;
+		
+			// get quicktags and default to off if not yet present
+			$richtext_media = bp_xprofile_get_meta( $field->id, 'field', 'richtext_media', true );
+			if ( $richtext_media === false ) $richtext_media = 0;
+			$richtext_media = ( $richtext_media == 1 ) ? true : false;
+
+			// define some default buttons for cases where teeny TInyMCE is set to false
+			$buttons = array(
+				'theme_advanced_buttons1' => 'bold,italic,underline,blockquote,strikethrough,|,link,unlink,|,spellchecker,removeformat,fullscreen',
+				'theme_advanced_buttons2' => '',
+				'theme_advanced_buttons3' => ''
+			);
+	
+			// define our editor
+			wp_editor( 
+	
+				'', 
+				'xprofile_textarea_' . $field->id,
+				array( 
+					'media_buttons' => apply_filters( 'bp_xprofile_field_type_textarea_addmedia', $richtext_media ), 
+					'teeny' => apply_filters( 'bp_xprofile_field_type_textarea_teeny', true ), 
+					'quicktags' => apply_filters( 'bp_xprofile_field_type_textarea_quicktags', $richtext_quicktags ),
+					'tinymce' => apply_filters( 'bp_xprofile_field_type_textarea_buttons', $buttons )
+				)
+		
+			);
+			
+		}
+	
 	}
 
 	/**
 	 * This method usually outputs HTML for this field type's children options on the wp-admin Profile Fields
-	 * "Add Field" and "Edit Field" screens, but for this field type, we don't want it, so it's stubbed out.
+	 * "Add Field" and "Edit Field" screens, but for this field type, we want to use it to choose if this field
+	 * uses TinyMCE or not.
 	 *
 	 * @param BP_XProfile_Field $current_field The current profile field on the add/edit screen.
 	 * @param string $control_type Optional. HTML input type used to render the current field's child options.
 	 * @since BuddyPress (2.0.0)
 	 */
-	public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {}
+	public function admin_new_field_html( BP_XProfile_Field $current_field, $control_type = '' ) {
+	
+		$type = array_search( get_class( $this ), bp_xprofile_get_field_types() );
+		if ( false === $type ) {
+			return;
+		}
+
+		$class            = $current_field->type != $type ? 'display: none;' : '';
+		$current_type_obj = bp_xprofile_create_field_type( $type );
+		
+		/*
+		print_r( array(
+			'current_field' => $current_field,
+			'current_type_obj' => $current_type_obj,
+		) ); die();
+		*/
+		
+		// get enabled and default to enabled if not yet present
+		$richtext_enabled = bp_xprofile_get_meta( $current_field->id, 'field', 'richtext_enabled', true );
+		if ( $richtext_enabled === false ) $richtext_enabled = 1;
+		
+		// get quicktags and default to off if not yet present
+		$richtext_quicktags = bp_xprofile_get_meta( $current_field->id, 'field', 'richtext_quicktags', true );
+		if ( $richtext_quicktags === false ) $richtext_quicktags = 0;
+		
+		// get quicktags and default to off if not yet present
+		$richtext_media = bp_xprofile_get_meta( $current_field->id, 'field', 'richtext_media', true );
+		if ( $richtext_media === false ) $richtext_media = 0;
+
+		?>
+
+		<div id="<?php echo esc_attr( $type ); ?>" class="postbox bp-options-box" style="<?php echo esc_attr( $class ); ?> margin-top: 15px;">
+			<h3><?php esc_html_e( 'Please select options for this Field:', 'buddypress' ); ?></h3>
+			<div class="inside">
+				<p><label for="<?php echo $current_field->type ?>-enabled"><input id="<?php echo $current_field->type ?>-enabled" name="<?php echo $current_field->type ?>-enabled" value="1" type="checkbox" <?php checked( $richtext_enabled ); ?> /> <?php esc_html_e( 'Use Visual Editor', 'buddypress' ); ?></label></p>
+				<p><label for="<?php echo $current_field->type ?>-quicktags"><input id="<?php echo $current_field->type ?>-quicktags" name="<?php echo $current_field->type ?>-quicktags" value="1" type="checkbox" <?php checked( $richtext_quicktags ); ?> /> <?php esc_html_e( 'Enable Quicktags', 'buddypress' ); ?></label></p>
+				<p><label for="<?php echo $current_field->type ?>-media"><input id="<?php echo $current_field->type ?>-media" name="<?php echo $current_field->type ?>-media" value="1" type="checkbox" <?php checked( $richtext_media ); ?> /> <?php esc_html_e( 'Enable Media Button', 'buddypress' ); ?></label></p>
+			</div>
+		</div>
+
+		<?php
+	}
+
+	/**
+	 * Save options for this field
+	 *
+	 * @param object $field
+	 * @return void
+	 */
+	public function save_options( $field = null ) {
+	
+		// sanity checks
+		if ( ! is_object( $field ) ) return;
+		if ( $field->type !== $this->type ) return;
+		
+		// get settings
+		$richtext_enabled = isset( $_POST[$field->type . '-enabled'] ) ? 1 : 0;
+		bp_xprofile_update_field_meta( $field->id, 'richtext_enabled', $richtext_enabled );
+		
+		$richtext_quicktags = isset( $_POST[$field->type . '-quicktags'] ) ? 1 : 0;
+		bp_xprofile_update_field_meta( $field->id, 'richtext_quicktags', $richtext_quicktags );
+		
+		$richtext_media = isset( $_POST[$field->type . '-media'] ) ? 1 : 0;
+		bp_xprofile_update_field_meta( $field->id, 'richtext_media', $richtext_media );
+		
+	}
+	
+	/**
+	 * Format Visual Editor content for display.
+	 *
+	 * @since BuddyPress (2.1.0)
+	 *
+	 * @param string $field_value The Visual Editor content, as saved in the database.
+	 * @return string Formatted HTML.
+	 */
+	public static function display_filter( $field_value ) {
+		
+		global $field;
+		
+		// sanity checks
+		if ( ! is_object( $field ) ) return;
+		if ( $field->type !== 'textarea' ) return;
+		
+		// get enabled and default to enabled if not yet present
+		$richtext_enabled = bp_xprofile_get_meta( $field->id, 'field', 'richtext_enabled', true );
+		if ( $richtext_enabled === false ) $richtext_enabled = 1;
+		$richtext_enabled = ( $richtext_enabled == 1 ) ? true : false;
+		
+		if ( $richtext_enabled ) {
+		
+			/**
+			 * This is a bit of a hack because formatted text looks strange with the
+			 * 'xprofile_filter_link_profile_data' filter applied. If instead, we parse
+			 * this field type in read mode after all BuddyPress filters have been applied
+			 * we can avoid this. Moreover, this method is called outside the scope of $this,
+			 * so we have to directly reference the name of this class in the filter
+			 */
+			add_filter( 'bp_get_the_profile_field_value', array( 'BP_XProfile_Field_Type_Textarea', 'get_field_value' ), 30, 3 );
+		
+		}
+		
+		// return the data as received and format in get_field_value() below
+		return $field_value;
+		
+	}
+
+	/**
+	 * Show our field type in read mode
+	 *
+	 * @param string $value
+	 * @param string $type
+	 * @param integer $id
+	 * @return string
+	 */
+	public function get_field_value( $value = '', $type = '', $id = '' ) {
+	
+		// is it our field type?
+		if ( $type == 'textarea' ) {
+	
+			global $field;
+		
+			// sanity check
+			if ( ! is_object( $field ) ) return $value;
+		
+			// get enabled and default to enabled if not yet present
+			$richtext_enabled = bp_xprofile_get_meta( $field->id, 'field', 'richtext_enabled', true );
+			if ( $richtext_enabled === false ) $richtext_enabled = 1;
+			$richtext_enabled = ( $richtext_enabled == 1 ) ? true : false;
+		
+			if ( $richtext_enabled ) {
+		
+				// we want the raw data, unfiltered
+				$value = $field->data->value;
+		
+				// apply content filter
+				$value = apply_filters( 'bp_xprofile_field_type_textarea_content', stripslashes( $value ) );
+			
+				return apply_filters( 'bp_xprofile_field_type_textarea_value', $value );
+				
+			}
+
+		}
+	
+		// fallback
+		return $value;
+		
+	}
+	
+	/**
+	 * Filter for those who use xprofile_get_field_data instead of get_field_value
+	 *
+	 * @param string $value
+	 * @param integer $field_id
+	 * @param integer $user_id
+	 * @return string
+	 */
+	public function get_field_data( $value = '', $field_id = '', $user_id = '' ) {
+	
+		// check we get a field ID
+		if ( $field_id === '' ) return $value;
+	
+		// get field object
+		$field = new BP_XProfile_Field( $field_id );
+	
+		// is it ours?
+		if ( $field->type == $this->type ) {
+
+			// get enabled and default to enabled if not yet present
+			$richtext_enabled = bp_xprofile_get_meta( $field->id, 'field', 'richtext_enabled', true );
+			if ( $richtext_enabled === false ) $richtext_enabled = 1;
+			$richtext_enabled = ( $richtext_enabled == 1 ) ? true : false;
+		
+			if ( $richtext_enabled ) {
+		
+				// apply content filter
+				$value = apply_filters( 'bp_xprofile_field_type_textarea_content', stripslashes( $value ) );
+
+				// return filtered value
+				return apply_filters( 'bp_xprofile_field_type_textarea_value', $value );
+				
+			}
+			
+		}
+		
+		// fallback
+		return $value;
+
+	}
+	
+	/**
+	 * Callback to allow tags that teeny TinyMCE enables
+	 *
+	 * @since BuddyPress (2.2.0)
+	 *
+	 * @param array $allowedtags The array of allowed tags
+	 * @param object $data_obj The xProfile data object (BP 2.1+)
+	 * @return array $allowedtags The modified array of allowed tags
+	 */
+	public function allowed_tags( $allowedtags, $data_obj = null ) {
+		
+		// test if BP has sent the data object
+		if ( ! is_null( $data_obj ) ) {
+			
+			// get field from data object
+			$field = new BP_XProfile_Field( $data_obj->field_id );
+			
+			// if this isn't our field, skip amending allowed tags
+			if ( $field->type != $this->type ) return $allowedtags;
+			
+			// get enabled and default to enabled if not yet present
+			$richtext_enabled = bp_xprofile_get_meta( $field->id, 'field', 'richtext_enabled', true );
+			if ( $richtext_enabled === false ) $richtext_enabled = 1;
+			$richtext_enabled = ( $richtext_enabled == 1 ) ? true : false;
+			
+			// bail if not rich text
+			if ( ! $richtext_enabled )  return $allowedtags;
+		
+		}
+		
+		// default tags we need to enable the teeny TinyMCE editor markup
+		$richtext_tags = array( 
+			'img'    => array( 'id' => 1, 'class' => 1, 'src' => 1, 'alt' => 1, 'width' => 1, 'height' => 1 ),
+			'ul'     => array( 'id' => 1, 'class' => 1 ),
+			'ol'     => array( 'id' => 1, 'class' => 1 ),
+			'li'     => array( 'id' => 1, 'class' => 1 ),
+			'span'   => array( 'style' => 1 ),
+			'p'      => array( 'style' => 1 ),
+		);
+		
+		$allowedtags = array_merge( $allowedtags, $richtext_tags );
+		
+		return apply_filters( 'bp_xprofile_field_type_textarea_allowedtags', $allowedtags, $data_obj );
+		
+	}
+	
 }
 
 /**
