import cl @40802
diff --git a/i18n/regexcmp.cpp b/i18n/regexcmp.cpp
index 7d0343e..09da39c 100644
--- a/i18n/regexcmp.cpp
+++ b/i18n/regexcmp.cpp
@@ -3692,6 +3692,9 @@
                 //    which are \0 followed by 1-3 octal digits.
                 //    Different from ICU Unescape handling of Octal, which does not
                 //    require the leading 0.
+                //  Java also has the convention of only consuning 2 octal digits if
+                //    the three digit number would be > 0xff
+                //
                 c.fChar = 0;
                 nextCharLL();    // Consume the initial 0.
                 int index;
@@ -3700,12 +3703,14 @@
                     if (ch<chDigit0 || ch>chDigit7) {
                         break;
                     }
-                    nextCharLL();
                     c.fChar <<= 3;
                     c.fChar += ch&7;
-                }
-                if (c.fChar>255) {
-                    error(U_REGEX_OCTAL_TOO_BIG);
+                    if (c.fChar <= 255) {
+                        nextCharLL();
+                    } else {
+                        // The last digit made the number too big.  Forget we saw it.
+                        c.fChar >>= 3;
+                    }
                 }
                 c.fQuoted = TRUE; 
             } 
@@ -3970,15 +3975,26 @@
     
     //
     //  The property as it was didn't work.
-    //    See if it looks like a Java "InBlockName", which
+    //    Do an emergency fixe -  
+    //       InGreek -> InGreek or Coptic, that being the official Unicode name for that block.
+    //
+    UnicodeString mPropName = propName;
+    if (mPropName.caseCompare(UnicodeString("InGreek", -1, UnicodeString::kInvariant), 0) == 0) {
+        mPropName = UnicodeString("InGreek and Coptic", -1 ,UnicodeString::kInvariant);
+    }
+    else if (mPropName.compare(UnicodeString("all", -1, UnicodeString::kInvariant)) == 0) {
+        mPropName = UnicodeString("javaValidCodePoint", -1 ,UnicodeString::kInvariant);
+    }
+    
+    //    See if the property looks like a Java "InBlockName", which
     //    we will recast as "Block=BlockName"
     //
     static const UChar IN[] = {0x49, 0x6E, 0};  // "In"
     static const UChar BLOCK[] = {0x42, 0x6C, 0x6f, 0x63, 0x6b, 0x3d, 00};  // "Block="
