diff --git a/src/terminal/console.rs b/src/terminal/console.rs
index 62d70ac12aeae7e45582f92b5451aeaca9c933ce..34b7acb139462a4e5fee86483e0901af1749067a 100644
--- a/src/terminal/console.rs
+++ b/src/terminal/console.rs
@@ -1,6 +1,6 @@
 extern crate ransid;
 
-use std::cmp;
+use std::{cmp, mem};
 use std::collections::{BTreeSet, VecDeque};
 use std::io::Result;
 
@@ -42,15 +42,20 @@ pub struct Block {
 pub struct Console {
     pub console: ransid::Console,
     pub window: Window,
+    pub alternate: bool,
     pub grid: Box<[Block]>,
+    pub alt_grid: Box<[Block]>,
     pub font: Font,
     pub font_bold: Font,
     pub changed: BTreeSet<usize>,
+    pub mouse_x: u16,
+    pub mouse_y: u16,
+    pub mouse_left: bool,
     pub ctrl: bool,
     pub input: Vec<u8>,
     pub end_of_input: bool,
     pub cooked: VecDeque<u8>,
-    pub requested: usize
+    pub requested: usize,
 }
 
 impl Console {
@@ -65,11 +70,16 @@ impl Console {
 
         Console {
             console: ransid,
-            grid: grid,
+            alternate: false,
+            grid: grid.clone(),
+            alt_grid: grid,
             window: window,
             font: Font::find(None, None, None).unwrap(),
             font_bold: Font::find(None, None, Some("Bold")).unwrap(),
             changed: BTreeSet::new(),
+            mouse_x: 0,
+            mouse_y: 0,
+            mouse_left: false,
             ctrl: false,
             input: Vec::new(),
             end_of_input: false,
@@ -138,9 +148,7 @@ impl Console {
                 }
 
                 if self.console.raw_mode {
-                    for &b in buf.iter() {
-                        self.input.push(b);
-                    }
+                    self.input.extend(buf);
                 } else {
                     for &b in buf.iter() {
                         match b {
@@ -171,8 +179,42 @@ impl Console {
                     }
                 }
             },
-            EventOption::Mouse(_) => {
-                //TODO: Mouse in terminal
+            EventOption::Mouse(mouse_event) => {
+                let x = (mouse_event.x/8) as u16 + 1;
+                let y = (mouse_event.y/16) as u16 + 1;
+                if self.console.mouse_rxvt && self.console.mouse_btn {
+                    if self.mouse_left && (x != self.mouse_x || y != self.mouse_y) {
+                        let string = format!("\x1B[<{};{};{}M", 32, self.mouse_x, self.mouse_y);
+                        self.input.extend(string.as_bytes());
+                    }
+                }
+                self.mouse_x = x;
+                self.mouse_y = y;
+            },
+            EventOption::Button(button_event) => {
+                if self.console.mouse_rxvt {
+                    if button_event.left {
+                        if ! self.mouse_left {
+                            let string = format!("\x1B[<{};{};{}M", 0, self.mouse_x, self.mouse_y);
+                            self.input.extend(string.as_bytes());
+                        }
+                    } else if self.mouse_left {
+                        let string = format!("\x1B[<{};{};{}m", 0, self.mouse_x, self.mouse_y);
+                        self.input.extend(string.as_bytes());
+                    }
+                    self.mouse_left = button_event.left;
+                }
+            },
+            EventOption::Scroll(scroll_event) => {
+                if self.console.mouse_rxvt {
+                    if scroll_event.y > 0 {
+                        let string = format!("\x1B[<{};{};{}M", 64, self.mouse_x, self.mouse_y);
+                        self.input.extend(string.as_bytes());
+                    } else if scroll_event.y < 0 {
+                        let string = format!("\x1B[<{};{};{}M", 65, self.mouse_x, self.mouse_y);
+                        self.input.extend(string.as_bytes());
+                    }
+                }
             },
             EventOption::Resize(resize_event) => {
                 let w = resize_event.width as usize/8;
@@ -182,6 +224,10 @@ impl Console {
                     c: '\0', fg: self.console.foreground.data, bg: self.console.background.data, bold: false
                 }; w * h].into_boxed_slice();
 
+                let mut alt_grid = vec![Block {
+                    c: '\0', fg: self.console.foreground.data, bg: self.console.background.data, bold: false
+                }; w * h].into_boxed_slice();
+
                 self.window.set(Color { data: self.console.background.data });
 
                 {
@@ -194,9 +240,12 @@ impl Console {
                             let block = self.grid[y * self.console.w + x];
                             if y < h && x < w {
                                 grid[y * w + x] = block;
+
+                                let alt_block = self.alt_grid[y * self.console.w + x];
+                                alt_grid[y * w + x] = alt_block;
                             }
 
-                            window.rect(x as i32 * 8, y as i32 * 16, w as u32 * 8, h as u32 * 16, Color { data: block.bg });
+                            window.rect(x as i32 * 8, y as i32 * 16, 8, 16, Color { data: block.bg });
                             if block.c != '\0' {
                                 if block.bold {
                                     font_bold.render(&block.c.encode_utf8(&mut str_buf), 16.0).draw(window, x as i32 * 8, y as i32 * 16, Color { data: block.fg });
@@ -205,12 +254,14 @@ impl Console {
                                 }
                             }
                         }
+                        self.changed.insert(y as usize);
                     }
                 }
 
                 self.console.w = w;
                 self.console.h = h;
                 self.grid = grid;
+                self.alt_grid = alt_grid;
 
                 if self.console.cursor && self.console.x < self.console.w && self.console.y < self.console.h {
                     let x = self.console.x;
@@ -218,7 +269,7 @@ impl Console {
                     self.invert(x * 8, y * 16, 8, 16);
                 }
 
-                self.redraw();
+                self.sync();
             },
             _ => ()
         }
@@ -269,8 +320,12 @@ impl Console {
         {
             let font = &self.font;
             let font_bold = &self.font_bold;
+            let console_bg = self.console.background;
             let console_w = self.console.w;
+            let console_h = self.console.h;
+            let alt = &mut self.alternate;
             let grid = &mut self.grid;
+            let alt_grid = &mut self.alt_grid;
             let window = &mut self.window;
             let input = &mut self.input;
             let changed = &mut self.changed;
@@ -278,41 +333,70 @@ impl Console {
             self.console.write(buf, |event| {
                 match event {
                     ransid::Event::Char { x, y, c, color, bold, .. } => {
+                        if bold {
+                            font_bold.render(&c.encode_utf8(&mut str_buf), 16.0).draw(window, x as i32 * 8, y as i32 * 16, Color { data: color.data });
+                        } else {
+                            font.render(&c.encode_utf8(&mut str_buf), 16.0).draw(window, x as i32 * 8, y as i32 * 16, Color { data: color.data });
+                        }
                         {
                             let block = &mut grid[y * console_w + x];
                             block.c = c;
                             block.fg = color.data;
                             block.bold = bold;
                         }
-                        if bold {
-                            font_bold.render(&c.encode_utf8(&mut str_buf), 16.0).draw(window, x as i32 * 8, y as i32 * 16, Color { data: color.data });
-                        } else {
-                            font.render(&c.encode_utf8(&mut str_buf), 16.0).draw(window, x as i32 * 8, y as i32 * 16, Color { data: color.data });
-                        }
                         changed.insert(y);
                     },
                     ransid::Event::Input { data } => {
                         input.extend(data);
                     },
                     ransid::Event::Rect { x, y, w, h, color } => {
-                        {
-                            let block = &mut grid[y * console_w + x];
-                            block.c = '\0';
-                            block.bg = color.data;
-                            block.bold = false;
-                        }
                         window.rect(x as i32 * 8, y as i32 * 16, w as u32 * 8, h as u32 * 16, Color { data: color.data });
+
                         for y2 in y..y + h {
+                            for x2 in x..x + w {
+                                let block = &mut grid[y2 * console_w + x2];
+                                block.c = '\0';
+                                block.bg = color.data;
+                            }
                             changed.insert(y2);
                         }
                     },
+                    ransid::Event::ScreenBuffer { alternate, clear } => {
+                        if *alt != alternate {
+                            mem::swap(grid, alt_grid);
+
+                            window.set(Color { data: console_bg.data });
+
+                            for y in 0..console_h {
+                                for x in 0..console_w {
+                                    let block = &mut grid[y * console_w + x];
+
+                                    if clear {
+                                        block.c = '\0';
+                                        block.bg = console_bg.data;
+                                    }
+
+                                    window.rect(x as i32 * 8, y as i32 * 16, 8, 16, Color { data: block.bg });
+                                    if block.c != '\0' {
+                                        if block.bold {
+                                            font_bold.render(&block.c.encode_utf8(&mut str_buf), 16.0).draw(window, x as i32 * 8, y as i32 * 16, Color { data: block.fg });
+                                        } else {
+                                            font.render(&block.c.encode_utf8(&mut str_buf), 16.0).draw(window, x as i32 * 8, y as i32 * 16, Color { data: block.fg });
+                                        }
+                                    }
+                                }
+                                changed.insert(y as usize);
+                            }
+                        }
+                        *alt = alternate;
+                    },
                     ransid::Event::Scroll { rows, color } => {
-                        let rows = rows as u32 * 16;
+                        let pixel_rows = rows as u32 * 16;
 
                         let width = window.width();
                         let height = window.height();
-                        if rows > 0 && rows < height {
-                            let off1 = rows * width;
+                        if pixel_rows > 0 && pixel_rows < height {
+                            let off1 = pixel_rows * width;
                             let off2 = height * width - off1;
                             unsafe {
                                 let data_ptr = window.data_mut().as_mut_ptr() as *mut u32;
@@ -321,7 +405,18 @@ impl Console {
                             }
                         }
 
-                        for y in 0..window.height()/16 {
+                        for y in 0..console_h {
+                            if y >= rows {
+                                for x in 0..console_w {
+                                    let mut block = grid[y * console_w + x];
+                                    grid[(y - rows) * console_w + x] = block;
+                                    if y >= console_h - rows {
+                                        block.c = '\0';
+                                        block.bg = console_bg.data;
+                                        grid[y * console_w + x] = block;
+                                    }
+                                }
+                            }
                             changed.insert(y as usize);
                         }
                     },
diff --git a/src/terminal/main.rs b/src/terminal/main.rs
index 94c80b13c4f8a5fdd56d688a000c6dcf5e650f02..d9fc56504b279d437b15c109f289dc1cb520aa47 100644
--- a/src/terminal/main.rs
+++ b/src/terminal/main.rs
@@ -218,7 +218,8 @@ fn handle(console: &mut Console, master_fd: RawFd, process: &mut Child) {
 }
 
 fn main() {
-    let shell = env::args().nth(1).unwrap_or("sh".to_string());
+    let mut args = env::args().skip(1);
+    let shell = args.next().unwrap_or("sh".to_string());
 
     let (master_fd, tty_path) = getpty();
 
@@ -234,16 +235,21 @@ fn main() {
     env::set_var("TERM", "linux");
     env::set_var("TTY", format!("{}", tty_path.display()));
 
-    match unsafe {
-        Command::new(&shell)
-            .stdin(Stdio::from_raw_fd(slave_stdin.into_raw_fd()))
-            .stdout(Stdio::from_raw_fd(slave_stdout.into_raw_fd()))
-            .stderr(Stdio::from_raw_fd(slave_stderr.into_raw_fd()))
-            .before_exec(|| {
-                before_exec()
-            })
-            .spawn()
-    } {
+    let mut command = Command::new(&shell);
+    for arg in args {
+        command.arg(arg);
+    }
+    unsafe {
+        command
+        .stdin(Stdio::from_raw_fd(slave_stdin.into_raw_fd()))
+        .stdout(Stdio::from_raw_fd(slave_stdout.into_raw_fd()))
+        .stderr(Stdio::from_raw_fd(slave_stderr.into_raw_fd()))
+        .before_exec(|| {
+            before_exec()
+        });
+    }
+
+    match command.spawn() {
         Ok(mut process) => {
             let mut console = Console::new(width, height);
             handle(&mut console, master_fd, &mut process);