Index: includes/linodef-filter.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/linodef/includes/linodef-filter.inc,v
retrieving revision 1.1.2.13
diff -u -r1.1.2.13 linodef-filter.inc
--- includes/linodef-filter.inc	12 Dec 2009 00:40:55 -0000	1.1.2.13
+++ includes/linodef-filter.inc	13 Dec 2009 00:35:13 -0000
@@ -418,23 +418,41 @@
 				return $output;
 			}
 			else {
-				$class = $fieldname ? 'linodef linodef_field linodef_field_' . $fieldname : 'linodef linodef_node linodef_node_' . $node->nid;
+				if (isset($options['attributes'])) {
+					$attributes = _linodef_filter_option_attributes_str2array($options['attributes']);
+				}
 
-				// Create the link title.
-				$attributes = array('title' => variable_get('linodef_' . $format . '_title_node', LINODEF_FORMAT_TITLE_NODE), 'class' => $class);
-				// Debug: print('Title node <b>' . $node->nid . '</b> in format <b>' . $format . '</b>: raw: <b>' . $attributes['title'] . '</b>');
-				if (module_exists('token') && variable_get('linodef_' . $format . '_title_node_token', 0)) {
-					$attributes['title'] = token_replace($attributes['title'], 'node', $node);
+				// Set the html tag class.
+				$class = $fieldname ? 'linodef linodef_field linodef_field_' . $fieldname : 'linodef linodef_node linodef_node_' . $node->nid;
+				if (isset($attributes['class'])) {
+					$attributes['class'] = $attributes['class'] . ' ' . $class;
 				}
 				else {
-					$linodef_tokens = linodef_tokens('node', $node);
-					$attributes['title'] = str_ireplace(array_keys($linodef_tokens), array_values($linodef_tokens), $attributes['title']);
+					$attributes['class'] = $class;
 				}
-				// Debug: print(' replaced: <b>' . $attributes['title'] . '</b><br />');
 
-				if (isset($options['attributes'])) {
-					$attributes += _linodef_filter_option_attributes_str2array($options['attributes']);
+				// Create the link title.
+				if (!isset($attributes['title'])) {
+					$attributes['title'] = variable_get('linodef_' . $format . '_title_node', LINODEF_FORMAT_TITLE_NODE);
+					// Debug: print('Title node <b>' . $node->nid . '</b> in format <b>' . $format . '</b>: raw: <b>' . $attributes['title'] . '</b>');
+					if (module_exists('token') && variable_get('linodef_' . $format . '_title_node_token', 0)) {
+						// Prevent multiple processing of the token module.
+						if (linodef_process_running('token_replace')) {
+							$attributes['title'] = preg_replace('/\[.*?\]/', '', $attributes['title']);
+						}
+						else {
+							linodef_process_running('token_replace', 1);
+							$attributes['title'] = token_replace($attributes['title'], 'node', $node);
+							linodef_process_running('token_replace', 0);
+						}
+					}
+					else {
+						$linodef_tokens = linodef_tokens('node', $node);
+						$attributes['title'] = str_ireplace(array_keys($linodef_tokens), array_values($linodef_tokens), $attributes['title']);
+					}
+					// Debug: print(' replaced: <b>' . $attributes['title'] . '</b><br />');
 				}
+
 				// Can cause bad HTML if field item contains html block elements. But Linodef shouldn't interfere with the content/formatting of the field.
 				return l($output, 'node/'. $node->nid, array('html' => TRUE, 'attributes' => $attributes));
 			}
@@ -471,6 +489,7 @@
 					return check_plain($term->name);
 				}
 			}
