--- .svn/text-base/node.module.svn-base	2006-12-04 22:55:04.000000000 -0700
+++ node.module	2006-12-06 22:40:33.000000000 -0700
@@ -173,19 +173,39 @@ function node_teaser($body, $format = NU
     return $body;
   }
 
+  // the teaser length is "the maximum number of characters used in the trimmed version of a post"
+  $teaser = truncate_utf8($body, $size);
+  // since we are trying to find the last occurance of something, the reversed teaser is useful
+  $haystack = strrev($teaser);
+
   // In some cases, no delimiter has been specified (e.g. when posting using
   // the Blogger API). In this case, we try to split at paragraph boundaries.
-  // When even the first paragraph is too long, we try to split at the end of
-  // the next sentence.
-  $breakpoints = array('</p>' => 4, '<br />' => 0, '<br>' => 0, "\n" => 0, '. ' => 1, '! ' => 1, '? ' => 1, '。' => 3, '؟ ' => 1);
+  $breakpoints = array('</p>' => 4, '<br />' => 0, '<br>' => 0, "\n" => 0);
+  // strrpos() doesn't accept multi-character needles in PHP4,
+  // so we use strpos() and reverse the haystack and the needle
   foreach ($breakpoints as $point => $charnum) {
-    if ($length = strpos($body, $point, $size)) {
-      return substr($body, 0, $length + $charnum);
+    $position = strpos($haystack, strrev($point));
+    if ($position === 0 and $charnum == strlen($point)) {
+      return $teaser;
+    }
+    if ($position > 0) {
+      return substr($teaser, 0, $charnum - strlen($point) - $position);
     }
   }
 
-  // If all else fails, we simply truncate the string.
-  return truncate_utf8($body, $size);
+  // When even the first paragraph is too long, we try to split at the end of
+  // the last full sentence.
+  $breakpoints = array('. ' => 1, '! ' => 1, '? ' => 1, '。' => 3, '؟ ' => 2);
+  // create regex pattern by reversing imploded keys and escaping any would-be special characters
+  $pattern = '/' . str_replace(array('.', '!', '?'), array('\.', '\!', '\?'), strrev(implode('|', array_keys($breakpoints)))) . '/';
+  if (preg_match($pattern, $haystack, $matches, PREG_OFFSET_CAPTURE)) {
+    // $matches[0][0] now contains the text that matched the pattern and
+    // $matches[0][1] contains the position of the match
+    return substr($teaser, 0, $breakpoints[strrev($matches[0][0])] - strlen($matches[0][0]) - $matches[0][1]);
+  }
+
+  // If all else fails, we simply return the truncated string.
+  return $teaser;
 }
 
 /**
