ICU-13851 case mapping data: when fetching delta make sure to read from start of exceptional values

X-SVN-Rev: 41550
diff --git a/icu4c/source/common/ucase.cpp b/icu4c/source/common/ucase.cpp
index cbd5a6e..8414c52 100644
--- a/icu4c/source/common/ucase.cpp
+++ b/icu4c/source/common/ucase.cpp
@@ -270,6 +270,7 @@
             }
         }
         if(HAS_SLOT(excWord, UCASE_EXC_DELTA)) {
+            pe=pe0;
             int32_t delta;
             GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta);
             sa->add(sa->set, (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta);
@@ -1167,7 +1168,7 @@
 
         if(HAS_SLOT(excWord, UCASE_EXC_DELTA) && UCASE_IS_UPPER_OR_TITLE(props)) {
             int32_t delta;
-            GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta);
+            GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe2, delta);
             return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
         }
         if(HAS_SLOT(excWord, UCASE_EXC_LOWER)) {
@@ -1261,7 +1262,7 @@
 
         if(HAS_SLOT(excWord, UCASE_EXC_DELTA) && UCASE_GET_TYPE(props)==UCASE_LOWER) {
             int32_t delta;
-            GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta);
+            GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe2, delta);
             return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
         }
         if(!upperNotTitle && HAS_SLOT(excWord, UCASE_EXC_TITLE)) {
@@ -1469,7 +1470,7 @@
         }
         if(HAS_SLOT(excWord, UCASE_EXC_DELTA) && UCASE_IS_UPPER_OR_TITLE(props)) {
             int32_t delta;
-            GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta);
+            GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe2, delta);
             return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
         }
         if(HAS_SLOT(excWord, UCASE_EXC_FOLD)) {
diff --git a/icu4c/source/test/intltest/strcase.cpp b/icu4c/source/test/intltest/strcase.cpp
index fe983da..3fb0584 100644
--- a/icu4c/source/test/intltest/strcase.cpp
+++ b/icu4c/source/test/intltest/strcase.cpp
@@ -68,6 +68,7 @@
     void TestBug13127();
     void TestInPlaceTitle();
     void TestCaseMapEditsIteratorDocs();
+    void TestCaseMapGreekExtended();
 
 private:
     void assertGreekUpper(const char16_t *s, const char16_t *expected);
@@ -113,6 +114,7 @@
     TESTCASE_AUTO(TestInPlaceTitle);
 #endif
     TESTCASE_AUTO(TestCaseMapEditsIteratorDocs);
+    TESTCASE_AUTO(TestCaseMapGreekExtended);
     TESTCASE_AUTO_END;
 }
 
@@ -1685,4 +1687,17 @@
     }
 }
 
+void StringCaseTest::TestCaseMapGreekExtended() {
+    // Ticket 13851
+    UnicodeString s(u"\u1F80\u1F88\u1FFC");
+    UnicodeString result(s);
+    result.toLower(Locale::getRoot());
+    assertEquals(u"lower", u"\u1F80\u1F80\u1FF3", result);
+#if !UCONFIG_NO_BREAK_ITERATION
+    result = s;
+    result.toTitle(nullptr, Locale::getRoot());
+    assertEquals(u"title", u"\u1F88\u1F80\u1FF3", result);
+#endif
+}
+
 //#endif
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/UCaseProps.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/UCaseProps.java
index ae267bb..a925507 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/UCaseProps.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/UCaseProps.java
@@ -318,6 +318,7 @@
                 }
             }
             if(hasSlot(excWord, EXC_DELTA)) {
+                excOffset=excOffset0;
                 int delta=getSlotValue(excWord, EXC_DELTA, excOffset);
                 set.add((excWord&EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta);
             }
@@ -1131,7 +1132,7 @@
             }
 
             if(hasSlot(excWord, EXC_DELTA) && isUpperOrTitleFromProps(props)) {
-                int delta=getSlotValue(excWord, EXC_DELTA, excOffset);
+                int delta=getSlotValue(excWord, EXC_DELTA, excOffset2);
                 return (excWord&EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
             }
             if(hasSlot(excWord, EXC_LOWER)) {
@@ -1227,7 +1228,7 @@
             }
 
             if(hasSlot(excWord, EXC_DELTA) && getTypeFromProps(props)==LOWER) {
-                int delta=getSlotValue(excWord, EXC_DELTA, excOffset);
+                int delta=getSlotValue(excWord, EXC_DELTA, excOffset2);
                 return (excWord&EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
             }
             if(!upperNotTitle && hasSlot(excWord, EXC_TITLE)) {
@@ -1448,7 +1449,7 @@
                 return ~c;
             }
             if(hasSlot(excWord, EXC_DELTA) && isUpperOrTitleFromProps(props)) {
-                int delta=getSlotValue(excWord, EXC_DELTA, excOffset);
+                int delta=getSlotValue(excWord, EXC_DELTA, excOffset2);
                 return (excWord&EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
             }
             if(hasSlot(excWord, EXC_FOLD)) {
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/lang/UCharacterCaseTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/lang/UCharacterCaseTest.java
index 7ee1f55..1649a71 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/lang/UCharacterCaseTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/lang/UCharacterCaseTest.java
@@ -1493,6 +1493,16 @@
         }
     }
 
+    @Test
+    public void TestCaseMapGreekExtended() {
+        // Ticket 13851
+        String s = "\u1F80\u1F88\u1FFC";
+        String result = CaseMap.toLower().apply(Locale.ROOT,  s);
+        assertEquals("lower", "\u1F80\u1F80\u1FF3", result);
+        result = CaseMap.toTitle().apply(Locale.ROOT, null, s);
+        assertEquals("title", "\u1F88\u1F80\u1FF3", result);
+    }
+
     // private data members - test data --------------------------------------
 
     private static final Locale TURKISH_LOCALE_ = new Locale("tr", "TR");