From 162e17a065cd2f397127a10df9bb6ea20120c26b Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Sat, 2 Jul 2016 21:05:16 -0600
Subject: [PATCH] Remove requirement on system crate, use ransid

---
 Cargo.lock              |   6 +
 Cargo.toml              |   1 +
 src/terminal/console.rs | 331 ++++++----------------------------------
 src/terminal/main.rs    |   5 +-
 4 files changed, 53 insertions(+), 290 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index dd803bf..883b0b4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6,6 +6,7 @@ dependencies = [
  "orbfont 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "orbimage 0.1.1 (git+https://github.com/redox-os/orbimage.git)",
  "orbtk 0.1.2 (git+https://github.com/redox-os/orbtk.git)",
+ "ransid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -218,6 +219,11 @@ dependencies = [
  "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "ransid"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "rustc-serialize"
 version = "0.3.19"
diff --git a/Cargo.toml b/Cargo.toml
index 303c222..0630980 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -36,3 +36,4 @@ orbclient = "0.1"
 orbfont = "0.1"
 orbimage = { git = "https://github.com/redox-os/orbimage.git" }
 orbtk = { git = "https://github.com/redox-os/orbtk.git" }
+ransid = "0.1"
diff --git a/src/terminal/console.rs b/src/terminal/console.rs
index c268cdd..d6d10a1 100644
--- a/src/terminal/console.rs
+++ b/src/terminal/console.rs
@@ -1,70 +1,19 @@
-extern crate system;
-
 extern crate orbfont;
-
-use self::system::graphics::{fast_copy, fast_set};
+extern crate ransid;
 
 use self::orbfont::Font;
 
-use std::{cmp, mem};
+use std::mem;
 
 use orbclient::{Color, Event, EventOption, Window};
 use orbclient::event;
 
-fn ansi_color(value: u8) -> Color {
-    match value {
-        0 => Color::rgb(0x00, 0x00, 0x00),
-        1 => Color::rgb(0x80, 0x00, 0x00),
-        2 => Color::rgb(0x00, 0x80, 0x00),
-        3 => Color::rgb(0x80, 0x80, 0x00),
-        4 => Color::rgb(0x00, 0x00, 0x80),
-        5 => Color::rgb(0x80, 0x00, 0x80),
-        6 => Color::rgb(0x00, 0x80, 0x80),
-        7 => Color::rgb(0xc0, 0xc0, 0xc0),
-        8 => Color::rgb(0x80, 0x80, 0x80),
-        9 => Color::rgb(0xff, 0x00, 0x00),
-        10 => Color::rgb(0x00, 0xff, 0x00),
-        11 => Color::rgb(0xff, 0xff, 0x00),
-        12 => Color::rgb(0x00, 0x00, 0xff),
-        13 => Color::rgb(0xff, 0x00, 0xff),
-        14 => Color::rgb(0x00, 0xff, 0xff),
-        15 => Color::rgb(0xff, 0xff, 0xff),
-        16 ... 231 => {
-            let convert = |value: u8| -> u8 {
-                match value {
-                    0 => 0,
-                    _ => value * 0x28 + 0x28
-                }
-            };
-
-            let r = convert((value - 16)/36 % 6);
-            let g = convert((value - 16)/6 % 6);
-            let b = convert((value - 16) % 6);
-            Color::rgb(r, g, b)
-        },
-        232 ... 255 => {
-            let gray = (value - 232) * 10 + 8;
-            Color::rgb(gray, gray, gray)
-        },
-        _ => Color::rgb(0, 0, 0)
-    }
-}
-
 pub struct Console {
     pub window: Window,
+    pub inner: ransid::Console,
     pub font: Font,
     pub font_bold: Font,
-    pub point_x: i32,
-    pub point_y: i32,
-    pub foreground: Color,
-    pub background: Color,
-    pub bold: bool,
-    pub redraw: bool,
     pub command: String,
-    pub escape: bool,
-    pub escape_sequence: bool,
-    pub sequence: Vec<String>,
-    pub raw_mode: bool,
 }
 
 impl Console {
@@ -73,239 +22,18 @@ impl Console {
         window.sync();
         Console {
             window: window,
+            inner: ransid::Console::new(width as usize/8, height as usize/16),
             font: Font::find(Some("Mono"), None, Some("Regular")).unwrap(),
             font_bold: Font::find(Some("Mono"), None, Some("Bold")).unwrap(),
-            point_x: 0,
-            point_y: 0,
-            foreground: ansi_color(7),
-            background: ansi_color(0),
-            bold: false,
-            redraw: true,
             command: String::new(),
-            escape: false,
-            escape_sequence: false,
-            sequence: Vec::new(),
-            raw_mode: false,
-        }
-    }
-
-    pub fn code(&mut self, c: char) {
-        if self.escape_sequence {
-            match c {
-                '0' ... '9' => {
-                    // Add a number to the sequence list
-                    if let Some(mut value) = self.sequence.last_mut() {
-                        value.push(c);
-                    }
-                },
-                ';' => {
-                    // Split sequence into list
-                    self.sequence.push(String::new());
-                },
-                'm' => {
-                    // Display attributes
-                    let mut value_iter = self.sequence.iter();
-                    while let Some(value_str) = value_iter.next() {
-                        let value = value_str.parse::<u8>().unwrap_or(0);
-                        match value {
-                            0 => {
-                                self.foreground = ansi_color(7);
-                                self.background = ansi_color(0);
-                                self.bold = false;
-                            },
-                            1 => {
-                                self.bold = true;
-                            },
-                            30 ... 37 => self.foreground = ansi_color(value - 30),
-                            38 => match value_iter.next().map_or("", |s| &s).parse::<usize>().unwrap_or(0) {
-                                2 => {
-                                    //True color
-                                    let r = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
-                                    let g = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
-                                    let b = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
-                                    self.foreground = Color::rgb(r, g, b);
-                                },
-                                5 => {
-                                    //256 color
-                                    let color_value = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
-                                    self.foreground = ansi_color(color_value);
-                                },
-                                _ => {}
-                            },
-                            40 ... 47 => self.background = ansi_color(value - 40),
-                            48 => match value_iter.next().map_or("", |s| &s).parse::<usize>().unwrap_or(0) {
-                                2 => {
-                                    //True color
-                                    let r = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
-                                    let g = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
-                                    let b = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
-                                    self.background = Color::rgb(r, g, b);
-                                },
-                                5 => {
-                                    //256 color
-                                    let color_value = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
-                                    self.background = ansi_color(color_value);
-                                },
-                                _ => {}
-                            },
-                            _ => {},
-                        }
-                    }
-
-                    self.escape_sequence = false;
-                },
-                'J' => {
-                    match self.sequence.get(0).map_or("", |p| &p).parse::<usize>().unwrap_or(0) {
-                        0 => {
-                            //TODO: Erase down
-                        },
-                        1 => {
-                            //TODO: Erase up
-                        },
-                        2 => {
-                            // Erase all
-                            self.point_x = 0;
-                            self.point_y = 0;
-                            self.window.set(self.background);
-                            self.redraw = true;
-                        },
-                        _ => {}
-                    }
-
-                    self.escape_sequence = false;
-                },
-                'H' | 'f' => {
-                    self.window.rect(self.point_x, self.point_y, 8, 16, self.background);
-
-                    let row = self.sequence.get(0).map_or("", |p| &p).parse::<isize>().unwrap_or(1);
-                    self.point_y = cmp::max(0, row - 1) as i32 * 16;
-
-                    let col = self.sequence.get(1).map_or("", |p| &p).parse::<isize>().unwrap_or(1);
-                    self.point_x = cmp::max(0, col - 1) as i32 * 8;
-
-                    self.window.rect(self.point_x, self.point_y, 8, 16, self.foreground);
-                    self.redraw = true;
-
-                    self.escape_sequence = false;
-                },
-/*
-@MANSTART{terminal-raw-mode}
-INTRODUCTION
-    Since Redox has no ioctl syscall, it uses escape codes for switching to raw mode.
-
-ENTERING AND EXITING RAW MODE
-    Entering raw mode is done using CSI-r (^[r). Unsetting raw mode is done by CSI-R (^[R).
-
-RAW MODE
-    Raw mode means that the stdin must be handled solely by the program itself. It will not automatically be printed nor will it be modified in any way (modulo escape codes).
-
-    This means that:
-        - stdin is not printed.
-        - newlines are interpreted as carriage returns in stdin.
-        - stdin is not buffered, meaning that the stream of bytes goes directly to the program, without the user having to press enter.
-@MANEND
-*/
-                'r' => {
-                    self.raw_mode = true;
-                    self.escape_sequence = false;
-                },
-                'R' => {
-                    self.raw_mode = false;
-                    self.escape_sequence = false;
-                },
-                _ => self.escape_sequence = false,
-
-            }
-
-            if !self.escape_sequence {
-                self.sequence.clear();
-                self.escape = false;
-            }
-        } else {
-            match c {
-                '[' => {
-                    // Control sequence initiator
-
-                    self.escape_sequence = true;
-                    self.sequence.push(String::new());
-                },
-                'c' => {
-                    // Reset
-                    self.point_x = 0;
-                    self.point_y = 0;
-                    self.raw_mode = false;
-                    self.foreground = ansi_color(7);
-                    self.background = ansi_color(0);
-                    self.bold = false;
-                    self.window.set(self.background);
-                    self.redraw = true;
-
-                    self.escape = false;
-                }
-                _ => self.escape = false,
-            }
-        }
-    }
-
-    pub fn scroll(&mut self, rows: usize) {
-        if rows > 0 && rows < self.window.height() as usize {
-            let offset = rows * self.window.width() as usize;
-            let data = self.window.data_mut();
-            unsafe {
-                fast_copy(data.as_mut_ptr() as *mut u32, data.as_ptr().offset(offset as isize) as *const u32, data.len() - offset);
-                fast_set(data.as_mut_ptr().offset((data.len() - offset) as isize) as *mut u32, self.background.data, offset);
-            }
         }
     }
 
-    pub fn character(&mut self, c: char) {
-        self.window.rect(self.point_x, self.point_y, 8, 16, self.background);
-
-        match c {
-            '\0' => {},
-            '\x1B' => self.escape = true,
-            '\n' => {
-                self.point_x = 0;
-                self.point_y += 16;
-            },
-            '\t' => self.point_x = ((self.point_x / 64) + 1) * 64,
-            '\r' => self.point_x = 0,
-            '\x08' => {
-                self.point_x -= 8;
-                if self.point_x < 0 {
-                    self.point_x = 0
-                }
-                self.window.rect(self.point_x, self.point_y, 8, 16, self.background);
-            },
-            _ => {
-                if self.bold {
-                    self.font_bold.render(&c.to_string(), 16.0).draw(&mut self.window, self.point_x, self.point_y, self.foreground);
-                } else {
-                    self.font.render(&c.to_string(), 16.0).draw(&mut self.window, self.point_x, self.point_y, self.foreground);
-                }
-                //self.window.char(self.point_x, self.point_y, c, self.foreground);
-                self.point_x += 8;
-            }
-        }
-
-        if self.point_x >= self.window.width() as i32 {
-            self.point_x = 0;
-            self.point_y += 16;
-        }
-
-        while self.point_y + 16 > self.window.height() as i32 {
-            self.scroll(16);
-            self.point_y -= 16;
-        }
-        self.window.rect(self.point_x, self.point_y, 8, 16, self.foreground);
-        self.redraw = true;
-    }
-
     pub fn event(&mut self, event: Event) -> Option<String> {
         match event.to_option() {
             EventOption::Key(key_event) => {
                 if key_event.pressed {
-                    if self.raw_mode {
+                    if self.inner.raw_mode {
                         match key_event.scancode {
                             event::K_BKSP => self.command.push_str("\x08"),
                             event::K_UP => self.command.push_str("\x1B[A"),
@@ -328,12 +56,16 @@ RAW MODE
                     } else {
                         match key_event.scancode {
                             event::K_BKSP => if ! self.command.is_empty() {
+                                self.inner.redraw = true;
+
                                 self.write(&[8]);
                                 self.command.pop();
                             },
                             _ => match key_event.character {
                                 '\0' => (),
                                 c => {
+                                    self.inner.redraw = true;
+
                                     self.write(&[c as u8]);
                                     self.command.push(c);
 
@@ -355,18 +87,41 @@ RAW MODE
     }
 
     pub fn write(&mut self, bytes: &[u8]) {
-        for byte in bytes.iter() {
-            let c = *byte as char;
-
-            if self.escape {
-                self.code(c);
-            } else {
-                self.character(c);
+        self.inner.write(bytes);
+        //TODO: if self.inner.redraw
+        {
+            self.inner.redraw = false;
+
+            self.window.set(Color {
+                data: self.inner.background.data
+            });
+            for y in 0..self.inner.h {
+                for x in 0..self.inner.w {
+                    let block = self.inner.display[y * self.inner.w + x];
+                    self.window.rect(x as i32 * 8, y as i32 * 16, 8, 16, Color {
+                        data: block.bg.data
+                    });
+                    if block.c != ' ' {
+                        match block.style {
+                            ransid::Style::Normal => {
+                                self.font.render(&block.c.to_string(), 16.0).draw(&mut self.window, x as i32 * 8, y as i32 * 16, Color {
+                                    data: block.fg.data
+                                });
+                            },
+                            ransid::Style::Bold => {
+                                self.font_bold.render(&block.c.to_string(), 16.0).draw(&mut self.window, x as i32 * 8, y as i32 * 16, Color {
+                                    data: block.fg.data
+                                });
+                            }
+                        }
+                    }
+                }
+            }
+            if self.inner.cursor {
+                self.window.rect(self.inner.x as i32 * 8, self.inner.y as i32 * 16, 8, 16, Color {
+                    data: self.inner.foreground.data
+                });
             }
-        }
-
-        if self.redraw {
-            self.redraw = false;
             self.window.sync();
         }
     }
diff --git a/src/terminal/main.rs b/src/terminal/main.rs
index 07ff35a..dab53e6 100644
--- a/src/terminal/main.rs
+++ b/src/terminal/main.rs
@@ -6,11 +6,12 @@ extern crate orbclient;
 use orbclient::event;
 
 use std::env;
+use std::error::Error;
 use std::io::{Read, Write, self};
 use std::process::{Command, Stdio};
 use std::sync::{Arc, Mutex};
+use std::time::Duration;
 use std::thread;
-use std::error::Error;
 
 use console::Console;
 
@@ -122,7 +123,7 @@ fn main() {
                     }
                 }
 
-                thread::sleep_ms(1);
+                thread::sleep(Duration::new(0, 1000000));
             }
         },
         Err(err) => {
-- 
GitLab