From 1da6d75b0888d393885104409ce7350881e4ec53 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sat, 21 Nov 2020 00:57:27 +0200 Subject: [PATCH] melib/text_processing: add new wcwidth implementation Download and parse Unicode data files to judge code point width. Inspired by https://github.com/ridiculousfish/widecharwidth/ --- melib/build.rs | 318 +++++- melib/src/text_processing/tables.rs | 1352 +++++++++++++++++++++++++- melib/src/text_processing/wcwidth.rs | 549 +---------- 3 files changed, 1692 insertions(+), 527 deletions(-) diff --git a/melib/build.rs b/melib/build.rs index 17570c0b2..7fa5ad963 100644 --- a/melib/build.rs +++ b/melib/build.rs @@ -25,6 +25,9 @@ include!("src/text_processing/types.rs"); fn main() -> Result<(), std::io::Error> { #[cfg(feature = "unicode_algorithms")] { + const MOD_PATH: &str = "src/text_processing/tables.rs"; + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed={}", MOD_PATH); /* Line break tables */ use std::fs::File; use std::io::prelude::*; @@ -33,8 +36,15 @@ fn main() -> Result<(), std::io::Error> { use std::process::{Command, Stdio}; const LINE_BREAK_TABLE_URL: &str = "http://www.unicode.org/Public/UCD/latest/ucd/LineBreak.txt"; + /* Grapheme width tables */ + const UNICODE_DATA_URL: &str = + "http://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt"; + const EAW_URL: &str = "http://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt"; + const EMOJI_DATA_URL: &str = + "https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt"; - let mod_path = Path::new("src/text_processing/tables.rs"); + + let mod_path = Path::new(MOD_PATH); if mod_path.exists() { eprintln!( "{} already exists, delete it if you want to replace it.", @@ -66,17 +76,255 @@ fn main() -> Result<(), std::io::Error> { let mut codepoint_iter = chars_str.split(".."); let first_codepoint: u32 = - u32::from_str_radix(std::dbg!(codepoint_iter.next().unwrap()), 16).unwrap(); + u32::from_str_radix(codepoint_iter.next().unwrap(), 16).unwrap(); let sec_codepoint: u32 = codepoint_iter .next() - .map(|v| u32::from_str_radix(std::dbg!(v), 16).unwrap()) + .map(|v| u32::from_str_radix(v, 16).unwrap()) .unwrap_or(first_codepoint); let class = &tokens[semicolon_idx + 1..semicolon_idx + 1 + 2]; line_break_table.push((first_codepoint, sec_codepoint, LineBreakClass::from(class))); } child.wait()?; + let child = Command::new("curl") + .args(&["-o", "-", UNICODE_DATA_URL]) + .stdout(Stdio::piped()) + .output()?; + + let unicode_data = String::from_utf8_lossy(&child.stdout); + + let child = Command::new("curl") + .args(&["-o", "-", EAW_URL]) + .stdout(Stdio::piped()) + .output()?; + + let eaw_data = String::from_utf8_lossy(&child.stdout); + + let child = Command::new("curl") + .args(&["-o", "-", EMOJI_DATA_URL]) + .stdout(Stdio::piped()) + .output()?; + + let emoji_data = String::from_utf8_lossy(&child.stdout); + + const MAX_CODEPOINT: usize = 0x110000; + // See https://www.unicode.org/L2/L1999/UnicodeData.html + const FIELD_CODEPOINT: usize = 0; + const FIELD_CATEGORY: usize = 2; + // Ambiguous East Asian characters + const WIDTH_AMBIGUOUS_EASTASIAN: isize = -3; + + // Width changed from 1 to 2 in Unicode 9.0 + const WIDTH_WIDENED_IN_9: isize = -6; + // Category for unassigned codepoints. + const CAT_UNASSIGNED: &str = "Cn"; + + // Category for private use codepoints. + const CAT_PRIVATE_USE: &str = "Co"; + + // Category for surrogates. + const CAT_SURROGATE: &str = "Cs"; + + struct Codepoint<'cat> { + raw: u32, + width: Option, + category: &'cat str, + } + + let mut codepoints: Vec = Vec::with_capacity(MAX_CODEPOINT + 1); + for i in 0..=MAX_CODEPOINT { + codepoints.push(Codepoint { + raw: i as u32, + width: None, + category: CAT_UNASSIGNED, + }); + } + + set_general_categories(&mut codepoints, &unicode_data); + set_eaw_widths(&mut codepoints, &eaw_data); + set_emoji_widths(&mut codepoints, &emoji_data); + set_hardcoded_ranges(&mut codepoints); + fn hexrange_to_range(hexrange: &str) -> std::ops::Range { + /* Given a string like 1F300..1F320 representing an inclusive range, + return the range of codepoints. + If the string is like 1F321, return a range of just that element. + */ + let hexrange = hexrange.trim(); + let fields = hexrange + .split("..") + .map(|h| usize::from_str_radix(h.trim(), 16).unwrap()) + .collect::>(); + if fields.len() == 1 { + fields[0]..(fields[0] + 1) + } else { + fields[0]..(fields[1] + 1) + } + } + + fn set_general_categories<'u>(codepoints: &mut Vec>, unicode_data: &'u str) { + for line in unicode_data.lines() { + let fields = line.trim().split(";").collect::>(); + if fields.len() > FIELD_CATEGORY { + for idx in hexrange_to_range(fields[FIELD_CODEPOINT]) { + codepoints[idx].category = fields[FIELD_CATEGORY]; + } + } + } + } + + fn set_eaw_widths(codepoints: &mut Vec>, eaw_data_lines: &str) { + // Read from EastAsianWidth.txt, set width values on the codepoints + for line in eaw_data_lines.lines() { + let line = line.trim().split('#').next().unwrap_or(line); + let fields = line.trim().split(';').collect::>(); + if fields.len() != 2 { + continue; + } + let hexrange = fields[0]; + let width_type = fields[1]; + // width_types: + // A: ambiguous, F: fullwidth, H: halfwidth, + // . N: neutral, Na: east-asian Narrow + let width: isize = if width_type == "A" { + WIDTH_AMBIGUOUS_EASTASIAN + } else if width_type == "F" || width_type == "W" { + 2 + } else { + 1 + }; + for cp in hexrange_to_range(hexrange) { + codepoints[cp].width = Some(width); + } + } + // Apply the following special cases: + // - The unassigned code points in the following blocks default to "W": + // CJK Unified Ideographs Extension A: U+3400..U+4DBF + // CJK Unified Ideographs: U+4E00..U+9FFF + // CJK Compatibility Ideographs: U+F900..U+FAFF + // - All undesignated code points in Planes 2 and 3, whether inside or + // outside of allocated blocks, default to "W": + // Plane 2: U+20000..U+2FFFD + // Plane 3: U+30000..U+3FFFD + const WIDE_RANGES: [(usize, usize); 5] = [ + (0x3400, 0x4DBF), + (0x4E00, 0x9FFF), + (0xF900, 0xFAFF), + (0x20000, 0x2FFFD), + (0x30000, 0x3FFFD), + ]; + for &wr in WIDE_RANGES.iter() { + for cp in wr.0..(wr.1 + 1) { + if codepoints[cp].width.is_none() { + codepoints[cp].width = Some(2); + } + } + } + } + fn set_emoji_widths(codepoints: &mut Vec>, emoji_data_lines: &str) { + // Read from emoji-data.txt, set codepoint widths + for line in emoji_data_lines.lines() { + if !line.contains("#") || line.trim().starts_with("#") { + continue; + } + let mut fields = line.trim().split('#').collect::>(); + if fields.len() != 2 { + continue; + } + let comment = fields.pop().unwrap(); + let fields = fields.pop().unwrap(); + + let hexrange = fields.split(";").next().unwrap(); + + // In later versions of emoji-data.txt there are some "reserved" + // entries that have "NA" instead of a Unicode version number + // of first use, they will now return a zero version instead of + // crashing the script + if comment.trim().starts_with("NA") { + continue; + } + + use std::str::FromStr; + let mut v = comment.trim().split_whitespace().next().unwrap(); + if v.starts_with("E") { + v = &v[1..]; + } + if v.as_bytes() + .get(0) + .map(|c| !c.is_ascii_digit()) + .unwrap_or(true) + { + continue; + } + let mut idx = 1; + while v + .as_bytes() + .get(idx) + .map(|c| c.is_ascii_digit()) + .unwrap_or(false) + { + idx += 1; + } + if v.as_bytes().get(idx).map(|&c| c != b'.').unwrap_or(true) { + continue; + } + idx += 1; + while v + .as_bytes() + .get(idx) + .map(|c| c.is_ascii_digit()) + .unwrap_or(false) + { + idx += 1; + } + v = &v[0..idx]; + + let version = f32::from_str(v).unwrap(); + for cp in hexrange_to_range(hexrange) { + // Don't consider <=1F000 values as emoji. These can only be made + // emoji through the variation selector which interacts terribly + // with wcwidth(). + if cp < 0x1F000 { + continue; + } + // Skip codepoints that are explicitly not wide. + // For example U+1F336 ("Hot Pepper") renders like any emoji but is + // marked as neutral in EAW so has width 1 for some reason. + //if codepoints[cp].width == Some(1) { + // continue; + //} + + // If this emoji was introduced before Unicode 9, then it was widened in 9. + codepoints[cp].width = if version >= 9.0 { + Some(2) + } else { + Some(WIDTH_WIDENED_IN_9) + }; + } + } + } + fn set_hardcoded_ranges(codepoints: &mut Vec>) { + // Mark private use and surrogate codepoints + // Private use can be determined awkwardly from UnicodeData.txt, + // but we just hard-code them. + // We do not treat "private use high surrogate" as private use + // so as to match wcwidth9(). + const PRIVATE_RANGES: [(usize, usize); 3] = + [(0xE000, 0xF8FF), (0xF0000, 0xFFFFD), (0x100000, 0x10FFFD)]; + for &(first, last) in PRIVATE_RANGES.iter() { + for idx in first..=last { + codepoints[idx].category = CAT_PRIVATE_USE; + } + } + + const SURROGATE_RANGES: [(usize, usize); 2] = [(0xD800, 0xDBFF), (0xDC00, 0xDFFF)]; + for &(first, last) in SURROGATE_RANGES.iter() { + for idx in first..=last { + codepoints[idx].category = CAT_SURROGATE; + } + } + } + let mut file = File::create(&mod_path)?; file.write_all( br#"/* @@ -110,7 +358,69 @@ pub const LINE_BREAK_RULES: &[(u32, u32, LineBreakClass)] = &[ file.write_all(format!(" (0x{:X}, 0x{:X}, {:?}),\n", l.0, l.1, l.2).as_bytes()) .unwrap(); } - file.write_all(b"];").unwrap(); + file.write_all(b"];\n").unwrap(); + + for (name, filter) in [ + ( + "ASCII", + Box::new(|c: &&Codepoint| c.raw < 0x7f && c.raw >= 0x20) + as Box bool>, + ), + ( + "PRIVATE", + Box::new(|c: &&Codepoint| c.category == CAT_PRIVATE_USE), + ), + ( + "NONPRINT", + Box::new(|c: &&Codepoint| { + ["Cc", "Cf", "Zl", "Zp", CAT_SURROGATE].contains(&c.category) + }), + ), + ( + "COMBINING", + Box::new(|c: &&Codepoint| ["Mn", "Mc", "Me"].contains(&c.category)), + ), + ("DOUBLEWIDE", Box::new(|c: &&Codepoint| c.width == Some(2))), + ( + "UNASSIGNED", + Box::new(|c: &&Codepoint| c.category == CAT_UNASSIGNED), + ), + ( + "AMBIGUOUS", + Box::new(|c: &&Codepoint| c.width == Some(WIDTH_AMBIGUOUS_EASTASIAN)), + ), + ( + "WIDENEDIN9", + Box::new(|c: &&Codepoint| c.width == Some(WIDTH_WIDENED_IN_9)), + ), + ] + .iter() + { + file.write_all( + format!( + r#" +pub const {}: &[(u32, u32)] = &[ +"#, + name + ) + .as_bytes(), + ) + .unwrap(); + let mut iter = codepoints.iter().filter(filter); + let mut prev = iter.next().unwrap().raw; + let mut a = prev; + for cp in iter { + if prev + 1 != cp.raw { + file.write_all(format!(" (0x{:X}, 0x{:X}),\n", a, prev).as_bytes()) + .unwrap(); + a = cp.raw; + } + prev = cp.raw; + } + file.write_all(format!(" (0x{:X}, 0x{:X}),\n", a, prev).as_bytes()) + .unwrap(); + file.write_all(b"];\n").unwrap(); + } } Ok(()) } diff --git a/melib/src/text_processing/tables.rs b/melib/src/text_processing/tables.rs index ea5120c6f..234074bb5 100644 --- a/melib/src/text_processing/tables.rs +++ b/melib/src/text_processing/tables.rs @@ -3453,4 +3453,1354 @@ pub const LINE_BREAK_RULES: &[(u32, u32, LineBreakClass)] = &[ (0xE0100, 0xE01EF, CM), (0xF0000, 0xFFFFD, XX), (0x100000, 0x10FFFD, XX), -]; \ No newline at end of file +]; + +pub const ASCII: &[(u32, u32)] = &[ + (0x20, 0x7E), +]; + +pub const PRIVATE: &[(u32, u32)] = &[ + (0xE000, 0xF8FF), + (0xF0000, 0xFFFFD), + (0x100000, 0x10FFFD), +]; + +pub const NONPRINT: &[(u32, u32)] = &[ + (0x0, 0x1F), + (0x7F, 0x9F), + (0xAD, 0xAD), + (0x600, 0x605), + (0x61C, 0x61C), + (0x6DD, 0x6DD), + (0x70F, 0x70F), + (0x8E2, 0x8E2), + (0x180E, 0x180E), + (0x200B, 0x200F), + (0x2028, 0x202E), + (0x2060, 0x2064), + (0x2066, 0x206F), + (0xD800, 0xDFFF), + (0xFEFF, 0xFEFF), + (0xFFF9, 0xFFFB), + (0x110BD, 0x110BD), + (0x110CD, 0x110CD), + (0x13430, 0x13438), + (0x1BCA0, 0x1BCA3), + (0x1D173, 0x1D17A), + (0xE0001, 0xE0001), + (0xE0020, 0xE007F), +]; + +pub const COMBINING: &[(u32, u32)] = &[ + (0x300, 0x36F), + (0x483, 0x489), + (0x591, 0x5BD), + (0x5BF, 0x5BF), + (0x5C1, 0x5C2), + (0x5C4, 0x5C5), + (0x5C7, 0x5C7), + (0x610, 0x61A), + (0x64B, 0x65F), + (0x670, 0x670), + (0x6D6, 0x6DC), + (0x6DF, 0x6E4), + (0x6E7, 0x6E8), + (0x6EA, 0x6ED), + (0x711, 0x711), + (0x730, 0x74A), + (0x7A6, 0x7B0), + (0x7EB, 0x7F3), + (0x7FD, 0x7FD), + (0x816, 0x819), + (0x81B, 0x823), + (0x825, 0x827), + (0x829, 0x82D), + (0x859, 0x85B), + (0x8D3, 0x8E1), + (0x8E3, 0x903), + (0x93A, 0x93C), + (0x93E, 0x94F), + (0x951, 0x957), + (0x962, 0x963), + (0x981, 0x983), + (0x9BC, 0x9BC), + (0x9BE, 0x9C4), + (0x9C7, 0x9C8), + (0x9CB, 0x9CD), + (0x9D7, 0x9D7), + (0x9E2, 0x9E3), + (0x9FE, 0x9FE), + (0xA01, 0xA03), + (0xA3C, 0xA3C), + (0xA3E, 0xA42), + (0xA47, 0xA48), + (0xA4B, 0xA4D), + (0xA51, 0xA51), + (0xA70, 0xA71), + (0xA75, 0xA75), + (0xA81, 0xA83), + (0xABC, 0xABC), + (0xABE, 0xAC5), + (0xAC7, 0xAC9), + (0xACB, 0xACD), + (0xAE2, 0xAE3), + (0xAFA, 0xAFF), + (0xB01, 0xB03), + (0xB3C, 0xB3C), + (0xB3E, 0xB44), + (0xB47, 0xB48), + (0xB4B, 0xB4D), + (0xB55, 0xB57), + (0xB62, 0xB63), + (0xB82, 0xB82), + (0xBBE, 0xBC2), + (0xBC6, 0xBC8), + (0xBCA, 0xBCD), + (0xBD7, 0xBD7), + (0xC00, 0xC04), + (0xC3E, 0xC44), + (0xC46, 0xC48), + (0xC4A, 0xC4D), + (0xC55, 0xC56), + (0xC62, 0xC63), + (0xC81, 0xC83), + (0xCBC, 0xCBC), + (0xCBE, 0xCC4), + (0xCC6, 0xCC8), + (0xCCA, 0xCCD), + (0xCD5, 0xCD6), + (0xCE2, 0xCE3), + (0xD00, 0xD03), + (0xD3B, 0xD3C), + (0xD3E, 0xD44), + (0xD46, 0xD48), + (0xD4A, 0xD4D), + (0xD57, 0xD57), + (0xD62, 0xD63), + (0xD81, 0xD83), + (0xDCA, 0xDCA), + (0xDCF, 0xDD4), + (0xDD6, 0xDD6), + (0xDD8, 0xDDF), + (0xDF2, 0xDF3), + (0xE31, 0xE31), + (0xE34, 0xE3A), + (0xE47, 0xE4E), + (0xEB1, 0xEB1), + (0xEB4, 0xEBC), + (0xEC8, 0xECD), + (0xF18, 0xF19), + (0xF35, 0xF35), + (0xF37, 0xF37), + (0xF39, 0xF39), + (0xF3E, 0xF3F), + (0xF71, 0xF84), + (0xF86, 0xF87), + (0xF8D, 0xF97), + (0xF99, 0xFBC), + (0xFC6, 0xFC6), + (0x102B, 0x103E), + (0x1056, 0x1059), + (0x105E, 0x1060), + (0x1062, 0x1064), + (0x1067, 0x106D), + (0x1071, 0x1074), + (0x1082, 0x108D), + (0x108F, 0x108F), + (0x109A, 0x109D), + (0x135D, 0x135F), + (0x1712, 0x1714), + (0x1732, 0x1734), + (0x1752, 0x1753), + (0x1772, 0x1773), + (0x17B4, 0x17D3), + (0x17DD, 0x17DD), + (0x180B, 0x180D), + (0x1885, 0x1886), + (0x18A9, 0x18A9), + (0x1920, 0x192B), + (0x1930, 0x193B), + (0x1A17, 0x1A1B), + (0x1A55, 0x1A5E), + (0x1A60, 0x1A7C), + (0x1A7F, 0x1A7F), + (0x1AB0, 0x1AC0), + (0x1B00, 0x1B04), + (0x1B34, 0x1B44), + (0x1B6B, 0x1B73), + (0x1B80, 0x1B82), + (0x1BA1, 0x1BAD), + (0x1BE6, 0x1BF3), + (0x1C24, 0x1C37), + (0x1CD0, 0x1CD2), + (0x1CD4, 0x1CE8), + (0x1CED, 0x1CED), + (0x1CF4, 0x1CF4), + (0x1CF7, 0x1CF9), + (0x1DC0, 0x1DF9), + (0x1DFB, 0x1DFF), + (0x20D0, 0x20F0), + (0x2CEF, 0x2CF1), + (0x2D7F, 0x2D7F), + (0x2DE0, 0x2DFF), + (0x302A, 0x302F), + (0x3099, 0x309A), + (0xA66F, 0xA672), + (0xA674, 0xA67D), + (0xA69E, 0xA69F), + (0xA6F0, 0xA6F1), + (0xA802, 0xA802), + (0xA806, 0xA806), + (0xA80B, 0xA80B), + (0xA823, 0xA827), + (0xA82C, 0xA82C), + (0xA880, 0xA881), + (0xA8B4, 0xA8C5), + (0xA8E0, 0xA8F1), + (0xA8FF, 0xA8FF), + (0xA926, 0xA92D), + (0xA947, 0xA953), + (0xA980, 0xA983), + (0xA9B3, 0xA9C0), + (0xA9E5, 0xA9E5), + (0xAA29, 0xAA36), + (0xAA43, 0xAA43), + (0xAA4C, 0xAA4D), + (0xAA7B, 0xAA7D), + (0xAAB0, 0xAAB0), + (0xAAB2, 0xAAB4), + (0xAAB7, 0xAAB8), + (0xAABE, 0xAABF), + (0xAAC1, 0xAAC1), + (0xAAEB, 0xAAEF), + (0xAAF5, 0xAAF6), + (0xABE3, 0xABEA), + (0xABEC, 0xABED), + (0xFB1E, 0xFB1E), + (0xFE00, 0xFE0F), + (0xFE20, 0xFE2F), + (0x101FD, 0x101FD), + (0x102E0, 0x102E0), + (0x10376, 0x1037A), + (0x10A01, 0x10A03), + (0x10A05, 0x10A06), + (0x10A0C, 0x10A0F), + (0x10A38, 0x10A3A), + (0x10A3F, 0x10A3F), + (0x10AE5, 0x10AE6), + (0x10D24, 0x10D27), + (0x10EAB, 0x10EAC), + (0x10F46, 0x10F50), + (0x11000, 0x11002), + (0x11038, 0x11046), + (0x1107F, 0x11082), + (0x110B0, 0x110BA), + (0x11100, 0x11102), + (0x11127, 0x11134), + (0x11145, 0x11146), + (0x11173, 0x11173), + (0x11180, 0x11182), + (0x111B3, 0x111C0), + (0x111C9, 0x111CC), + (0x111CE, 0x111CF), + (0x1122C, 0x11237), + (0x1123E, 0x1123E), + (0x112DF, 0x112EA), + (0x11300, 0x11303), + (0x1133B, 0x1133C), + (0x1133E, 0x11344), + (0x11347, 0x11348), + (0x1134B, 0x1134D), + (0x11357, 0x11357), + (0x11362, 0x11363), + (0x11366, 0x1136C), + (0x11370, 0x11374), + (0x11435, 0x11446), + (0x1145E, 0x1145E), + (0x114B0, 0x114C3), + (0x115AF, 0x115B5), + (0x115B8, 0x115C0), + (0x115DC, 0x115DD), + (0x11630, 0x11640), + (0x116AB, 0x116B7), + (0x1171D, 0x1172B), + (0x1182C, 0x1183A), + (0x11930, 0x11935), + (0x11937, 0x11938), + (0x1193B, 0x1193E), + (0x11940, 0x11940), + (0x11942, 0x11943), + (0x119D1, 0x119D7), + (0x119DA, 0x119E0), + (0x119E4, 0x119E4), + (0x11A01, 0x11A0A), + (0x11A33, 0x11A39), + (0x11A3B, 0x11A3E), + (0x11A47, 0x11A47), + (0x11A51, 0x11A5B), + (0x11A8A, 0x11A99), + (0x11C2F, 0x11C36), + (0x11C38, 0x11C3F), + (0x11C92, 0x11CA7), + (0x11CA9, 0x11CB6), + (0x11D31, 0x11D36), + (0x11D3A, 0x11D3A), + (0x11D3C, 0x11D3D), + (0x11D3F, 0x11D45), + (0x11D47, 0x11D47), + (0x11D8A, 0x11D8E), + (0x11D90, 0x11D91), + (0x11D93, 0x11D97), + (0x11EF3, 0x11EF6), + (0x16AF0, 0x16AF4), + (0x16B30, 0x16B36), + (0x16F4F, 0x16F4F), + (0x16F51, 0x16F87), + (0x16F8F, 0x16F92), + (0x16FE4, 0x16FE4), + (0x16FF0, 0x16FF1), + (0x1BC9D, 0x1BC9E), + (0x1D165, 0x1D169), + (0x1D16D, 0x1D172), + (0x1D17B, 0x1D182), + (0x1D185, 0x1D18B), + (0x1D1AA, 0x1D1AD), + (0x1D242, 0x1D244), + (0x1DA00, 0x1DA36), + (0x1DA3B, 0x1DA6C), + (0x1DA75, 0x1DA75), + (0x1DA84, 0x1DA84), + (0x1DA9B, 0x1DA9F), + (0x1DAA1, 0x1DAAF), + (0x1E000, 0x1E006), + (0x1E008, 0x1E018), + (0x1E01B, 0x1E021), + (0x1E023, 0x1E024), + (0x1E026, 0x1E02A), + (0x1E130, 0x1E136), + (0x1E2EC, 0x1E2EF), + (0x1E8D0, 0x1E8D6), + (0x1E944, 0x1E94A), + (0xE0100, 0xE01EF), +]; + +pub const DOUBLEWIDE: &[(u32, u32)] = &[ + (0x1100, 0x115F), + (0x231A, 0x231B), + (0x2329, 0x232A), + (0x23E9, 0x23EC), + (0x23F0, 0x23F0), + (0x23F3, 0x23F3), + (0x25FD, 0x25FE), + (0x2614, 0x2615), + (0x2648, 0x2653), + (0x267F, 0x267F), + (0x2693, 0x2693), + (0x26A1, 0x26A1), + (0x26AA, 0x26AB), + (0x26BD, 0x26BE), + (0x26C4, 0x26C5), + (0x26CE, 0x26CE), + (0x26D4, 0x26D4), + (0x26EA, 0x26EA), + (0x26F2, 0x26F3), + (0x26F5, 0x26F5), + (0x26FA, 0x26FA), + (0x26FD, 0x26FD), + (0x2705, 0x2705), + (0x270A, 0x270B), + (0x2728, 0x2728), + (0x274C, 0x274C), + (0x274E, 0x274E), + (0x2753, 0x2755), + (0x2757, 0x2757), + (0x2795, 0x2797), + (0x27B0, 0x27B0), + (0x27BF, 0x27BF), + (0x2B1B, 0x2B1C), + (0x2B50, 0x2B50), + (0x2B55, 0x2B55), + (0x2E80, 0x2E99), + (0x2E9B, 0x2EF3), + (0x2F00, 0x2FD5), + (0x2FF0, 0x2FFB), + (0x3000, 0x303E), + (0x3041, 0x3096), + (0x3099, 0x30FF), + (0x3105, 0x312F), + (0x3131, 0x318E), + (0x3190, 0x31E3), + (0x31F0, 0x321E), + (0x3220, 0x3247), + (0x3250, 0x4DBF), + (0x4E00, 0xA48C), + (0xA490, 0xA4C6), + (0xA960, 0xA97C), + (0xAC00, 0xD7A3), + (0xF900, 0xFAFF), + (0xFE10, 0xFE19), + (0xFE30, 0xFE52), + (0xFE54, 0xFE66), + (0xFE68, 0xFE6B), + (0xFF01, 0xFF60), + (0xFFE0, 0xFFE6), + (0x16FE0, 0x16FE4), + (0x16FF0, 0x16FF1), + (0x17000, 0x187F7), + (0x18800, 0x18CD5), + (0x18D00, 0x18D08), + (0x1B000, 0x1B11E), + (0x1B150, 0x1B152), + (0x1B164, 0x1B167), + (0x1B170, 0x1B2FB), + (0x1F200, 0x1F200), + (0x1F210, 0x1F219), + (0x1F21B, 0x1F22E), + (0x1F230, 0x1F231), + (0x1F23B, 0x1F23B), + (0x1F240, 0x1F248), + (0x1F6D5, 0x1F6D7), + (0x1F6F9, 0x1F6FC), + (0x1F7E0, 0x1F7EB), + (0x1F90C, 0x1F90F), + (0x1F93F, 0x1F93F), + (0x1F94D, 0x1F94F), + (0x1F96C, 0x1F978), + (0x1F97A, 0x1F97F), + (0x1F998, 0x1F9BF), + (0x1F9C1, 0x1F9CB), + (0x1F9CD, 0x1F9CF), + (0x1F9E7, 0x1F9FF), + (0x1FA70, 0x1FA74), + (0x1FA78, 0x1FA7A), + (0x1FA80, 0x1FA86), + (0x1FA90, 0x1FAA8), + (0x1FAB0, 0x1FAB6), + (0x1FAC0, 0x1FAC2), + (0x1FAD0, 0x1FAD6), + (0x20000, 0x2FFFD), + (0x30000, 0x3FFFD), +]; + +pub const UNASSIGNED: &[(u32, u32)] = &[ + (0x378, 0x379), + (0x380, 0x383), + (0x38B, 0x38B), + (0x38D, 0x38D), + (0x3A2, 0x3A2), + (0x530, 0x530), + (0x557, 0x558), + (0x58B, 0x58C), + (0x590, 0x590), + (0x5C8, 0x5CF), + (0x5EB, 0x5EE), + (0x5F5, 0x5FF), + (0x61D, 0x61D), + (0x70E, 0x70E), + (0x74B, 0x74C), + (0x7B2, 0x7BF), + (0x7FB, 0x7FC), + (0x82E, 0x82F), + (0x83F, 0x83F), + (0x85C, 0x85D), + (0x85F, 0x85F), + (0x86B, 0x89F), + (0x8B5, 0x8B5), + (0x8C8, 0x8D2), + (0x984, 0x984), + (0x98D, 0x98E), + (0x991, 0x992), + (0x9A9, 0x9A9), + (0x9B1, 0x9B1), + (0x9B3, 0x9B5), + (0x9BA, 0x9BB), + (0x9C5, 0x9C6), + (0x9C9, 0x9CA), + (0x9CF, 0x9D6), + (0x9D8, 0x9DB), + (0x9DE, 0x9DE), + (0x9E4, 0x9E5), + (0x9FF, 0xA00), + (0xA04, 0xA04), + (0xA0B, 0xA0E), + (0xA11, 0xA12), + (0xA29, 0xA29), + (0xA31, 0xA31), + (0xA34, 0xA34), + (0xA37, 0xA37), + (0xA3A, 0xA3B), + (0xA3D, 0xA3D), + (0xA43, 0xA46), + (0xA49, 0xA4A), + (0xA4E, 0xA50), + (0xA52, 0xA58), + (0xA5D, 0xA5D), + (0xA5F, 0xA65), + (0xA77, 0xA80), + (0xA84, 0xA84), + (0xA8E, 0xA8E), + (0xA92, 0xA92), + (0xAA9, 0xAA9), + (0xAB1, 0xAB1), + (0xAB4, 0xAB4), + (0xABA, 0xABB), + (0xAC6, 0xAC6), + (0xACA, 0xACA), + (0xACE, 0xACF), + (0xAD1, 0xADF), + (0xAE4, 0xAE5), + (0xAF2, 0xAF8), + (0xB00, 0xB00), + (0xB04, 0xB04), + (0xB0D, 0xB0E), + (0xB11, 0xB12), + (0xB29, 0xB29), + (0xB31, 0xB31), + (0xB34, 0xB34), + (0xB3A, 0xB3B), + (0xB45, 0xB46), + (0xB49, 0xB4A), + (0xB4E, 0xB54), + (0xB58, 0xB5B), + (0xB5E, 0xB5E), + (0xB64, 0xB65), + (0xB78, 0xB81), + (0xB84, 0xB84), + (0xB8B, 0xB8D), + (0xB91, 0xB91), + (0xB96, 0xB98), + (0xB9B, 0xB9B), + (0xB9D, 0xB9D), + (0xBA0, 0xBA2), + (0xBA5, 0xBA7), + (0xBAB, 0xBAD), + (0xBBA, 0xBBD), + (0xBC3, 0xBC5), + (0xBC9, 0xBC9), + (0xBCE, 0xBCF), + (0xBD1, 0xBD6), + (0xBD8, 0xBE5), + (0xBFB, 0xBFF), + (0xC0D, 0xC0D), + (0xC11, 0xC11), + (0xC29, 0xC29), + (0xC3A, 0xC3C), + (0xC45, 0xC45), + (0xC49, 0xC49), + (0xC4E, 0xC54), + (0xC57, 0xC57), + (0xC5B, 0xC5F), + (0xC64, 0xC65), + (0xC70, 0xC76), + (0xC8D, 0xC8D), + (0xC91, 0xC91), + (0xCA9, 0xCA9), + (0xCB4, 0xCB4), + (0xCBA, 0xCBB), + (0xCC5, 0xCC5), + (0xCC9, 0xCC9), + (0xCCE, 0xCD4), + (0xCD7, 0xCDD), + (0xCDF, 0xCDF), + (0xCE4, 0xCE5), + (0xCF0, 0xCF0), + (0xCF3, 0xCFF), + (0xD0D, 0xD0D), + (0xD11, 0xD11), + (0xD45, 0xD45), + (0xD49, 0xD49), + (0xD50, 0xD53), + (0xD64, 0xD65), + (0xD80, 0xD80), + (0xD84, 0xD84), + (0xD97, 0xD99), + (0xDB2, 0xDB2), + (0xDBC, 0xDBC), + (0xDBE, 0xDBF), + (0xDC7, 0xDC9), + (0xDCB, 0xDCE), + (0xDD5, 0xDD5), + (0xDD7, 0xDD7), + (0xDE0, 0xDE5), + (0xDF0, 0xDF1), + (0xDF5, 0xE00), + (0xE3B, 0xE3E), + (0xE5C, 0xE80), + (0xE83, 0xE83), + (0xE85, 0xE85), + (0xE8B, 0xE8B), + (0xEA4, 0xEA4), + (0xEA6, 0xEA6), + (0xEBE, 0xEBF), + (0xEC5, 0xEC5), + (0xEC7, 0xEC7), + (0xECE, 0xECF), + (0xEDA, 0xEDB), + (0xEE0, 0xEFF), + (0xF48, 0xF48), + (0xF6D, 0xF70), + (0xF98, 0xF98), + (0xFBD, 0xFBD), + (0xFCD, 0xFCD), + (0xFDB, 0xFFF), + (0x10C6, 0x10C6), + (0x10C8, 0x10CC), + (0x10CE, 0x10CF), + (0x1249, 0x1249), + (0x124E, 0x124F), + (0x1257, 0x1257), + (0x1259, 0x1259), + (0x125E, 0x125F), + (0x1289, 0x1289), + (0x128E, 0x128F), + (0x12B1, 0x12B1), + (0x12B6, 0x12B7), + (0x12BF, 0x12BF), + (0x12C1, 0x12C1), + (0x12C6, 0x12C7), + (0x12D7, 0x12D7), + (0x1311, 0x1311), + (0x1316, 0x1317), + (0x135B, 0x135C), + (0x137D, 0x137F), + (0x139A, 0x139F), + (0x13F6, 0x13F7), + (0x13FE, 0x13FF), + (0x169D, 0x169F), + (0x16F9, 0x16FF), + (0x170D, 0x170D), + (0x1715, 0x171F), + (0x1737, 0x173F), + (0x1754, 0x175F), + (0x176D, 0x176D), + (0x1771, 0x1771), + (0x1774, 0x177F), + (0x17DE, 0x17DF), + (0x17EA, 0x17EF), + (0x17FA, 0x17FF), + (0x180F, 0x180F), + (0x181A, 0x181F), + (0x1879, 0x187F), + (0x18AB, 0x18AF), + (0x18F6, 0x18FF), + (0x191F, 0x191F), + (0x192C, 0x192F), + (0x193C, 0x193F), + (0x1941, 0x1943), + (0x196E, 0x196F), + (0x1975, 0x197F), + (0x19AC, 0x19AF), + (0x19CA, 0x19CF), + (0x19DB, 0x19DD), + (0x1A1C, 0x1A1D), + (0x1A5F, 0x1A5F), + (0x1A7D, 0x1A7E), + (0x1A8A, 0x1A8F), + (0x1A9A, 0x1A9F), + (0x1AAE, 0x1AAF), + (0x1AC1, 0x1AFF), + (0x1B4C, 0x1B4F), + (0x1B7D, 0x1B7F), + (0x1BF4, 0x1BFB), + (0x1C38, 0x1C3A), + (0x1C4A, 0x1C4C), + (0x1C89, 0x1C8F), + (0x1CBB, 0x1CBC), + (0x1CC8, 0x1CCF), + (0x1CFB, 0x1CFF), + (0x1DFA, 0x1DFA), + (0x1F16, 0x1F17), + (0x1F1E, 0x1F1F), + (0x1F46, 0x1F47), + (0x1F4E, 0x1F4F), + (0x1F58, 0x1F58), + (0x1F5A, 0x1F5A), + (0x1F5C, 0x1F5C), + (0x1F5E, 0x1F5E), + (0x1F7E, 0x1F7F), + (0x1FB5, 0x1FB5), + (0x1FC5, 0x1FC5), + (0x1FD4, 0x1FD5), + (0x1FDC, 0x1FDC), + (0x1FF0, 0x1FF1), + (0x1FF5, 0x1FF5), + (0x1FFF, 0x1FFF), + (0x2065, 0x2065), + (0x2072, 0x2073), + (0x208F, 0x208F), + (0x209D, 0x209F), + (0x20C0, 0x20CF), + (0x20F1, 0x20FF), + (0x218C, 0x218F), + (0x2427, 0x243F), + (0x244B, 0x245F), + (0x2B74, 0x2B75), + (0x2B96, 0x2B96), + (0x2C2F, 0x2C2F), + (0x2C5F, 0x2C5F), + (0x2CF4, 0x2CF8), + (0x2D26, 0x2D26), + (0x2D28, 0x2D2C), + (0x2D2E, 0x2D2F), + (0x2D68, 0x2D6E), + (0x2D71, 0x2D7E), + (0x2D97, 0x2D9F), + (0x2DA7, 0x2DA7), + (0x2DAF, 0x2DAF), + (0x2DB7, 0x2DB7), + (0x2DBF, 0x2DBF), + (0x2DC7, 0x2DC7), + (0x2DCF, 0x2DCF), + (0x2DD7, 0x2DD7), + (0x2DDF, 0x2DDF), + (0x2E53, 0x2E7F), + (0x2E9A, 0x2E9A), + (0x2EF4, 0x2EFF), + (0x2FD6, 0x2FEF), + (0x2FFC, 0x2FFF), + (0x3040, 0x3040), + (0x3097, 0x3098), + (0x3100, 0x3104), + (0x3130, 0x3130), + (0x318F, 0x318F), + (0x31E4, 0x31EF), + (0x321F, 0x321F), + (0x3401, 0x4DBE), + (0x4E01, 0x9FFB), + (0x9FFD, 0x9FFF), + (0xA48D, 0xA48F), + (0xA4C7, 0xA4CF), + (0xA62C, 0xA63F), + (0xA6F8, 0xA6FF), + (0xA7C0, 0xA7C1), + (0xA7CB, 0xA7F4), + (0xA82D, 0xA82F), + (0xA83A, 0xA83F), + (0xA878, 0xA87F), + (0xA8C6, 0xA8CD), + (0xA8DA, 0xA8DF), + (0xA954, 0xA95E), + (0xA97D, 0xA97F), + (0xA9CE, 0xA9CE), + (0xA9DA, 0xA9DD), + (0xA9FF, 0xA9FF), + (0xAA37, 0xAA3F), + (0xAA4E, 0xAA4F), + (0xAA5A, 0xAA5B), + (0xAAC3, 0xAADA), + (0xAAF7, 0xAB00), + (0xAB07, 0xAB08), + (0xAB0F, 0xAB10), + (0xAB17, 0xAB1F), + (0xAB27, 0xAB27), + (0xAB2F, 0xAB2F), + (0xAB6C, 0xAB6F), + (0xABEE, 0xABEF), + (0xABFA, 0xABFF), + (0xAC01, 0xD7A2), + (0xD7A4, 0xD7AF), + (0xD7C7, 0xD7CA), + (0xD7FC, 0xD7FF), + (0xFA6E, 0xFA6F), + (0xFADA, 0xFAFF), + (0xFB07, 0xFB12), + (0xFB18, 0xFB1C), + (0xFB37, 0xFB37), + (0xFB3D, 0xFB3D), + (0xFB3F, 0xFB3F), + (0xFB42, 0xFB42), + (0xFB45, 0xFB45), + (0xFBC2, 0xFBD2), + (0xFD40, 0xFD4F), + (0xFD90, 0xFD91), + (0xFDC8, 0xFDEF), + (0xFDFE, 0xFDFF), + (0xFE1A, 0xFE1F), + (0xFE53, 0xFE53), + (0xFE67, 0xFE67), + (0xFE6C, 0xFE6F), + (0xFE75, 0xFE75), + (0xFEFD, 0xFEFE), + (0xFF00, 0xFF00), + (0xFFBF, 0xFFC1), + (0xFFC8, 0xFFC9), + (0xFFD0, 0xFFD1), + (0xFFD8, 0xFFD9), + (0xFFDD, 0xFFDF), + (0xFFE7, 0xFFE7), + (0xFFEF, 0xFFF8), + (0xFFFE, 0xFFFF), + (0x1000C, 0x1000C), + (0x10027, 0x10027), + (0x1003B, 0x1003B), + (0x1003E, 0x1003E), + (0x1004E, 0x1004F), + (0x1005E, 0x1007F), + (0x100FB, 0x100FF), + (0x10103, 0x10106), + (0x10134, 0x10136), + (0x1018F, 0x1018F), + (0x1019D, 0x1019F), + (0x101A1, 0x101CF), + (0x101FE, 0x1027F), + (0x1029D, 0x1029F), + (0x102D1, 0x102DF), + (0x102FC, 0x102FF), + (0x10324, 0x1032C), + (0x1034B, 0x1034F), + (0x1037B, 0x1037F), + (0x1039E, 0x1039E), + (0x103C4, 0x103C7), + (0x103D6, 0x103FF), + (0x1049E, 0x1049F), + (0x104AA, 0x104AF), + (0x104D4, 0x104D7), + (0x104FC, 0x104FF), + (0x10528, 0x1052F), + (0x10564, 0x1056E), + (0x10570, 0x105FF), + (0x10737, 0x1073F), + (0x10756, 0x1075F), + (0x10768, 0x107FF), + (0x10806, 0x10807), + (0x10809, 0x10809), + (0x10836, 0x10836), + (0x10839, 0x1083B), + (0x1083D, 0x1083E), + (0x10856, 0x10856), + (0x1089F, 0x108A6), + (0x108B0, 0x108DF), + (0x108F3, 0x108F3), + (0x108F6, 0x108FA), + (0x1091C, 0x1091E), + (0x1093A, 0x1093E), + (0x10940, 0x1097F), + (0x109B8, 0x109BB), + (0x109D0, 0x109D1), + (0x10A04, 0x10A04), + (0x10A07, 0x10A0B), + (0x10A14, 0x10A14), + (0x10A18, 0x10A18), + (0x10A36, 0x10A37), + (0x10A3B, 0x10A3E), + (0x10A49, 0x10A4F), + (0x10A59, 0x10A5F), + (0x10AA0, 0x10ABF), + (0x10AE7, 0x10AEA), + (0x10AF7, 0x10AFF), + (0x10B36, 0x10B38), + (0x10B56, 0x10B57), + (0x10B73, 0x10B77), + (0x10B92, 0x10B98), + (0x10B9D, 0x10BA8), + (0x10BB0, 0x10BFF), + (0x10C49, 0x10C7F), + (0x10CB3, 0x10CBF), + (0x10CF3, 0x10CF9), + (0x10D28, 0x10D2F), + (0x10D3A, 0x10E5F), + (0x10E7F, 0x10E7F), + (0x10EAA, 0x10EAA), + (0x10EAE, 0x10EAF), + (0x10EB2, 0x10EFF), + (0x10F28, 0x10F2F), + (0x10F5A, 0x10FAF), + (0x10FCC, 0x10FDF), + (0x10FF7, 0x10FFF), + (0x1104E, 0x11051), + (0x11070, 0x1107E), + (0x110C2, 0x110CC), + (0x110CE, 0x110CF), + (0x110E9, 0x110EF), + (0x110FA, 0x110FF), + (0x11135, 0x11135), + (0x11148, 0x1114F), + (0x11177, 0x1117F), + (0x111E0, 0x111E0), + (0x111F5, 0x111FF), + (0x11212, 0x11212), + (0x1123F, 0x1127F), + (0x11287, 0x11287), + (0x11289, 0x11289), + (0x1128E, 0x1128E), + (0x1129E, 0x1129E), + (0x112AA, 0x112AF), + (0x112EB, 0x112EF), + (0x112FA, 0x112FF), + (0x11304, 0x11304), + (0x1130D, 0x1130E), + (0x11311, 0x11312), + (0x11329, 0x11329), + (0x11331, 0x11331), + (0x11334, 0x11334), + (0x1133A, 0x1133A), + (0x11345, 0x11346), + (0x11349, 0x1134A), + (0x1134E, 0x1134F), + (0x11351, 0x11356), + (0x11358, 0x1135C), + (0x11364, 0x11365), + (0x1136D, 0x1136F), + (0x11375, 0x113FF), + (0x1145C, 0x1145C), + (0x11462, 0x1147F), + (0x114C8, 0x114CF), + (0x114DA, 0x1157F), + (0x115B6, 0x115B7), + (0x115DE, 0x115FF), + (0x11645, 0x1164F), + (0x1165A, 0x1165F), + (0x1166D, 0x1167F), + (0x116B9, 0x116BF), + (0x116CA, 0x116FF), + (0x1171B, 0x1171C), + (0x1172C, 0x1172F), + (0x11740, 0x117FF), + (0x1183C, 0x1189F), + (0x118F3, 0x118FE), + (0x11907, 0x11908), + (0x1190A, 0x1190B), + (0x11914, 0x11914), + (0x11917, 0x11917), + (0x11936, 0x11936), + (0x11939, 0x1193A), + (0x11947, 0x1194F), + (0x1195A, 0x1199F), + (0x119A8, 0x119A9), + (0x119D8, 0x119D9), + (0x119E5, 0x119FF), + (0x11A48, 0x11A4F), + (0x11AA3, 0x11ABF), + (0x11AF9, 0x11BFF), + (0x11C09, 0x11C09), + (0x11C37, 0x11C37), + (0x11C46, 0x11C4F), + (0x11C6D, 0x11C6F), + (0x11C90, 0x11C91), + (0x11CA8, 0x11CA8), + (0x11CB7, 0x11CFF), + (0x11D07, 0x11D07), + (0x11D0A, 0x11D0A), + (0x11D37, 0x11D39), + (0x11D3B, 0x11D3B), + (0x11D3E, 0x11D3E), + (0x11D48, 0x11D4F), + (0x11D5A, 0x11D5F), + (0x11D66, 0x11D66), + (0x11D69, 0x11D69), + (0x11D8F, 0x11D8F), + (0x11D92, 0x11D92), + (0x11D99, 0x11D9F), + (0x11DAA, 0x11EDF), + (0x11EF9, 0x11FAF), + (0x11FB1, 0x11FBF), + (0x11FF2, 0x11FFE), + (0x1239A, 0x123FF), + (0x1246F, 0x1246F), + (0x12475, 0x1247F), + (0x12544, 0x12FFF), + (0x1342F, 0x1342F), + (0x13439, 0x143FF), + (0x14647, 0x167FF), + (0x16A39, 0x16A3F), + (0x16A5F, 0x16A5F), + (0x16A6A, 0x16A6D), + (0x16A70, 0x16ACF), + (0x16AEE, 0x16AEF), + (0x16AF6, 0x16AFF), + (0x16B46, 0x16B4F), + (0x16B5A, 0x16B5A), + (0x16B62, 0x16B62), + (0x16B78, 0x16B7C), + (0x16B90, 0x16E3F), + (0x16E9B, 0x16EFF), + (0x16F4B, 0x16F4E), + (0x16F88, 0x16F8E), + (0x16FA0, 0x16FDF), + (0x16FE5, 0x16FEF), + (0x16FF2, 0x16FFF), + (0x17001, 0x187F6), + (0x187F8, 0x187FF), + (0x18CD6, 0x18CFF), + (0x18D01, 0x18D07), + (0x18D09, 0x1AFFF), + (0x1B11F, 0x1B14F), + (0x1B153, 0x1B163), + (0x1B168, 0x1B16F), + (0x1B2FC, 0x1BBFF), + (0x1BC6B, 0x1BC6F), + (0x1BC7D, 0x1BC7F), + (0x1BC89, 0x1BC8F), + (0x1BC9A, 0x1BC9B), + (0x1BCA4, 0x1CFFF), + (0x1D0F6, 0x1D0FF), + (0x1D127, 0x1D128), + (0x1D1E9, 0x1D1FF), + (0x1D246, 0x1D2DF), + (0x1D2F4, 0x1D2FF), + (0x1D357, 0x1D35F), + (0x1D379, 0x1D3FF), + (0x1D455, 0x1D455), + (0x1D49D, 0x1D49D), + (0x1D4A0, 0x1D4A1), + (0x1D4A3, 0x1D4A4), + (0x1D4A7, 0x1D4A8), + (0x1D4AD, 0x1D4AD), + (0x1D4BA, 0x1D4BA), + (0x1D4BC, 0x1D4BC), + (0x1D4C4, 0x1D4C4), + (0x1D506, 0x1D506), + (0x1D50B, 0x1D50C), + (0x1D515, 0x1D515), + (0x1D51D, 0x1D51D), + (0x1D53A, 0x1D53A), + (0x1D53F, 0x1D53F), + (0x1D545, 0x1D545), + (0x1D547, 0x1D549), + (0x1D551, 0x1D551), + (0x1D6A6, 0x1D6A7), + (0x1D7CC, 0x1D7CD), + (0x1DA8C, 0x1DA9A), + (0x1DAA0, 0x1DAA0), + (0x1DAB0, 0x1DFFF), + (0x1E007, 0x1E007), + (0x1E019, 0x1E01A), + (0x1E022, 0x1E022), + (0x1E025, 0x1E025), + (0x1E02B, 0x1E0FF), + (0x1E12D, 0x1E12F), + (0x1E13E, 0x1E13F), + (0x1E14A, 0x1E14D), + (0x1E150, 0x1E2BF), + (0x1E2FA, 0x1E2FE), + (0x1E300, 0x1E7FF), + (0x1E8C5, 0x1E8C6), + (0x1E8D7, 0x1E8FF), + (0x1E94C, 0x1E94F), + (0x1E95A, 0x1E95D), + (0x1E960, 0x1EC70), + (0x1ECB5, 0x1ED00), + (0x1ED3E, 0x1EDFF), + (0x1EE04, 0x1EE04), + (0x1EE20, 0x1EE20), + (0x1EE23, 0x1EE23), + (0x1EE25, 0x1EE26), + (0x1EE28, 0x1EE28), + (0x1EE33, 0x1EE33), + (0x1EE38, 0x1EE38), + (0x1EE3A, 0x1EE3A), + (0x1EE3C, 0x1EE41), + (0x1EE43, 0x1EE46), + (0x1EE48, 0x1EE48), + (0x1EE4A, 0x1EE4A), + (0x1EE4C, 0x1EE4C), + (0x1EE50, 0x1EE50), + (0x1EE53, 0x1EE53), + (0x1EE55, 0x1EE56), + (0x1EE58, 0x1EE58), + (0x1EE5A, 0x1EE5A), + (0x1EE5C, 0x1EE5C), + (0x1EE5E, 0x1EE5E), + (0x1EE60, 0x1EE60), + (0x1EE63, 0x1EE63), + (0x1EE65, 0x1EE66), + (0x1EE6B, 0x1EE6B), + (0x1EE73, 0x1EE73), + (0x1EE78, 0x1EE78), + (0x1EE7D, 0x1EE7D), + (0x1EE7F, 0x1EE7F), + (0x1EE8A, 0x1EE8A), + (0x1EE9C, 0x1EEA0), + (0x1EEA4, 0x1EEA4), + (0x1EEAA, 0x1EEAA), + (0x1EEBC, 0x1EEEF), + (0x1EEF2, 0x1EFFF), + (0x1F02C, 0x1F02F), + (0x1F094, 0x1F09F), + (0x1F0AF, 0x1F0B0), + (0x1F0C0, 0x1F0C0), + (0x1F0D0, 0x1F0D0), + (0x1F0F6, 0x1F0FF), + (0x1F1AE, 0x1F1E5), + (0x1F203, 0x1F20F), + (0x1F23C, 0x1F23F), + (0x1F249, 0x1F24F), + (0x1F252, 0x1F25F), + (0x1F266, 0x1F2FF), + (0x1F6D8, 0x1F6DF), + (0x1F6ED, 0x1F6EF), + (0x1F6FD, 0x1F6FF), + (0x1F774, 0x1F77F), + (0x1F7D9, 0x1F7DF), + (0x1F7EC, 0x1F7FF), + (0x1F80C, 0x1F80F), + (0x1F848, 0x1F84F), + (0x1F85A, 0x1F85F), + (0x1F888, 0x1F88F), + (0x1F8AE, 0x1F8AF), + (0x1F8B2, 0x1F8FF), + (0x1F979, 0x1F979), + (0x1F9CC, 0x1F9CC), + (0x1FA54, 0x1FA5F), + (0x1FA6E, 0x1FA6F), + (0x1FA75, 0x1FA77), + (0x1FA7B, 0x1FA7F), + (0x1FA87, 0x1FA8F), + (0x1FAA9, 0x1FAAF), + (0x1FAB7, 0x1FABF), + (0x1FAC3, 0x1FACF), + (0x1FAD7, 0x1FAFF), + (0x1FB93, 0x1FB93), + (0x1FBCB, 0x1FBEF), + (0x1FBFA, 0x1FFFF), + (0x20001, 0x2A6DC), + (0x2A6DE, 0x2A6FF), + (0x2A701, 0x2B733), + (0x2B735, 0x2B73F), + (0x2B741, 0x2B81C), + (0x2B81E, 0x2B81F), + (0x2B821, 0x2CEA0), + (0x2CEA2, 0x2CEAF), + (0x2CEB1, 0x2EBDF), + (0x2EBE1, 0x2F7FF), + (0x2FA1E, 0x2FFFF), + (0x30001, 0x31349), + (0x3134B, 0xE0000), + (0xE0002, 0xE001F), + (0xE0080, 0xE00FF), + (0xE01F0, 0xEFFFF), + (0xFFFFE, 0xFFFFF), + (0x10FFFE, 0x110000), +]; + +pub const AMBIGUOUS: &[(u32, u32)] = &[ + (0xA1, 0xA1), + (0xA4, 0xA4), + (0xA7, 0xA8), + (0xAA, 0xAA), + (0xAD, 0xAE), + (0xB0, 0xB4), + (0xB6, 0xBA), + (0xBC, 0xBF), + (0xC6, 0xC6), + (0xD0, 0xD0), + (0xD7, 0xD8), + (0xDE, 0xE1), + (0xE6, 0xE6), + (0xE8, 0xEA), + (0xEC, 0xED), + (0xF0, 0xF0), + (0xF2, 0xF3), + (0xF7, 0xFA), + (0xFC, 0xFC), + (0xFE, 0xFE), + (0x101, 0x101), + (0x111, 0x111), + (0x113, 0x113), + (0x11B, 0x11B), + (0x126, 0x127), + (0x12B, 0x12B), + (0x131, 0x133), + (0x138, 0x138), + (0x13F, 0x142), + (0x144, 0x144), + (0x148, 0x14B), + (0x14D, 0x14D), + (0x152, 0x153), + (0x166, 0x167), + (0x16B, 0x16B), + (0x1CE, 0x1CE), + (0x1D0, 0x1D0), + (0x1D2, 0x1D2), + (0x1D4, 0x1D4), + (0x1D6, 0x1D6), + (0x1D8, 0x1D8), + (0x1DA, 0x1DA), + (0x1DC, 0x1DC), + (0x251, 0x251), + (0x261, 0x261), + (0x2C4, 0x2C4), + (0x2C7, 0x2C7), + (0x2C9, 0x2CB), + (0x2CD, 0x2CD), + (0x2D0, 0x2D0), + (0x2D8, 0x2DB), + (0x2DD, 0x2DD), + (0x2DF, 0x2DF), + (0x300, 0x36F), + (0x391, 0x3A1), + (0x3A3, 0x3A9), + (0x3B1, 0x3C1), + (0x3C3, 0x3C9), + (0x401, 0x401), + (0x410, 0x44F), + (0x451, 0x451), + (0x2010, 0x2010), + (0x2013, 0x2016), + (0x2018, 0x2019), + (0x201C, 0x201D), + (0x2020, 0x2022), + (0x2024, 0x2027), + (0x2030, 0x2030), + (0x2032, 0x2033), + (0x2035, 0x2035), + (0x203B, 0x203B), + (0x203E, 0x203E), + (0x2074, 0x2074), + (0x207F, 0x207F), + (0x2081, 0x2084), + (0x20AC, 0x20AC), + (0x2103, 0x2103), + (0x2105, 0x2105), + (0x2109, 0x2109), + (0x2113, 0x2113), + (0x2116, 0x2116), + (0x2121, 0x2122), + (0x2126, 0x2126), + (0x212B, 0x212B), + (0x2153, 0x2154), + (0x215B, 0x215E), + (0x2160, 0x216B), + (0x2170, 0x2179), + (0x2189, 0x2189), + (0x2190, 0x2199), + (0x21B8, 0x21B9), + (0x21D2, 0x21D2), + (0x21D4, 0x21D4), + (0x21E7, 0x21E7), + (0x2200, 0x2200), + (0x2202, 0x2203), + (0x2207, 0x2208), + (0x220B, 0x220B), + (0x220F, 0x220F), + (0x2211, 0x2211), + (0x2215, 0x2215), + (0x221A, 0x221A), + (0x221D, 0x2220), + (0x2223, 0x2223), + (0x2225, 0x2225), + (0x2227, 0x222C), + (0x222E, 0x222E), + (0x2234, 0x2237), + (0x223C, 0x223D), + (0x2248, 0x2248), + (0x224C, 0x224C), + (0x2252, 0x2252), + (0x2260, 0x2261), + (0x2264, 0x2267), + (0x226A, 0x226B), + (0x226E, 0x226F), + (0x2282, 0x2283), + (0x2286, 0x2287), + (0x2295, 0x2295), + (0x2299, 0x2299), + (0x22A5, 0x22A5), + (0x22BF, 0x22BF), + (0x2312, 0x2312), + (0x2460, 0x24E9), + (0x24EB, 0x254B), + (0x2550, 0x2573), + (0x2580, 0x258F), + (0x2592, 0x2595), + (0x25A0, 0x25A1), + (0x25A3, 0x25A9), + (0x25B2, 0x25B3), + (0x25B6, 0x25B7), + (0x25BC, 0x25BD), + (0x25C0, 0x25C1), + (0x25C6, 0x25C8), + (0x25CB, 0x25CB), + (0x25CE, 0x25D1), + (0x25E2, 0x25E5), + (0x25EF, 0x25EF), + (0x2605, 0x2606), + (0x2609, 0x2609), + (0x260E, 0x260F), + (0x261C, 0x261C), + (0x261E, 0x261E), + (0x2640, 0x2640), + (0x2642, 0x2642), + (0x2660, 0x2661), + (0x2663, 0x2665), + (0x2667, 0x266A), + (0x266C, 0x266D), + (0x266F, 0x266F), + (0x269E, 0x269F), + (0x26BF, 0x26BF), + (0x26C6, 0x26CD), + (0x26CF, 0x26D3), + (0x26D5, 0x26E1), + (0x26E3, 0x26E3), + (0x26E8, 0x26E9), + (0x26EB, 0x26F1), + (0x26F4, 0x26F4), + (0x26F6, 0x26F9), + (0x26FB, 0x26FC), + (0x26FE, 0x26FF), + (0x273D, 0x273D), + (0x2776, 0x277F), + (0x2B56, 0x2B59), + (0x3248, 0x324F), + (0xE000, 0xF8FF), + (0xFE00, 0xFE0F), + (0xFFFD, 0xFFFD), + (0x1F100, 0x1F10A), + (0x1F110, 0x1F12D), + (0x1F130, 0x1F169), + (0x1F172, 0x1F17D), + (0x1F180, 0x1F18D), + (0x1F18F, 0x1F190), + (0x1F19B, 0x1F1AC), + (0xE0100, 0xE01EF), + (0xF0000, 0xFFFFD), + (0x100000, 0x10FFFD), +]; + +pub const WIDENEDIN9: &[(u32, u32)] = &[ + (0x1F000, 0x1F0FF), + (0x1F10D, 0x1F10F), + (0x1F12F, 0x1F12F), + (0x1F16C, 0x1F171), + (0x1F17E, 0x1F17F), + (0x1F18E, 0x1F18E), + (0x1F191, 0x1F19A), + (0x1F1AD, 0x1F1FF), + (0x1F201, 0x1F20F), + (0x1F21A, 0x1F21A), + (0x1F22F, 0x1F22F), + (0x1F232, 0x1F23A), + (0x1F23C, 0x1F23F), + (0x1F249, 0x1F53D), + (0x1F546, 0x1F64F), + (0x1F680, 0x1F6D4), + (0x1F6D8, 0x1F6F8), + (0x1F6FD, 0x1F6FF), + (0x1F774, 0x1F77F), + (0x1F7D5, 0x1F7DF), + (0x1F7EC, 0x1F7FF), + (0x1F80C, 0x1F80F), + (0x1F848, 0x1F84F), + (0x1F85A, 0x1F85F), + (0x1F888, 0x1F88F), + (0x1F8AE, 0x1F8FF), + (0x1F910, 0x1F93A), + (0x1F93C, 0x1F93E), + (0x1F940, 0x1F945), + (0x1F947, 0x1F94C), + (0x1F950, 0x1F96B), + (0x1F979, 0x1F979), + (0x1F980, 0x1F997), + (0x1F9C0, 0x1F9C0), + (0x1F9CC, 0x1F9CC), + (0x1F9D0, 0x1F9E6), + (0x1FA00, 0x1FA6F), + (0x1FA75, 0x1FA77), + (0x1FA7B, 0x1FA7F), + (0x1FA87, 0x1FA8F), + (0x1FAA9, 0x1FAAF), + (0x1FAB7, 0x1FABF), + (0x1FAC3, 0x1FACF), + (0x1FAD7, 0x1FAFF), + (0x1FC00, 0x1FFFD), + (0xE0020, 0xE007F), +]; diff --git a/melib/src/text_processing/wcwidth.rs b/melib/src/text_processing/wcwidth.rs index 7cf5ea78b..186326c13 100644 --- a/melib/src/text_processing/wcwidth.rs +++ b/melib/src/text_processing/wcwidth.rs @@ -136,174 +136,36 @@ fn bisearch(ucs: WChar, table: &'static [Interval]) -> bool { false } -/* The following functions define the column width of an ISO 10646 - * character as follows: - * - * - The null character (U+0000) has a column width of 0. - * - * - Other C0/C1 control characters and DEL will lead to a return - * value of -1. - * - * - Non-spacing and enclosing combining characters (general - * category code Mn or Me in the Unicode database) have a - * column width of 0. - * - * - Other format characters (general category code Cf in the Unicode - * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0. - * - * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF) - * have a column width of 0. - * - * - Spacing characters in the East Asian Wide (W) or East Asian - * FullWidth (F) category as defined in Unicode Technical - * Report #11 have a column width of 2. - * - * - All remaining characters (including all printable - * ISO 8859-1 and WGL4 characters, Unicode control characters, - * etc.) have a column width of 1. - * - * This implementation assumes that wchar_t characters are encoded - * in ISO 10646. - */ - pub fn wcwidth(ucs: WChar) -> Option { - /* sorted list of non-overlapping intervals of non-spacing characters */ - const COMBINING: &[Interval] = &[ - (0x0300, 0x034E), - (0x0360, 0x0362), - (0x0483, 0x0486), - (0x0488, 0x0489), - (0x0591, 0x05A1), - (0x05A3, 0x05B9), - (0x05BB, 0x05BD), - (0x05BF, 0x05BF), - (0x05C1, 0x05C2), - (0x05C4, 0x05C4), - (0x064B, 0x0655), - (0x0670, 0x0670), - (0x06D6, 0x06E4), - (0x06E7, 0x06E8), - (0x06EA, 0x06ED), - (0x070F, 0x070F), - (0x0711, 0x0711), - (0x0730, 0x074A), - (0x07A6, 0x07B0), - (0x0901, 0x0902), - (0x093C, 0x093C), - (0x0941, 0x0948), - (0x094D, 0x094D), - (0x0951, 0x0954), - (0x0962, 0x0963), - (0x0981, 0x0981), - (0x09BC, 0x09BC), - (0x09C1, 0x09C4), - (0x09CD, 0x09CD), - (0x09E2, 0x09E3), - (0x0A02, 0x0A02), - (0x0A3C, 0x0A3C), - (0x0A41, 0x0A42), - (0x0A47, 0x0A48), - (0x0A4B, 0x0A4D), - (0x0A70, 0x0A71), - (0x0A81, 0x0A82), - (0x0ABC, 0x0ABC), - (0x0AC1, 0x0AC5), - (0x0AC7, 0x0AC8), - (0x0ACD, 0x0ACD), - (0x0B01, 0x0B01), - (0x0B3C, 0x0B3C), - (0x0B3F, 0x0B3F), - (0x0B41, 0x0B43), - (0x0B4D, 0x0B4D), - (0x0B56, 0x0B56), - (0x0B82, 0x0B82), - (0x0BC0, 0x0BC0), - (0x0BCD, 0x0BCD), - (0x0C3E, 0x0C40), - (0x0C46, 0x0C48), - (0x0C4A, 0x0C4D), - (0x0C55, 0x0C56), - (0x0CBF, 0x0CBF), - (0x0CC6, 0x0CC6), - (0x0CCC, 0x0CCD), - (0x0D41, 0x0D43), - (0x0D4D, 0x0D4D), - (0x0DCA, 0x0DCA), - (0x0DD2, 0x0DD4), - (0x0DD6, 0x0DD6), - (0x0E31, 0x0E31), - (0x0E34, 0x0E3A), - (0x0E47, 0x0E4E), - (0x0EB1, 0x0EB1), - (0x0EB4, 0x0EB9), - (0x0EBB, 0x0EBC), - (0x0EC8, 0x0ECD), - (0x0F18, 0x0F19), - (0x0F35, 0x0F35), - (0x0F37, 0x0F37), - (0x0F39, 0x0F39), - (0x0F71, 0x0F7E), - (0x0F80, 0x0F84), - (0x0F86, 0x0F87), - (0x0F90, 0x0F97), - (0x0F99, 0x0FBC), - (0x0FC6, 0x0FC6), - (0x102D, 0x1030), - (0x1032, 0x1032), - (0x1036, 0x1037), - (0x1039, 0x1039), - (0x1058, 0x1059), - (0x1160, 0x11FF), - (0x17B7, 0x17BD), - (0x17C6, 0x17C6), - (0x17C9, 0x17D3), - (0x180B, 0x180E), - (0x18A9, 0x18A9), - (0x200B, 0x200F), - (0x202A, 0x202E), - (0x206A, 0x206F), - (0x20D0, 0x20E3), - (0x302A, 0x302F), - (0x3099, 0x309A), - (0xFB1E, 0xFB1E), - (0xFE20, 0xFE23), - (0xFEFF, 0xFEFF), - (0xFFF9, 0xFFFB), - ]; - - /* test for 8-bit control characters */ - if ucs == 0 { - return Some(0); - } - if ucs < 32 || (ucs >= 0x7f && ucs < 0xa0) { - return None; + if bisearch(ucs, super::tables::ASCII) { + Some(1) + } else if bisearch(ucs, super::tables::PRIVATE) { + None + } else if bisearch(ucs, super::tables::NONPRINT) { + None + } else if bisearch(ucs, super::tables::COMBINING) { + None + } else if bisearch(ucs, super::tables::DOUBLEWIDE) { + Some(2) + } else if bisearch(ucs, super::tables::AMBIGUOUS) { + Some(1) + } else if bisearch(ucs, super::tables::UNASSIGNED) { + Some(2) + } else if bisearch(ucs, super::tables::WIDENEDIN9) { + Some(2) + } else { + Some(1) } +} - /* binary search in table of emojis */ - if bisearch(ucs, EMOJI_RANGES) { - return Some(2); - } - /* binary search in table of non-spacing characters */ - if bisearch(ucs, COMBINING) { - return Some(1); - } - - /* if we arrive here, ucs is not a combining or C0/C1 control character */ - - Some( - 1 + big_if_true!( - ucs >= 0x1100 - && (ucs <= 0x115f || /* Hangul Jamo init. consonants */ - (ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & !0x0011) != 0x300a && - ucs != 0x303f) || /* CJK ... Yi */ - (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ - (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ - (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ - (ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */ - (ucs >= 0xffe0 && ucs <= 0xffe6) || - (ucs >= 0x20000 && ucs <= 0x2ffff)) - ), - ) +#[test] +fn test_wcwidth() { + use crate::text_processing::grapheme_clusters::TextProcessing; + assert_eq!("โ—".grapheme_width(), 1); + assert_eq!("โ—๐Ÿ“Ž".grapheme_width(), 3); + assert_eq!("โ—\u{FE0E}๐Ÿ“Ž\u{FE0E}".grapheme_width(), 3); + assert_eq!("๐ŸŽƒ".grapheme_width(), 2); + assert_eq!("๐Ÿ‘ป".grapheme_width(), 2); } pub fn wcswidth(mut pwcs: WChar, mut n: usize) -> Option { @@ -322,360 +184,3 @@ pub fn wcswidth(mut pwcs: WChar, mut n: usize) -> Option { Some(width) } - -const EMOJI_RANGES: &[Interval] = &[ - (0x231A, 0x231B), // ; Basic_Emoji ; watch # 1.1 [2] (โŒš..โŒ›) - (0x23E9, 0x23EC), // ; Basic_Emoji ; fast-forward button # 6.0 [4] (โฉ..โฌ) - (0x23F0, 0x23F0), // ; Basic_Emoji ; alarm clock # 6.0 [1] (โฐ) - (0x23F3, 0x23F3), // ; Basic_Emoji ; hourglass not done # 6.0 [1] (โณ) - (0x25FD, 0x25FE), // ; Basic_Emoji ; white medium-small square # 3.2 [2] (โ—ฝ..โ—พ) - (0x2614, 0x2615), // ; Basic_Emoji ; umbrella with rain drops # 4.0 [2] (โ˜”..โ˜•) - (0x2648, 0x2653), // ; Basic_Emoji ; Aries # 1.1 [12] (โ™ˆ..โ™“) - (0x267F, 0x267F), // ; Basic_Emoji ; wheelchair symbol # 4.1 [1] (โ™ฟ) - (0x2693, 0x2693), // ; Basic_Emoji ; anchor # 4.1 [1] (โš“) - (0x26A1, 0x26A1), // ; Basic_Emoji ; high voltage # 4.0 [1] (โšก) - (0x26AA, 0x26AB), // ; Basic_Emoji ; white circle # 4.1 [2] (โšช..โšซ) - (0x26BD, 0x26BE), // ; Basic_Emoji ; soccer ball # 5.2 [2] (โšฝ..โšพ) - (0x26C4, 0x26C5), // ; Basic_Emoji ; snowman without snow # 5.2 [2] (โ›„..โ›…) - (0x26CE, 0x26CE), // ; Basic_Emoji ; Ophiuchus # 6.0 [1] (โ›Ž) - (0x26D4, 0x26D4), // ; Basic_Emoji ; no entry # 5.2 [1] (โ›”) - (0x26EA, 0x26EA), // ; Basic_Emoji ; church # 5.2 [1] (โ›ช) - (0x26F2, 0x26F3), // ; Basic_Emoji ; fountain # 5.2 [2] (โ›ฒ..โ›ณ) - (0x26F5, 0x26F5), // ; Basic_Emoji ; sailboat # 5.2 [1] (โ›ต) - (0x26FA, 0x26FA), // ; Basic_Emoji ; tent # 5.2 [1] (โ›บ) - (0x26FD, 0x26FD), // ; Basic_Emoji ; fuel pump # 5.2 [1] (โ›ฝ) - (0x2705, 0x2705), // ; Basic_Emoji ; check mark button # 6.0 [1] (โœ…) - (0x270A, 0x270B), // ; Basic_Emoji ; raised fist # 6.0 [2] (โœŠ..โœ‹) - (0x2728, 0x2728), // ; Basic_Emoji ; sparkles # 6.0 [1] (โœจ) - (0x274C, 0x274C), // ; Basic_Emoji ; cross mark # 6.0 [1] (โŒ) - (0x274E, 0x274E), // ; Basic_Emoji ; cross mark button # 6.0 [1] (โŽ) - (0x2753, 0x2755), // ; Basic_Emoji ; question mark # 6.0 [3] (โ“..โ•) - (0x2757, 0x2757), // ; Basic_Emoji ; exclamation mark # 5.2 [1] (โ—) - (0x2795, 0x2797), // ; Basic_Emoji ; plus sign # 6.0 [3] (โž•..โž—) - (0x27B0, 0x27B0), // ; Basic_Emoji ; curly loop # 6.0 [1] (โžฐ) - (0x27BF, 0x27BF), // ; Basic_Emoji ; double curly loop # 6.0 [1] (โžฟ) - (0x2B1B, 0x2B1C), // ; Basic_Emoji ; black large square # 5.1 [2] (โฌ›..โฌœ) - (0x2B50, 0x2B50), // ; Basic_Emoji ; star # 5.1 [1] (โญ) - (0x2B55, 0x2B55), // ; Basic_Emoji ; hollow red circle # 5.2 [1] (โญ•) - (0x1F004, 0x1F004), // ; Basic_Emoji ; mahjong red dragon # 5.1 [1] (๐Ÿ€„) - (0x1F0CF, 0x1F0CF), // ; Basic_Emoji ; joker # 6.0 [1] (๐Ÿƒ) - (0x1F18E, 0x1F18E), // ; Basic_Emoji ; AB button (blood type) # 6.0 [1] (๐Ÿ†Ž) - (0x1F191, 0x1F19A), // ; Basic_Emoji ; CL button # 6.0 [10] (๐Ÿ†‘..๐Ÿ†š) - (0x1F201, 0x1F201), // ; Basic_Emoji ; Japanese โ€œhereโ€ button # 6.0 [1] (๐Ÿˆ) - (0x1F21A, 0x1F21A), // ; Basic_Emoji ; Japanese โ€œfree of chargeโ€ button # 5.2 [1] (๐Ÿˆš) - (0x1F22F, 0x1F22F), // ; Basic_Emoji ; Japanese โ€œreservedโ€ button # 5.2 [1] (๐Ÿˆฏ) - (0x1F232, 0x1F236), // ; Basic_Emoji ; Japanese โ€œprohibitedโ€ button # 6.0 [5] (๐Ÿˆฒ..๐Ÿˆถ) - (0x1F238, 0x1F23A), // ; Basic_Emoji ; Japanese โ€œapplicationโ€ button # 6.0 [3] (๐Ÿˆธ..๐Ÿˆบ) - (0x1F250, 0x1F251), // ; Basic_Emoji ; Japanese โ€œbargainโ€ button # 6.0 [2] (๐Ÿ‰..๐Ÿ‰‘) - (0x1F300, 0x1F320), // ; Basic_Emoji ; cyclone # 6.0 [33] (๐ŸŒ€..๐ŸŒ ) - (0x1F32D, 0x1F32F), // ; Basic_Emoji ; hot dog # 8.0 [3] (๐ŸŒญ..๐ŸŒฏ) - (0x1F330, 0x1F335), // ; Basic_Emoji ; chestnut # 6.0 [6] (๐ŸŒฐ..๐ŸŒต) - (0x1F337, 0x1F37C), // ; Basic_Emoji ; tulip # 6.0 [70] (๐ŸŒท..๐Ÿผ) - (0x1F37E, 0x1F37F), // ; Basic_Emoji ; bottle with popping cork # 8.0 [2] (๐Ÿพ..๐Ÿฟ) - (0x1F380, 0x1F393), // ; Basic_Emoji ; ribbon # 6.0 [20] (๐ŸŽ€..๐ŸŽ“) - (0x1F3A0, 0x1F3C4), // ; Basic_Emoji ; carousel horse # 6.0 [37] (๐ŸŽ ..๐Ÿ„) - (0x1F3C5, 0x1F3C5), // ; Basic_Emoji ; sports medal # 7.0 [1] (๐Ÿ…) - (0x1F3C6, 0x1F3CA), // ; Basic_Emoji ; trophy # 6.0 [5] (๐Ÿ†..๐ŸŠ) - (0x1F3CF, 0x1F3D3), // ; Basic_Emoji ; cricket game # 8.0 [5] (๐Ÿ..๐Ÿ“) - (0x1F3E0, 0x1F3F0), // ; Basic_Emoji ; house # 6.0 [17] (๐Ÿ ..๐Ÿฐ) - (0x1F3F4, 0x1F3F4), // ; Basic_Emoji ; black flag # 7.0 [1] (๐Ÿด) - (0x1F3F8, 0x1F3FF), // ; Basic_Emoji ; badminton # 8.0 [8] (๐Ÿธ..๐Ÿฟ) - (0x1F400, 0x1F43E), // ; Basic_Emoji ; rat # 6.0 [63] (๐Ÿ€..๐Ÿพ) - (0x1F440, 0x1F440), // ; Basic_Emoji ; eyes # 6.0 [1] (๐Ÿ‘€) - (0x1F442, 0x1F4F7), // ; Basic_Emoji ; ear # 6.0[182] (๐Ÿ‘‚..๐Ÿ“ท) - (0x1F4F8, 0x1F4F8), // ; Basic_Emoji ; camera with flash # 7.0 [1] (๐Ÿ“ธ) - (0x1F4F9, 0x1F4FC), // ; Basic_Emoji ; video camera # 6.0 [4] (๐Ÿ“น..๐Ÿ“ผ) - (0x1F4FF, 0x1F4FF), // ; Basic_Emoji ; prayer beads # 8.0 [1] (๐Ÿ“ฟ) - (0x1F500, 0x1F53D), // ; Basic_Emoji ; shuffle tracks button # 6.0 [62] (๐Ÿ”€..๐Ÿ”ฝ) - (0x1F54B, 0x1F54E), // ; Basic_Emoji ; kaaba # 8.0 [4] (๐Ÿ•‹..๐Ÿ•Ž) - (0x1F550, 0x1F567), // ; Basic_Emoji ; one oโ€™clock # 6.0 [24] (๐Ÿ•..๐Ÿ•ง) - (0x1F57A, 0x1F57A), // ; Basic_Emoji ; man dancing # 9.0 [1] (๐Ÿ•บ) - (0x1F595, 0x1F596), // ; Basic_Emoji ; middle finger # 7.0 [2] (๐Ÿ–•..๐Ÿ––) - (0x1F5A4, 0x1F5A4), // ; Basic_Emoji ; black heart # 9.0 [1] (๐Ÿ–ค) - (0x1F5FB, 0x1F5FF), // ; Basic_Emoji ; mount fuji # 6.0 [5] (๐Ÿ—ป..๐Ÿ—ฟ) - (0x1F600, 0x1F600), // ; Basic_Emoji ; grinning face # 6.1 [1] (๐Ÿ˜€) - (0x1F601, 0x1F610), // ; Basic_Emoji ; beaming face with smiling eyes # 6.0 [16] (๐Ÿ˜..๐Ÿ˜) - (0x1F611, 0x1F611), // ; Basic_Emoji ; expressionless face # 6.1 [1] (๐Ÿ˜‘) - (0x1F612, 0x1F614), // ; Basic_Emoji ; unamused face # 6.0 [3] (๐Ÿ˜’..๐Ÿ˜”) - (0x1F615, 0x1F615), // ; Basic_Emoji ; confused face # 6.1 [1] (๐Ÿ˜•) - (0x1F616, 0x1F616), // ; Basic_Emoji ; confounded face # 6.0 [1] (๐Ÿ˜–) - (0x1F617, 0x1F617), // ; Basic_Emoji ; kissing face # 6.1 [1] (๐Ÿ˜—) - (0x1F618, 0x1F618), // ; Basic_Emoji ; face blowing a kiss # 6.0 [1] (๐Ÿ˜˜) - (0x1F619, 0x1F619), // ; Basic_Emoji ; kissing face with smiling eyes # 6.1 [1] (๐Ÿ˜™) - (0x1F61A, 0x1F61A), // ; Basic_Emoji ; kissing face with closed eyes # 6.0 [1] (๐Ÿ˜š) - (0x1F61B, 0x1F61B), // ; Basic_Emoji ; face with tongue # 6.1 [1] (๐Ÿ˜›) - (0x1F61C, 0x1F61E), // ; Basic_Emoji ; winking face with tongue # 6.0 [3] (๐Ÿ˜œ..๐Ÿ˜ž) - (0x1F61F, 0x1F61F), // ; Basic_Emoji ; worried face # 6.1 [1] (๐Ÿ˜Ÿ) - (0x1F620, 0x1F625), // ; Basic_Emoji ; angry face # 6.0 [6] (๐Ÿ˜ ..๐Ÿ˜ฅ) - (0x1F626, 0x1F627), // ; Basic_Emoji ; frowning face with open mouth # 6.1 [2] (๐Ÿ˜ฆ..๐Ÿ˜ง) - (0x1F628, 0x1F62B), // ; Basic_Emoji ; fearful face # 6.0 [4] (๐Ÿ˜จ..๐Ÿ˜ซ) - (0x1F62C, 0x1F62C), // ; Basic_Emoji ; grimacing face # 6.1 [1] (๐Ÿ˜ฌ) - (0x1F62D, 0x1F62D), // ; Basic_Emoji ; loudly crying face # 6.0 [1] (๐Ÿ˜ญ) - (0x1F62E, 0x1F62F), // ; Basic_Emoji ; face with open mouth # 6.1 [2] (๐Ÿ˜ฎ..๐Ÿ˜ฏ) - (0x1F630, 0x1F633), // ; Basic_Emoji ; anxious face with sweat # 6.0 [4] (๐Ÿ˜ฐ..๐Ÿ˜ณ) - (0x1F634, 0x1F634), // ; Basic_Emoji ; sleeping face # 6.1 [1] (๐Ÿ˜ด) - (0x1F635, 0x1F640), // ; Basic_Emoji ; dizzy face # 6.0 [12] (๐Ÿ˜ต..๐Ÿ™€) - (0x1F641, 0x1F642), // ; Basic_Emoji ; slightly frowning face # 7.0 [2] (๐Ÿ™..๐Ÿ™‚) - (0x1F643, 0x1F644), // ; Basic_Emoji ; upside-down face # 8.0 [2] (๐Ÿ™ƒ..๐Ÿ™„) - (0x1F645, 0x1F64F), // ; Basic_Emoji ; person gesturing NO # 6.0 [11] (๐Ÿ™…..๐Ÿ™) - (0x1F680, 0x1F6C5), // ; Basic_Emoji ; rocket # 6.0 [70] (๐Ÿš€..๐Ÿ›…) - (0x1F6CC, 0x1F6CC), // ; Basic_Emoji ; person in bed # 7.0 [1] (๐Ÿ›Œ) - (0x1F6D0, 0x1F6D0), // ; Basic_Emoji ; place of worship # 8.0 [1] (๐Ÿ›) - (0x1F6D1, 0x1F6D2), // ; Basic_Emoji ; stop sign # 9.0 [2] (๐Ÿ›‘..๐Ÿ›’) - (0x1F6D5, 0x1F6D5), // ; Basic_Emoji ; hindu temple # 12.0 [1] (๐Ÿ›•) - (0x1F6EB, 0x1F6EC), // ; Basic_Emoji ; airplane departure # 7.0 [2] (๐Ÿ›ซ..๐Ÿ›ฌ) - (0x1F6F4, 0x1F6F6), // ; Basic_Emoji ; kick scooter # 9.0 [3] (๐Ÿ›ด..๐Ÿ›ถ) - (0x1F6F7, 0x1F6F8), // ; Basic_Emoji ; sled # 10.0 [2] (๐Ÿ›ท..๐Ÿ›ธ) - (0x1F6F9, 0x1F6F9), // ; Basic_Emoji ; skateboard # 11.0 [1] (๐Ÿ›น) - (0x1F6FA, 0x1F6FA), // ; Basic_Emoji ; auto rickshaw # 12.0 [1] (๐Ÿ›บ) - (0x1F7E0, 0x1F7EB), // ; Basic_Emoji ; orange circle # 12.0 [12] (๐ŸŸ ..๐ŸŸซ) - (0x1F90D, 0x1F90F), // ; Basic_Emoji ; white heart # 12.0 [3] (๐Ÿค..๐Ÿค) - (0x1F910, 0x1F918), // ; Basic_Emoji ; zipper-mouth face # 8.0 [9] (๐Ÿค..๐Ÿค˜) - (0x1F919, 0x1F91E), // ; Basic_Emoji ; call me hand # 9.0 [6] (๐Ÿค™..๐Ÿคž) - (0x1F91F, 0x1F91F), // ; Basic_Emoji ; love-you gesture # 10.0 [1] (๐ŸคŸ) - (0x1F920, 0x1F927), // ; Basic_Emoji ; cowboy hat face # 9.0 [8] (๐Ÿค ..๐Ÿคง) - (0x1F928, 0x1F92F), // ; Basic_Emoji ; face with raised eyebrow # 10.0 [8] (๐Ÿคจ..๐Ÿคฏ) - (0x1F930, 0x1F930), // ; Basic_Emoji ; pregnant woman # 9.0 [1] (๐Ÿคฐ) - (0x1F931, 0x1F932), // ; Basic_Emoji ; breast-feeding # 10.0 [2] (๐Ÿคฑ..๐Ÿคฒ) - (0x1F933, 0x1F93A), // ; Basic_Emoji ; selfie # 9.0 [8] (๐Ÿคณ..๐Ÿคบ) - (0x1F93C, 0x1F93E), // ; Basic_Emoji ; people wrestling # 9.0 [3] (๐Ÿคผ..๐Ÿคพ) - (0x1F93F, 0x1F93F), // ; Basic_Emoji ; diving mask # 12.0 [1] (๐Ÿคฟ) - (0x1F940, 0x1F945), // ; Basic_Emoji ; wilted flower # 9.0 [6] (๐Ÿฅ€..๐Ÿฅ…) - (0x1F947, 0x1F94B), // ; Basic_Emoji ; 1st place medal # 9.0 [5] (๐Ÿฅ‡..๐Ÿฅ‹) - (0x1F94C, 0x1F94C), // ; Basic_Emoji ; curling stone # 10.0 [1] (๐ŸฅŒ) - (0x1F94D, 0x1F94F), // ; Basic_Emoji ; lacrosse # 11.0 [3] (๐Ÿฅ..๐Ÿฅ) - (0x1F950, 0x1F95E), // ; Basic_Emoji ; croissant # 9.0 [15] (๐Ÿฅ..๐Ÿฅž) - (0x1F95F, 0x1F96B), // ; Basic_Emoji ; dumpling # 10.0 [13] (๐ŸฅŸ..๐Ÿฅซ) - (0x1F96C, 0x1F970), // ; Basic_Emoji ; leafy green # 11.0 [5] (๐Ÿฅฌ..๐Ÿฅฐ) - (0x1F971, 0x1F971), // ; Basic_Emoji ; yawning face # 12.0 [1] (๐Ÿฅฑ) - (0x1F973, 0x1F976), // ; Basic_Emoji ; partying face # 11.0 [4] (๐Ÿฅณ..๐Ÿฅถ) - (0x1F97A, 0x1F97A), // ; Basic_Emoji ; pleading face # 11.0 [1] (๐Ÿฅบ) - (0x1F97B, 0x1F97B), // ; Basic_Emoji ; sari # 12.0 [1] (๐Ÿฅป) - (0x1F97C, 0x1F97F), // ; Basic_Emoji ; lab coat # 11.0 [4] (๐Ÿฅผ..๐Ÿฅฟ) - (0x1F980, 0x1F984), // ; Basic_Emoji ; crab # 8.0 [5] (๐Ÿฆ€..๐Ÿฆ„) - (0x1F985, 0x1F991), // ; Basic_Emoji ; eagle # 9.0 [13] (๐Ÿฆ…..๐Ÿฆ‘) - (0x1F992, 0x1F997), // ; Basic_Emoji ; giraffe # 10.0 [6] (๐Ÿฆ’..๐Ÿฆ—) - (0x1F998, 0x1F9A2), // ; Basic_Emoji ; kangaroo # 11.0 [11] (๐Ÿฆ˜..๐Ÿฆข) - (0x1F9A5, 0x1F9AA), // ; Basic_Emoji ; sloth # 12.0 [6] (๐Ÿฆฅ..๐Ÿฆช) - (0x1F9AE, 0x1F9AF), // ; Basic_Emoji ; guide dog # 12.0 [2] (๐Ÿฆฎ..๐Ÿฆฏ) - (0x1F9B0, 0x1F9B9), // ; Basic_Emoji ; red hair # 11.0 [10] (๐Ÿฆฐ..๐Ÿฆน) - (0x1F9BA, 0x1F9BF), // ; Basic_Emoji ; safety vest # 12.0 [6] (๐Ÿฆบ..๐Ÿฆฟ) - (0x1F9C0, 0x1F9C0), // ; Basic_Emoji ; cheese wedge # 8.0 [1] (๐Ÿง€) - (0x1F9C1, 0x1F9C2), // ; Basic_Emoji ; cupcake # 11.0 [2] (๐Ÿง..๐Ÿง‚) - (0x1F9C3, 0x1F9CA), // ; Basic_Emoji ; beverage box # 12.0 [8] (๐Ÿงƒ..๐ŸงŠ) - (0x1F9CD, 0x1F9CF), // ; Basic_Emoji ; person standing # 12.0 [3] (๐Ÿง..๐Ÿง) - (0x1F9D0, 0x1F9E6), // ; Basic_Emoji ; face with monocle # 10.0 [23] (๐Ÿง..๐Ÿงฆ) - (0x1F9E7, 0x1F9FF), // ; Basic_Emoji ; red envelope # 11.0 [25] (๐Ÿงง..๐Ÿงฟ) - (0x1FA70, 0x1FA73), // ; Basic_Emoji ; ballet shoes # 12.0 [4] (๐Ÿฉฐ..๐Ÿฉณ) - (0x1FA78, 0x1FA7A), // ; Basic_Emoji ; drop of blood # 12.0 [3] (๐Ÿฉธ..๐Ÿฉบ) - (0x1FA80, 0x1FA82), // ; Basic_Emoji ; yo-yo # 12.0 [3] (๐Ÿช€..๐Ÿช‚) - (0x1FA90, 0x1FA95), // ; Basic_Emoji ; ringed planet # 12.0 [6] (๐Ÿช..๐Ÿช•) -]; -/* -00A9 FE0F ; Basic_Emoji ; copyright # 3.2 [1] (ยฉ๏ธ) -00AE FE0F ; Basic_Emoji ; registered # 3.2 [1] (ยฎ๏ธ) -203C FE0F ; Basic_Emoji ; double exclamation mark # 3.2 [1] (โ€ผ๏ธ) -2049 FE0F ; Basic_Emoji ; exclamation question mark # 3.2 [1] (โ‰๏ธ) -2122 FE0F ; Basic_Emoji ; trade mark # 3.2 [1] (โ„ข๏ธ) -2139 FE0F ; Basic_Emoji ; information # 3.2 [1] (โ„น๏ธ) -2194 FE0F ; Basic_Emoji ; left-right arrow # 3.2 [1] (โ†”๏ธ) -2195 FE0F ; Basic_Emoji ; up-down arrow # 3.2 [1] (โ†•๏ธ) -2196 FE0F ; Basic_Emoji ; up-left arrow # 3.2 [1] (โ†–๏ธ) -2197 FE0F ; Basic_Emoji ; up-right arrow # 3.2 [1] (โ†—๏ธ) -2198 FE0F ; Basic_Emoji ; down-right arrow # 3.2 [1] (โ†˜๏ธ) -2199 FE0F ; Basic_Emoji ; down-left arrow # 3.2 [1] (โ†™๏ธ) -21A9 FE0F ; Basic_Emoji ; right arrow curving left # 3.2 [1] (โ†ฉ๏ธ) -21AA FE0F ; Basic_Emoji ; left arrow curving right # 3.2 [1] (โ†ช๏ธ) -2328 FE0F ; Basic_Emoji ; keyboard # 3.2 [1] (โŒจ๏ธ) -23CF FE0F ; Basic_Emoji ; eject button # 4.0 [1] (โ๏ธ) -23ED FE0F ; Basic_Emoji ; next track button # 6.0 [1] (โญ๏ธ) -23EE FE0F ; Basic_Emoji ; last track button # 6.0 [1] (โฎ๏ธ) -23EF FE0F ; Basic_Emoji ; play or pause button # 6.0 [1] (โฏ๏ธ) -23F1 FE0F ; Basic_Emoji ; stopwatch # 6.0 [1] (โฑ๏ธ) -23F2 FE0F ; Basic_Emoji ; timer clock # 6.0 [1] (โฒ๏ธ) -23F8 FE0F ; Basic_Emoji ; pause button # 7.0 [1] (โธ๏ธ) -23F9 FE0F ; Basic_Emoji ; stop button # 7.0 [1] (โน๏ธ) -23FA FE0F ; Basic_Emoji ; record button # 7.0 [1] (โบ๏ธ) -24C2 FE0F ; Basic_Emoji ; circled M # 3.2 [1] (โ“‚๏ธ) -25AA FE0F ; Basic_Emoji ; black small square # 3.2 [1] (โ–ช๏ธ) -25AB FE0F ; Basic_Emoji ; white small square # 3.2 [1] (โ–ซ๏ธ) -25B6 FE0F ; Basic_Emoji ; play button # 3.2 [1] (โ–ถ๏ธ) -25C0 FE0F ; Basic_Emoji ; reverse button # 3.2 [1] (โ—€๏ธ) -25FB FE0F ; Basic_Emoji ; white medium square # 3.2 [1] (โ—ป๏ธ) -25FC FE0F ; Basic_Emoji ; black medium square # 3.2 [1] (โ—ผ๏ธ) -2600 FE0F ; Basic_Emoji ; sun # 3.2 [1] (โ˜€๏ธ) -2601 FE0F ; Basic_Emoji ; cloud # 3.2 [1] (โ˜๏ธ) -2602 FE0F ; Basic_Emoji ; umbrella # 3.2 [1] (โ˜‚๏ธ) -2603 FE0F ; Basic_Emoji ; snowman # 3.2 [1] (โ˜ƒ๏ธ) -2604 FE0F ; Basic_Emoji ; comet # 3.2 [1] (โ˜„๏ธ) -260E FE0F ; Basic_Emoji ; telephone # 3.2 [1] (โ˜Ž๏ธ) -2611 FE0F ; Basic_Emoji ; check box with check # 3.2 [1] (โ˜‘๏ธ) -2618 FE0F ; Basic_Emoji ; shamrock # 4.1 [1] (โ˜˜๏ธ) -261D FE0F ; Basic_Emoji ; index pointing up # 3.2 [1] (โ˜๏ธ) -2620 FE0F ; Basic_Emoji ; skull and crossbones # 3.2 [1] (โ˜ ๏ธ) -2622 FE0F ; Basic_Emoji ; radioactive # 3.2 [1] (โ˜ข๏ธ) -2623 FE0F ; Basic_Emoji ; biohazard # 3.2 [1] (โ˜ฃ๏ธ) -2626 FE0F ; Basic_Emoji ; orthodox cross # 3.2 [1] (โ˜ฆ๏ธ) -262A FE0F ; Basic_Emoji ; star and crescent # 3.2 [1] (โ˜ช๏ธ) -262E FE0F ; Basic_Emoji ; peace symbol # 3.2 [1] (โ˜ฎ๏ธ) -262F FE0F ; Basic_Emoji ; yin yang # 3.2 [1] (โ˜ฏ๏ธ) -2638 FE0F ; Basic_Emoji ; wheel of dharma # 3.2 [1] (โ˜ธ๏ธ) -2639 FE0F ; Basic_Emoji ; frowning face # 3.2 [1] (โ˜น๏ธ) -263A FE0F ; Basic_Emoji ; smiling face # 3.2 [1] (โ˜บ๏ธ) -2640 FE0F ; Basic_Emoji ; female sign # 3.2 [1] (โ™€๏ธ) -2642 FE0F ; Basic_Emoji ; male sign # 3.2 [1] (โ™‚๏ธ) -265F FE0F ; Basic_Emoji ; chess pawn # 3.2 [1] (โ™Ÿ๏ธ) -2660 FE0F ; Basic_Emoji ; spade suit # 3.2 [1] (โ™ ๏ธ) -2663 FE0F ; Basic_Emoji ; club suit # 3.2 [1] (โ™ฃ๏ธ) -2665 FE0F ; Basic_Emoji ; heart suit # 3.2 [1] (โ™ฅ๏ธ) -2666 FE0F ; Basic_Emoji ; diamond suit # 3.2 [1] (โ™ฆ๏ธ) -2668 FE0F ; Basic_Emoji ; hot springs # 3.2 [1] (โ™จ๏ธ) -267B FE0F ; Basic_Emoji ; recycling symbol # 3.2 [1] (โ™ป๏ธ) -267E FE0F ; Basic_Emoji ; infinity # 4.1 [1] (โ™พ๏ธ) -2692 FE0F ; Basic_Emoji ; hammer and pick # 4.1 [1] (โš’๏ธ) -2694 FE0F ; Basic_Emoji ; crossed swords # 4.1 [1] (โš”๏ธ) -2695 FE0F ; Basic_Emoji ; medical symbol # 4.1 [1] (โš•๏ธ) -2696 FE0F ; Basic_Emoji ; balance scale # 4.1 [1] (โš–๏ธ) -2697 FE0F ; Basic_Emoji ; alembic # 4.1 [1] (โš—๏ธ) -2699 FE0F ; Basic_Emoji ; gear # 4.1 [1] (โš™๏ธ) -269B FE0F ; Basic_Emoji ; atom symbol # 4.1 [1] (โš›๏ธ) -269C FE0F ; Basic_Emoji ; fleur-de-lis # 4.1 [1] (โšœ๏ธ) -26A0 FE0F ; Basic_Emoji ; warning # 4.0 [1] (โš ๏ธ) -26B0 FE0F ; Basic_Emoji ; coffin # 4.1 [1] (โšฐ๏ธ) -26B1 FE0F ; Basic_Emoji ; funeral urn # 4.1 [1] (โšฑ๏ธ) -26C8 FE0F ; Basic_Emoji ; cloud with lightning and rain # 5.2 [1] (โ›ˆ๏ธ) -26CF FE0F ; Basic_Emoji ; pick # 5.2 [1] (โ›๏ธ) -26D1 FE0F ; Basic_Emoji ; rescue workerโ€™s helmet # 5.2 [1] (โ›‘๏ธ) -26D3 FE0F ; Basic_Emoji ; chains # 5.2 [1] (โ›“๏ธ) -26E9 FE0F ; Basic_Emoji ; shinto shrine # 5.2 [1] (โ›ฉ๏ธ) -26F0 FE0F ; Basic_Emoji ; mountain # 5.2 [1] (โ›ฐ๏ธ) -26F1 FE0F ; Basic_Emoji ; umbrella on ground # 5.2 [1] (โ›ฑ๏ธ) -26F4 FE0F ; Basic_Emoji ; ferry # 5.2 [1] (โ›ด๏ธ) -26F7 FE0F ; Basic_Emoji ; skier # 5.2 [1] (โ›ท๏ธ) -26F8 FE0F ; Basic_Emoji ; ice skate # 5.2 [1] (โ›ธ๏ธ) -26F9 FE0F ; Basic_Emoji ; person bouncing ball # 5.2 [1] (โ›น๏ธ) -2702 FE0F ; Basic_Emoji ; scissors # 3.2 [1] (โœ‚๏ธ) -2708 FE0F ; Basic_Emoji ; airplane # 3.2 [1] (โœˆ๏ธ) -2709 FE0F ; Basic_Emoji ; envelope # 3.2 [1] (โœ‰๏ธ) -270C FE0F ; Basic_Emoji ; victory hand # 3.2 [1] (โœŒ๏ธ) -270D FE0F ; Basic_Emoji ; writing hand # 3.2 [1] (โœ๏ธ) -270F FE0F ; Basic_Emoji ; pencil # 3.2 [1] (โœ๏ธ) -2712 FE0F ; Basic_Emoji ; black nib # 3.2 [1] (โœ’๏ธ) -2714 FE0F ; Basic_Emoji ; check mark # 3.2 [1] (โœ”๏ธ) -2716 FE0F ; Basic_Emoji ; multiplication sign # 3.2 [1] (โœ–๏ธ) -271D FE0F ; Basic_Emoji ; latin cross # 3.2 [1] (โœ๏ธ) -2721 FE0F ; Basic_Emoji ; star of David # 3.2 [1] (โœก๏ธ) -2733 FE0F ; Basic_Emoji ; eight-spoked asterisk # 3.2 [1] (โœณ๏ธ) -2734 FE0F ; Basic_Emoji ; eight-pointed star # 3.2 [1] (โœด๏ธ) -2744 FE0F ; Basic_Emoji ; snowflake # 3.2 [1] (โ„๏ธ) -2747 FE0F ; Basic_Emoji ; sparkle # 3.2 [1] (โ‡๏ธ) -2763 FE0F ; Basic_Emoji ; heart exclamation # 3.2 [1] (โฃ๏ธ) -2764 FE0F ; Basic_Emoji ; red heart # 3.2 [1] (โค๏ธ) -27A1 FE0F ; Basic_Emoji ; right arrow # 3.2 [1] (โžก๏ธ) -2934 FE0F ; Basic_Emoji ; right arrow curving up # 3.2 [1] (โคด๏ธ) -2935 FE0F ; Basic_Emoji ; right arrow curving down # 3.2 [1] (โคต๏ธ) -2B05 FE0F ; Basic_Emoji ; left arrow # 4.0 [1] (โฌ…๏ธ) -2B06 FE0F ; Basic_Emoji ; up arrow # 4.0 [1] (โฌ†๏ธ) -2B07 FE0F ; Basic_Emoji ; down arrow # 4.0 [1] (โฌ‡๏ธ) -3030 FE0F ; Basic_Emoji ; wavy dash # 3.2 [1] (ใ€ฐ๏ธ) -303D FE0F ; Basic_Emoji ; part alternation mark # 3.2 [1] (ใ€ฝ๏ธ) -3297 FE0F ; Basic_Emoji ; Japanese โ€œcongratulationsโ€ button # 3.2 [1] (ใŠ—๏ธ) -3299 FE0F ; Basic_Emoji ; Japanese โ€œsecretโ€ button # 3.2 [1] (ใŠ™๏ธ) -1F170 FE0F ; Basic_Emoji ; A button (blood type) # 6.0 [1] (๐Ÿ…ฐ๏ธ) -1F171 FE0F ; Basic_Emoji ; B button (blood type) # 6.0 [1] (๐Ÿ…ฑ๏ธ) -1F17E FE0F ; Basic_Emoji ; O button (blood type) # 6.0 [1] (๐Ÿ…พ๏ธ) -1F17F FE0F ; Basic_Emoji ; P button # 5.2 [1] (๐Ÿ…ฟ๏ธ) -1F202 FE0F ; Basic_Emoji ; Japanese โ€œservice chargeโ€ button # 6.0 [1] (๐Ÿˆ‚๏ธ) -1F237 FE0F ; Basic_Emoji ; Japanese โ€œmonthly amountโ€ button # 6.0 [1] (๐Ÿˆท๏ธ) -1F321 FE0F ; Basic_Emoji ; thermometer # 7.0 [1] (๐ŸŒก๏ธ) -1F324 FE0F ; Basic_Emoji ; sun behind small cloud # 7.0 [1] (๐ŸŒค๏ธ) -1F325 FE0F ; Basic_Emoji ; sun behind large cloud # 7.0 [1] (๐ŸŒฅ๏ธ) -1F326 FE0F ; Basic_Emoji ; sun behind rain cloud # 7.0 [1] (๐ŸŒฆ๏ธ) -1F327 FE0F ; Basic_Emoji ; cloud with rain # 7.0 [1] (๐ŸŒง๏ธ) -1F328 FE0F ; Basic_Emoji ; cloud with snow # 7.0 [1] (๐ŸŒจ๏ธ) -1F329 FE0F ; Basic_Emoji ; cloud with lightning # 7.0 [1] (๐ŸŒฉ๏ธ) -1F32A FE0F ; Basic_Emoji ; tornado # 7.0 [1] (๐ŸŒช๏ธ) -1F32B FE0F ; Basic_Emoji ; fog # 7.0 [1] (๐ŸŒซ๏ธ) -1F32C FE0F ; Basic_Emoji ; wind face # 7.0 [1] (๐ŸŒฌ๏ธ) -1F336 FE0F ; Basic_Emoji ; hot pepper # 7.0 [1] (๐ŸŒถ๏ธ) -1F37D FE0F ; Basic_Emoji ; fork and knife with plate # 7.0 [1] (๐Ÿฝ๏ธ) -1F396 FE0F ; Basic_Emoji ; military medal # 7.0 [1] (๐ŸŽ–๏ธ) -1F397 FE0F ; Basic_Emoji ; reminder ribbon # 7.0 [1] (๐ŸŽ—๏ธ) -1F399 FE0F ; Basic_Emoji ; studio microphone # 7.0 [1] (๐ŸŽ™๏ธ) -1F39A FE0F ; Basic_Emoji ; level slider # 7.0 [1] (๐ŸŽš๏ธ) -1F39B FE0F ; Basic_Emoji ; control knobs # 7.0 [1] (๐ŸŽ›๏ธ) -1F39E FE0F ; Basic_Emoji ; film frames # 7.0 [1] (๐ŸŽž๏ธ) -1F39F FE0F ; Basic_Emoji ; admission tickets # 7.0 [1] (๐ŸŽŸ๏ธ) -1F3CB FE0F ; Basic_Emoji ; person lifting weights # 7.0 [1] (๐Ÿ‹๏ธ) -1F3CC FE0F ; Basic_Emoji ; person golfing # 7.0 [1] (๐ŸŒ๏ธ) -1F3CD FE0F ; Basic_Emoji ; motorcycle # 7.0 [1] (๐Ÿ๏ธ) -1F3CE FE0F ; Basic_Emoji ; racing car # 7.0 [1] (๐ŸŽ๏ธ) -1F3D4 FE0F ; Basic_Emoji ; snow-capped mountain # 7.0 [1] (๐Ÿ”๏ธ) -1F3D5 FE0F ; Basic_Emoji ; camping # 7.0 [1] (๐Ÿ•๏ธ) -1F3D6 FE0F ; Basic_Emoji ; beach with umbrella # 7.0 [1] (๐Ÿ–๏ธ) -1F3D7 FE0F ; Basic_Emoji ; building construction # 7.0 [1] (๐Ÿ—๏ธ) -1F3D8 FE0F ; Basic_Emoji ; houses # 7.0 [1] (๐Ÿ˜๏ธ) -1F3D9 FE0F ; Basic_Emoji ; cityscape # 7.0 [1] (๐Ÿ™๏ธ) -1F3DA FE0F ; Basic_Emoji ; derelict house # 7.0 [1] (๐Ÿš๏ธ) -1F3DB FE0F ; Basic_Emoji ; classical building # 7.0 [1] (๐Ÿ›๏ธ) -1F3DC FE0F ; Basic_Emoji ; desert # 7.0 [1] (๐Ÿœ๏ธ) -1F3DD FE0F ; Basic_Emoji ; desert island # 7.0 [1] (๐Ÿ๏ธ) -1F3DE FE0F ; Basic_Emoji ; national park # 7.0 [1] (๐Ÿž๏ธ) -1F3DF FE0F ; Basic_Emoji ; stadium # 7.0 [1] (๐ŸŸ๏ธ) -1F3F3 FE0F ; Basic_Emoji ; white flag # 7.0 [1] (๐Ÿณ๏ธ) -1F3F5 FE0F ; Basic_Emoji ; rosette # 7.0 [1] (๐Ÿต๏ธ) -1F3F7 FE0F ; Basic_Emoji ; label # 7.0 [1] (๐Ÿท๏ธ) -1F43F FE0F ; Basic_Emoji ; chipmunk # 7.0 [1] (๐Ÿฟ๏ธ) -1F441 FE0F ; Basic_Emoji ; eye # 7.0 [1] (๐Ÿ‘๏ธ) -1F4FD FE0F ; Basic_Emoji ; film projector # 7.0 [1] (๐Ÿ“ฝ๏ธ) -1F549 FE0F ; Basic_Emoji ; om # 7.0 [1] (๐Ÿ•‰๏ธ) -1F54A FE0F ; Basic_Emoji ; dove # 7.0 [1] (๐Ÿ•Š๏ธ) -1F56F FE0F ; Basic_Emoji ; candle # 7.0 [1] (๐Ÿ•ฏ๏ธ) -1F570 FE0F ; Basic_Emoji ; mantelpiece clock # 7.0 [1] (๐Ÿ•ฐ๏ธ) -1F573 FE0F ; Basic_Emoji ; hole # 7.0 [1] (๐Ÿ•ณ๏ธ) -1F574 FE0F ; Basic_Emoji ; man in suit levitating # 7.0 [1] (๐Ÿ•ด๏ธ) -1F575 FE0F ; Basic_Emoji ; detective # 7.0 [1] (๐Ÿ•ต๏ธ) -1F576 FE0F ; Basic_Emoji ; sunglasses # 7.0 [1] (๐Ÿ•ถ๏ธ) -1F577 FE0F ; Basic_Emoji ; spider # 7.0 [1] (๐Ÿ•ท๏ธ) -1F578 FE0F ; Basic_Emoji ; spider web # 7.0 [1] (๐Ÿ•ธ๏ธ) -1F579 FE0F ; Basic_Emoji ; joystick # 7.0 [1] (๐Ÿ•น๏ธ) -1F587 FE0F ; Basic_Emoji ; linked paperclips # 7.0 [1] (๐Ÿ–‡๏ธ) -1F58A FE0F ; Basic_Emoji ; pen # 7.0 [1] (๐Ÿ–Š๏ธ) -1F58B FE0F ; Basic_Emoji ; fountain pen # 7.0 [1] (๐Ÿ–‹๏ธ) -1F58C FE0F ; Basic_Emoji ; paintbrush # 7.0 [1] (๐Ÿ–Œ๏ธ) -1F58D FE0F ; Basic_Emoji ; crayon # 7.0 [1] (๐Ÿ–๏ธ) -1F590 FE0F ; Basic_Emoji ; hand with fingers splayed # 7.0 [1] (๐Ÿ–๏ธ) -1F5A5 FE0F ; Basic_Emoji ; desktop computer # 7.0 [1] (๐Ÿ–ฅ๏ธ) -1F5A8 FE0F ; Basic_Emoji ; printer # 7.0 [1] (๐Ÿ–จ๏ธ) -1F5B1 FE0F ; Basic_Emoji ; computer mouse # 7.0 [1] (๐Ÿ–ฑ๏ธ) -1F5B2 FE0F ; Basic_Emoji ; trackball # 7.0 [1] (๐Ÿ–ฒ๏ธ) -1F5BC FE0F ; Basic_Emoji ; framed picture # 7.0 [1] (๐Ÿ–ผ๏ธ) -1F5C2 FE0F ; Basic_Emoji ; card index dividers # 7.0 [1] (๐Ÿ—‚๏ธ) -1F5C3 FE0F ; Basic_Emoji ; card file box # 7.0 [1] (๐Ÿ—ƒ๏ธ) -1F5C4 FE0F ; Basic_Emoji ; file cabinet # 7.0 [1] (๐Ÿ—„๏ธ) -1F5D1 FE0F ; Basic_Emoji ; wastebasket # 7.0 [1] (๐Ÿ—‘๏ธ) -1F5D2 FE0F ; Basic_Emoji ; spiral notepad # 7.0 [1] (๐Ÿ—’๏ธ) -1F5D3 FE0F ; Basic_Emoji ; spiral calendar # 7.0 [1] (๐Ÿ—“๏ธ) -1F5DC FE0F ; Basic_Emoji ; clamp # 7.0 [1] (๐Ÿ—œ๏ธ) -1F5DD FE0F ; Basic_Emoji ; old key # 7.0 [1] (๐Ÿ—๏ธ) -1F5DE FE0F ; Basic_Emoji ; rolled-up newspaper # 7.0 [1] (๐Ÿ—ž๏ธ) -1F5E1 FE0F ; Basic_Emoji ; dagger # 7.0 [1] (๐Ÿ—ก๏ธ) -1F5E3 FE0F ; Basic_Emoji ; speaking head # 7.0 [1] (๐Ÿ—ฃ๏ธ) -1F5E8 FE0F ; Basic_Emoji ; left speech bubble # 7.0 [1] (๐Ÿ—จ๏ธ) -1F5EF FE0F ; Basic_Emoji ; right anger bubble # 7.0 [1] (๐Ÿ—ฏ๏ธ) -1F5F3 FE0F ; Basic_Emoji ; ballot box with ballot # 7.0 [1] (๐Ÿ—ณ๏ธ) -1F5FA FE0F ; Basic_Emoji ; world map # 7.0 [1] (๐Ÿ—บ๏ธ) -1F6CB FE0F ; Basic_Emoji ; couch and lamp # 7.0 [1] (๐Ÿ›‹๏ธ) -1F6CD FE0F ; Basic_Emoji ; shopping bags # 7.0 [1] (๐Ÿ›๏ธ) -1F6CE FE0F ; Basic_Emoji ; bellhop bell # 7.0 [1] (๐Ÿ›Ž๏ธ) -1F6CF FE0F ; Basic_Emoji ; bed # 7.0 [1] (๐Ÿ›๏ธ) -1F6E0 FE0F ; Basic_Emoji ; hammer and wrench # 7.0 [1] (๐Ÿ› ๏ธ) -1F6E1 FE0F ; Basic_Emoji ; shield # 7.0 [1] (๐Ÿ›ก๏ธ) -1F6E2 FE0F ; Basic_Emoji ; oil drum # 7.0 [1] (๐Ÿ›ข๏ธ) -1F6E3 FE0F ; Basic_Emoji ; motorway # 7.0 [1] (๐Ÿ›ฃ๏ธ) -1F6E4 FE0F ; Basic_Emoji ; railway track # 7.0 [1] (๐Ÿ›ค๏ธ) -1F6E5 FE0F ; Basic_Emoji ; motor boat # 7.0 [1] (๐Ÿ›ฅ๏ธ) -1F6E9 FE0F ; Basic_Emoji ; small airplane # 7.0 [1] (๐Ÿ›ฉ๏ธ) -1F6F0 FE0F ; Basic_Emoji ; satellite # 7.0 [1] (๐Ÿ›ฐ๏ธ) -1F6F3 FE0F ; Basic_Emoji ; passenger ship # 7.0 [1] (๐Ÿ›ณ๏ธ) -*/