#
-# Copyright (C) 2002-2003, International Business Machines Corporation and others.
+# Copyright (C) 2002-2015, International Business Machines Corporation and others.
# All Rights Reserved.
#
# file: char.txt
#
# ICU Character Break Rules, also known as Grapheme Cluster Boundaries
# See Unicode Standard Annex #29.
-# These rules are based on TR29 Version 4.0.0
+# These rules are based on UAX #29 Revision 20 for Unicode Version 6.2
#
#
# Character Class Definitions.
-# The names are those from TR29.
#
-$CR = \r;
-$LF = \n;
-$Control = [[:Zl:] [:Zp:] [:Cc:] [:Cf:]];
+$CR = [\p{Grapheme_Cluster_Break = CR}];
+$LF = [\p{Grapheme_Cluster_Break = LF}];
+$Control = [\p{Grapheme_Cluster_Break = Control}];
+# TODO: Restore if the Prepend set becomes non-empty again: $Prepend = [\p{Grapheme_Cluster_Break = Prepend}];
+$Extend = [\p{Grapheme_Cluster_Break = Extend}];
+$SpacingMark = [\p{Grapheme_Cluster_Break = SpacingMark}];
+$RI = [\p{Grapheme_Cluster_Break = Regional_Indicator}];
-$Extend = [[:Grapheme_Extend = TRUE:]];
+# Special character classes for people & body part emoji:
+# Subsets of $Extend:
+$ZWJ = \u200D;
+$EmojiVar = [\uFE0F];
+# The following are subsets of \p{Grapheme_Cluster_Break = Other} which is not otherwise used here
+$EmojiForSeqs = [\u2764 \U0001F441 \U0001F466-\U0001F469 \U0001F48B \U0001F5E8];
+$EmojiForMods = [\u261D \u26F9 \u270A-\u270D \U0001F385 \U0001F3C3-\U0001F3C4 \U0001F3C7 \U0001F3CA-\U0001F3CB \U0001F442-\U0001F443 \U0001F446-\U0001F450 \U0001F466-\U0001F469 \U0001F46E-\U0001F478 \U0001F47C \U0001F481-\U0001F483 \U0001F485-\U0001F487 \U0001F4AA \U0001F590 \U0001F595 \U0001F596 \U0001F645-\U0001F647 \U0001F64B-\U0001F64F \U0001F6A3 \U0001F6B4-\U0001F6B6 \U0001F6C0 \U0001F918];
+$EmojiMods = [\U0001F3FB-\U0001F3FF];
#
# Korean Syllable Definitions
#
-$L = [:Hangul_Syllable_Type = L:];
-$V = [:Hangul_Syllable_Type = V:];
-$T = [:Hangul_Syllable_Type = T:];
+$L = [\p{Grapheme_Cluster_Break = L}];
+$V = [\p{Grapheme_Cluster_Break = V}];
+$T = [\p{Grapheme_Cluster_Break = T}];
-$LV = [:Hangul_Syllable_Type = LV:];
-$LVT = [:Hangul_Syllable_Type = LVT:];
+$LV = [\p{Grapheme_Cluster_Break = LV}];
+$LVT = [\p{Grapheme_Cluster_Break = LVT}];
-$HangulSyllable = $L+ | ($L* ($LV? $V+ | $LV | $LVT) $T*) | $T+;
-#
-# Forward Break Rules
-#
+## -------------------------------------------------
+!!chain;
+!!RINoChain;
+
+!!forward;
+
$CR $LF;
-([^$Control] | $HangulSyllable) $Extend*;
-.;
+$L ($L | $V | $LV | $LVT);
+($LV | $V) ($V | $T);
+($LVT | $T) $T;
+
+$RI $RI $Extend* / $RI;
+$RI $RI $Extend*;
+
+[^$Control $CR $LF] $Extend;
+
+[^$Control $CR $LF] $SpacingMark;
+# TODO: Restore if the Prepend set becomes non-empty again: $Prepend [^$Control $CR $LF];
+
+# Special forward rules for people & body part emoji:
+# don't break $ZWJ from subsequent $EmojiForSeqs; don't break between relevant emoji and $EmojiMods
+$ZWJ $EmojiForSeqs;
+$EmojiForMods $EmojiVar? $EmojiMods;
+
+
+## -------------------------------------------------
+
+!!reverse;
+$LF $CR;
+($L | $V | $LV | $LVT) $L;
+($V | $T) ($LV | $V);
+$T ($LVT | $T);
+
+$Extend* $RI $RI / $Extend* $RI $RI;
+$Extend* $RI $RI;
+
+$Extend [^$Control $CR $LF];
+$SpacingMark [^$Control $CR $LF];
+# TODO: Restore if the Prepend set becomes non-empty again: [^$Control $CR $LF] $Prepend;
+
+# Special reverse rules for people & body part emoji:
+# don't break $ZWJ from subsequent $EmojiForSeqs; don't break between relevant emoji and $EmojiMods
+$EmojiForSeqs $ZWJ;
+$EmojiMods $EmojiVar? $EmojiForMods;
+
+## -------------------------------------------------
+# We don't logically need safe char break rules, but if we don't provide any at all
+# the engine for preceding() and following() will fall back to the
+# old style inefficient algorithm.
+
+!!safe_reverse;
+$LF $CR;
+$RI $RI+;
+[$EmojiVar $EmojiMods]+ $EmojiForMods;
+
+## -------------------------------------------------
+
+!!safe_forward;
+$CR $LF;
+$RI $RI+;
+$EmojiForMods [$EmojiVar $EmojiMods]+;
-#
-# Reverse Rule, back up to the beginning of some preceding grapheme cluster.
-#
-! ($Extend | $V | $T )* ($LF $CR | ($LV | $LVT)?$L* | .);