+
 			$termlink = taxonomy_term_path($term);
 			if (isset($options['override'])) {
 				$output = $options['override'];
@@ -478,18 +497,38 @@
 			else {
 				$output = $term->name;
 			}
-			// Create the link title.
-			$attributes = array('title' => variable_get('linodef_' . $format . '_title_term', LINODEF_FORMAT_TITLE_TERM), 'class' => 'linodef linodef_term linodef_term_' . $term->name);
-			if (module_exists('token') && variable_get('linodef_' . $format . '_title_term_token', 0)) {
-				$attributes['title'] = token_replace($attributes['title'], 'node', $node);
+
+			if (isset($options['attributes'])) {
+				$attributes = _linodef_filter_option_attributes_str2array($options['attributes']);
+			}
+
+			// Set the html tag class.
+			$class = 'linodef linodef_term linodef_term_' . $term->name;
+			if (isset($attributes['class'])) {
+				$attributes['class'] = $attributes['class'] . ' ' . $class;
 			}
 			else {
-				$linodef_tokens = linodef_tokens('term', $term);
-				$attributes['title'] = str_ireplace(array_keys($linodef_tokens), array_values($linodef_tokens), $attributes['title']);
+				$attributes['class'] = $class;
 			}
 
-			if (isset($options['attributes'])) {
-				$attributes += _linodef_filter_option_attributes_str2array($options['attributes']);
+			// Create the link title.
+			if (!isset($attributes['title'])) {
+				$attributes['title'] = variable_get('linodef_' . $format . '_title_term', LINODEF_FORMAT_TITLE_TERM);
+				if (module_exists('token') && variable_get('linodef_' . $format . '_title_term_token', 0)) {
+					// Prevent multiple processing of the token module.
+					if (linodef_process_running('token_replace')) {
+						$attributes['title'] = preg_replace('/\[.*?\]/', '', $attributes['title']);
+					}
+					else {
+						linodef_process_running('token_replace', 1);
+						$attributes['title'] = token_replace($attributes['title'], 'taxonomy', $term);
+						linodef_process_running('token_replace', 0);
+					}
+				}
+				else {
+					$linodef_tokens = linodef_tokens('term', $term);
+					$attributes['title'] = str_ireplace(array_keys($linodef_tokens), array_values($linodef_tokens), $attributes['title']);
+				}
 			}
 
 			return l($output, $termlink, array('attributes' => $attributes));
Index: linodef.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/linodef/linodef.module,v
retrieving revision 1.1.2.10
diff -u -r1.1.2.10 linodef.module
--- linodef.module	12 Dec 2009 00:40:54 -0000	1.1.2.10
+++ linodef.module	13 Dec 2009 00:30:04 -0000
@@ -79,7 +79,7 @@
 							'#type' => 'checkbox',
 							'#title' => t('Use token module (experimental)'),
 							'#default_value' => variable_get('linodef_' . $format . '_title_node_token', 0),
-							'#description' => t('This offers more tokens but since the CCK token plugin reloads full-fledged node and field objects this can cause major performance issues especially when many fields are used. Furthermore this causes the appearance of unrelated Linodef messages.'),
+							'#description' => t('This offers more tokens but since the CCK token plugin reloads full-fledged node and field objects this can cause major performance issues especially when many fields are used.'),
 						);
 						$form['linodef_settings']['node_token_help'] = array(
 							'#title' => t('Replacement patterns'),
@@ -667,6 +667,20 @@
 }
 
 /**
+ * Keep track of running processes, e.g. to prevent execution when already running.
+ *
+ * @param int $in_running
+ *   Set the running status or leave blank to retrieve it.
+ * @param string $type
+ *   An unique type so this function can track several processes at once.
+ */
+function linodef_process_running($type, $in_running = NULL) {
+   static $running;
+   if (isset($in_running)) $running[$type] = $in_running;
+   return $running[$type];
+}
+
+/**
  * Returns messages that are needed several times in the filter and Buttons API and thus should be identical and in modules root.
  *
  * Additionally the function supports custom messages and all messages can be set with Drupals message system, too.
@@ -702,6 +716,11 @@
  * @see drupal_set_message() linodef_theme_settings()
  */
 function linodef_message($message = array(), $drupal_set_message_type = NULL, $drupal_set_message = TRUE) {
+	// Skip if the linodef filter is called by token_replace() from
+	// within the linodef filter. This prevents duplicated messages.
+	if (linodef_process_running('token_replace')) {
+		return '';
+	}
 	// Message appearance, see linodef_theme_settings().
 	$message_location = variable_get('linodef_message_location', array('inline' => 'inline', 'page' => 'page'));
 	$message_location_none = (empty($message_location['page']) && empty($message_location['inline'])) ? TRUE : FALSE;