-    if (propName.startsWith(IN, 2) && propName.length()>=3) {
+    if (mPropName.startsWith(IN, 2) && propName.length()>=3) {
         setExpr.truncate(4);   // Leaves "[\p{", or "[\P{"
         setExpr.append(BLOCK, -1);
-        setExpr.append(UnicodeString(propName, 2));  // Property with the leading "In" removed.
+        setExpr.append(UnicodeString(mPropName, 2));  // Property with the leading "In" removed.
         setExpr.append(chRBrace);
         setExpr.append(chRBracket);
         *fStatus = U_ZERO_ERROR;
@@ -4012,16 +4028,18 @@
         {"javaUpperCase",              "[\\p{Lu}]"},
         {"javaValidCodePoint",         "[\\u0000-\\U0010ffff]"},
         {"javaWhitespace",             "[[\\p{Z}-[\\u00a0\\u2007\\u202f]]\\u0009-\\u000d\\u001c-\\u001f]"},
+        {"all",                        "[\\u0000-\\U0010ffff]"},
         {NULL,                         NULL}
     };
     
 
     UnicodeString Java("java", -1, UnicodeString::kInvariant);
-    if (propName.startsWith(Java)) {
+    if (propName.startsWith(Java) ||
+        propName.compare(UnicodeString("all", -1, UnicodeString::kInvariant)) == 0) {
         int i;
         setExpr.remove();
         for (i=0; javaProps[i][0] != NULL; i++) {
-            if (propName.compare(UnicodeString(javaProps[i][0], -1, UnicodeString::kInvariant))==0) {
+            if (mPropName.compare(UnicodeString(javaProps[i][0], -1, UnicodeString::kInvariant))==0) {
                 setExpr = UnicodeString(javaProps[i][1]);  // Default code page conversion here.
                 break;                                        //   Somewhat Inefficient.
             }
diff --git a/i18n/rematch.cpp b/i18n/rematch.cpp
index 503303e..47bb1cc 100644
--- a/i18n/rematch.cpp
+++ b/i18n/rematch.cpp
@@ -5,7 +5,7 @@
 **************************************************************************
 */
 //
-//  file:  rematch.cpp    
+//  file:  rematch.cpp
 //
 //         Contains the implementation of class RegexMatcher,
 //         which is one of the main API classes for the ICU regular expression package.
@@ -44,6 +44,8 @@
     fStack             = new UVector32(fDeferredStatus); 
     fData              = fSmallData;
     fWordBreakItr      = NULL;
+    fTransparentBounds = FALSE;
+    fAnchoringBounds   = TRUE;
     if (pat==NULL) {
         fDeferredStatus = U_ILLEGAL_ARGUMENT_ERROR;
         return;
@@ -54,7 +56,7 @@
     if (fStack == NULL || fData == NULL) {
         fDeferredStatus = U_MEMORY_ALLOCATION_ERROR;
     }
-        
+
     reset(RegexStaticSets::gStaticSets->fEmptyString);
 }
 
@@ -70,6 +72,8 @@
     fStack             = new UVector32(status); 
     fData              = fSmallData;
     fWordBreakItr      = NULL;
+    fTransparentBounds = FALSE;
+    fAnchoringBounds   = TRUE;
     if (U_FAILURE(status)) {
         return;
     }
@@ -93,6 +97,8 @@
     fPatternOwned      = RegexPattern::compile(regexp, flags, pe, status);
     fPattern           = fPatternOwned;
     fWordBreakItr      = NULL;
+    fTransparentBounds = FALSE;
+    fAnchoringBounds   = TRUE;
     if (U_FAILURE(status)) {
         return;
     }
@@ -149,11 +155,11 @@
     }
 
     // Copy input string from the end of previous match to start of current match
-    int32_t  len = fMatchStart-fLastReplaceEnd;
+    int32_t  len = fMatchStart-fAppendPosition;
     if (len > 0) {
-        dest.append(*fInput, fLastReplaceEnd, len);
+        dest.append(*fInput, fAppendPosition, len);
     }
-    fLastReplaceEnd = fMatchEnd;
+    fAppendPosition = fMatchEnd;
     
 
     // scan the replacement text, looking for substitutions ($n) and \escapes.
@@ -249,11 +255,13 @@
 //                   To the destination string, append everything following
 //                   the last match position from the input string.
 //
+//                   Note:  Match ranges do not affect appendTail or appendReplacement
+//
 //--------------------------------------------------------------------------------
 UnicodeString &RegexMatcher::appendTail(UnicodeString &dest) {
-    int32_t  len = fInput->length()-fMatchEnd;
+    int32_t  len = fInput->length() - fAppendPosition;
     if (len > 0) {
-        dest.append(*fInput, fMatchEnd, len);
+        dest.append(*fInput, fAppendPosition, len);
     }
     return dest;
 }
@@ -312,7 +320,12 @@
         return FALSE;
     }
 
+    // TODO:  FAILURE HERE WITH REGIONS, fMatchEnd resets to 0, not regionStart.
+    //          Watch for interactions with replace operations when fixing.
     int32_t startPos = fMatchEnd;
+    if (startPos==0) {
+        startPos = fRegionStart;
+    }
 
     if (fMatch) {
         // Save the position of any previous successful match.
@@ -321,7 +334,7 @@
         if (fMatchStart == fMatchEnd) {
             // Previous match had zero length.  Move start position up one position
             //  to avoid sending find() into a loop on zero-length matches.
-            if (startPos == fInput->length()) {
+            if (startPos >= fRegionLimit) {
                 fMatch = FALSE;
                 return FALSE;
             }
@@ -336,11 +349,10 @@
         }
     }
 
-    int32_t inputLen = fInput->length();
 
     // Compute the position in the input string beyond which a match can not begin, because
     //   the minimum length match would extend past the end of the input.
-    int32_t testLen  = inputLen - fPattern->fMinMatchLen;
+    int32_t testLen  = fRegionLimit - fPattern->fMinMatchLen;
     if (startPos > testLen) {
         fMatch = FALSE;
         return FALSE;
@@ -355,7 +367,7 @@
         // No optimization was found. 
         //  Try a match at each input position.
         for (;;) {
-            MatchAt(startPos, fDeferredStatus);
+            MatchAt(startPos, FALSE, fDeferredStatus);
             if (U_FAILURE(fDeferredStatus)) {
                 return FALSE;
             }
@@ -363,9 +375,10 @@
                 return TRUE;
             }
             if (startPos >= testLen) {
+                fHitEnd = TRUE;
                 return FALSE;
             }
-            U16_FWD_1(inputBuf, startPos, inputLen);
+            U16_FWD_1(inputBuf, startPos, fRegionLimit);
             // Note that it's perfectly OK for a pattern to have a zero-length
             //   match at the end of a string, so we must make sure that the loop
             //   runs with startPos == testLen the last time through.
@@ -375,11 +388,11 @@
     case START_START:
         // Matches are only possible at the start of the input string
         //   (pattern begins with ^ or \A)
-        if (startPos > 0) {
+        if (startPos > fRegionStart) {
             fMatch = FALSE;
             return FALSE;
         }
-        MatchAt(startPos, fDeferredStatus);
+        MatchAt(startPos, FALSE, fDeferredStatus);
         if (U_FAILURE(fDeferredStatus)) {
             return FALSE;
         }
@@ -389,13 +402,14 @@
     case START_SET:
         {
             // Match may start on any char from a pre-computed set.
+            //  TODO:  left off on region changes at this point
             U_ASSERT(fPattern->fMinMatchLen > 0);
             for (;;) {
                 int32_t pos = startPos;
-                U16_NEXT(inputBuf, startPos, inputLen, c);  // like c = inputBuf[startPos++];
+                U16_NEXT(inputBuf, startPos, fRegionLimit, c);  // like c = inputBuf[startPos++];
                 if (c<256 && fPattern->fInitialChars8->contains(c) ||
                     c>=256 && fPattern->fInitialChars->contains(c)) {
-                    MatchAt(pos, fDeferredStatus);
+                    MatchAt(pos, FALSE, fDeferredStatus);
                     if (U_FAILURE(fDeferredStatus)) {
                         return FALSE;
                     }
@@ -419,9 +433,9 @@
             UChar32 theChar = fPattern->fInitialChar;
             for (;;) {
                 int32_t pos = startPos;
-                U16_NEXT(inputBuf, startPos, inputLen, c);  // like c = inputBuf[startPos++];
+                U16_NEXT(inputBuf, startPos, fRegionLimit, c);  // like c = inputBuf[startPos++];
                 if (c == theChar) {
-                    MatchAt(pos, fDeferredStatus);
+                    MatchAt(pos, FALSE, fDeferredStatus);
                     if (U_FAILURE(fDeferredStatus)) {
                         return FALSE;
                     }
@@ -441,24 +455,24 @@
         {
             UChar32  c;
             if (startPos == 0) {
-                MatchAt(startPos, fDeferredStatus);
+                MatchAt(startPos, FALSE, fDeferredStatus);
                 if (U_FAILURE(fDeferredStatus)) {
                     return FALSE;
                 }
                 if (fMatch) {
                     return TRUE;
                 }
-                U16_NEXT(inputBuf, startPos, inputLen, c);  // like c = inputBuf[startPos++];
+                U16_NEXT(inputBuf, startPos, fRegionLimit, c);  // like c = inputBuf[startPos++];
             }
 
             for (;;) {
                 c = inputBuf[startPos-1];
                 if (((c & 0x7f) <= 0x29) &&     // First quickly bypass as many chars as possible
                     ((c<=0x0d && c>=0x0a) || c==0x85 ||c==0x2028 || c==0x2029 )) {
-                        if (c == 0x0d && startPos < inputLen && inputBuf[startPos] == 0x0a) {
+                        if (c == 0x0d && startPos < fRegionLimit && inputBuf[startPos] == 0x0a) {
                             startPos++;
                         }
-                        MatchAt(startPos, fDeferredStatus);
+                        MatchAt(startPos, FALSE, fDeferredStatus);
                         if (U_FAILURE(fDeferredStatus)) {
                             return FALSE;
                         }
@@ -470,7 +484,7 @@
                     fMatch = FALSE;
                     return FALSE;
                 }
-                U16_NEXT(inputBuf, startPos, inputLen, c);  // like c = inputBuf[startPos++];
+                U16_NEXT(inputBuf, startPos, fRegionLimit, c);  // like c = inputBuf[startPos++];
                 // Note that it's perfectly OK for a pattern to have a zero-length
                 //   match at the end of a string, so we must make sure that the loop
                 //   runs with startPos == testLen the last time through.
@@ -495,13 +509,14 @@
         status = fDeferredStatus;
         return FALSE;
     }
-    int32_t inputLen = fInput->length();
-    if (start < 0 || start > inputLen) {
+    this->reset();                        // Note:  Reset() is specified by Java Matcher documentation.
+                                          //        This will reset the region to be the full input length.
+    if (start < fRegionStart || start > fRegionLimit) {
         status = U_INDEX_OUTOFBOUNDS_ERROR;
         return FALSE;
     }
-    this->reset();
-    fMatchEnd = start;
+    fMatchEnd = start;    // TODO:  restructure so start position goes as a parameter to an internal find()
+                          //        that is used both here and by the public API find()?
     return find();
 }
 
@@ -554,10 +569,38 @@
 }
 
 
+//--------------------------------------------------------------------------------
+//
+//  hasAnchoringBounds()
+//
+//--------------------------------------------------------------------------------
+UBool RegexMatcher::hasAnchoringBounds() const {
+    return fAnchoringBounds;
+}
 
 
 //--------------------------------------------------------------------------------
 //
+//  hasTransparentBounds()
+//
+//--------------------------------------------------------------------------------
+UBool RegexMatcher::hasTransparentBounds() const {
+    return fTransparentBounds;
+}
+
+
+
+//--------------------------------------------------------------------------------
+//
+//  hitEnd()
+//
+//--------------------------------------------------------------------------------
+UBool RegexMatcher::hitEnd() const {
+    return fHitEnd;
+}
+
+//--------------------------------------------------------------------------------
+//
 //  lookingAt()
 //
 //--------------------------------------------------------------------------------
@@ -570,7 +613,7 @@
         return FALSE;
     }
     reset();
-    MatchAt(0, status);
+    MatchAt(0, FALSE, status);
     return fMatch;
 }
 
@@ -583,12 +626,12 @@
         status = fDeferredStatus;
         return FALSE;
     }
-    if (start < 0 || start > fInput->length()) {
+    reset();
+    if (start < 0 || start > fRegionLimit) {
         status = U_INDEX_OUTOFBOUNDS_ERROR;
         return FALSE;
     }
-    reset();
-    MatchAt(start, status);
+    MatchAt(start, FALSE, status);
     return fMatch;
 }
 
@@ -607,10 +650,9 @@
         status = fDeferredStatus;
         return FALSE;
     }
-    reset();
-    MatchAt(0, status);
-    UBool   success  = (fMatch && fMatchEnd==fInput->length());
-    return success;
+    resetPreserveRegion();
+    MatchAt(fRegionStart, TRUE, status);
+    return fMatch;
 }
 
 
@@ -622,18 +664,22 @@
         status = fDeferredStatus;
         return FALSE;
     }
-    if (start < 0 || start > fInput->length()) {
+    reset();
+    if (start < fRegionStart || start > fRegionLimit) {
         status = U_INDEX_OUTOFBOUNDS_ERROR;
         return FALSE;
     }
-    reset();
-    MatchAt(start, status);
-    UBool   success  = (fMatch && fMatchEnd==fInput->length());
-    return success;
+    MatchAt(start, TRUE, status);
+    return fMatch;
 }
 
 
 
+//--------------------------------------------------------------------------------
+//
+//    pattern
+//
+//--------------------------------------------------------------------------------
 const RegexPattern &RegexMatcher::pattern() const {
     return *fPattern;
 }
@@ -642,6 +688,53 @@
 
 //--------------------------------------------------------------------------------
 //
+//    region
+//
+//--------------------------------------------------------------------------------
+RegexMatcher &RegexMatcher::region(int32_t start, int32_t limit, UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return *this;
+    }
+    if (start>limit || start<0 || limit<0 || limit>fInput->length()) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+    }
+    this->reset();
+    fRegionStart = start;
+    fRegionLimit = limit;
+    if (!fTransparentBounds) {
+        fLookStart = start;
+        fLookLimit = limit;
+    }
+    if (fAnchoringBounds) {
+        fAnchorStart = start;
+        fAnchorLimit = limit;
+    }
+}
+
+
+
+//--------------------------------------------------------------------------------
+//
+//    regionEnd
+//
+//--------------------------------------------------------------------------------
+int RegexMatcher::regionEnd() const {
+    return fRegionLimit;
+}
+
+
+//--------------------------------------------------------------------------------
+//
+//    regionStart
+//
+//--------------------------------------------------------------------------------
+int RegexMatcher::regionStart() const {
+    return fRegionStart;
+}
+
+
+//--------------------------------------------------------------------------------
+//
 //    replaceAll
 //
 //--------------------------------------------------------------------------------
@@ -654,7 +747,8 @@
         return *fInput;
     }
     UnicodeString destString;
-    for (reset(); find(); ) {
+    reset();
+    while (find()) {
         appendReplacement(destString, replacement, status);
         if (U_FAILURE(status)) {
             break;
@@ -693,6 +787,15 @@
 }
 
 
+//--------------------------------------------------------------------------------
+//
+//     requireEnd
+//
+//--------------------------------------------------------------------------------
+UBool RegexMatcher::requireEnd() const {
+    return fRequireEnd;
+}
+
 
 //--------------------------------------------------------------------------------
 //
@@ -700,17 +803,30 @@
 //
 //--------------------------------------------------------------------------------
 RegexMatcher &RegexMatcher::reset() {
-    fMatchStart     = 0;
-    fMatchEnd       = 0;
-    fLastMatchEnd   = -1;
-    fLastReplaceEnd = 0;
-    fMatch          = FALSE;
-    resetStack();
+    fRegionStart    = 0;
+    fRegionLimit    = fInput->length();
+    fAnchorStart    = 0;
+    fAnchorLimit    = fRegionLimit;
+    fLookStart      = 0;
+    fLookLimit      = fRegionLimit;
+    resetPreserveRegion();
     return *this;
 }
 
 
 
+void RegexMatcher::resetPreserveRegion() {
+    fMatchStart     = 0;
+    fMatchEnd       = 0;
+    fLastMatchEnd   = -1;
+    fAppendPosition = 0;
+    fMatch          = FALSE;
+    fHitEnd         = FALSE;
+    fRequireEnd     = FALSE;
+    resetStack();
+}
+
+
 RegexMatcher &RegexMatcher::reset(const UnicodeString &input) {
     fInput          = &input;
     reset();
@@ -732,8 +848,8 @@
     if (U_FAILURE(status)) {
         return *this;
     }
-    reset();
-    if (position < 0 || position >= fInput->length()) {
+    reset();       // Reset also resets the region to be the entire string.
+    if (position < 0 || position >= fRegionLimit) {
         status = U_INDEX_OUTOFBOUNDS_ERROR;
         return *this;
     }
@@ -778,18 +894,15 @@
         return 0;
     }
 
-
     //
     // Reset for the input text
     //
     reset(input);
-    int32_t   inputLen = input.length();
     int32_t   nextOutputStringStart = 0;
-    if (inputLen == 0) {
+    if (fRegionLimit == 0) {
         return 0;
     }
 
-
     //
     // Loop through the input text, searching for the delimiter pattern
     //
@@ -804,7 +917,7 @@
             //    last capture group saved in favor of the unprocessed remainder of the
             //    input string.)
             i = destCapacity-1;
-            int32_t remainingLength = inputLen-nextOutputStringStart;
+            int32_t remainingLength = fRegionLimit-nextOutputStringStart;
             if (remainingLength > 0) {
                 dest[i].setTo(input, nextOutputStringStart, remainingLength);
             }
@@ -828,7 +941,7 @@
                 dest[i] = group(groupNum, status);
             }
 
-            if (nextOutputStringStart == inputLen) {
+            if (nextOutputStringStart == fRegionLimit) {
                 // The delimiter was at the end of the string.  We're done.
                 break;
             }
@@ -838,7 +951,7 @@
         {
             // We ran off the end of the input while looking for the next delimiter.
             // All the remaining text goes into the current output string.
-            dest[i].setTo(input, nextOutputStringStart, inputLen-nextOutputStringStart);
+            dest[i].setTo(input, nextOutputStringStart, fRegionLimit-nextOutputStringStart);
             break;
         }
     }
@@ -859,6 +972,11 @@
 
 
 
+//--------------------------------------------------------------------------------
+//
+//     start(int32_t group, UErrorCode &status)
+//
+//--------------------------------------------------------------------------------
 int32_t RegexMatcher::start(int32_t group, UErrorCode &status) const {
     if (U_FAILURE(status)) {
         return -1;
@@ -889,6 +1007,34 @@
 
 
 
+//--------------------------------------------------------------------------------
+//
+//     useAnchoringBounds
+//
+//--------------------------------------------------------------------------------
+RegexMatcher &RegexMatcher::useAnchoringBounds(UBool b) {
+    fAnchoringBounds = b;
+    UErrorCode status = U_ZERO_ERROR;
+    region(fRegionStart, fRegionLimit, status); 
+    U_ASSERT(U_SUCCESS(status));
+    return *this;
+}
+
+
+//--------------------------------------------------------------------------------
+//
+//     useTransparentBounds
+//
+//--------------------------------------------------------------------------------
+RegexMatcher &RegexMatcher::useTransparentBounds(UBool b) {
+    fTransparentBounds = b;
+    UErrorCode status = U_ZERO_ERROR;
+    region(fRegionStart, fRegionLimit, status); 
+    U_ASSERT(U_SUCCESS(status));
+    return *this;
+}
+
+
 //================================================================================
 //
 //    Code following this point in this file is the internal
@@ -938,9 +1084,11 @@
     UBool isBoundary = FALSE;
     UBool cIsWord    = FALSE;
     
-    // Determine whether char c at current position is a member of the word set of chars.
-    // If we're off the end of the string, behave as though we're not at a word char.
-    if (pos < fInput->length()) {
+    if (pos >= fLookLimit) {
+        fHitEnd = TRUE;
+    } else {
+        // Determine whether char c at current position is a member of the word set of chars.
+        // If we're off the end of the string, behave as though we're not at a word char.
         UChar32  c = fInput->char32At(pos);
         if (u_hasBinaryProperty(c, UCHAR_GRAPHEME_EXTEND) || u_charType(c) == U_FORMAT_CHAR) {
             // Current char is a combining one.  Not a boundary.
@@ -954,7 +1102,7 @@
     UBool prevCIsWord = FALSE;
     int32_t prevPos = pos;
     for (;;) {
-        if (prevPos == 0) {
+        if (prevPos <= fLookStart) {
             break;
         }
         prevPos = fInput->moveIndex32(prevPos, -1);
@@ -976,6 +1124,8 @@
 //         Test for a word boundary using RBBI word break.
 //
 //          parameters:   pos   - the current position in the input buffer
+//          TODO:  RBBI won't honor non-transparent region bounds.
+//                 Perhaps best to just document it.
 //
 //--------------------------------------------------------------------------------
 UBool RegexMatcher::isUWordBoundary(int32_t pos) {
@@ -994,14 +1144,21 @@
         fWordBreakItr->setText(*fInput);
     }
 
-    returnVal = fWordBreakItr->isBoundary(pos);
+    if (pos >= fLookLimit) {
+        fHitEnd = TRUE;
+        returnVal = TRUE;   // With Unicode word rules, only positions within the interior of "real"
+                            //    words are not boundaries.  All non-word chars stand by themselves,
+                            //    with word boundaries on both sides.
+    } else {
+        returnVal = fWordBreakItr->isBoundary(pos);
+    }
 #endif
     return   returnVal;
 }
 
 //--------------------------------------------------------------------------------
 //
-//   StateSave      
+//   StateSave
 //       Make a new stack frame, initialized as a copy of the current stack frame.
 //       Set the pattern index in the original stack frame from the operand value
 //       in the opcode.  Execution of the engine continues with the state in
@@ -1029,14 +1186,17 @@
     fp->fPatIdx = savePatIdx;
     return (REStackFrame *)newFP;
 }
-    
-            
+
+
 //--------------------------------------------------------------------------------
 //
 //   MatchAt      This is the actual matching engine.
 //
+//                  startIdx:    begin matching a this index.
+//                  toEnd:       if true, match must extend to end of the input region
+//
 //--------------------------------------------------------------------------------
-void RegexMatcher::MatchAt(int32_t startIdx, UErrorCode &status) {
+void RegexMatcher::MatchAt(int32_t startIdx, UBool toEnd, UErrorCode &status) {
     UBool       isMatch  = FALSE;      // True if the we have a match.
 
     int32_t     op;                    // Operation from the compiled pattern, split into
@@ -1077,7 +1237,7 @@
 
     const UChar         *litText       = fPattern->fLiteralText.getBuffer();
     UVector             *sets          = fPattern->fSets;
-    int32_t              inputLen      = fInput->length();
+
     const UChar         *inputBuf      = fInput->getBuffer();
 
     REStackFrame        *fp            = resetStack();
@@ -1130,12 +1290,14 @@
 
 
         case URX_ONECHAR:
-            if (fp->fInputIdx < inputLen) {
+            if (fp->fInputIdx < fRegionLimit) {
                 UChar32   c;
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
-                if (c == opValue) {           
+                U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
+                if (c == opValue) {
                     break;
                 }
+            } else {
+                fHitEnd = TRUE;
             }
             fp = (REStackFrame *)fStack->popFrame(frameSize);
             break;
@@ -1156,8 +1318,13 @@
                 U_ASSERT(opType == URX_STRING_LEN);
                 U_ASSERT(stringLen >= 2);
 
-                if (fp->fInputIdx + stringLen > inputLen) {
+                if (fp->fInputIdx + stringLen > fRegionLimit) {
                     // No match.  String is longer than the remaining input text.
+                    //   TODO:  Should fHitEnd only be set if the string matches for whatever amount
+                    //          of input is actually available?  Probably, although one could argue
+                    //          that it would be equally valid to begin the comparison at the end of
+                    //          the string.
+                    fHitEnd = TRUE;
                     fp = (REStackFrame *)fStack->popFrame(frameSize);
                     break;
                 }
@@ -1193,6 +1360,11 @@
         case URX_END:
             // The match loop will exit via this path on a successful match,
             //   when we reach the end of the pattern.
+            if (toEnd && fp->fInputIdx != fRegionLimit) {
+                // The pattern matched, but not to the end of input.  Try some more.
+                fp = (REStackFrame *)fStack->popFrame(frameSize);
+                break;
+            }
             isMatch = TRUE;
             goto  breakFromLoop;
 
@@ -1218,30 +1390,36 @@
             
         case URX_DOLLAR:                   //  $, test for End of line
                                            //     or for position before new line at end of input
-            if (fp->fInputIdx < inputLen-2) {
+            if (fp->fInputIdx < fAnchorLimit-2) {
                 // We are no where near the end of input.  Fail.
                 fp = (REStackFrame *)fStack->popFrame(frameSize);
                 break;
             }
-            if (fp->fInputIdx >= inputLen) {
+            if (fp->fInputIdx >= fAnchorLimit) {
                 // We really are at the end of input.  Success.
+                fHitEnd = TRUE;
+                fRequireEnd = TRUE;
                 break;
             }
             // If we are positioned just before a new-line that is located at the
             //   end of input, succeed.
-            if (fp->fInputIdx == inputLen-1) {
+            if (fp->fInputIdx == fAnchorLimit-1) {
                 UChar32 c = fInput->char32At(fp->fInputIdx);
                 if ((c<=0x0d && c>=0x0a) || c==0x85 ||c==0x2028 || c==0x2029) {
                     // If not in the middle of a CR/LF sequence
-                    if ( !(c==0x0a && fp->fInputIdx>0 && inputBuf[fp->fInputIdx-1]==0x0d)) {
+                    if ( !(c==0x0a && fp->fInputIdx>fAnchorStart && inputBuf[fp->fInputIdx-1]==0x0d)) {
                         break;
+                        fHitEnd = TRUE;
+                        fRequireEnd = TRUE;
                         // At new-line at end of input. Success
                     }
                 }
             }
 
-            if (fp->fInputIdx == inputLen-2) {
+            if (fp->fInputIdx == fAnchorLimit-2) {
                 if (fInput->char32At(fp->fInputIdx) == 0x0d && fInput->char32At(fp->fInputIdx+1) == 0x0a) {
+                    fHitEnd = TRUE;
+                    fRequireEnd = TRUE;
                     break;                         // At CR/LF at end of input.  Success
                 }
             }
@@ -1253,8 +1431,10 @@
 
          case URX_DOLLAR_M:                //  $, test for End of line in multi-line mode
              {
-                 if (fp->fInputIdx >= inputLen) {
+                 if (fp->fInputIdx >= fAnchorLimit) {
                      // We really are at the end of input.  Success.
+                     fHitEnd = TRUE;
+                     fRequireEnd = TRUE;
                      break;
                  }
                  // If we are positioned just before a new-line, succeed.
@@ -1262,11 +1442,12 @@
                  UChar32 c = inputBuf[fp->fInputIdx];
                  if ((c<=0x0d && c>=0x0a) || c==0x85 ||c==0x2028 || c==0x2029) {
                      // At a line end, except for the odd chance of  being in the middle of a CR/LF sequence
-                     if ( !(c==0x0a && fp->fInputIdx>0 && inputBuf[fp->fInputIdx-1]==0x0d)) {
-                        break;                         // At new-line at end of input. Success
+                     //  In multi-line mode, hitting a new-line just before the end of input does not
+                     //   set the hitEnd or requireEnd flags
+                     if ( !(c==0x0a && fp->fInputIdx>fAnchorStart && inputBuf[fp->fInputIdx-1]==0x0d)) {
+                        break;
                      }
                  }
-                 
                  // not at a new line.  Fail.
                  fp = (REStackFrame *)fStack->popFrame(frameSize);
              }
@@ -1274,29 +1455,29 @@
 
 
        case URX_CARET:                    //  ^, test for start of line
-            if (fp->fInputIdx != 0) {
+            if (fp->fInputIdx != fAnchorStart) {
                 fp = (REStackFrame *)fStack->popFrame(frameSize);
-            }           
+            }
             break;
 
 
        case URX_CARET_M:                   //  ^, test for start of line in mulit-line mode
            {
-               if (fp->fInputIdx == 0) {
+               if (fp->fInputIdx == fAnchorStart) {
                    // We are at the start input.  Success.
                    break;
                }
                // Check whether character just before the current pos is a new-line
                //   unless we are at the end of input
                UChar  c = inputBuf[fp->fInputIdx - 1]; 
-               if ((fp->fInputIdx < inputLen) && 
+               if ((fp->fInputIdx < fAnchorLimit) && 
                    ((c<=0x0d && c>=0x0a) || c==0x85 ||c==0x2028 || c==0x2029)) {
                    //  It's a new-line.  ^ is true.  Success.
-                   break;                        
+                   break;
                }
                // Not at the start of a line.  Fail.
                fp = (REStackFrame *)fStack->popFrame(frameSize);
-           }             
+           }
            break;
 
 
@@ -1324,13 +1505,14 @@
 
         case URX_BACKSLASH_D:            // Test for decimal digit
             {
-                if (fp->fInputIdx >= inputLen) {
+                if (fp->fInputIdx >= fRegionLimit) {
+                    fHitEnd = TRUE;
                     fp = (REStackFrame *)fStack->popFrame(frameSize);
                     break;
                 }
 
-                UChar32 c = fInput->char32At(fp->fInputIdx);   
-                int8_t ctype = u_charType(c);
+                UChar32 c = fInput->char32At(fp->fInputIdx);
+                int8_t ctype = u_charType(c);     // TODO:  make a unicode set for this.  Will be faster.
                 UBool success = (ctype == U_DECIMAL_DIGIT_NUMBER);
                 success ^= (opValue != 0);        // flip sense for \D
                 if (success) {
@@ -1342,10 +1524,8 @@
             break;
 
 
-
-
         case URX_BACKSLASH_G:          // Test for position at end of previous match
-            if (!((fMatch && fp->fInputIdx==fMatchEnd) || fMatch==FALSE && fp->fInputIdx==0)) {
+            if (!((fMatch && fp->fInputIdx==fMatchEnd) || fMatch==FALSE && fp->fInputIdx==fRegionStart)) {
                 fp = (REStackFrame *)fStack->popFrame(frameSize);
             }
             break;
@@ -1355,10 +1535,11 @@
             //  Match a Grapheme, as defined by Unicode TR 29.
             //  Differs slightly from Perl, which consumes combining marks independently
             //    of context.
-            {                  
+            {
 
                 // Fail if at end of input
-                if (fp->fInputIdx >= inputLen) {
+                if (fp->fInputIdx >= fRegionLimit) {
+                    fHitEnd = TRUE;
                     fp = (REStackFrame *)fStack->popFrame(frameSize);
                     break;
                 }
@@ -1366,7 +1547,7 @@
                 // Examine (and consume) the current char.
                 //   Dispatch into a little state machine, based on the char.
                 UChar32  c;
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
+                U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
                 UnicodeSet **sets = fPattern->fStaticSets;
                 if (sets[URX_GC_NORMAL]->contains(c))  goto GC_Extend;
                 if (sets[URX_GC_CONTROL]->contains(c)) goto GC_Control;
@@ -1380,8 +1561,8 @@
 
 
 GC_L:
-                if (fp->fInputIdx >= inputLen)         goto GC_Done;
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
+                if (fp->fInputIdx >= fRegionLimit)         goto GC_Done;
+                U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
                 if (sets[URX_GC_L]->contains(c))       goto GC_L;
                 if (sets[URX_GC_LV]->contains(c))      goto GC_V;
                 if (sets[URX_GC_LVT]->contains(c))     goto GC_T;
@@ -1390,16 +1571,16 @@
                 goto GC_Extend;
 
 GC_V:
-                if (fp->fInputIdx >= inputLen)         goto GC_Done;
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
+                if (fp->fInputIdx >= fRegionLimit)         goto GC_Done;
+                U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
                 if (sets[URX_GC_V]->contains(c))       goto GC_V;
                 if (sets[URX_GC_T]->contains(c))       goto GC_T;
                 U16_PREV(inputBuf, 0, fp->fInputIdx, c);
                 goto GC_Extend;
 
 GC_T:
-                if (fp->fInputIdx >= inputLen)         goto GC_Done;
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
+                if (fp->fInputIdx >= fRegionLimit)         goto GC_Done;
+                U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
                 if (sets[URX_GC_T]->contains(c))       goto GC_T;
                 U16_PREV(inputBuf, 0, fp->fInputIdx, c);
                 goto GC_Extend;
@@ -1407,33 +1588,37 @@
 GC_Extend:
                 // Combining characters are consumed here
                 for (;;) {
-                    if (fp->fInputIdx >= inputLen) {
+                    if (fp->fInputIdx >= fRegionLimit) {
                         break;
                     }
-                    U16_GET(inputBuf, 0, fp->fInputIdx, inputLen, c);
+                    U16_GET(inputBuf, 0, fp->fInputIdx, fRegionLimit, c);
                     if (sets[URX_GC_EXTEND]->contains(c) == FALSE) {
                         break;
                     }
-                    U16_FWD_1(inputBuf, fp->fInputIdx, inputLen);
+                    U16_FWD_1(inputBuf, fp->fInputIdx, fRegionLimit);
                 }
                 goto GC_Done;
 
 GC_Control:
                 // Most control chars stand alone (don't combine with combining chars),  
                 //   except for that CR/LF sequence is a single grapheme cluster.
-                if (c == 0x0d && fp->fInputIdx < inputLen && inputBuf[fp->fInputIdx] == 0x0a) {
+                if (c == 0x0d && fp->fInputIdx < fRegionLimit && inputBuf[fp->fInputIdx] == 0x0a) {
                     fp->fInputIdx++;
                 }
 
 GC_Done:
+                if (fp->fInputIdx >= fRegionLimit) {
+                    fHitEnd = TRUE;
+                }
                 break;
             }
             
 
 
 
-        case URX_BACKSLASH_Z:          // Test for end of line
-            if (fp->fInputIdx < inputLen) {
+        case URX_BACKSLASH_Z:          // Test for end of Input
+            if (fp->fInputIdx < fAnchorLimit) {
+                fHitEnd = TRUE;
                 fp = (REStackFrame *)fStack->popFrame(frameSize);
             }
             break;
@@ -1447,7 +1632,8 @@
                 // The high bit of the op value is a flag for the match polarity.
                 //    0:   success if input char is in set.
                 //    1:   success if input char is not in set.
-                if (fp->fInputIdx >= inputLen) {
+                if (fp->fInputIdx >= fRegionLimit) {
+                    fHitEnd = TRUE;
                     fp = (REStackFrame *)fStack->popFrame(frameSize);
                     break;
                 }
@@ -1456,7 +1642,7 @@
                 opValue &= ~URX_NEG_SET;
                 U_ASSERT(opValue > 0 && opValue < URX_LAST_SET);
                 UChar32  c;
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
+                U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
                 if (c < 256) {
                     Regex8BitSet *s8 = &fPattern->fStaticSets8[opValue];
                     if (s8->contains(c)) {
@@ -1479,14 +1665,15 @@
             {
                 // Test input character for NOT being a member of  one of 
                 //    the predefined sets (Word Characters, for example)
-                if (fp->fInputIdx >= inputLen) {
+                if (fp->fInputIdx >= fRegionLimit) {
+                    fHitEnd = TRUE;
                     fp = (REStackFrame *)fStack->popFrame(frameSize);
                     break;
                 }
 
                 U_ASSERT(opValue > 0 && opValue < URX_LAST_SET);
                 UChar32  c;
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
+                U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
                 if (c < 256) {
                     Regex8BitSet *s8 = &fPattern->fStaticSets8[opValue];
                     if (s8->contains(c) == FALSE) {
@@ -1505,42 +1692,44 @@
             
 
         case URX_SETREF:
-            if (fp->fInputIdx < inputLen) {
-                // There is input left.  Pick up one char and test it for set membership.
-                UChar32   c;
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
-                U_ASSERT(opValue > 0 && opValue < sets->size());
-                if (c<256) {
-                    Regex8BitSet *s8 = &fPattern->fSets8[opValue];
-                    if (s8->contains(c)) {
-                        break;
-                    }
-                } else {
-                    
-                    UnicodeSet *s = (UnicodeSet *)sets->elementAt(opValue);
-                    if (s->contains(c)) {
-                        // The character is in the set.  A Match.
-                        break;
-                    }
+            if (fp->fInputIdx >= fRegionLimit) {
+                fHitEnd = TRUE;
+                fp = (REStackFrame *)fStack->popFrame(frameSize);
+                break;
+            }
+            // There is input left.  Pick up one char and test it for set membership.
+            UChar32   c;
+            U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
+            U_ASSERT(opValue > 0 && opValue < sets->size());
+            if (c<256) {
+                Regex8BitSet *s8 = &fPattern->fSets8[opValue];
+                if (s8->contains(c)) {
+                    break;
                 }
-            } 
-            // Either at end of input, or the character wasn't in the set.
-            // Either way, we need to back track out.
+            } else {
+                UnicodeSet *s = (UnicodeSet *)sets->elementAt(opValue);
+                if (s->contains(c)) {
+                    // The character is in the set.  A Match.
+                    break;
+                }
+            }
+            // the character wasn't in the set. Back track out.
             fp = (REStackFrame *)fStack->popFrame(frameSize);
             break;
-            
+
 
         case URX_DOTANY:
             {
                 // . matches anything, but stops at end-of-line.
-                if (fp->fInputIdx >= inputLen) {
+                if (fp->fInputIdx >= fRegionLimit) {
                     // At end of input.  Match failed.  Backtrack out.
+                    fHitEnd = TRUE;
                     fp = (REStackFrame *)fStack->popFrame(frameSize);
                     break;
                 }
                 // There is input left.  Advance over one char, unless we've hit end-of-line
                 UChar32 c;
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
+                U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
                 if (((c & 0x7f) <= 0x29) &&     // First quickly bypass as many chars as possible
                     ((c<=0x0d && c>=0x0a) || c==0x85 ||c==0x2028 || c==0x2029)) {
                     // End of line in normal mode.   . does not match.
@@ -1554,16 +1743,17 @@
         case URX_DOTANY_ALL:
             {
                 // ., in dot-matches-all (including new lines) mode
-                if (fp->fInputIdx >= inputLen) {
+                if (fp->fInputIdx >= fRegionLimit) {
                     // At end of input.  Match failed.  Backtrack out.
+                    fHitEnd = TRUE;
                     fp = (REStackFrame *)fStack->popFrame(frameSize);
                     break;
                 }
                 // There is input left.  Advance over one char, except if we are
                 //   at a cr/lf, advance over both of them.
                 UChar32 c; 
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
-                if (c==0x0d) {
+                U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
+                if (c==0x0d && fp->fInputIdx < fRegionLimit) {
                     // In the case of a CR/LF, we need to advance over both.
                     UChar nextc = inputBuf[fp->fInputIdx];
                     if (nextc == 0x0a) {
@@ -1577,14 +1767,15 @@
             // Match all up to and end-of-line or end-of-input.
             {
                 //  Fail if input already exhausted.
-                if (fp->fInputIdx >= inputLen) {
+                if (fp->fInputIdx >= fRegionLimit) {
+                    fHitEnd = TRUE;
                     fp = (REStackFrame *)fStack->popFrame(frameSize);
                     break;
                 }
-                
+
                 // There is input left. Fail if we are  at the end of a line.
                 UChar32 c;
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
+                U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
                 if (((c & 0x7f) <= 0x29) &&     // First quickly bypass as many chars as possible
                     ((c<=0x0d && c>=0x0a) || c==0x85 ||c==0x2028 || c==0x2029)) {
                     // End of line in normal mode.   . does not match.
@@ -1594,8 +1785,12 @@
                 
                 // There was input left.  Consume it until we hit the end of a line,
                 //   or until it's exhausted.
-                while  (fp->fInputIdx < inputLen) {
-                    U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
+                for (;;) {
+                    if (fp->fInputIdx >=  fRegionLimit) {
+                        fHitEnd = TRUE;
+                        break;
+                    }
+                    U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
                     if (((c & 0x7f) <= 0x29) &&     // First quickly bypass as many chars as possible
                         ((c<=0x0d && c>=0x0a) || c==0x85 ||c==0x2028 || c==0x2029)) {
                         U16_BACK_1(inputBuf, 0, fp->fInputIdx)
@@ -1607,13 +1802,12 @@
             break;
 
         case URX_DOTANY_ALL_PL:
-            {
-                // Match up to end of input.  Fail if already at end of input.
-                if (fp->fInputIdx >= inputLen) {
-                    fp = (REStackFrame *)fStack->popFrame(frameSize);
-                } else {
-                    fp->fInputIdx = inputLen;
-                }
+            // Match up to end of input.  Fail if already at end of input.
+            fHitEnd = TRUE;
+            if (fp->fInputIdx >= fRegionLimit) {
+                fp = (REStackFrame *)fStack->popFrame(frameSize);
+            } else {
+                fp->fInputIdx = fRegionLimit;
             }
             break;
 
@@ -1812,7 +2006,7 @@
                     }
 
                 UBool  haveMatch = FALSE;
-                if (fp->fInputIdx + len <= inputLen) {
+                if (fp->fInputIdx + len <= fRegionLimit) {
                     if (opType == URX_BACKREF) {
                         if (u_strncmp(inputBuf+groupStartIdx, inputBuf+fp->fInputIdx, len) == 0) {
                             haveMatch = TRUE;
@@ -1823,6 +2017,10 @@
                             haveMatch = TRUE;
                         }
                     }
+                } else {
+                    // TODO: probably need to do a partial string comparison, and only
+                    //       set HitEnd if the available input matched.
+                    fHitEnd = TRUE;
                 }
                 if (haveMatch) {
                     fp->fInputIdx += len;     // Match.  Advance current input position.
@@ -1856,6 +2054,7 @@
             break;
 
         case URX_LA_START:
+            //  TODO:  setup for trnsaparent bounds, 
             {
                 // Entering a lookahead block.
                 // Save Stack Ptr, Input Pos.
@@ -1869,6 +2068,7 @@
             {
                 // Leaving a look-ahead block.
                 //  restore Stack Ptr, Input Pos to positions they had on entry to block.
+                //  TODO:  will need to restore Region bounds as well, for Transparent Bounds.
                 U_ASSERT(opValue>=0 && opValue+1<fPattern->fDataSize);
                 int32_t stackSize = fStack->size();
                 int32_t newStackSize = fData[opValue];
@@ -1887,13 +2087,15 @@
             break;
 
         case URX_ONECHAR_I:
-            if (fp->fInputIdx < inputLen) {
+            if (fp->fInputIdx < fRegionLimit) {
                 UChar32   c;
-                U16_NEXT(inputBuf, fp->fInputIdx, inputLen, c);
-                if (u_foldCase(c, U_FOLD_CASE_DEFAULT) == opValue) {           
+                U16_NEXT(inputBuf, fp->fInputIdx, fRegionLimit, c);
+                if (u_foldCase(c, U_FOLD_CASE_DEFAULT) == opValue) {
                     break;
                 }
-            } 
+            } else {
+                fHitEnd = TRUE;
+            }
             fp = (REStackFrame *)fStack->popFrame(frameSize);
             break;
 
@@ -1913,14 +2115,18 @@
                 stringLen = opValue;
                 
                 int32_t stringEndIndex = fp->fInputIdx + stringLen;
-                if (stringEndIndex <= inputLen) {
+                if (stringEndIndex <= fRegionLimit) {
                     if (u_strncasecmp(inputBuf+fp->fInputIdx, litText+stringStartIdx,
                         stringLen, U_FOLD_CASE_DEFAULT) == 0) {
                         // Success.  Advance the current input position.
                         fp->fInputIdx = stringEndIndex;
                         break;
                     }
-                }                 
+                } else {
+                    // TODO:  for HitEnd, probably need to check for match of
+                    //        however much input was available.
+                    fHitEnd = TRUE;
+                }
                 // No match.  Back up matching to a saved state
                 fp = (REStackFrame *)fStack->popFrame(frameSize);
             }
@@ -1930,6 +2136,7 @@
             {
                 // Entering a look-behind block.
                 // Save Stack Ptr, Input Pos.
+                //   TODO:  implement transparent bounds.
                 U_ASSERT(opValue>=0 && opValue+1<fPattern->fDataSize);
                 fData[opValue]   = fStack->size();
                 fData[opValue+1] = fp->fInputIdx;
@@ -1937,8 +2144,8 @@
                 fData[opValue+2] = -1;
                 // Save input string length, then reset to pin any matches to end at
                 //   the current position.
-                fData[opValue+3] = inputLen;
-                inputLen         = fp->fInputIdx;
+                fData[opValue+3] = fRegionLimit;
+                fRegionLimit     = fp->fInputIdx;
             }
             break;
 
@@ -1977,9 +2184,9 @@
                     //   Look Behind altogether.
                     fp = (REStackFrame *)fStack->popFrame(frameSize);
                     int32_t restoreInputLen = fData[opValue+3];
-                    U_ASSERT(restoreInputLen >= inputLen);
+                    U_ASSERT(restoreInputLen >= fRegionLimit);
                     U_ASSERT(restoreInputLen <= fInput->length());
-                    inputLen = restoreInputLen;
+                    fRegionLimit = restoreInputLen;
                     break;
                 }
 
@@ -1994,7 +2201,7 @@
             // End of a look-behind block, after a successful match.
             {
                 U_ASSERT(opValue>=0 && opValue+1<fPattern->fDataSize);
-                if (fp->fInputIdx != inputLen) {
+                if (fp->fInputIdx != fRegionLimit) {
                     //  The look-behind expression matched, but the match did not
                     //    extend all the way to the point that we are looking behind from.
                     //  FAIL out of here, which will take us back to the LB_CONT, which
@@ -2008,9 +2215,9 @@
                 //   which had been truncated to pin the end of the lookbehind match to the 
                 //   position being looked-behind.
                 int32_t originalInputLen = fData[opValue+3];
-                U_ASSERT(originalInputLen >= inputLen);
+                U_ASSERT(originalInputLen >= fRegionLimit);
                 U_ASSERT(originalInputLen <= fInput->length());
-                inputLen = originalInputLen;
+                fRegionLimit = originalInputLen;
             }
             break;
 
@@ -2050,9 +2257,9 @@
                     //  getting a match, which means that the negative lookbehind as
                     //  a whole has succeeded.  Jump forward to the continue location
                     int32_t restoreInputLen = fData[opValue+3];
-                    U_ASSERT(restoreInputLen >= inputLen);
+                    U_ASSERT(restoreInputLen >= fRegionLimit);
                     U_ASSERT(restoreInputLen <= fInput->length());
-                    inputLen = restoreInputLen;
+                    fRegionLimit = restoreInputLen;
                     fp->fPatIdx = continueLoc;
                     break;
                 }
@@ -2068,7 +2275,7 @@
             // End of a negative look-behind block, after a successful match.
             {
                 U_ASSERT(opValue>=0 && opValue+1<fPattern->fDataSize);
-                if (fp->fInputIdx != inputLen) {
+                if (fp->fInputIdx != fRegionLimit) {
                     //  The look-behind expression matched, but the match did not
                     //    extend all the way to the point that we are looking behind from.
                     //  FAIL out of here, which will take us back to the LB_CONT, which
@@ -2085,9 +2292,9 @@
                 //   inorder to pin the end of the lookbehind match  
                 //   to the position being looked-behind.
                 int32_t originalInputLen = fData[opValue+3];
-                U_ASSERT(originalInputLen >= inputLen);
+                U_ASSERT(originalInputLen >= fRegionLimit);
                 U_ASSERT(originalInputLen <= fInput->length());
-                inputLen = originalInputLen;
+                fRegionLimit = originalInputLen;
 
                 // Restore original stack position, discarding any state saved
                 //   by the successful pattern match.
@@ -2117,11 +2324,12 @@
                 //   we reach a character that is not a member of the set.
                 int32_t ix = fp->fInputIdx;
                 for (;;) {
-                    if (ix >= inputLen) {
+                    if (ix >= fRegionLimit) {
+                        fHitEnd = TRUE;
                         break;
                     }
                     UChar32   c;
-                    U16_NEXT(inputBuf, ix, inputLen, c);
+                    U16_NEXT(inputBuf, ix, fRegionLimit, c);
                     if (c<256) {
                         if (s8->contains(c) == FALSE) {
                             U16_BACK_1(inputBuf, 0, ix);
@@ -2171,21 +2379,23 @@
                 int32_t ix;
                 if (opValue == 1) {
                     // Multi-line mode.
-                    ix = inputLen;
+                    ix = fRegionLimit;
+                    fHitEnd = TRUE;
                 } else {
                     // NOT multi-line mode.  Line endings do not match '.'
                     // Scan forward until a line ending or end of input.
                     ix = fp->fInputIdx;
                     for (;;) {
-                        if (ix >= inputLen) {
-                            ix = inputLen;
+                        if (ix >= fRegionLimit) {
+                            fHitEnd = TRUE;
+                            ix = fRegionLimit;
                             break;
                         }
                         UChar32   c;
-                        U16_NEXT(inputBuf, ix, inputLen, c);   // c = inputBuf[ix++]
+                        U16_NEXT(inputBuf, ix, fRegionLimit, c);   // c = inputBuf[ix++]
                         if (((c & 0x7f) <= 0x29) &&     
                             ((c<=0x0d && c>=0x0a) || c==0x85 ||c==0x2028 || c==0x2029)) {
-                            //  char is a line ending.  Put the input pos back to the  
+                            //  char is a line ending.  Put the input pos back to the
                             //    line ending char, and exit the scanning loop.
                             U16_BACK_1(inputBuf, 0, ix);
                             break;
diff --git a/i18n/unicode/regex.h b/i18n/unicode/regex.h
index 27f4b40..798ecfa 100644
--- a/i18n/unicode/regex.h
+++ b/i18n/unicode/regex.h
@@ -517,7 +517,7 @@
 
 
    /**
-    *   Attempts to match the entire input string against the pattern.
+    *   Attempts to match the entire input region against the pattern.
     *    @param   status     A reference to a UErrorCode to receive any errors.
     *    @return TRUE if there is a match
     *    @stable ICU 2.4
@@ -525,8 +525,10 @@
     virtual UBool matches(UErrorCode &status);
 
    /**
-    *   Attempts to match the input string, beginning at startIndex, against the pattern.
-    *   The match must extend to the end of the input string.
+    *   Resets the matcher, then attempts to match the input beginning 
+    *   at the specified startIndex, and extending to the end of the input.
+    *   The input region is reset to include the entire input string.
+    *   A successful match must extend to the end of the input.
     *    @param   startIndex The input string index at which to begin matching.
     *    @param   status     A reference to a UErrorCode to receive any errors.
     *    @return TRUE if there is a match
@@ -538,9 +540,10 @@
 
 
    /**
-    *   Attempts to match the input string, starting from the beginning, against the pattern.
-    *   Like the matches() method, this function always starts at the beginning of the input string;
-    *   unlike that function, it does not require that the entire input string be matched.
+    *   Attempts to match the input string, starting from the beginning of the region,
+    *   against the pattern.  Like the matches() method, this function 
+    *   always starts at the beginning of the input region;
+    *   unlike that function, it does not require that the entire region be matched.
     *
     *   <p>If the match succeeds then more information can be obtained via the <code>start()</code>,
     *     <code>end()</code>, and <code>group()</code> functions.</p>
@@ -699,6 +702,12 @@
     *   The effect is to remove any memory of previous matches,
     *       and to cause subsequent find() operations to begin at
     *       the specified position in the input string.
+    * <p>
+    *   The matcher's region is reset to its default, wich is the entire
+    *   input string.
+    * <p>
+    *   An alternative to this function is to set a match region
+    *   beginning at the desired index.
     *
     *   @return this RegexMatcher.
     *   @stable ICU 2.8
@@ -743,6 +752,130 @@
     *   @stable ICU 2.4
     */
     virtual const UnicodeString &input() const;
+    
+    
+
+   /** Sets the limits of this matcher's region.
+     * The region is the part of the input string that will be searched to find a match.
+     * Invoking this method resets the matcher, and then sets the region to start
+     * at the index specified by the start parameter and end at the index specified
+     * by the end parameter.
+     *
+     * Depending on the transparency and anchoring being used (see useTransparentBounds
+     * and useAnchoringBounds), certain constructs such as anchors may behave differently
+     * at or around the boundaries of the region
+     *
+     * The function will fail if start is greater than limit, or if either index
+     *  is less than zero or greater than the length of the string being matched.
+     *
+     * @param start  The index to begin searches at.
+     * @param limit  The index to end searches at (exclusive).
+     * @param status A reference to a UErrorCode to receive any errors.
+     * @draft ICU 4.0
+     */
+     virtual RegexMatcher &region(int32_t start, int32_t limit, UErrorCode &status);
+
+
+   /**
+     * Reports the start index of this matcher's region. The searches this matcher
+     * conducts are limited to finding matches within regionStart (inclusive) and
+     * regionEnd (exclusive).
+     *
+     * @return The starting index of this matcher's region.
+     * @draft ICU 4.0
+     */
+     virtual int32_t regionStart() const;
+
+
+    /**
+      * Reports the end (limit) index (exclusive) of this matcher's region. The searches
+      * this matcher conducts are limited to finding matches within regionStart
+      * (inclusive) and regionEnd (exclusive).
+      *
+      * @return The ending point of this matcher's region.
+      * @draft ICU 4.0
+      */
+      virtual int32_t regionEnd() const;
+
+    /**
+      * Queries the transparency of region bounds for this matcher.
+      * See useTransparentBounds for a description of transparent and opaque bounds.
+      * By default, a matcher uses opaque region boundaries.
+      *
+      * @return TRUE if this matcher is using opaque bounds, false if it is not.
+      * @draft ICU 4.0
+      */
+      virtual UBool hasTransparentBounds() const;
+
+    /**
+      * Sets the transparency of region bounds for this matcher.
+      * Invoking this function with an argument of true will set this matcher to use transparent bounds.
+      * If the boolean argument is false, then opaque bounds will be used.
+      *
+      * Using transparent bounds, the boundaries of this matcher's region are transparent
+      * to lookahead, lookbehind, and boundary matching constructs. Those constructs can
+      * see text beyond the boundaries of the region while checking for a match.
+      *
+      * With opaque bounds, no text outside of the matcher's region is visible to lookahead,
+      * lookbehind, and boundary matching constructs.
+      *
+      * By default, a matcher uses opaque bounds.
+      *
+      * @param   b TRUE for transparent bounds; FALSE for opaque bounds
+      * @return  This Matcher;
+      * @draft   ICU 4.0
+      **/
+      virtual RegexMatcher &useTransparentBounds(UBool b);
+
+     
+    /**
+      * Return true if this matcher is using anchoring bounds.
+      * By default, matchers use anchoring region boounds.
+      *
+      * @return TRUE if this matcher is using anchoring bounds.
+      * @draft  ICU 4.0
+      */    
+      virtual UBool hasAnchoringBounds() const;
+
+    /**
+      * Set whether this matcher is using Anchoring Bounds for its region.
+      * With anchoring bounds, pattern anchors such as ^ and $ will match at the start
+      * and end of the region.  Without Anchoring Bounds, anchors will only match at
+      * the positions they would in the complete text.
+      *
+      * Anchoring Bounds are the default for regions.
+      *
+      * @param b TRUE if to enable anchoring bounds; FALSE to disable them.
+      * @return  This Matcher
+      * @draft   ICU 4.0
+      */
+      virtual RegexMatcher &useAnchoringBounds(UBool b);
+
+    /**
+      * Return TRUE if the most recent matching operation touched the
+      *  end of the text being processed.  In this case, additional input text could
+      *  change the results of that match.
+      *
+      *   (TODO:  how does this interact with transparent bounds and look-ahead?)
+      *
+      *  @return  TRUE if the most recent match hit the end of input
+      *  @draft   ICU 4.0
+      */
+      virtual UBool hitEnd() const;
+
+    /**
+      * Return TRUE the most recent match succeeded and additional input could cause
+      * it to fail. If this method returns false and a match was found, then more input
+      * might change the match but the match won't be lost. If a match was not found,
+      * then requireEnd has no meaning.
+      *
+      * @return TRUE if more input could cause the most recent match to no longer match.
+      * @draft  ICU 4.0
+      */
+      virtual UBool requireEnd() const;
+
+
+
 
 
    /**
@@ -901,12 +1034,14 @@
     RegexMatcher &operator =(const RegexMatcher &rhs);
     friend class RegexPattern;
     friend class RegexCImpl;
+    
+    void resetPreserveRegion();  // Reset matcher state, but preserve any region.
 
     //
     //  MatchAt   This is the internal interface to the match engine itself.
     //            Match status comes back in matcher member variables.
     //
-    void                 MatchAt(int32_t startIdx, UErrorCode &status);
+    void                 MatchAt(int32_t startIdx, UBool toEnd, UErrorCode &status);
     inline void          backTrack(int32_t &inputIdx, int32_t &patIdx);
     UBool                isWordBoundary(int32_t pos);         // perform Perl-like  \b test
     UBool                isUWordBoundary(int32_t pos);        // perform RBBI based \b test
@@ -918,18 +1053,38 @@
     const RegexPattern  *fPattern;
     RegexPattern        *fPatternOwned;    // Non-NULL if this matcher owns the pattern, and
                                            //   should delete it when through.
-    const UnicodeString *fInput;
 
-    UBool                fMatch;           // True if the last match was successful.
+    const UnicodeString *fInput;           // The text being matched. Is never NULL.
+    
+    int32_t              fRegionStart;     // Start of the input region, default = 0.
+    int32_t              fRegionLimit;     // End of input region, default to input.length.
+    
+    int32_t              fAnchorStart;     // Region bounds for anchoring operations (^ or $).
+    int32_t              fAnchorLimit;     //   See useAnchoringBounds
+    
+    int32_t              fLookStart;       // Region bounds for look-ahead/behind and
+    int32_t              fLookLimit;       //   and other boundary tests.  See
+                                           //   useTransparentBounds
+    UBool                fTransparentBounds;  // True if using transparent bounds.
+    UBool                fAnchoringBounds; // True if using anchoring bounds.
+
+    UBool                fMatch;           // True if the last attempted match was successful.
     int32_t              fMatchStart;      // Position of the start of the most recent match
     int32_t              fMatchEnd;        // First position after the end of the most recent match
+                                           //   Zero if no previous match, even when a region
+                                           //   is active.
     int32_t              fLastMatchEnd;    // First position after the end of the previous match,
                                            //   or -1 if there was no previous match.
-    int32_t              fLastReplaceEnd;  // First position after the end of the previous appendReplacement();
+    int32_t              fAppendPosition;  // First position after the end of the previous
+                                           //   appendReplacement().  As described JavaDoc for  
+                                           //   Java Matcher, where it is called "append position"
+    UBool                fHitEnd;          // True if the last match touched the end of input.
+    UBool                fRequireEnd;      // True if the last match required end-of-input
+                                           //    (matched $ or Z)
 
     UVector32           *fStack;
-    REStackFrame        *fFrame;           // After finding a match, the last active stack
-                                           //   frame, which will contain the capture group results.
+    REStackFrame        *fFrame;           // After finding a match, the last active stack frame,
+                                           //   which will contain the capture group results.
                                            //   NOT valid while match engine is running.
 
     int32_t             *fData;            // Data area for use by the compiled pattern.
diff --git a/i18n/unicode/uregex.h b/i18n/unicode/uregex.h
index 3b0e701..0bb565d 100644
--- a/i18n/unicode/uregex.h
+++ b/i18n/unicode/uregex.h
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 2004-2006, International Business Machines
+*   Copyright (C) 2004-2007, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   file name:  regex.h
@@ -313,10 +313,10 @@
             UErrorCode         *status);
 
 /**
-  *  Find the next pattern match in the input string.
-  *  Begin searching the input at the location following the end of
-  *  the previous match, or at the start of the string if there is no previous match.
-  *  If a match is found, <code>uregex_start(), uregex_end()</code>, and
+  *  Find the next pattern match in the input string.  Begin searching 
+  *  the input at the location following the end of he previous match, 
+  *  or at the start of the string (or region) if there is no 
+  *  previous match.  If a match is found, <code>uregex_start(), uregex_end()</code>, and
   *  <code>uregex_group()</code> will provide more information regarding the match.
   *
   *  @param   regexp      The compiled regular expression.
@@ -405,7 +405,8 @@
   *  Reset any saved state from the previous match.  Has the effect of
   *  causing uregex_findNext to begin at the specified index, and causing
   *  uregex_start(), uregex_end() and uregex_group() to return an error 
-  *  indicating that there is no match information available.
+  *  indicating that there is no match information available.  Clears any
+  *  match region that may have been set.
   *
   *    @param   regexp      The compiled regular expression.
   *    @param   index       The position in the text at which a
@@ -417,6 +418,152 @@
 uregex_reset(URegularExpression    *regexp,
              int32_t               index,
              UErrorCode            *status);
+             
+             
+/** Sets the limits of the matching region for this URegularExpression.
+  * The region is the part of the input string that will be considered when matching.
+  * Invoking this method resets any saved state from the previous match, 
+  * then sets the region to start at the index specified by the start parameter
+  * and end at the index specified by the end parameter.
+  *
+  * Depending on the transparency and anchoring being used (see useTransparentBounds
+  * and useAnchoringBounds), certain constructs such as anchors may behave differently
+  * at or around the boundaries of the region
+  *
+  * The function will fail if start is greater than limit, or if either index
+  *  is less than zero or greater than the length of the string being matched.
+  *
+  * @param regexp The compiled regular expression.
+  * @param start  The index to begin searches at.
+  * @param limit  The index to end searches at (exclusive).
+  * @param status A reference to a UErrorCode to receive any errors.
+  * @draft ICU 4.0
+  */
+U_DRAFT void U_EXPORT2
+uregex_setRegion(URegularExpression   *regexp,
+                 int32_t               regionStart,
+                 int32_t               regionLimit,
+                 UErrorCode           *status);
+                 
+/**
+  * Reports the start index of the matching region. Any matches found are limited to
+  * to the region bounded by regionStart (inclusive) and regionEnd (exclusive).
+  *
+  * @return The starting index of this matcher's region.
+  * @draft ICU 4.0
+  */
+U_DRAFT int32_t U_EXPORT2
+uregex_regionStart(const  URegularExpression   *regexp,
+                          UErrorCode           *status);
+
+
+
+/**
+  * Reports the end index (exclusive) of the matching region for this URegularExpression.
+  * Any matches found are limited to to the region bounded by regionStart (inclusive)
+  * and regionEnd (exclusive).
+  *
+  * @return The ending point of this matcher's region.
+  * @draft ICU 4.0
+  */
+U_DRAFT int32_t U_EXPORT2
+uregex_regionEnd(const  URegularExpression   *regexp,
+                        UErrorCode           *status);
+
+/**
+  * Queries the transparency of region bounds for this URegularExpression.
+  * See useTransparentBounds for a description of transparent and opaque bounds.
+  * By default, matching boundaries are opaque.
+  *
+  * @return TRUE if this matcher is using opaque bounds, false if it is not.
+  * @draft ICU 4.0
+  */
+U_DRAFT UBool U_EXPORT2
+uregex_hasTransparentBounds(const  URegularExpression   *regexp,
+                                   UErrorCode           *status);
+
+
+/**
+  * Sets the transparency of region bounds for this URegularExpression.
+  * Invoking this function with an argument of TRUE will set matches to use transparent bounds.
+  * If the boolean argument is FALSE, then opaque bounds will be used.
+  *
+  * Using transparent bounds, the boundaries of the matching region are transparent
+  * to lookahead, lookbehind, and boundary matching constructs. Those constructs can
+  * see text beyond the boundaries of the region while checking for a match.
+  *
+  * With opaque bounds, no text outside of the matching region is visible to lookahead,
+  * lookbehind, and boundary matching constructs.
+  *
+  * By default, a matcher uses opaque bounds.
+  *
+  * @param   b TRUE for transparent bounds; FALSE for opaque bounds
+  * @return  This Matcher;
+  * @draft   ICU 4.0
+  **/
+U_DRAFT void U_EXPORT2  
+uregex_useTransparentBounds(URegularExpression   *regexp, 
+                            UBool                b,
+                            UErrorCode           *status);
+
+  
+/**
+  * Return true if this matcher is using anchoring bounds.
+  * By default, matchers use anchoring region boounds.
+  *
+  * @return TRUE if this matcher is using anchoring bounds.
+  * @draft  ICU 4.0
+  */    
+U_DRAFT UBool U_EXPORT2
+uregex_hasAnchoringBounds(const  URegularExpression   *regexp,
+                                 UErrorCode           *status);
+
+
+/**
+  * Set whether this URegularExpression is using Anchoring Bounds for its region.
+  * With anchoring bounds, pattern anchors such as ^ and $ will match at the start
+  * and end of the region.  Without Anchoring Bounds, anchors will only match at
+  * the positions they would in the complete text.
+  *
+  * Anchoring Bounds are the default for regions.
+  *
+  * @param b TRUE if to enable anchoring bounds; FALSE to disable them.
+  * @return  This Matcher
+  * @draft   ICU 4.0
+  */
+U_DRAFT void U_EXPORT2
+uregex_useAnchoringBounds(URegularExpression   *regexp,
+                          UBool                 b,
+                          UErrorCode           *status);
+
+/**
+  * Return TRUE if the most recent matching operation touched the
+  *  end of the text being processed.  In this case, additional input text could
+  *  change the results of that match.
+  *
+  *  @return  TRUE if the most recent match hit the end of input
+  *  @draft   ICU 4.0
+  */
+U_DRAFT UBool U_EXPORT2
+uregex_hitEnd(const  URegularExpression   *regexp,
+                     UErrorCode           *status);
+
+/**
+  * Return TRUE the most recent match succeeded and additional input could cause
+  * it to fail. If this function returns false and a match was found, then more input
+  * might change the match but the match won't be lost. If a match was not found,
+  * then requireEnd has no meaning.
+  *
+  * @return TRUE if more input could cause the most recent match to no longer match.
+  * @draft  ICU 4.0
+  */
+U_DRAFT UBool U_EXPORT2   
+uregex_requireEnd(const  URegularExpression   *regexp,
+                         UErrorCode           *status);
+
+
+
+
 
 /**
   *    Replaces every substring of the input that matches the pattern
diff --git a/i18n/uregex.cpp b/i18n/uregex.cpp
index 7207b6e..f869d2e 100644
--- a/i18n/uregex.cpp
+++ b/i18n/uregex.cpp
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-*   Copyright (C) 2004-2006, International Business Machines
+*   Copyright (C) 2004-2007, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *******************************************************************************
 *   file name:  regex.cpp
@@ -481,6 +481,145 @@
 
 //------------------------------------------------------------------------------
 //
+//    uregex_setRegion
+//
+//------------------------------------------------------------------------------
+U_CAPI void U_EXPORT2 
+uregex_setRegion(URegularExpression   *regexp,
+                 int32_t               regionStart,
+                 int32_t               regionLimit,
+                 UErrorCode           *status)  {
+    if (validateRE(regexp, status) == FALSE) {
+        return;
+    }
+    regexp->fMatcher->region(regionStart, regionLimit, *status);
+}
+
+
+//------------------------------------------------------------------------------
+//
+//    uregex_regionStart
+//
+//------------------------------------------------------------------------------
+U_CAPI int32_t U_EXPORT2 
+uregex_regionStart(const  URegularExpression   *regexp,
+                          UErrorCode           *status)  {
+    if (validateRE(regexp, status) == FALSE) {
+        return 0;
+    }
+    return regexp->fMatcher->regionStart();
+}
+
+
+//------------------------------------------------------------------------------
+//
+//    uregex_regionEnd
+//
+//------------------------------------------------------------------------------
+U_CAPI int32_t U_EXPORT2 
+uregex_regionEnd(const  URegularExpression   *regexp,
+                        UErrorCode           *status)  {
+    if (validateRE(regexp, status) == FALSE) {
+        return 0;
+    }
+    return regexp->fMatcher->regionEnd();
+}
+
+
+//------------------------------------------------------------------------------
+//
+//    uregex_hasTransparentBounds
+//
+//------------------------------------------------------------------------------
+U_CAPI UBool U_EXPORT2 
+uregex_hasTransparentBounds(const  URegularExpression   *regexp,
+                                   UErrorCode           *status)  {
+    if (validateRE(regexp, status) == FALSE) {
+        return FALSE;
+    }
+    return regexp->fMatcher->hasTransparentBounds();
+}
+
+
+//------------------------------------------------------------------------------
+//
+//    uregex_useTransparentBounds
+//
+//------------------------------------------------------------------------------
+U_CAPI void U_EXPORT2 
+uregex_useTransparentBounds(URegularExpression    *regexp,
+             UBool                 b,
+             UErrorCode            *status)  {
+    if (validateRE(regexp, status) == FALSE) {
+        return;
+    }
+    regexp->fMatcher->useTransparentBounds(b);
+}
+
+
+//------------------------------------------------------------------------------
+//
+//    uregex_hasAnchoringBounds
+//
+//------------------------------------------------------------------------------
+U_CAPI UBool U_EXPORT2 
+uregex_hasAnchoringBounds(const  URegularExpression   *regexp,
+                                   UErrorCode           *status)  {
+    if (validateRE(regexp, status) == FALSE) {
+        return FALSE;
+    }
+    return regexp->fMatcher->hasAnchoringBounds();
+}
+
+
+//------------------------------------------------------------------------------
+//
+//    uregex_useAnchoringBounds
+//
+//------------------------------------------------------------------------------
+U_CAPI void U_EXPORT2 
+uregex_useAnchoringBounds(URegularExpression    *regexp,
+             UBool                 b,
+             UErrorCode            *status)  {
+    if (validateRE(regexp, status) == FALSE) {
+        return;
+    }
+    regexp->fMatcher->useAnchoringBounds(b);
+}
+
+
+//------------------------------------------------------------------------------
+//
+//    uregex_hitEnd
+//
+//------------------------------------------------------------------------------
+U_CAPI UBool U_EXPORT2 
+uregex_hitEnd(const  URegularExpression   *regexp,
+                     UErrorCode           *status)  {
+    if (validateRE(regexp, status) == FALSE) {
+        return FALSE;
+    }
+    return regexp->fMatcher->hitEnd();
+}
+
+
+//------------------------------------------------------------------------------
+//
+//    uregex_requireEnd
+//
+//------------------------------------------------------------------------------
+U_CAPI UBool U_EXPORT2 
+uregex_requireEnd(const  URegularExpression   *regexp,
+                         UErrorCode           *status)  {
+    if (validateRE(regexp, status) == FALSE) {
+        return FALSE;
+    }
+    return regexp->fMatcher->requireEnd();
+}
+
+
+//------------------------------------------------------------------------------
+//
 //    uregex_replaceAll
 //
 //------------------------------------------------------------------------------
diff --git a/test/intltest/regextst.cpp b/test/intltest/regextst.cpp
index 2218e94..e984c2a 100644
--- a/test/intltest/regextst.cpp
+++ b/test/intltest/regextst.cpp
@@ -175,228 +175,6 @@
 
 
 
-//---------------------------------------------------------------------------
-//
-//    regex_find(pattern, flags, inputString, lineNumber)
-//
-//         function to simplify writing regex tests.
-//
-//          The input text is unescaped.  The pattern is not.
-//          The input text is marked with the expected match positions
-//              <0>text  <1> more text </1>   </0>
-//          The <n> </n> tags are removed before trying the match.
-//          The tags mark the start and end of the match and of any capture groups.
-//
-//
-//---------------------------------------------------------------------------
-
-
-//  Set a value into a UVector at position specified by a decimal number in
-//   a UnicodeString.   This is a utility function needed by the actual test function,
-//   which follows.
-static void set(UVector &vec, int32_t val, UnicodeString index) {
-    UErrorCode  status=U_ZERO_ERROR;
-    int32_t  idx = 0;
-    for (int32_t i=0; i<index.length(); i++) {
-        int32_t d=u_charDigitValue(index.charAt(i));
-        if (d<0) {return;}
-        idx = idx*10 + d;
-    }
-    while (vec.size()<idx+1) {vec.addElement(-1, status);}
-    vec.setElementAt(val, idx);
-}
-
-void RegexTest::regex_find(const UnicodeString &pattern,
-                           const UnicodeString &flags,
-                           const UnicodeString &inputString,
-                           int32_t line) {
-    UnicodeString       unEscapedInput;
-    UnicodeString       deTaggedInput;
-
-    UErrorCode          status         = U_ZERO_ERROR;
-    UParseError         pe;
-    RegexPattern        *parsePat      = NULL;
-    RegexMatcher        *parseMatcher  = NULL;
-    RegexPattern        *callerPattern = NULL;
-    RegexMatcher        *matcher       = NULL;
-    UVector             groupStarts(status);
-    UVector             groupEnds(status);
-    UBool               isMatch        = FALSE;
-    UBool               failed         = FALSE;
-    int32_t                 numFinds;
-    int32_t                 i;
-
-    //
-    //  Compile the caller's pattern
-    //
-    uint32_t bflags = 0;
-    if (flags.indexOf((UChar)0x69) >= 0)  { // 'i' flag
-        bflags |= UREGEX_CASE_INSENSITIVE;
-    }
-    if (flags.indexOf((UChar)0x78) >= 0)  { // 'x' flag
-        bflags |= UREGEX_COMMENTS;
-    }
-    if (flags.indexOf((UChar)0x73) >= 0)  { // 's' flag
-        bflags |= UREGEX_DOTALL;
-    }
-    if (flags.indexOf((UChar)0x6d) >= 0)  { // 'm' flag
-        bflags |= UREGEX_MULTILINE;
-    }
-    
-    if (flags.indexOf((UChar)0x65) >= 0) { // 'e' flag
-        bflags |= UREGEX_ERROR_ON_UNKNOWN_ESCAPES;
-    }
-
-
-    callerPattern = RegexPattern::compile(pattern, bflags, pe, status);
-    if (status != U_ZERO_ERROR) {
-        #if UCONFIG_NO_BREAK_ITERATION==1
-        // 'v' test flag means that the test pattern should not compile if ICU was configured
-        //     to not include break iteration.  RBBI is needed for Unicode word boundaries.
-        if (flags.indexOf((UChar)0x76) >= 0 /*'v'*/ && status == U_UNSUPPORTED_ERROR) {
-            goto cleanupAndReturn;
-        }
-        #endif
-        if (flags.indexOf((UChar)0x45) >= 0) {  //  flags contain 'E'
-            // Expected pattern compilation error.
-            if (flags.indexOf((UChar)0x64) >= 0) {   // flags contain 'd'
-                logln("Pattern Compile returns \"%s\"", u_errorName(status));
-            }
-            goto cleanupAndReturn;
-        } else {
-            // Unexpected pattern compilation error.
-            errln("Line %d: error %s compiling pattern.", line, u_errorName(status));
-            goto cleanupAndReturn;
-        }
-    }
-
-    if (flags.indexOf((UChar)0x64) >= 0) {  // 'd' flag
-        RegexPatternDump(callerPattern);
-    }
-
-    if (flags.indexOf((UChar)0x45) >= 0) {  // 'E' flag
-        errln("Expected, but did not get, a pattern compilation error.");
-        goto cleanupAndReturn;
-    }
-
-
-    //
-    // Number of times find() should be called on the test string, default to 1
-    //
-    numFinds = 1;
-    for (i=2; i<=9; i++) {
-        if (flags.indexOf((UChar)(0x30 + i)) >= 0) {   // digit flag
-            if (numFinds != 1) {
-                errln("Line %d: more than one digit flag.  Scanning %d.", line, i);
-                goto cleanupAndReturn;
-            }
-            numFinds = i;
-        }
-    }
-
-    //
-    //  Find the tags in the input data, remove them, and record the group boundary
-    //    positions.
-    //
-    parsePat = RegexPattern::compile("<(/?)([0-9]+)>", 0, pe, status);
-    REGEX_CHECK_STATUS_L(line);
-
-    unEscapedInput = inputString.unescape();
-    parseMatcher = parsePat->matcher(unEscapedInput, status);
-    REGEX_CHECK_STATUS_L(line);
-    while(parseMatcher->find()) {
-        parseMatcher->appendReplacement(deTaggedInput, "", status);
-        REGEX_CHECK_STATUS;
-        UnicodeString groupNum = parseMatcher->group(2, status);
-        if (parseMatcher->group(1, status) == "/") {
-            // close tag
-            set(groupEnds, deTaggedInput.length(), groupNum);
-        } else {
-            set(groupStarts, deTaggedInput.length(), groupNum);
-        }
-    }
-    parseMatcher->appendTail(deTaggedInput);
-    REGEX_ASSERT_L(groupStarts.size() == groupEnds.size(), line);
-
-
-    //
-    // Do a find on the de-tagged input using the caller's pattern
-    //
-    matcher = callerPattern->matcher(deTaggedInput, status);
-    REGEX_CHECK_STATUS_L(line);
-    if (flags.indexOf((UChar)'t') >= 0) {
-        matcher->setTrace(TRUE);
-    }
-
-    for (i=0; i<numFinds; i++) {
-        isMatch = matcher->find();
-    }
-    matcher->setTrace(FALSE);
-
-    //
-    // Match up the groups from the find() with the groups from the tags
-    //
-
-    // number of tags should match number of groups from find operation.
-    // matcher->groupCount does not include group 0, the entire match, hence the +1.
-    //   G option in test means that capture group data is not available in the
-    //     expected results, so the check needs to be suppressed.
-    if (isMatch == FALSE && groupStarts.size() != 0) {
-        errln("Error at line %d:  Match expected, but none found.\n", line);
-        failed = TRUE;
-        goto cleanupAndReturn;
-    }
-
-    if (flags.indexOf((UChar)0x47 /*G*/) >= 0) {
-        // Only check for match / no match.  Don't check capture groups.
-        if (isMatch && groupStarts.size() == 0) {
-            errln("Error at line %d:  No match expected, but one found.\n", line);
-            failed = TRUE;
-        }
-        goto cleanupAndReturn;
-    }
-
-    for (i=0; i<=matcher->groupCount(); i++) {
-        int32_t  expectedStart = (i >= groupStarts.size()? -1 : groupStarts.elementAti(i));
-        if (matcher->start(i, status) != expectedStart) {
-            errln("Error at line %d: incorrect start position for group %d.  Expected %d, got %d",
-                line, i, expectedStart, matcher->start(i, status));
-            failed = TRUE;
-            goto cleanupAndReturn;  // Good chance of subsequent bogus errors.  Stop now.
-        }
-        int32_t  expectedEnd = (i >= groupEnds.size()? -1 : groupEnds.elementAti(i));
-        if (matcher->end(i, status) != expectedEnd) {
-            errln("Error at line %d: incorrect end position for group %d.  Expected %d, got %d",
-                line, i, expectedEnd, matcher->end(i, status));
-            failed = TRUE;
-            // Error on end position;  keep going; real error is probably yet to come as group
-            //   end positions work from end of the input data towards the front.
-        }
-    }
-    if ( matcher->groupCount()+1 < groupStarts.size()) {
-        errln("Error at line %d: Expected %d capture groups, found %d.",
-            line, groupStarts.size()-1, matcher->groupCount());
-        failed = TRUE;
-        }
-
-cleanupAndReturn:
-    if (failed) {
-        errln((UnicodeString)"\""+pattern+(UnicodeString)"\"  "
-            +flags+(UnicodeString)"  \""+inputString+(UnicodeString)"\"");
-        // callerPattern->dump();
-    }
-    delete parseMatcher;
-    delete parsePat;
-    delete matcher;
-    delete callerPattern;
-}
-
-
-
-
-
-
-
 
 //---------------------------------------------------------------------------
 //
@@ -957,6 +735,87 @@
         delete m;
         delete p;
     }
+    
+    //
+    // Regions
+    //
+    {
+        UErrorCode status = U_ZERO_ERROR;
+        UnicodeString testString("This is test data");
+        RegexMatcher m(".*", testString,  0, status);
+        REGEX_CHECK_STATUS;
+        REGEX_ASSERT(m.regionStart() == 0);
+        REGEX_ASSERT(m.regionEnd() == testString.length());
+        REGEX_ASSERT(m.hasTransparentBounds() == FALSE);
+        REGEX_ASSERT(m.hasAnchoringBounds() == TRUE);
+        
+        m.region(2,4, status);
+        REGEX_CHECK_STATUS;
+        REGEX_ASSERT(m.matches(status));
+        REGEX_ASSERT(m.start(status)==2);
+        REGEX_ASSERT(m.end(status)==4);
+        REGEX_CHECK_STATUS;
+        
+        m.reset();
+        REGEX_ASSERT(m.regionStart() == 0);
+        REGEX_ASSERT(m.regionEnd() == testString.length());
+        
+        UnicodeString shorterString("short");
+        m.reset(shorterString);
+        REGEX_ASSERT(m.regionStart() == 0);
+        REGEX_ASSERT(m.regionEnd() == shorterString.length());
+        
+        REGEX_ASSERT(m.hasAnchoringBounds() == TRUE);
+        REGEX_ASSERT(&m == &m.useAnchoringBounds(FALSE));
+        REGEX_ASSERT(m.hasAnchoringBounds() == FALSE);
+        REGEX_ASSERT(&m == &m.reset());
+        REGEX_ASSERT(m.hasAnchoringBounds() == FALSE);
+        
+        REGEX_ASSERT(&m == &m.useAnchoringBounds(TRUE));
+        REGEX_ASSERT(m.hasAnchoringBounds() == TRUE);
+        REGEX_ASSERT(&m == &m.reset());
+        REGEX_ASSERT(m.hasAnchoringBounds() == TRUE);
+    
+        REGEX_ASSERT(m.hasTransparentBounds() == FALSE);
+        REGEX_ASSERT(&m == &m.useTransparentBounds(TRUE));
+        REGEX_ASSERT(m.hasTransparentBounds() == TRUE);
+        REGEX_ASSERT(&m == &m.reset());
+        REGEX_ASSERT(m.hasTransparentBounds() == TRUE);
+
+        REGEX_ASSERT(&m == &m.useTransparentBounds(FALSE));
+        REGEX_ASSERT(m.hasTransparentBounds() == FALSE);
+        REGEX_ASSERT(&m == &m.reset());
+        REGEX_ASSERT(m.hasTransparentBounds() == FALSE);
+        
+    }
+    
+    //
+    // hitEnd() and requireEnd()
+    //
+    {
+        UErrorCode status = U_ZERO_ERROR;
+        UnicodeString testString("aabb");
+        RegexMatcher m1(".*", testString,  0, status);
+        REGEX_ASSERT(m1.lookingAt(status) == TRUE);
+        REGEX_ASSERT(m1.hitEnd() == TRUE);
+        REGEX_ASSERT(m1.requireEnd() == FALSE);
+        REGEX_CHECK_STATUS;
+        
+        status = U_ZERO_ERROR;
+        RegexMatcher m2("a*", testString, 0, status);
+        REGEX_ASSERT(m2.lookingAt(status) == TRUE);
+        REGEX_ASSERT(m2.hitEnd() == FALSE);
+        REGEX_ASSERT(m2.requireEnd() == FALSE);
+        REGEX_CHECK_STATUS;
+
+        status = U_ZERO_ERROR;
+        RegexMatcher m3(".*$", testString, 0, status);
+        REGEX_ASSERT(m3.lookingAt(status) == TRUE);
+        REGEX_ASSERT(m3.hitEnd() == TRUE);
+        REGEX_ASSERT(m3.requireEnd() == TRUE);
+        REGEX_CHECK_STATUS;
+    }
+
 
     //
     // Compilation error on reset with UChar *
@@ -1501,7 +1360,7 @@
 
     RegexMatcher    quotedStuffMat("\\s*([\\'\\\"/])(.*?)\\1", 0, status);
     RegexMatcher    commentMat    ("\\s*(#.*)?$", 0, status);
-    RegexMatcher    flagsMat      ("\\s*([ixsmdteEGv2-9]*)([:letter:]*)", 0, status);
+    RegexMatcher    flagsMat      ("\\s*([ixsmdteEGMvatyYzZ2-9]*)([:letter:]*)", 0, status);
 
     RegexMatcher    lineMat("(.*?)\\r?\\n", testString, 0, status);
     UnicodeString   testPattern;   // The pattern for test from the test file.
@@ -1602,6 +1461,284 @@
 
 //---------------------------------------------------------------------------
 //
+//    regex_find(pattern, flags, inputString, lineNumber)
+//
+//         Function to run a single test from the Extended (data driven) tests.
+//         See file test/testdata/regextst.txt for a description of the
+//         pattern and inputString fields, and the allowed flags.
+//         lineNumber is the source line in regextst.txt of the test.
+//
+//---------------------------------------------------------------------------
+
+
+//  Set a value into a UVector at position specified by a decimal number in
+//   a UnicodeString.   This is a utility function needed by the actual test function,
+//   which follows.
+static void set(UVector &vec, int32_t val, UnicodeString index) {
+    UErrorCode  status=U_ZERO_ERROR;
+    int32_t  idx = 0;
+    for (int32_t i=0; i<index.length(); i++) {
+        int32_t d=u_charDigitValue(index.charAt(i));
+        if (d<0) {return;}
+        idx = idx*10 + d;
+    }
+    while (vec.size()<idx+1) {vec.addElement(-1, status);}
+    vec.setElementAt(val, idx);
+}
+
+void RegexTest::regex_find(const UnicodeString &pattern,
+                           const UnicodeString &flags,
+                           const UnicodeString &inputString,
+                           int32_t line) {
+    UnicodeString       unEscapedInput;
+    UnicodeString       deTaggedInput;
+
+    UErrorCode          status         = U_ZERO_ERROR;
+    UParseError         pe;
+    RegexPattern        *parsePat      = NULL;
+    RegexMatcher        *parseMatcher  = NULL;
+    RegexPattern        *callerPattern = NULL;
+    RegexMatcher        *matcher       = NULL;
+    UVector             groupStarts(status);
+    UVector             groupEnds(status);
+    UBool               isMatch        = FALSE;
+    UBool               failed         = FALSE;
+    int32_t             numFinds;
+    int32_t             i;
+    UBool               useMatchesFunc   = FALSE;
+    int32_t             regionStart    = -1;
+    int32_t             regionEnd      = -1;
+
+    //
+    //  Compile the caller's pattern
+    //
+    uint32_t bflags = 0;
+    if (flags.indexOf((UChar)0x69) >= 0)  { // 'i' flag
+        bflags |= UREGEX_CASE_INSENSITIVE;
+    }
+    if (flags.indexOf((UChar)0x78) >= 0)  { // 'x' flag
+        bflags |= UREGEX_COMMENTS;
+    }
+    if (flags.indexOf((UChar)0x73) >= 0)  { // 's' flag
+        bflags |= UREGEX_DOTALL;
+    }
+    if (flags.indexOf((UChar)0x6d) >= 0)  { // 'm' flag
+        bflags |= UREGEX_MULTILINE;
+    }
+    
+    if (flags.indexOf((UChar)0x65) >= 0) { // 'e' flag
+        bflags |= UREGEX_ERROR_ON_UNKNOWN_ESCAPES;
+    }
+
+
+    callerPattern = RegexPattern::compile(pattern, bflags, pe, status);
+    if (status != U_ZERO_ERROR) {
+        #if UCONFIG_NO_BREAK_ITERATION==1
+        // 'v' test flag means that the test pattern should not compile if ICU was configured
+        //     to not include break iteration.  RBBI is needed for Unicode word boundaries.
+        if (flags.indexOf((UChar)0x76) >= 0 /*'v'*/ && status == U_UNSUPPORTED_ERROR) {
+            goto cleanupAndReturn;
+        }
+        #endif
+        if (flags.indexOf((UChar)0x45) >= 0) {  //  flags contain 'E'
+            // Expected pattern compilation error.
+            if (flags.indexOf((UChar)0x64) >= 0) {   // flags contain 'd'
+                logln("Pattern Compile returns \"%s\"", u_errorName(status));
+            }
+            goto cleanupAndReturn;
+        } else {
+            // Unexpected pattern compilation error.
+            errln("Line %d: error %s compiling pattern.", line, u_errorName(status));
+            goto cleanupAndReturn;
+        }
+    }
+
+    if (flags.indexOf((UChar)0x64) >= 0) {  // 'd' flag
+        RegexPatternDump(callerPattern);
+    }
+
+    if (flags.indexOf((UChar)0x45) >= 0) {  // 'E' flag
+        errln("Expected, but did not get, a pattern compilation error.");
+        goto cleanupAndReturn;
+    }
+
+
+    //
+    // Number of times find() should be called on the test string, default to 1
+    //
+    numFinds = 1;
+    for (i=2; i<=9; i++) {
+        if (flags.indexOf((UChar)(0x30 + i)) >= 0) {   // digit flag
+            if (numFinds != 1) {
+                errln("Line %d: more than one digit flag.  Scanning %d.", line, i);
+                goto cleanupAndReturn;
+            }
+            numFinds = i;
+        }
+    }
+    
+    // 'M' flag.  Use matches() instead of find()
+    if (flags.indexOf((UChar)0x4d) >= 0) {
+        useMatchesFunc = TRUE;
+    }
+
+    //
+    //  Find the tags in the input data, remove them, and record the group boundary
+    //    positions.
+    //
+    parsePat = RegexPattern::compile("<(/?)(r|[0-9]+)>", 0, pe, status);
+    REGEX_CHECK_STATUS_L(line);
+
+    unEscapedInput = inputString.unescape();
+    parseMatcher = parsePat->matcher(unEscapedInput, status);
+    REGEX_CHECK_STATUS_L(line);
+    while(parseMatcher->find()) {
+        parseMatcher->appendReplacement(deTaggedInput, "", status);
+        REGEX_CHECK_STATUS;
+        UnicodeString groupNum = parseMatcher->group(2, status);
+        if (groupNum == "r") {
+            // <r> or </r>, a region specification within the string
+            if (parseMatcher->group(1, status) == "/") {
+                regionEnd = deTaggedInput.length();
+            } else {
+                regionStart = deTaggedInput.length();
+            }
+        } else {
+            // <digits> or </digits>, a group match boundary tag.
+            if (parseMatcher->group(1, status) == "/") {
+                set(groupEnds, deTaggedInput.length(), groupNum);
+            } else {
+                set(groupStarts, deTaggedInput.length(), groupNum);
+            }
+        }
+    }
+    parseMatcher->appendTail(deTaggedInput);
+    REGEX_ASSERT_L(groupStarts.size() == groupEnds.size(), line);
+    if ((regionStart>=0 || regionEnd>=0) && (regionStart<0 || regionStart>regionEnd)) {
+      errln("mismatched <r> tags");
+      failed = TRUE;
+      goto cleanupAndReturn;
+    }
+
+
+    //
+    //  Configure the matcher according to the flags specified with this test.
+    //
+    matcher = callerPattern->matcher(deTaggedInput, status);
+    REGEX_CHECK_STATUS_L(line);
+    if (flags.indexOf((UChar)0x74) >= 0) {   //  't' trace flag
+        matcher->setTrace(TRUE);
+    }
+    if (regionStart>=0) {
+       matcher->region(regionStart, regionEnd, status);
+       REGEX_CHECK_STATUS_L(line);
+    }
+    if (flags.indexOf((UChar)0x61) >= 0) {   //  'a' anchoring bounds flag
+        matcher->useAnchoringBounds(FALSE);
+    }
+    if (flags.indexOf((UChar)0x62) >= 0) {   //  'b' transparent bounds flag
+        matcher->useTransparentBounds(TRUE);
+    }
+    
+    
+
+    //
+    // Do a find on the de-tagged input using the caller's pattern
+    //
+    for (i=0; i<numFinds; i++) {
+        if (useMatchesFunc) {
+            isMatch = matcher->matches(status);
+        } else {
+            isMatch = matcher->find();
+        }
+    }
+    matcher->setTrace(FALSE);
+
+    //
+    // Match up the groups from the find() with the groups from the tags
+    //
+
+    // number of tags should match number of groups from find operation.
+    // matcher->groupCount does not include group 0, the entire match, hence the +1.
+    //   G option in test means that capture group data is not available in the
+    //     expected results, so the check needs to be suppressed.
+    if (isMatch == FALSE && groupStarts.size() != 0) {
+        errln("Error at line %d:  Match expected, but none found.\n", line);
+        failed = TRUE;
+        goto cleanupAndReturn;
+    }
+
+    if (flags.indexOf((UChar)0x47 /*G*/) >= 0) {
+        // Only check for match / no match.  Don't check capture groups.
+        if (isMatch && groupStarts.size() == 0) {
+            errln("Error at line %d:  No match expected, but one found.\n", line);
+            failed = TRUE;
+        }
+        goto cleanupAndReturn;
+    }
+
+    for (i=0; i<=matcher->groupCount(); i++) {
+        int32_t  expectedStart = (i >= groupStarts.size()? -1 : groupStarts.elementAti(i));
+        if (matcher->start(i, status) != expectedStart) {
+            errln("Error at line %d: incorrect start position for group %d.  Expected %d, got %d",
+                line, i, expectedStart, matcher->start(i, status));
+            failed = TRUE;
+            goto cleanupAndReturn;  // Good chance of subsequent bogus errors.  Stop now.
+        }
+        int32_t  expectedEnd = (i >= groupEnds.size()? -1 : groupEnds.elementAti(i));
+        if (matcher->end(i, status) != expectedEnd) {
+            errln("Error at line %d: incorrect end position for group %d.  Expected %d, got %d",
+                line, i, expectedEnd, matcher->end(i, status));
+            failed = TRUE;
+            // Error on end position;  keep going; real error is probably yet to come as group
+            //   end positions work from end of the input data towards the front.
+        }
+    }
+    if ( matcher->groupCount()+1 < groupStarts.size()) {
+        errln("Error at line %d: Expected %d capture groups, found %d.",
+            line, groupStarts.size()-1, matcher->groupCount());
+        failed = TRUE;
+        }
+
+    if ((flags.indexOf((UChar)0x59) >= 0) &&   //  'Y' flag:  RequireEnd() == false
+        matcher->requireEnd() == TRUE) {
+        errln("requireEnd() returned TRUE.  Expected FALSE");
+        failed = TRUE;
+    }
+    if ((flags.indexOf((UChar)0x79) >= 0) &&   //  'y' flag:  RequireEnd() == true
+        matcher->requireEnd() == FALSE) {
+        errln("requireEnd() returned FALSE.  Expected TRUE");
+        failed = TRUE;
+    }
+    if ((flags.indexOf((UChar)0x5A) >= 0) &&   //  'Z' flag:  hitEnd() == false
+        matcher->hitEnd() == TRUE) {
+        errln("hitEnd() returned TRUE.  Expected FALSE");
+        failed = TRUE;
+    }
+    if ((flags.indexOf((UChar)0x7A) >= 0) &&   //  'z' flag:  hitEnd() == true
+        matcher->hitEnd() == FALSE) {
+        errln("hitEnd() returned FALSE.  Expected TRUE");
+        failed = TRUE;
+    }
+
+
+cleanupAndReturn:
+    if (failed) {
+        errln((UnicodeString)"\""+pattern+(UnicodeString)"\"  "
+            +flags+(UnicodeString)"  \""+inputString+(UnicodeString)"\"");
+        // callerPattern->dump();
+    }
+    delete parseMatcher;
+    delete parsePat;
+    delete matcher;
+    delete callerPattern;
+}
+
+
+
+
+//---------------------------------------------------------------------------
+//
 //      Errors     Check for error handling in patterns.
 //
 //---------------------------------------------------------------------------
diff --git a/test/testdata/regextst.txt b/test/testdata/regextst.txt
index 2aa6db6..3a51386 100644
--- a/test/testdata/regextst.txt
+++ b/test/testdata/regextst.txt
@@ -13,11 +13,15 @@
 #               <tagged string> = text, with the start and end of each
 #                                 capture group tagged with <n>...</n>.  The overall match,
 #                                 if any, is group 0, as in <0>matched text</0>
+#
+#                                  A region can be specified with <r>...</r> tags.
+#
 #               <flags>         = any combination of
 #                                   i      case insensitive match
 #                                   x      free spacing and comments
 #                                   s      dot-matches-all mode
-#                                   m      multi-line mode.  $ and ^ match at embedded new-lines
+#                                   m      multi-line mode.  
+#                                            ($ and ^ match at embedded new-lines)
 #                                   v      If icu configured without break iteration, this
 #                                          regex test pattern should not compile.
 #                                   e      set the UREGEX_ERROR_ON_UNKNOWN_ESCAPES flag
@@ -28,6 +32,16 @@
 #                                          for the last find() in the sequence.
 #                                   G      Only check match / no match.  Do not check capture groups.
 #                                   E      Pattern compilation error expected
+#                                   M      Use matches() rather than find().
+#
+#                                   a      Use non-Anchoring Bounds.
+#                                   b      Use Transparent Bounds.
+#                                          The a and t options only make a difference if
+#                                          a <r>region</r> has been specified in the string.
+#                                   z|Z    hitEnd was expected(z) or not expected (Z).
+#                                          With neither, hitEnd is not checked.
+#                                   y|Y    Require End expeted(y) or not expected (Y).
+#
 #                                 White space must be present between the flags and the match string.
 #
 
@@ -429,6 +443,8 @@
 #
 #  Octal Escaping.   This conforms to Java conventions, not Perl.
 "\0101\0\03\073\0154\01442"      "<0>A\u0000\u0003\u003b\u006c\u0064\u0032</0>"
+"\0776"                          "<0>\u003f\u0036</0>"  # overflow, the 6 is literal.
+"\0376xyz"                       "<0>\u00fexyz</0>"
 
 #
 #  \u Surrogate Pairs
@@ -541,6 +557,15 @@
 ".{6}"                         s  "<0>123\u000a\u000dX</0>Y"
 
 
+#
+# Ranges
+#
+".*"                              "abc<r><0>def</0></r>ghi"
+"a"                               "aaa<r><0>a</0>aa</r>aaa"
+"a"                           2   "aaa<r>a<0>a</0>a</r>aaa"
+"a"                           3   "aaa<r>aa<0>a</0></r>aaa"
+"a"                           4   "aaa<r>aaa</r>aaa"
+"a"                               "aaa<r><0>a</0>aa</r>aaa"
 
 #
 # [set] parsing, systematically run through all of the parser states.
@@ -656,6 +681,8 @@
 "[:^InBasic Latin:]+"              "<0>ΓΔΕΖΗΘ</0>hello, world.ニヌネノハバパ"
 "\p{InBasicLatin}+"                "ΓΔΕΖΗΘ<0>hello, world.</0>ニヌネノハバパ"
 "\P{InBasicLatin}+"                "<0>ΓΔΕΖΗΘ</0>hello, world.ニヌネノハバパ"
+"\p{InGreek}+"                     "<0>ΓΔΕΖΗΘ</0>hello, world.ニヌネノハバパ"
+
 
 "\p{javaDefined}+"                 "\uffff<0>abcd</0>\U00045678"
 "\p{javaDigit}+"                   "abc<0>1234</0>xyz"
@@ -675,6 +702,8 @@
 "\p{javaUpperCase}+"               "abc<0>ABC</0>123"
 "\p{javaValidCodePoint}+"          "<0>\u0000abc\ud800 unpaired \udfff |\U0010ffff</0>"
 "\p{javaWhitespace}+"              "abc\u00a0\u2007\u202f<0> \u0009\u001c\u001f\u2028</0>42"
+"\p{all}+"                         "<0>123\u0000\U0010ffff</0>"
+"\P{all}+"                         "123\u0000\U0010ffff"
 
 #
 #  Errors on unrecognized ASCII letter escape sequences.
@@ -799,6 +828,17 @@
 "[a-z&&[cde]]+"                   "ab<0>cde</0>fg"
 
 #
+# bug 6019  matches() needs to backtrack and check for a longer match if the
+#                     first match(es) found don't match the entire input.
+#
+"a?|b"                            "<0></0>b"
+"a?|b"                         M  "<0>b</0>"
+"a?|.*?u|stuff|d"              M  "<0>stuff</0>"
+"a?|.*?(u)|stuff|d"            M  "<0>stuff<1>u</1></0>"
+"a+?"                             "<0>a</0>aaaaaaaaaaaa"
+"a+?"                          M  "<0>aaaaaaaaaaaaa</0>"
+
+#
 #  Random debugging, Temporary
 #
 #"^(?:a?b?)*$"	                  "a--"