Add UTF-8 mouse mode support

Fixes #1934.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b29c6c1..c7edd33 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,7 @@
 - Alternate scroll escape sequence (`CSI ? 1007 h` / `CSI ? 1007 l`)
 - Print name of launch command if Alacritty failed to execute it
 - Live reload font settings from config
+- UTF-8 mouse mode escape sequence (`CSI ? 1005 h` / `CSI ? 1005 l`)
 
 ### Changed
 
diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs
index 422d6a3..5a85266 100644
--- a/alacritty/src/input.rs
+++ b/alacritty/src/input.rs
@@ -368,19 +368,36 @@
 
     pub fn normal_mouse_report(&mut self, button: u8) {
         let (line, column) = (self.ctx.mouse().line, self.ctx.mouse().column);
+        let utf8 = self.ctx.terminal().mode().contains(TermMode::UTF8_MOUSE);
 
-        if line < Line(223) && column < Column(223) {
-            let msg = vec![
-                b'\x1b',
-                b'[',
-                b'M',
-                32 + button,
-                32 + 1 + column.0 as u8,
-                32 + 1 + line.0 as u8,
-            ];
+        let max_point = if utf8 { 2015 } else { 223 };
 
-            self.ctx.write_to_pty(msg);
+        if line >= Line(max_point) || column >= Column(max_point) {
+            return;
         }
+
+        let mut msg = vec![b'\x1b', b'[', b'M', 32 + button];
+
+        let mouse_pos_encode = |pos: usize| -> Vec<u8> {
+            let pos = 32 + 1 + pos;
+            let first = 0xC0 + pos / 64;
+            let second = 0x80 + (pos & 63);
+            vec![first as u8, second as u8]
+        };
+
+        if utf8 && column >= Column(95) {
+            msg.append(&mut mouse_pos_encode(column.0));
+        } else {
+            msg.push(32 + 1 + column.0 as u8);
+        }
+
+        if utf8 && line >= Line(95) {
+            msg.append(&mut mouse_pos_encode(line.0));
+        } else {
+            msg.push(32 + 1 + line.0 as u8);
+        }
+
+        self.ctx.write_to_pty(msg);
     }
 
     pub fn sgr_mouse_report(&mut self, button: u8, state: ElementState) {
diff --git a/alacritty_terminal/src/ansi.rs b/alacritty_terminal/src/ansi.rs
index a05904d..55c064e 100644
--- a/alacritty_terminal/src/ansi.rs
+++ b/alacritty_terminal/src/ansi.rs
@@ -406,6 +406,8 @@
     ReportAllMouseMotion = 1003,
     /// ?1004
     ReportFocusInOut = 1004,
+    /// ?1005
+    Utf8Mouse = 1005,
     /// ?1006
     SgrMouse = 1006,
     /// ?1007
@@ -439,6 +441,7 @@
                 1002 => Mode::ReportCellMouseMotion,
                 1003 => Mode::ReportAllMouseMotion,
                 1004 => Mode::ReportFocusInOut,
+                1005 => Mode::Utf8Mouse,
                 1006 => Mode::SgrMouse,
                 1007 => Mode::AlternateScroll,
                 1049 => Mode::SwapScreenAndSetRestoreCursor,
diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs
index f7b37b2..570dc7f 100644
--- a/alacritty_terminal/src/term/mod.rs
+++ b/alacritty_terminal/src/term/mod.rs
@@ -436,23 +436,24 @@
 
     bitflags! {
         pub struct TermMode: u16 {
-            const SHOW_CURSOR         = 0b000_0000_0000_0001;
-            const APP_CURSOR          = 0b000_0000_0000_0010;
-            const APP_KEYPAD          = 0b000_0000_0000_0100;
-            const MOUSE_REPORT_CLICK  = 0b000_0000_0000_1000;
-            const BRACKETED_PASTE     = 0b000_0000_0001_0000;
-            const SGR_MOUSE           = 0b000_0000_0010_0000;
-            const MOUSE_MOTION        = 0b000_0000_0100_0000;
-            const LINE_WRAP           = 0b000_0000_1000_0000;
-            const LINE_FEED_NEW_LINE  = 0b000_0001_0000_0000;
-            const ORIGIN              = 0b000_0010_0000_0000;
-            const INSERT              = 0b000_0100_0000_0000;
-            const FOCUS_IN_OUT        = 0b000_1000_0000_0000;
-            const ALT_SCREEN          = 0b001_0000_0000_0000;
-            const MOUSE_DRAG          = 0b010_0000_0000_0000;
-            const MOUSE_MODE          = 0b010_0000_0100_1000;
-            const ALTERNATE_SCROLL    = 0b100_0000_0000_0000;
-            const ANY                 = 0b111_1111_1111_1111;
+            const SHOW_CURSOR         = 0b0000_0000_0000_0001;
+            const APP_CURSOR          = 0b0000_0000_0000_0010;
+            const APP_KEYPAD          = 0b0000_0000_0000_0100;
+            const MOUSE_REPORT_CLICK  = 0b0000_0000_0000_1000;
+            const BRACKETED_PASTE     = 0b0000_0000_0001_0000;
+            const SGR_MOUSE           = 0b0000_0000_0010_0000;
+            const MOUSE_MOTION        = 0b0000_0000_0100_0000;
+            const LINE_WRAP           = 0b0000_0000_1000_0000;
+            const LINE_FEED_NEW_LINE  = 0b0000_0001_0000_0000;
+            const ORIGIN              = 0b0000_0010_0000_0000;
+            const INSERT              = 0b0000_0100_0000_0000;
+            const FOCUS_IN_OUT        = 0b0000_1000_0000_0000;
+            const ALT_SCREEN          = 0b0001_0000_0000_0000;
+            const MOUSE_DRAG          = 0b0010_0000_0000_0000;
+            const MOUSE_MODE          = 0b0010_0000_0100_1000;
+            const UTF8_MOUSE          = 0b0100_0000_0000_0000;
+            const ALTERNATE_SCROLL    = 0b1000_0000_0000_0000;
+            const ANY                 = 0b1111_1111_1111_1111;
             const NONE                = 0;
         }
     }
@@ -1867,6 +1868,7 @@
             ansi::Mode::ReportFocusInOut => self.mode.insert(TermMode::FOCUS_IN_OUT),
             ansi::Mode::BracketedPaste => self.mode.insert(TermMode::BRACKETED_PASTE),
             ansi::Mode::SgrMouse => self.mode.insert(TermMode::SGR_MOUSE),
+            ansi::Mode::Utf8Mouse => self.mode.insert(TermMode::UTF8_MOUSE),
             ansi::Mode::AlternateScroll => self.mode.insert(TermMode::ALTERNATE_SCROLL),
             ansi::Mode::LineWrap => self.mode.insert(TermMode::LINE_WRAP),
             ansi::Mode::LineFeedNewLine => self.mode.insert(TermMode::LINE_FEED_NEW_LINE),
@@ -1908,6 +1910,7 @@
             ansi::Mode::ReportFocusInOut => self.mode.remove(TermMode::FOCUS_IN_OUT),
             ansi::Mode::BracketedPaste => self.mode.remove(TermMode::BRACKETED_PASTE),
             ansi::Mode::SgrMouse => self.mode.remove(TermMode::SGR_MOUSE),
+            ansi::Mode::Utf8Mouse => self.mode.remove(TermMode::UTF8_MOUSE),
             ansi::Mode::AlternateScroll => self.mode.remove(TermMode::ALTERNATE_SCROLL),
             ansi::Mode::LineWrap => self.mode.remove(TermMode::LINE_WRAP),
             ansi::Mode::LineFeedNewLine => self.mode.remove(TermMode::LINE_FEED_NEW_LINE),