vte-0.3.3/.gitignore010064400017500001750000000000221276534151200125240ustar0000000000000000target Cargo.lock vte-0.3.3/.travis.yml010066400017500001750000000001321322702320400126360ustar0000000000000000language: rust cache: cargo rust: - stable - nightly script: - cargo test --all vte-0.3.3/Cargo.toml.orig010066400017500001750000000006151333432553700134370ustar0000000000000000[package] name = "vte" version = "0.3.3" authors = ["Joe Wilm "] license = "Apache-2.0 OR MIT" description = "Parser for implementing terminal emulators" keywords = ["ansi", "vte", "parser", "terminal"] repository = "https://github.com/jwilm/vte" documentation = "https://docs.rs/vte/" readme = "README.md" [dependencies.utf8parse] path = "utf8parse" version = "0.1" [workspace] vte-0.3.3/Cargo.toml0000644000000015670000000000000077030ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "vte" version = "0.3.3" authors = ["Joe Wilm "] description = "Parser for implementing terminal emulators" documentation = "https://docs.rs/vte/" readme = "README.md" keywords = ["ansi", "vte", "parser", "terminal"] license = "Apache-2.0 OR MIT" repository = "https://github.com/jwilm/vte" [dependencies.utf8parse] version = "0.1" vte-0.3.3/Cargo.toml.orig0000644000000006150000000000000106330ustar00[package] name = "vte" version = "0.3.3" authors = ["Joe Wilm "] license = "Apache-2.0 OR MIT" description = "Parser for implementing terminal emulators" keywords = ["ansi", "vte", "parser", "terminal"] repository = "https://github.com/jwilm/vte" documentation = "https://docs.rs/vte/" readme = "README.md" [dependencies.utf8parse] path = "utf8parse" version = "0.1" [workspace] vte-0.3.3/CHANGELOG.md010066400017500001750000000005271333432564100123570ustar0000000000000000CHANGELOG ========= ## 0.3.3 - Fix off-by-one error in CSI parsing when params list was at max length (previously caused a panic). ## 0.2.0 - Removes `osc_start`, `osc_put`, and `osc_end` - Adds `osc_dispatch` which simply receives a list of parameters - Removes `byte: u8` parameter from `hook` and `unhook` because it's always zero. vte-0.3.3/examples/parselog.rs010066400017500001750000000035571333432535100145520ustar0000000000000000//! Parse input from stdin and log actions on stdout extern crate vte; use std::io::{self, Read}; /// A type implementing Perform that just logs actions struct Log; impl vte::Perform for Log { fn print(&mut self, c: char) { println!("[print] {:?}", c); } fn execute(&mut self, byte: u8) { println!("[execute] {:02x}", byte); } fn hook(&mut self, params: &[i64], intermediates: &[u8], ignore: bool) { println!("[hook] params={:?}, intermediates={:?}, ignore={:?}", params, intermediates, ignore); } fn put(&mut self, byte: u8) { println!("[put] {:02x}", byte); } fn unhook(&mut self) { println!("[unhook]"); } fn osc_dispatch(&mut self, params: &[&[u8]]) { println!("[osc_dispatch] params={:?}", params); } fn csi_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, c: char) { println!("[csi_dispatch] params={:?}, intermediates={:?}, ignore={:?}, char={:?}", params, intermediates, ignore, c); } fn esc_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, byte: u8) { println!("[esc_dispatch] params={:?}, intermediates={:?}, ignore={:?}, byte={:02x}", params, intermediates, ignore, byte); } } fn main() { let input = io::stdin(); let mut handle = input.lock(); let mut statemachine = vte::Parser::new(); let mut parser = Log; let mut buf: [u8; 2048] = unsafe { std::mem::uninitialized() }; loop { match handle.read(&mut buf) { Ok(0) => break, Ok(n) => { for byte in &buf[..n] { statemachine.advance(&mut parser, *byte); } }, Err(err) => { println!("err: {}", err); break; } } } } vte-0.3.3/LICENSE-APACHE010066400017500001750000000227731276735652000125120ustar0000000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS vte-0.3.3/LICENSE-MIT010066400017500001750000000020341276735650700122130ustar0000000000000000Copyright (c) 2016 Joe Wilm Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. vte-0.3.3/README.md010066400017500001750000000020211322702320400120030ustar0000000000000000vte === [![Build Status](https://travis-ci.org/jwilm/vte.svg?branch=master)](https://travis-ci.org/jwilm/vte) [![Crates.io Version](https://img.shields.io/crates/v/vte.svg)](https://crates.io/crates/vte/) Parser for implementing virtual terminal emulators in Rust. The parser is implemented according to [Paul Williams' ANSI parser state machine]. The state machine doesn't assign meaning to the parsed data and is thus not itself sufficient for writing a terminal emulator. Instead, it is expected that an implementation of the `Perform` trait which does something useful with the parsed data. The `Parser` handles the book keeping, and the `Perform` gets to simply handle actions. See the [docs] for more info. ## Developer Notes If contributing to either `vte` or the `utf8parse` crate and modifying a _table.rs.in_ file, make sure to `cargo run` from the _codegen_ folder so that the compiled tables are updated. [Paul Williams' ANSI parser state machine]: https://vt100.net/emu/dec_ansi_parser [docs]: https://docs.rs/crate/vte/ vte-0.3.3/src/definitions.rs010066400017500001750000000034311322702320400142020ustar0000000000000000#[allow(dead_code)] #[derive(Debug, Copy, Clone)] pub enum State { Anywhere = 0, CsiEntry = 1, CsiIgnore = 2, CsiIntermediate = 3, CsiParam = 4, DcsEntry = 5, DcsIgnore = 6, DcsIntermediate = 7, DcsParam = 8, DcsPassthrough = 9, Escape = 10, EscapeIntermediate = 11, Ground = 12, OscString = 13, SosPmApcString = 14, Utf8 = 15, } #[allow(dead_code)] #[derive(Debug, Clone, Copy)] pub enum Action { None = 0, Clear = 1, Collect = 2, CsiDispatch = 3, EscDispatch = 4, Execute = 5, Hook = 6, Ignore = 7, OscEnd = 8, OscPut = 9, OscStart = 10, Param = 11, Print = 12, Put = 13, Unhook = 14, BeginUtf8 = 15, } /// Unpack a u8 into a State and Action /// /// The implementation of this assumes that there are *precisely* 16 variants for both Action and /// State. Furthermore, it assumes that the enums are tag-only; that is, there is no data in any /// variant. /// /// Bad things will happen if those invariants are violated. #[inline(always)] pub fn unpack(delta: u8) -> (State, Action) { ( // State is stored in bottom 4 bits unsafe { ::core::mem::transmute(delta & 0x0f) }, // Action is stored in top 4 bits unsafe { ::core::mem::transmute(delta >> 4) }, ) } #[cfg(test)] mod tests { use super::{State, Action, unpack}; #[test] fn unpack_state_action() { match unpack(0xee) { (State::SosPmApcString, Action::Unhook) => (), _ => panic!("unpack failed"), } match unpack(0x0f) { (State::Utf8, Action::None) => (), _ => panic!("unpack failed"), } match unpack(0xff) { (State::Utf8, Action::BeginUtf8) => (), _ => panic!("unpack failed"), } } } vte-0.3.3/src/lib.rs010066400017500001750000000476401333432552700124630ustar0000000000000000//! Parser for implementing virtual terminal emulators //! //! [`Parser`] is implemented according to [Paul Williams' ANSI parser //! state machine]. The state machine doesn't assign meaning to the parsed data //! and is thus not itself sufficient for writing a terminal emulator. Instead, //! it is expected that an implementation of [`Perform`] is provided which does //! something useful with the parsed data. The [`Parser`] handles the book //! keeping, and the [`Perform`] gets to simply handle actions. //! //! # Examples //! //! For an example of using the [`Parser`] please see the examples folder. The example included //! there simply logs all the actions [`Perform`] does. One quick thing to see it in action is to //! pipe `vim` into it //! //! ```ignore //! cargo build --release --example parselog //! vim | target/release/examples/parselog //! ``` //! //! Just type `:q` to exit. //! //! # Differences from original state machine description //! //! * UTF-8 Support for Input //! * OSC Strings can be terminated by 0x07 //! * Only supports 7-bit codes. Some 8-bit codes are still supported, but they //! no longer work in all states. //! //! [`Parser`]: struct.Parser.html //! [`Perform`]: trait.Perform.html //! [Paul Williams' ANSI parser state machine]: https://vt100.net/emu/dec_ansi_parser #![no_std] extern crate utf8parse as utf8; use core::mem; mod table; mod definitions; use definitions::{Action, State, unpack}; use table::{EXIT_ACTIONS, ENTRY_ACTIONS, STATE_CHANGE}; impl State { /// Get exit action for this state #[inline(always)] pub fn exit_action(&self) -> Action { unsafe { *EXIT_ACTIONS.get_unchecked(*self as usize) } } /// Get entry action for this state #[inline(always)] pub fn entry_action(&self) -> Action { unsafe { *ENTRY_ACTIONS.get_unchecked(*self as usize) } } } const MAX_INTERMEDIATES: usize = 2; const MAX_OSC_RAW: usize = 1024; const MAX_PARAMS: usize = 16; struct VtUtf8Receiver<'a, P: Perform + 'a>(&'a mut P, &'a mut State); impl<'a, P: Perform> utf8::Receiver for VtUtf8Receiver<'a, P> { fn codepoint(&mut self, c: char) { self.0.print(c); *self.1 = State::Ground; } fn invalid_sequence(&mut self) { self.0.print('�'); *self.1 = State::Ground; } } /// Parser for raw _VTE_ protocol which delegates actions to a [`Perform`] /// /// [`Perform`]: trait.Perform.html pub struct Parser { state: State, intermediates: [u8; MAX_INTERMEDIATES], intermediate_idx: usize, params: [i64; MAX_PARAMS], param: i64, collecting_param: bool, num_params: usize, osc_raw: [u8; MAX_OSC_RAW], osc_params: [(usize, usize); MAX_PARAMS], osc_idx: usize, osc_num_params: usize, ignoring: bool, utf8_parser: utf8::Parser, } impl Parser { /// Create a new Parser pub fn new() -> Parser { Parser { state: State::Ground, intermediates: [0u8; MAX_INTERMEDIATES], intermediate_idx: 0, params: [0i64; MAX_PARAMS], param: 0, collecting_param: false, num_params: 0, osc_raw: [0; MAX_OSC_RAW], osc_params: [(0, 0); MAX_PARAMS], osc_idx: 0, osc_num_params: 0, ignoring: false, utf8_parser: utf8::Parser::new(), } } #[inline] fn params(&self) -> &[i64] { &self.params[..self.num_params] } #[inline] fn intermediates(&self) -> &[u8] { &self.intermediates[..self.intermediate_idx] } /// Advance the parser state /// /// Requires a [`Perform`] in case `byte` triggers an action /// /// [`Perform`]: trait.Perform.html #[inline] pub fn advance(&mut self, performer: &mut P, byte: u8) { // Utf8 characters are handled out-of-band. if let State::Utf8 = self.state { self.process_utf8(performer, byte); return; } // Handle state changes in the anywhere state before evaluating changes // for current state. let mut change = STATE_CHANGE[State::Anywhere as usize][byte as usize]; if change == 0 { change = STATE_CHANGE[self.state as usize][byte as usize]; } // Unpack into a state and action let (state, action) = unpack(change); self.perform_state_change(performer, state, action, byte); } #[inline] fn process_utf8

(&mut self, performer: &mut P, byte: u8) where P: Perform { let mut receiver = VtUtf8Receiver(performer, &mut self.state); let utf8_parser = &mut self.utf8_parser; utf8_parser.advance(&mut receiver, byte); } #[inline] fn perform_state_change

(&mut self, performer: &mut P, state: State, action: Action, byte: u8) where P: Perform { macro_rules! maybe_action { ($action:expr, $arg:expr) => { match $action { Action::None => (), action => { self.perform_action(performer, action, $arg); }, } } } match state { State::Anywhere => { // Just run the action self.perform_action(performer, action, byte); }, state => { // Exit action for previous state let exit_action = self.state.exit_action(); maybe_action!(exit_action, 0); // Transition action maybe_action!(action, byte); // Entry action for new state maybe_action!(state.entry_action(), 0); // Assume the new state self.state = state; } } } /// Separate method for osc_dispatch that borrows self as read-only /// /// The aliasing is needed here for multiple slices into self.osc_raw #[inline] fn osc_dispatch(&self, performer: &mut P) { let mut slices: [&[u8]; MAX_PARAMS] = unsafe { mem::uninitialized() }; for i in 0..self.osc_num_params { let indices = self.osc_params[i]; slices[i] = &self.osc_raw[indices.0..indices.1]; } performer.osc_dispatch( &slices[..self.osc_num_params], ); } #[inline] fn perform_action(&mut self, performer: &mut P, action: Action, byte: u8) { match action { Action::Print => performer.print(byte as char), Action::Execute => performer.execute(byte), Action::Hook => { performer.hook( self.params(), self.intermediates(), self.ignoring, ); }, Action::Put => performer.put(byte), Action::OscStart => { self.osc_idx = 0; self.osc_num_params = 0; }, Action::OscPut => { let idx = self.osc_idx; if idx == self.osc_raw.len() { return; } // Param separator if byte == b';' { let param_idx = self.osc_num_params; match param_idx { // Only process up to MAX_PARAMS MAX_PARAMS => return, // First param is special - 0 to current byte index 0 => { self.osc_params[param_idx] = (0, idx); }, // All other params depend on previous indexing _ => { let prev = self.osc_params[param_idx - 1]; let begin = prev.1; self.osc_params[param_idx] = (begin, idx); } } self.osc_num_params += 1; } else { self.osc_raw[idx] = byte; self.osc_idx += 1; } }, Action::OscEnd => { let param_idx = self.osc_num_params; let idx = self.osc_idx; match param_idx { // Finish last parameter if not already maxed MAX_PARAMS => (), // First param is special - 0 to current byte index 0 => { self.osc_params[param_idx] = (0, idx); self.osc_num_params += 1; }, // All other params depend on previous indexing _ => { let prev = self.osc_params[param_idx - 1]; let begin = prev.1; self.osc_params[param_idx] = (begin, idx); self.osc_num_params += 1; } } self.osc_dispatch(performer); }, Action::Unhook => performer.unhook(), Action::CsiDispatch => { if self.collecting_param { let idx = self.num_params; self.params[idx] = self.param; self.num_params += 1; } performer.csi_dispatch( self.params(), self.intermediates(), self.ignoring, byte as char ); self.num_params = 0; self.param = 0; self.collecting_param = false; } Action::EscDispatch => { performer.esc_dispatch( self.params(), self.intermediates(), self.ignoring, byte ); }, Action::Ignore | Action::None => (), Action::Collect => { if self.intermediate_idx == MAX_INTERMEDIATES { self.ignoring = true; } else { self.intermediates[self.intermediate_idx] = byte; self.intermediate_idx += 1; } }, Action::Param => { if byte == b';' { // Completed a param let idx = self.num_params; if idx == MAX_PARAMS - 1 { return; } self.params[idx] = self.param; self.param = 0; self.num_params += 1; self.collecting_param = false; } else { // Continue collecting bytes into param self.param = self.param.saturating_mul(10); self.param = self.param.saturating_add((byte - b'0') as i64); self.collecting_param = true; } }, Action::Clear => { self.intermediate_idx = 0; self.num_params = 0; self.ignoring = false; }, Action::BeginUtf8 => { self.process_utf8(performer, byte); }, } } } /// Performs actions requested by the Parser /// /// Actions in this case mean, for example, handling a CSI escape sequence describing cursor /// movement, or simply printing characters to the screen. /// /// The methods on this type correspond to actions described in /// http://vt100.net/emu/dec_ansi_parser. I've done my best to describe them in /// a useful way in my own words for completeness, but the site should be /// referenced if something isn't clear. If the site disappears at some point in /// the future, consider checking archive.org. pub trait Perform { /// Draw a character to the screen and update states fn print(&mut self, char); /// Execute a C0 or C1 control function fn execute(&mut self, byte: u8); /// Invoked when a final character arrives in first part of device control string /// /// The control function should be determined from the private marker, final character, and /// execute with a parameter list. A handler should be selected for remaining characters in the /// string; the handler function should subsequently be called by `put` for every character in /// the control string. /// /// The `ignore` flag indicates that more than two intermediates arrived and /// subsequent characters were ignored. fn hook(&mut self, params: &[i64], intermediates: &[u8], ignore: bool); /// Pass bytes as part of a device control string to the handle chosen in `hook`. C0 controls /// will also be passed to the handler. fn put(&mut self, byte: u8); /// Called when a device control string is terminated /// /// The previously selected handler should be notified that the DCS has /// terminated. fn unhook(&mut self); /// Dispatch an operating system command fn osc_dispatch(&mut self, params: &[&[u8]]); /// A final character has arrived for a CSI sequence /// /// The `ignore` flag indicates that more than two intermediates arrived and /// subsequent characters were ignored. fn csi_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, char); /// The final character of an escape sequence has arrived. /// /// The `ignore` flag indicates that more than two intermediates arrived and /// subsequent characters were ignored. fn esc_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, byte: u8); } #[cfg(test)] #[macro_use] extern crate std; #[cfg(test)] mod tests { use std::vec::Vec; use super::{Parser, Perform}; use core::i64; static OSC_BYTES: &'static [u8] = &[0x1b, 0x5d, // Begin OSC b'2', b';', b'j', b'w', b'i', b'l', b'm', b'@', b'j', b'w', b'i', b'l', b'm', b'-', b'd', b'e', b's', b'k', b':', b' ', b'~', b'/', b'c', b'o', b'd', b'e', b'/', b'a', b'l', b'a', b'c', b'r', b'i', b't', b't', b'y', 0x07 // End OSC ]; #[derive(Default)] struct OscDispatcher { dispatched_osc: bool, params: Vec>, } // All empty bodies except osc_dispatch impl Perform for OscDispatcher { fn print(&mut self, _: char) {} fn execute(&mut self, _byte: u8) {} fn hook(&mut self, _params: &[i64], _intermediates: &[u8], _ignore: bool) {} fn put(&mut self, _byte: u8) {} fn unhook(&mut self) {} fn osc_dispatch(&mut self, params: &[&[u8]]) { // Set a flag so we know these assertions all run self.dispatched_osc = true; self.params = params.iter().map(|p| p.to_vec()).collect(); } fn csi_dispatch(&mut self, _params: &[i64], _intermediates: &[u8], _ignore: bool, _c: char) {} fn esc_dispatch(&mut self, _params: &[i64], _intermediates: &[u8], _ignore: bool, _byte: u8) {} } #[derive(Default)] struct CsiDispatcher { dispatched_csi: bool, params: Vec>, } impl Perform for CsiDispatcher { fn print(&mut self, _: char) {} fn execute(&mut self, _byte: u8) {} fn hook(&mut self, _params: &[i64], _intermediates: &[u8], _ignore: bool) {} fn put(&mut self, _byte: u8) {} fn unhook(&mut self) {} fn osc_dispatch(&mut self, _params: &[&[u8]]) { } fn csi_dispatch(&mut self, params: &[i64], _intermediates: &[u8], _ignore: bool, _c: char) { self.dispatched_csi = true; self.params.push(params.to_vec()); } fn esc_dispatch(&mut self, _params: &[i64], _intermediates: &[u8], _ignore: bool, _byte: u8) {} } #[test] fn parse_osc() { // Create dispatcher and check state let mut dispatcher = OscDispatcher::default(); assert_eq!(dispatcher.dispatched_osc, false); // Run parser using OSC_BYTES let mut parser = Parser::new(); for byte in OSC_BYTES { parser.advance(&mut dispatcher, *byte); } // Check that flag is set and thus osc_dispatch assertions ran. assert!(dispatcher.dispatched_osc); assert_eq!(dispatcher.params.len(), 2); assert_eq!(dispatcher.params[0], &OSC_BYTES[2..3]); assert_eq!(dispatcher.params[1], &OSC_BYTES[4..(OSC_BYTES.len() - 1)]); } #[test] fn parse_empty_osc() { // Create dispatcher and check state let mut dispatcher = OscDispatcher::default(); assert_eq!(dispatcher.dispatched_osc, false); // Run parser using OSC_BYTES let mut parser = Parser::new(); for byte in &[0x1b, 0x5d, 0x07] { parser.advance(&mut dispatcher, *byte); } // Check that flag is set and thus osc_dispatch assertions ran. assert!(dispatcher.dispatched_osc); } #[test] fn parse_osc_max_params() { use MAX_PARAMS; static INPUT: &'static [u8] = b"\x1b];;;;;;;;;;;;;;;;;\x1b"; // Create dispatcher and check state let mut dispatcher = OscDispatcher::default(); assert_eq!(dispatcher.dispatched_osc, false); // Run parser using OSC_BYTES let mut parser = Parser::new(); for byte in INPUT { parser.advance(&mut dispatcher, *byte); } // Check that flag is set and thus osc_dispatch assertions ran. assert!(dispatcher.dispatched_osc); assert_eq!(dispatcher.params.len(), MAX_PARAMS); for param in dispatcher.params.iter() { assert_eq!(param.len(), 0); } } #[test] fn parse_csi_max_params() { use MAX_PARAMS; static INPUT: &'static [u8] = b"\x1b[1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;p"; // Create dispatcher and check state let mut dispatcher = CsiDispatcher::default(); assert!(!dispatcher.dispatched_csi); // Run parser using OSC_BYTES let mut parser = Parser::new(); for byte in INPUT { parser.advance(&mut dispatcher, *byte); } // Check that flag is set and thus csi_dispatch assertions ran. assert!(dispatcher.dispatched_csi); assert_eq!(dispatcher.params.len(), 1); assert_eq!(dispatcher.params[0].len(), MAX_PARAMS); } #[test] fn parse_semi_set_underline() { // Create dispatcher and check state let mut dispatcher = CsiDispatcher::default(); // Run parser using OSC_BYTES let mut parser = Parser::new(); for byte in b"\x1b[;4m" { parser.advance(&mut dispatcher, *byte); } // Check that flag is set and thus osc_dispatch assertions ran. assert_eq!(dispatcher.params[0], &[0, 4]); } #[test] fn parse_long_csi_param() { // The important part is the parameter, which is (i64::MAX + 1) static INPUT: &'static [u8] = b"\x1b[9223372036854775808m"; let mut dispatcher = CsiDispatcher::default(); let mut parser = Parser::new(); for byte in INPUT { parser.advance(&mut dispatcher, *byte); } assert_eq!(dispatcher.params[0], &[i64::MAX as i64]); } #[test] fn parse_osc_with_utf8_arguments() { static INPUT: &'static [u8] = &[ 0x0d, 0x1b, 0x5d, 0x32, 0x3b, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x27, 0xc2, 0xaf, 0x5c, 0x5f, 0x28, 0xe3, 0x83, 0x84, 0x29, 0x5f, 0x2f, 0xc2, 0xaf, 0x27, 0x20, 0x26, 0x26, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x31, 0x07 ]; // Create dispatcher and check state let mut dispatcher = OscDispatcher { params: vec![], dispatched_osc: false }; // Run parser using OSC_BYTES let mut parser = Parser::new(); for byte in INPUT { parser.advance(&mut dispatcher, *byte); } // Check that flag is set and thus osc_dispatch assertions ran. assert_eq!(dispatcher.params[0], &[b'2']); assert_eq!(dispatcher.params[1], &INPUT[5..(INPUT.len() - 1)]); } } vte-0.3.3/src/table.rs010066400017500001750000000644761305573065200130110ustar0000000000000000 /// This is the state change table. It's indexed first by current state and then by the next /// character in the pty stream. use definitions::Action; pub static STATE_CHANGE: [[u8; 256]; 16] = [ // Beginning of UTF-8 2 byte sequence // Beginning of UTF-8 3 byte sequence // Beginning of UTF-8 4 byte sequence [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 92u8, 0u8, 92u8, 10u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 0u8, 80u8, 0u8, 0u8, 80u8, 80u8, 80u8, 80u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 180u8, 180u8, 180u8, 180u8, 180u8, 180u8, 180u8, 180u8, 180u8, 180u8, 2u8, 180u8, 36u8, 36u8, 36u8, 36u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 0u8, 80u8, 0u8, 0u8, 80u8, 80u8, 80u8, 80u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 12u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 0u8, 80u8, 0u8, 0u8, 80u8, 80u8, 80u8, 80u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 2u8, 2u8, 2u8, 2u8, 2u8, 2u8, 2u8, 2u8, 2u8, 2u8, 2u8, 2u8, 2u8, 2u8, 2u8, 2u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 0u8, 80u8, 0u8, 0u8, 80u8, 80u8, 80u8, 80u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 35u8, 176u8, 176u8, 176u8, 176u8, 176u8, 176u8, 176u8, 176u8, 176u8, 176u8, 2u8, 176u8, 2u8, 2u8, 2u8, 2u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 60u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 0u8, 112u8, 0u8, 0u8, 112u8, 112u8, 112u8, 112u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 184u8, 184u8, 184u8, 184u8, 184u8, 184u8, 184u8, 184u8, 184u8, 184u8, 6u8, 184u8, 40u8, 40u8, 40u8, 40u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 0u8, 112u8, 0u8, 0u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 12u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 0u8, 112u8, 0u8, 0u8, 112u8, 112u8, 112u8, 112u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 6u8, 6u8, 6u8, 6u8, 6u8, 6u8, 6u8, 6u8, 6u8, 6u8, 6u8, 6u8, 6u8, 6u8, 6u8, 6u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 0u8, 112u8, 0u8, 0u8, 112u8, 112u8, 112u8, 112u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 39u8, 176u8, 176u8, 176u8, 176u8, 176u8, 176u8, 176u8, 176u8, 176u8, 176u8, 6u8, 176u8, 6u8, 6u8, 6u8, 6u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 9u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 0u8, 208u8, 0u8, 0u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 208u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 12u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 0u8, 80u8, 0u8, 0u8, 80u8, 80u8, 80u8, 80u8, 43u8, 43u8, 43u8, 43u8, 43u8, 43u8, 43u8, 43u8, 43u8, 43u8, 43u8, 43u8, 43u8, 43u8, 43u8, 43u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 5u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 14u8, 76u8, 76u8, 1u8, 76u8, 13u8, 14u8, 14u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 0u8, 80u8, 0u8, 0u8, 80u8, 80u8, 80u8, 80u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 32u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 76u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 0u8, 80u8, 0u8, 0u8, 80u8, 80u8, 80u8, 80u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 192u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 0u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 80u8, 0u8, 80u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 12u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 0u8, 112u8, 0u8, 0u8, 112u8, 112u8, 112u8, 112u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8, 144u8], [112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 0u8, 112u8, 0u8, 0u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 112u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 12u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], [0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]]; pub static ENTRY_ACTIONS: &'static [Action] = &[Action::None, // State::Anywhere Action::Clear, // State::CsiEntry Action::None, // State::CsiIgnore Action::None, // State::CsiIntermediate Action::None, // State::CsiParam Action::Clear, // State::DcsEntry Action::None, // State::DcsIgnore Action::None, // State::DcsIntermediate Action::None, // State::DcsParam Action::Hook, // State::DcsPassthrough Action::Clear, // State::Escape Action::None, // State::EscapeIntermediate Action::None, // State::Ground Action::OscStart, // State::OscString Action::None, // State::SosPmApcString Action::None]; // State::Utf8 pub static EXIT_ACTIONS: &'static [Action] = &[Action::None, // State::Anywhere Action::None, // State::CsiEntry Action::None, // State::CsiIgnore Action::None, // State::CsiIntermediate Action::None, // State::CsiParam Action::None, // State::DcsEntry Action::None, // State::DcsIgnore Action::None, // State::DcsIntermediate Action::None, // State::DcsParam Action::Unhook, // State::DcsPassthrough Action::None, // State::Escape Action::None, // State::EscapeIntermediate Action::None, // State::Ground Action::OscEnd, // State::OscString Action::None, // State::SosPmApcString Action::None]; // State::Utf8 vte-0.3.3/src/table.rs.in010066400017500001750000000165351305573064300134070ustar0000000000000000/// This is the state change table. It's indexed first by current state and then by the next /// character in the pty stream. use definitions::Action; pub static STATE_CHANGE: [[u8; 256]; 16] = vt_state_table! { State::Anywhere => { 0x18 => (Action::Execute, State::Ground), 0x1a => (Action::Execute, State::Ground), 0x1b => State::Escape, }, State::Ground => { 0x00...0x17 => Action::Execute, 0x19 => Action::Execute, 0x1c...0x1f => Action::Execute, 0x20...0x7f => Action::Print, 0x80...0x8f => Action::Execute, 0x91...0x9a => Action::Execute, 0x9c => Action::Execute, // Beginning of UTF-8 2 byte sequence 0xc2...0xdf => (State::Utf8, Action::BeginUtf8), // Beginning of UTF-8 3 byte sequence 0xe0...0xef => (State::Utf8, Action::BeginUtf8), // Beginning of UTF-8 4 byte sequence 0xf0...0xf4 => (State::Utf8, Action::BeginUtf8), }, State::Escape => { 0x00...0x17 => Action::Execute, 0x19 => Action::Execute, 0x1c...0x1f => Action::Execute, 0x7f => Action::Ignore, 0x20...0x2f => (Action::Collect, State::EscapeIntermediate), 0x30...0x4f => (Action::EscDispatch, State::Ground), 0x51...0x57 => (Action::EscDispatch, State::Ground), 0x59 => (Action::EscDispatch, State::Ground), 0x5a => (Action::EscDispatch, State::Ground), 0x5c => (Action::EscDispatch, State::Ground), 0x60...0x7e => (Action::EscDispatch, State::Ground), 0x5b => State::CsiEntry, 0x5d => State::OscString, 0x50 => State::DcsEntry, 0x58 => State::SosPmApcString, 0x5e => State::SosPmApcString, 0x5f => State::SosPmApcString, }, State::EscapeIntermediate => { 0x00...0x17 => Action::Execute, 0x19 => Action::Execute, 0x1c...0x1f => Action::Execute, 0x20...0x2f => Action::Collect, 0x7f => Action::Ignore, 0x30...0x7e => (Action::EscDispatch, State::Ground) }, State::CsiEntry => { 0x00...0x17 => Action::Execute, 0x19 => Action::Execute, 0x1c...0x1f => Action::Execute, 0x7f => Action::Ignore, 0x20...0x2f => (Action::Collect, State::CsiIntermediate), 0x3a => State::CsiIgnore, 0x30...0x39 => (Action::Param, State::CsiParam), 0x3b => (Action::Param, State::CsiParam), 0x3c...0x3f => (Action::Collect, State::CsiParam), 0x40...0x7e => (Action::CsiDispatch, State::Ground) }, State::CsiIgnore => { 0x00...0x17 => Action::Execute, 0x19 => Action::Execute, 0x1c...0x1f => Action::Execute, 0x20...0x3f => Action::Ignore, 0x7f => Action::Ignore, 0x40...0x7e => State::Ground, }, State::CsiParam => { 0x00...0x17 => Action::Execute, 0x19 => Action::Execute, 0x1c...0x1f => Action::Execute, 0x30...0x39 => Action::Param, 0x3b => Action::Param, 0x7f => Action::Ignore, 0x3a => State::CsiIgnore, 0x3c...0x3f => State::CsiIgnore, 0x20...0x2f => (Action::Collect, State::CsiIntermediate), 0x40...0x7e => (Action::CsiDispatch, State::Ground) }, State::CsiIntermediate => { 0x00...0x17 => Action::Execute, 0x19 => Action::Execute, 0x1c...0x1f => Action::Execute, 0x20...0x2f => Action::Collect, 0x7f => Action::Ignore, 0x30...0x3f => State::CsiIgnore, 0x40...0x7e => (Action::CsiDispatch, State::Ground), }, State::DcsEntry => { 0x00...0x17 => Action::Ignore, 0x19 => Action::Ignore, 0x1c...0x1f => Action::Ignore, 0x7f => Action::Ignore, 0x3a => State::DcsIgnore, 0x20...0x2f => (Action::Collect, State::DcsIntermediate), 0x30...0x39 => (Action::Param, State::DcsParam), 0x3b => (Action::Param, State::DcsParam), 0x3c...0x3f => (Action::Collect, State::DcsParam), 0x40...0x7e => State::DcsPassthrough }, State::DcsIntermediate => { 0x00...0x17 => Action::Ignore, 0x19 => Action::Ignore, 0x1c...0x1f => Action::Ignore, 0x20...0x2f => Action::Collect, 0x7f => Action::Ignore, 0x30...0x3f => State::DcsIgnore, 0x40...0x7e => State::DcsPassthrough }, State::DcsIgnore => { 0x00...0x17 => Action::Ignore, 0x19 => Action::Ignore, 0x1c...0x1f => Action::Ignore, 0x20...0x7f => Action::Ignore, 0x9c => State::Ground }, State::DcsParam => { 0x00...0x17 => Action::Ignore, 0x19 => Action::Ignore, 0x1c...0x1f => Action::Ignore, 0x30...0x39 => Action::Param, 0x3b => Action::Param, 0x7f => Action::Ignore, 0x3a => State::DcsIgnore, 0x3c...0x3f => State::DcsIgnore, 0x20...0x2f => (Action::Collect, State::DcsIntermediate), 0x40...0x7e => State::DcsPassthrough }, State::DcsPassthrough => { 0x00...0x17 => Action::Put, 0x19 => Action::Put, 0x1c...0x1f => Action::Put, 0x20...0x7e => Action::Put, 0x7f => Action::Ignore, 0x9c => State::Ground, }, State::SosPmApcString => { 0x00...0x17 => Action::Ignore, 0x19 => Action::Ignore, 0x1c...0x1f => Action::Ignore, 0x20...0x7f => Action::Ignore, 0x9c => State::Ground }, State::OscString => { 0x00...0x06 => Action::Ignore, 0x07 => State::Ground, 0x08...0x17 => Action::Ignore, 0x19 => Action::Ignore, 0x1c...0x1f => Action::Ignore, 0x20...0xff => Action::OscPut, } }; pub static ENTRY_ACTIONS: &'static [Action] = &[ Action::None, // State::Anywhere Action::Clear, // State::CsiEntry Action::None, // State::CsiIgnore Action::None, // State::CsiIntermediate Action::None, // State::CsiParam Action::Clear, // State::DcsEntry Action::None, // State::DcsIgnore Action::None, // State::DcsIntermediate Action::None, // State::DcsParam Action::Hook, // State::DcsPassthrough Action::Clear, // State::Escape Action::None, // State::EscapeIntermediate Action::None, // State::Ground Action::OscStart, // State::OscString Action::None, // State::SosPmApcString Action::None, // State::Utf8 ]; pub static EXIT_ACTIONS: &'static [Action] = &[ Action::None, // State::Anywhere Action::None, // State::CsiEntry Action::None, // State::CsiIgnore Action::None, // State::CsiIntermediate Action::None, // State::CsiParam Action::None, // State::DcsEntry Action::None, // State::DcsIgnore Action::None, // State::DcsIntermediate Action::None, // State::DcsParam Action::Unhook, // State::DcsPassthrough Action::None, // State::Escape Action::None, // State::EscapeIntermediate Action::None, // State::Ground Action::OscEnd, // State::OscString Action::None, // State::SosPmApcString Action::None, // State::Utf8 ]; vte-0.3.3/examples/vim10m.rs010066400017500001750000000027221317773342100140460ustar0000000000000000#![feature(test)] extern crate vte; extern crate test; use test::{black_box}; struct BlackBox; impl vte::Perform for BlackBox { fn print(&mut self, c: char) { black_box(c); } fn execute(&mut self, byte: u8) { black_box(byte); } fn hook(&mut self, params: &[i64], intermediates: &[u8], ignore: bool) { black_box(params); black_box(intermediates); black_box(ignore); } fn put(&mut self, byte: u8) { black_box(byte); } fn unhook(&mut self) { black_box("unhook"); } fn osc_dispatch(&mut self, params: &[&[u8]]) { black_box(params); } fn csi_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, c: char) { black_box(params); black_box(intermediates); black_box(ignore); black_box(c); } fn esc_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, byte: u8) { black_box(params); black_box(intermediates); black_box(ignore); black_box(byte); } } /// Large vim scrolling fn main() { let buffer = include_bytes!("../benches/large_vim_scroll.recording"); let bytes = buffer.len(); let target = 100 * 1024 * 1024; let iterations = target / bytes; let (mut state, mut parser) = (BlackBox, vte::Parser::new()); for _ in 0..iterations { for byte in &buffer[..] { parser.advance(&mut state, *byte); } } } vte-0.3.3/foos/large_vim_scroll.recording010066400017500001750000011201231317773677100167500ustar0000000000000000% jwilm@kurast.local ➜  ~/code/alacritty  [?1h=[?2004hvvivim ssrrcc//rreennderer//mmood.rs  [?1l>[?2004l [?1049h[?1h=▽ [?12;25h[?12l[?25h[?25l"src/renderer/mod.rs" 1354L, 40527C[>c 78 impl ::std::fmt::Display for Error {   79  fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {   80 match *self {   81 Error::ShaderCreation(ref err) => {   82 write!(f, "There was an error initializing the shaders: {}", err)   83 }   84 }   85  }   86 }   87    88 impl From<ShaderCreationError> for Error {   89  fn from(val: ShaderCreationError) -> Error {   90 Error::ShaderCreation(val)   91  }   92 }   93    94    95 /// Text drawing program   96 ///   97 /// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a".   98 #[derive(Debug)]   99 pub struct ShaderProgram {   100  // Program id   101  id: GLuint,   102    103  /// projection matrix uniform   104  u_projection: GLint,   105    106  /// Terminal dimensions (pixels)   107  u_term_dim: GLint,   108    109  /// Cell dimensions (pixels)   110  u_cell_dim: GLint,   111    112  /// Visual bell   113  u_visual_bell: GLint,   114    115  /// Background pass flag   116  ///   117  /// Rendering is split into two passes; 1 for backgrounds, and one for text   118  u_background: GLint,   119    120  padding_x: f32,   121  padding_y: f32,   122 }   123    124    125 #[derive(Debug, Clone)]   126 pub struct Glyph {   127  tex_id: GLuint,   128  top: f32,   129  left: f32,   130  width: f32,   131  height: f32,   132  uv_bot: f32,   133  uv_left: f32, 105,0-15%[?12l[?25h[?25l 1 // Copyright 2016 Joe Wilm, The Alacritty Project Contributors   2 //   3 // Licensed under the Apache License, Version 2.0 (the "License");   4 // you may not use this file except in compliance with the License.   5 // You may obtain a copy of the License at   6 //   7 // http://www.apache.org/licenses/LICENSE-2.0   8 //   9 // Unless required by applicable law or agreed to in writing, software   10 // distributed under the License is distributed on an "AS IS" BASIS,   11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   12 // See the License for the specific language governing permissions and   13 // limitations under the License.   14 use std::collections::HashMap;   15 use std::hash::BuildHasherDefault;   16 use std::fs::File;   17 use std::io::{self, Read};   18 use std::mem::size_of;   19 use std::path::{PathBuf};   20 use std::ptr;   21 use std::sync::mpsc;   22    23 use cgmath;   24 use fnv::FnvHasher;   25 use font::{self, Rasterizer, Rasterize, RasterizedGlyph, FontDesc, GlyphKey, FontKey};   26 use gl::types::*;   27 use gl;   28 use index::{Line, Column, RangeInclusive};   29 use notify::{Watcher as WatcherApi, RecommendedWatcher as Watcher, op};   30    31 use config::{self, Config, Delta};   32 use term::{self, cell, RenderableCell};   33 use window::{Size, Pixels};   34    35 use Rgb;   36    37 // Shader paths for live reload   38 static TEXT_SHADER_F_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl");    39 static TEXT_SHADER_V_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl");    40    41 // Shader source which is used when live-shader-reload feature is disable   42 static TEXT_SHADER_F: &'static str = include_str!(   43  concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl")   44 );   45 static TEXT_SHADER_V: &'static str = include_str!(   46  concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.v.glsl")   47 );   48    49 /// `LoadGlyph` allows for copying a rasterized glyph into graphics memory   50 pub trait LoadGlyph {   51  /// Load the rasterized glyph into GPU memory   52  fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph;   53 }   54    55 enum Msg {   56  ShaderReload, 1,1Top[?12l[?25h[?25l2[?12l[?25h[?25l3[?12l[?25h[?25l4[?12l[?25h[?25l5[?12l[?25h[?25l6[?12l[?25h[?25l7[?12l[?25h[?25l8[?12l[?25h[?25l9[?12l[?25h[?25l10,1[?12l[?25h[?25l1[?12l[?25h[?25l2[?12l[?25h[?25l3[?12l[?25h[?25l4[?12l[?25h[?25l5[?12l[?25h[?25l6[?12l[?25h[?25l7[?12l[?25h[?25l8[?12l[?25h[?25l9[?12l[?25h[?25l20[?12l[?25h[?25l1[?12l[?25h[?25l2,0-1[?12l[?25h[?25l3,1 [?12l[?25h[?25l4[?12l[?25h[?25l5[?12l[?25h[?25l6[?12l[?25h[?25l7[?12l[?25h[?25l8[?12l[?25h[?25l9[?12l[?25h[?25l30,0-1[?12l[?25h[?25l1,1 [?12l[?25h[?25l2[?12l[?25h[?25l3[?12l[?25h[?25l4,0-1[?12l[?25h[?25l5,1 [?12l[?25h[?25l6,0-1[?12l[?25h[?25l7,1 [?12l[?25h[?25l8[?12l[?25h[?25l9[?12l[?25h[?25l40,0-1[?12l[?25h[?25l1,1 [?12l[?25h[?25l2[?12l[?25h[?25l3[?12l[?25h[?25l()4[?12l[?25h[?25l()5[?12l[?25h[?25l6[?12l[?25h[?25l()7[?12l[?25h[?25l()8,0-1[?12l[?25h[?25l9,1 [?12l[?25h[?25l50[?12l[?25h[?25l1[?12l[?25h[?25l2[?12l[?25h[?25l{}3[?12l[?25h[?25l{}4,0-1[?12l[?25h[?25l5,1 [?12l[?25h[?25l6[?12l[?25h[?25l {  57 } 57,10%[?12l[?25h[?25l {}  58  58,0-10%[?12l[?25h[?25l  59 #[derive(Debug)] 59,10%[?12l[?25h[?25l  60 pub enum Error { 60,10%[?12l[?25h[?25l  61  ShaderCreation(ShaderCreationError), 61,10%[?12l[?25h[?25l {  62 } 62,10%[?12l[?25h[?25l {}  63  63,0-10%[?12l[?25h[?25l  64 impl ::std::error::Error for Error { 64,10%[?12l[?25h[?25l  65  fn cause(&self) -> Option<&::std::error::Error> { 65,10%[?12l[?25h[?25l  66 match *self { 66,10%[?12l[?25h[?25l  67 Error::ShaderCreation(ref err) => Some(err), 67,10%[?12l[?25h[?25l  68 } 68,10%[?12l[?25h[?25l  69  } 69,11%[?12l[?25h[?25l  70  70,0-11%[?12l[?25h[?25l  71  fn description(&self) -> &str { 71,11%[?12l[?25h[?25l  72 match *self { 72,11%[?12l[?25h[?25l  73 Error::ShaderCreation(ref err) => err.description(), 73,11%[?12l[?25h[?25l  74 } 74,11%[?12l[?25h[?25l  75  } 75,11%[?12l[?25h[?25l { 76 } 76,11%[?12l[?25h[?25l {}  77  77,0-11%[?12l[?25h[?25l  78 impl ::std::fmt::Display for Error { 78,11%[?12l[?25h[?25l  79  fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { 79,11%[?12l[?25h[?25l  80 match *self { 80,11%[?12l[?25h[?25l  81 Error::ShaderCreation(ref err) => { 81,11%[?12l[?25h[?25l  82 write!(f, "There was an error initializing the shaders: {}", err) 82,12%[?12l[?25h[?25l  83 } 83,12%[?12l[?25h[?25l  84 } 84,12%[?12l[?25h[?25l  85  } 85,12%[?12l[?25h[?25l { 86 } 86,12%[?12l[?25h[?25l {}  87  87,0-12%[?12l[?25h[?25l  88 impl From<ShaderCreationError> for Error { 88,12%[?12l[?25h[?25l  89  fn from(val: ShaderCreationError) -> Error { 89,12%[?12l[?25h[?25l  90 Error::ShaderCreation(val) 90,12%[?12l[?25h[?25l  91  } 91,12%[?12l[?25h[?25l { 92 } 92,12%[?12l[?25h[?25l {}  93  93,0-12%[?12l[?25h[?25l  94  94,0-12%[?12l[?25h[?25l  95 /// Text drawing program 95,13%[?12l[?25h[?25l  96 /// 96,13%[?12l[?25h[?25l  97 /// Uniforms are prefixed with "u", and vertex attributes are prefixed with "a". 97,13%[?12l[?25h[?25l  98 #[derive(Debug)] 98,13%[?12l[?25h[?25l  99 pub struct ShaderProgram { 99,13%[?12l[?25h[?25l  100  // Program id 100,13%[?12l[?25h[?25l  101  id: GLuint, 101,13%[?12l[?25h[?25l  102  102,0-13%[?12l[?25h[?25l  103  /// projection matrix uniform 103,13%[?12l[?25h[?25l  104  u_projection: GLint, 104,13%[?12l[?25h[?25l  105  105,0-13%[?12l[?25h[?25l  106  /// Terminal dimensions (pixels) 106,13%[?12l[?25h[?25l  107  u_term_dim: GLint, 107,13%[?12l[?25h[?25l  108  108,0-14%[?12l[?25h[?25l  109  /// Cell dimensions (pixels) 109,14%[?12l[?25h[?25l  110  u_cell_dim: GLint, 110,14%[?12l[?25h[?25l  111  111,0-14%[?12l[?25h[?25l  112  /// Visual bell 112,14%[?12l[?25h[?25l  113  u_visual_bell: GLint, 113,14%[?12l[?25h[?25l  114  114,0-14%[?12l[?25h[?25l  115  /// Background pass flag 115,14%[?12l[?25h[?25l  116  /// 116,14%[?12l[?25h[?25l  117  /// Rendering is split into two passes; 1 for backgrounds, and one for text 117,14%[?12l[?25h[?25l  118  u_background: GLint, 118,14%[?12l[?25h[?25l  119  119,0-14%[?12l[?25h[?25l  120  padding_x: f32, 120,14%[?12l[?25h[?25l  121  padding_y: f32, 121,15%[?12l[?25h[?25l { 122 } 122,15%[?12l[?25h[?25l {}  123  123,0-15%[?12l[?25h[?25l  124  124,0-15%[?12l[?25h[?25l  125 #[derive(Debug, Clone)] 125,15%[?12l[?25h[?25l  126 pub struct Glyph { 126,15%[?12l[?25h[?25l  127  tex_id: GLuint, 127,15%[?12l[?25h[?25l  128  top: f32, 128,15%[?12l[?25h[?25l  129  left: f32, 129,15%[?12l[?25h[?25l  130  width: f32, 130,15%[?12l[?25h[?25l  131  height: f32, 131,15%[?12l[?25h[?25l  132  uv_bot: f32, 132,15%[?12l[?25h[?25l  133  uv_left: f32, 133,15%[?12l[?25h[?25l  134  uv_width: f32, 134,16%[?12l[?25h[?25l  135  uv_height: f32, 135,16%[?12l[?25h[?25l { 136 } 136,16%[?12l[?25h[?25l {}  137  137,0-16%[?12l[?25h[?25l  138 /// Naïve glyph cache 138,16%[?12l[?25h[?25l  139 /// 139,16%[?12l[?25h[?25l  140 /// Currently only keyed by `char`, and thus not possible to hold different 140,16%[?12l[?25h[?25l  141 /// representations of the same code point. 141,16%[?12l[?25h[?25l  142 pub struct GlyphCache { 142,16%[?12l[?25h[?25l  143  /// Cache of buffered glyphs 143,16%[?12l[?25h[?25l  144  cache: HashMap<GlyphKey, Glyph, BuildHasherDefault<FnvHasher>>, 144,16%[?12l[?25h[?25l  145  145,0-16%[?12l[?25h[?25l  146  /// Rasterizer for loading new glyphs 146,16%[?12l[?25h[?25l  147  rasterizer: Rasterizer, 147,17%[?12l[?25h[?25l  148  148,0-17%[?12l[?25h[?25l  149  /// regular font 149,17%[?12l[?25h[?25l  150  font_key: FontKey, 150,17%[?12l[?25h[?25l  151  151,0-17%[?12l[?25h[?25l  152  /// italic font 152,17%[?12l[?25h[?25l  153  italic_key: FontKey, 153,17%[?12l[?25h[?25l  154  154,0-17%[?12l[?25h[?25l  155  /// bold font 155,17%[?12l[?25h[?25l  156  bold_key: FontKey, 156,17%[?12l[?25h[?25l  157  157,0-17%[?12l[?25h[?25l  158  /// font size 158,17%[?12l[?25h[?25l  159  font_size: font::Size, 159,17%[?12l[?25h[?25l  160  160,0-18%[?12l[?25h[?25l  161  /// glyph offset 161,18%[?12l[?25h[?25l  162  glyph_offset: Delta, 162,18%[?12l[?25h[?25l  163  163,0-18%[?12l[?25h[?25l  164  metrics: ::font::Metrics, 164,18%[?12l[?25h[?25l { 165 } 165,18%[?12l[?25h[?25l {}  166  166,0-18%[?12l[?25h[?25l  167 impl GlyphCache { 167,18%[?12l[?25h[?25l  168  pub fn new<L>( 168,18%[?12l[?25h[?25l  169 mut rasterizer: Rasterizer, 169,18%[?12l[?25h[?25l  170 config: &Config, 170,18%[?12l[?25h[?25l  171 loader: &mut L 171,18%[?12l[?25h[?25l  172  ) -> Result<GlyphCache, font::Error> 172,18%[?12l[?25h[?25l  173 where L: LoadGlyph 173,19%[?12l[?25h[?25l  174  { 174,19%[?12l[?25h[?25l  175 let font = config.font(); 175,19%[?12l[?25h[?25l  176 let size = font.size(); 176,19%[?12l[?25h[?25l  177 let glyph_offset = *font.glyph_offset(); 177,19%[?12l[?25h[?25l  178  178,0-19%[?12l[?25h[?25l  179 fn make_desc( 179,19%[?12l[?25h[?25l  180 desc: &config::FontDescription, 180,19%[?12l[?25h[?25l  181 slant: font::Slant, 181,19%[?12l[?25h[?25l  182 weight: font::Weight, 182,19%[?12l[?25h[?25l  183 ) -> FontDesc 183,19%[?12l[?25h[?25l  184 { 184,19%[?12l[?25h[?25l  185 let style = if let Some(ref spec) = desc.style { 185,19%[?12l[?25h[?25l  186 font::Style::Specific(spec.to_owned()) 186,110%[?12l[?25h[?25l  187 } else { 187,110%[?12l[?25h[?25l  188 font::Style::Description {slant:slant, weight:weight} 188,110%[?12l[?25h[?25l  189 }; 189,110%[?12l[?25h[?25l  190 FontDesc::new(&desc.family[..], style) 190,110%[?12l[?25h[?25l  191 } 191,110%[?12l[?25h[?25l  192  192,0-110%[?12l[?25h[?25l  193 // Load regular font 193,110%[?12l[?25h[?25l  194 let regular_desc = make_desc(&font.normal, font::Slant::Normal, font::Weight::Normal);  194,110%[?12l[?25h[?25l  195  195,0-110%[?12l[?25h[?25l  196 let regular = rasterizer 196,110%[?12l[?25h[?25l  197 .load_font(&regular_desc, size)?; 197,110%[?12l[?25h[?25l  198  198,0-110%[?12l[?25h[?25l  199 // helper to load a description if it is not the regular_desc 199,111%[?12l[?25h[?25l  200 let load_or_regular = |desc:FontDesc, rasterizer: &mut Rasterizer| { 200,111%[?12l[?25h[?25l  201 if desc == regular_desc { 201,111%[?12l[?25h[?25l  202 regular 202,111%[?12l[?25h[?25l  203 } else { 203,111%[?12l[?25h[?25l  204 rasterizer.load_font(&desc, size).unwrap_or_else(|_| regular) 204,111%[?12l[?25h[?25l  205 } 205,111%[?12l[?25h[?25l  206 }; 206,111%[?12l[?25h[?25l  207  207,0-111%[?12l[?25h[?25l  208 // Load bold font 208,111%[?12l[?25h[?25l  209 let bold_desc = make_desc(&font.bold, font::Slant::Normal, font::Weight::Bold); 209,111%[?12l[?25h[?25l  210  210,0-111%[?12l[?25h[?25l  211 let bold = load_or_regular(bold_desc, &mut rasterizer); 211,111%[?12l[?25h[?25l  212  212,0-112%[?12l[?25h[?25l  213 // Load italic font 213,112%[?12l[?25h[?25l  214 let italic_desc = make_desc(&font.italic, font::Slant::Italic, font::Weight::Normal); 214,112%[?12l[?25h[?25l  215  215,0-112%[?12l[?25h[?25l  216 let italic = load_or_regular(italic_desc, &mut rasterizer); 216,112%[?12l[?25h[?25l  217  217,0-112%[?12l[?25h[?25l  218 // Need to load at least one glyph for the face before calling metrics. 218,112%[?12l[?25h[?25l  219 // The glyph requested here ('m' at the time of writing) has no special 219,112%[?12l[?25h[?25l  220 // meaning. 220,112%[?12l[?25h[?25l  221 rasterizer.get_glyph(&GlyphKey { font_key: regular, c: 'm', size: font.size() })?; 221,112%[?12l[?25h[?25l  222 let metrics = rasterizer.metrics(regular)?; 222,112%[?12l[?25h[?25l  223  223,0-112%[?12l[?25h[?25l  224 let mut cache = GlyphCache { 224,112%[?12l[?25h[?25l  225 cache: HashMap::default(), 225,113%[?12l[?25h[?25l  226 rasterizer: rasterizer, 226,113%[?12l[?25h[?25l  227 font_size: font.size(), 227,113%[?12l[?25h[?25l  228 font_key: regular, 228,113%[?12l[?25h[?25l  229 bold_key: bold, 229,113%[?12l[?25h[?25l  230 italic_key: italic, 230,113%[?12l[?25h[?25l  231 glyph_offset: glyph_offset, 231,113%[?12l[?25h[?25l  232 metrics: metrics 232,113%[?12l[?25h[?25l  233 }; 233,113%[?12l[?25h[?25l  234  234,0-113%[?12l[?25h[?25l  235 macro_rules! load_glyphs_for_font { 235,113%[?12l[?25h[?25l  236 ($font:expr) => { 236,113%[?12l[?25h[?25l  237 for i in RangeInclusive::new(32u8, 128u8) { 237,113%[?12l[?25h[?25l  238 cache.get(&GlyphKey { 238,114%[?12l[?25h[?25l  239 font_key: $font, 239,114%[?12l[?25h[?25l  240 c: i as char, 240,114%[?12l[?25h[?25l  241 size: font.size() 241,114%[?12l[?25h[?25l  242 }, loader); 242,114%[?12l[?25h[?25l  243 } 243,114%[?12l[?25h[?25l  244 } 244,114%[?12l[?25h[?25l  245 } 245,114%[?12l[?25h[?25l  246  246,0-114%[?12l[?25h[?25l  247 load_glyphs_for_font!(regular); 247,114%[?12l[?25h[?25l  248 load_glyphs_for_font!(bold); 248,114%[?12l[?25h[?25l  249 load_glyphs_for_font!(italic); 249,114%[?12l[?25h[?25l  250  250,0-114%[?12l[?25h[?25l  251 Ok(cache) 251,115%[?12l[?25h[?25l  252  } 252,115%[?12l[?25h[?25l  253  253,0-115%[?12l[?25h[?25l  254  pub fn font_metrics(&self) -> font::Metrics { 254,115%[?12l[?25h[?25l  255 self.rasterizer 255,115%[?12l[?25h[?25l  256 .metrics(self.font_key) 256,115%[?12l[?25h[?25l  257 .expect("metrics load since font is loaded at glyph cache creation") 257,115%[?12l[?25h[?25l  258  } 258,115%[?12l[?25h[?25l  259  259,0-115%[?12l[?25h[?25l  260  pub fn get<'a, L>(&'a mut self, glyph_key: &GlyphKey, loader: &mut L) -> &'a Glyph 260,115%[?12l[?25h[?25l  261 where L: LoadGlyph 261,115%[?12l[?25h[?25l  262  { 262,115%[?12l[?25h[?25l  263 let glyph_offset = self.glyph_offset; 263,115%[?12l[?25h[?25l  264 let rasterizer = &mut self.rasterizer; 264,116%[?12l[?25h[?25l  265 let metrics = &self.metrics; 265,116%[?12l[?25h[?25l  266 self.cache 266,116%[?12l[?25h[?25l  267 .entry(*glyph_key) 267,116%[?12l[?25h[?25l  268 .or_insert_with(|| { 268,116%[?12l[?25h[?25l  269 let mut rasterized = rasterizer.get_glyph(&glyph_key) 269,116%[?12l[?25h[?25l  270 .unwrap_or_else(|_| Default::default()); 270,116%[?12l[?25h[?25l  271  271,0-116%[?12l[?25h[?25l  272 rasterized.left += glyph_offset.x as i32; 272,116%[?12l[?25h[?25l  273 rasterized.top += glyph_offset.y as i32; 273,116%[?12l[?25h[?25l  274 rasterized.top -= metrics.descent as i32; 274,116%[?12l[?25h[?25l  275  275,0-116%[?12l[?25h[?25l  276 loader.load_glyph(&rasterized) 276,116%[?12l[?25h[?25l  277 }) 277,117%[?12l[?25h[?25l  278  } 278,117%[?12l[?25h[?25l  279 } 279,117%[?12l[?25h[?25l  280  280,0-117%[?12l[?25h[?25l  281 #[derive(Debug)] 281,117%[?12l[?25h[?25l  282 #[repr(C)] 282,117%[?12l[?25h[?25l  283 struct InstanceData { 283,117%[?12l[?25h[?25l  284  // coords 284,117%[?12l[?25h[?25l  285  col: f32, 285,117%[?12l[?25h[?25l  286  row: f32, 286,117%[?12l[?25h[?25l  287  // glyph offset 287,117%[?12l[?25h[?25l  288  left: f32, 288,117%[?12l[?25h[?25l  289  top: f32, 289,117%[?12l[?25h[?25l  290  // glyph scale 290,118%[?12l[?25h[?25l  291  width: f32, 291,118%[?12l[?25h[?25l  292  height: f32, 292,118%[?12l[?25h[?25l  293  // uv offset 293,118%[?12l[?25h[?25l  294  uv_left: f32, 294,118%[?12l[?25h[?25l  295  uv_bot: f32, 295,118%[?12l[?25h[?25l  296  // uv scale 296,118%[?12l[?25h[?25l  297  uv_width: f32, 297,118%[?12l[?25h[?25l  298  uv_height: f32, 298,118%[?12l[?25h[?25l  299  // color 299,118%[?12l[?25h[?25l  300  r: f32, 300,118%[?12l[?25h[?25l  301  g: f32, 301,118%[?12l[?25h[?25l  302  b: f32, 302,118%[?12l[?25h[?25l  303  // background color 303,119%[?12l[?25h[?25l  304  bg_r: f32, 304,119%[?12l[?25h[?25l  305  bg_g: f32, 305,119%[?12l[?25h[?25l  306  bg_b: f32, 306,119%[?12l[?25h[?25l { 307 } 307,119%[?12l[?25h[?25l {}  308  308,0-119%[?12l[?25h[?25l  309 #[derive(Debug)] 309,119%[?12l[?25h[?25l  310 pub struct QuadRenderer { 310,119%[?12l[?25h[?25l  311  program: ShaderProgram, 311,119%[?12l[?25h[?25l  312  vao: GLuint, 312,119%[?12l[?25h[?25l  313  vbo: GLuint, 313,119%[?12l[?25h[?25l  314  ebo: GLuint, 314,119%[?12l[?25h[?25l  315  vbo_instance: GLuint, 315,119%[?12l[?25h[?25l  316  atlas: Vec<Atlas>, 316,120%[?12l[?25h[?25l  317  active_tex: GLuint, 317,120%[?12l[?25h[?25l  318  batch: Batch, 318,120%[?12l[?25h[?25l  319  rx: mpsc::Receiver<Msg>, 319,120%[?12l[?25h[?25l { 320 } 320,120%[?12l[?25h[?25l {}  321  321,0-120%[?12l[?25h[?25l  322 #[derive(Debug)] 322,120%[?12l[?25h[?25l  323 pub struct RenderApi<'a> { 323,120%[?12l[?25h[?25l  324  active_tex: &'a mut GLuint, 324,120%[?12l[?25h[?25l  325  batch: &'a mut Batch, 325,120%[?12l[?25h[?25l  326  atlas: &'a mut Vec<Atlas>, 326,120%[?12l[?25h[?25l  327  program: &'a mut ShaderProgram, 327,120%[?12l[?25h[?25l  328  config: &'a Config, 328,120%[?12l[?25h[?25l  329  visual_bell_intensity: f32 329,121%[?12l[?25h[?25l { 330 } 330,121%[?12l[?25h[?25l {}  331  331,0-121%[?12l[?25h[?25l  332 #[derive(Debug)] 332,121%[?12l[?25h[?25l  333 pub struct LoaderApi<'a> { 333,121%[?12l[?25h[?25l  334  active_tex: &'a mut GLuint, 334,121%[?12l[?25h[?25l  335  atlas: &'a mut Vec<Atlas>, 335,121%[?12l[?25h[?25l {  336 } 336,121%[?12l[?25h[?25l {}  337  337,0-121%[?12l[?25h[?25l  338 #[derive(Debug)] 338,121%[?12l[?25h[?25l  339 pub struct PackedVertex { 339,121%[?12l[?25h[?25l  340  x: f32, 340,121%[?12l[?25h[?25l  341  y: f32, 341,121%[?12l[?25h[?25l {  342 } 342,122%[?12l[?25h[?25l {}  343  343,0-122%[?12l[?25h[?25l  344 #[derive(Debug)] 344,122%[?12l[?25h[?25l  345 pub struct Batch { 345,122%[?12l[?25h[?25l  346  tex: GLuint, 346,122%[?12l[?25h[?25l  347  instances: Vec<InstanceData>, 347,122%[?12l[?25h[?25l {  348 } 348,122%[?12l[?25h[?25l {}  349  349,0-122%[?12l[?25h[?25l  350 impl Batch { 350,122%[?12l[?25h[?25l  351  #[inline] 351,122%[?12l[?25h[?25l  352  pub fn new() -> Batch { 352,122%[?12l[?25h[?25l  353 Batch { 353,122%[?12l[?25h[?25l  354 tex: 0, 354,122%[?12l[?25h[?25l  355 instances: Vec::with_capacity(BATCH_MAX), 355,123%[?12l[?25h[?25l  356 } 356,123%[?12l[?25h[?25l  357  } 357,123%[?12l[?25h[?25l  358  358,0-123%[?12l[?25h[?25l  359  pub fn add_item( 359,123%[?12l[?25h[?25l  360 &mut self, 360,123%[?12l[?25h[?25l  361 cell: &RenderableCell, 361,123%[?12l[?25h[?25l  362 glyph: &Glyph, 362,123%[?12l[?25h[?25l  363  ) { 363,123%[?12l[?25h[?25l  364 if self.is_empty() { 364,123%[?12l[?25h[?25l  365 self.tex = glyph.tex_id; 365,123%[?12l[?25h[?25l  366 } 366,123%[?12l[?25h[?25l  367  367,0-123%[?12l[?25h[?25l  368 self.instances.push(InstanceData { 368,124%[?12l[?25h[?25l  369 col: cell.column.0 as f32, 369,124%[?12l[?25h[?25l  370 row: cell.line.0 as f32, 370,124%[?12l[?25h[?25l  371  371,0-124%[?12l[?25h[?25l  372 top: glyph.top, 372,124%[?12l[?25h[?25l  373 left: glyph.left, 373,124%[?12l[?25h[?25l  374 width: glyph.width, 374,124%[?12l[?25h[?25l  375 height: glyph.height, 375,124%[?12l[?25h[?25l  376  376,0-124%[?12l[?25h[?25l  377 uv_bot: glyph.uv_bot, 377,124%[?12l[?25h[?25l  378 uv_left: glyph.uv_left, 378,124%[?12l[?25h[?25l  379 uv_width: glyph.uv_width, 379,124%[?12l[?25h[?25l  380 uv_height: glyph.uv_height, 380,124%[?12l[?25h[?25l  381  381,0-125%[?12l[?25h[?25l  382 r: cell.fg.r as f32, 382,125%[?12l[?25h[?25l  383 g: cell.fg.g as f32, 383,125%[?12l[?25h[?25l  384 b: cell.fg.b as f32, 384,125%[?12l[?25h[?25l  385  385,0-125%[?12l[?25h[?25l  386 bg_r: cell.bg.r as f32, 386,125%[?12l[?25h[?25l  387 bg_g: cell.bg.g as f32, 387,125%[?12l[?25h[?25l  388 bg_b: cell.bg.b as f32, 388,125%[?12l[?25h[?25l  389 }); 389,125%[?12l[?25h[?25l  390  } 390,125%[?12l[?25h[?25l  391  391,0-125%[?12l[?25h[?25l  392  #[inline] 392,125%[?12l[?25h[?25l  393  pub fn full(&self) -> bool { 393,125%[?12l[?25h[?25l  394 self.capacity() == self.len() 394,126%[?12l[?25h[?25l  395  } 395,126%[?12l[?25h[?25l  396  396,0-126%[?12l[?25h[?25l  397  #[inline] 397,126%[?12l[?25h[?25l  398  pub fn len(&self) -> usize { 398,126%[?12l[?25h[?25l  399 self.instances.len() 399,126%[?12l[?25h[?25l  400  } 400,126%[?12l[?25h[?25l  401  401,0-126%[?12l[?25h[?25l  402  #[inline] 402,126%[?12l[?25h[?25l  403  pub fn capacity(&self) -> usize { 403,126%[?12l[?25h[?25l  404 BATCH_MAX 404,126%[?12l[?25h[?25l  405  } 405,126%[?12l[?25h[?25l  406  406,0-126%[?12l[?25h[?25l  407  #[inline] 407,127%[?12l[?25h[?25l  408  pub fn is_empty(&self) -> bool { 408,127%[?12l[?25h[?25l  409 self.len() == 0 409,127%[?12l[?25h[?25l  410  } 410,127%[?12l[?25h[?25l  411  411,0-127%[?12l[?25h[?25l  412  #[inline] 412,127%[?12l[?25h[?25l  413  pub fn size(&self) -> usize { 413,127%[?12l[?25h[?25l  414 self.len() * size_of::<InstanceData>() 414,127%[?12l[?25h[?25l  415  } 415,127%[?12l[?25h[?25l  416  416,0-127%[?12l[?25h[?25l  417  pub fn clear(&mut self) { 417,127%[?12l[?25h[?25l  418 self.tex = 0; 418,127%[?12l[?25h[?25l  419 self.instances.clear(); 419,127%[?12l[?25h[?25l  420  } 420,128%[?12l[?25h[?25l  421 } 421,128%[?12l[?25h[?25l  422  422,0-128%[?12l[?25h[?25l  423 /// Maximum items to be drawn in a batch. 423,128%[?12l[?25h[?25l  424 const BATCH_MAX: usize = 65_536; 424,128%[?12l[?25h[?25l  425 const ATLAS_SIZE: i32 = 1024; 425,128%[?12l[?25h[?25l  426  426,0-128%[?12l[?25h[?25l  427 impl QuadRenderer { 427,128%[?12l[?25h[?25l  428  // TODO should probably hand this a transform instead of width/height 428,128%[?12l[?25h[?25l  429  pub fn new(config: &Config, size: Size<Pixels<u32>>) -> Result<QuadRenderer, Error> { 429,128%[?12l[?25h[?25l  430 let program = ShaderProgram::new(config, size)?; 430,128%[?12l[?25h[?25l  431  431,0-128%[?12l[?25h[?25l  432 let mut vao: GLuint = 0; 432,128%[?12l[?25h[?25l  433 let mut vbo: GLuint = 0; 433,129%[?12l[?25h[?25l  434 let mut ebo: GLuint = 0; 434,129%[?12l[?25h[?25l  435  435,0-129%[?12l[?25h[?25l  436 let mut vbo_instance: GLuint = 0; 436,129%[?12l[?25h[?25l  437  437,0-129%[?12l[?25h[?25l  438 unsafe { 438,129%[?12l[?25h[?25l  439 gl::Enable(gl::BLEND); 439,129%[?12l[?25h[?25l  440 gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR); 440,129%[?12l[?25h[?25l  441 gl::Enable(gl::MULTISAMPLE); 441,129%[?12l[?25h[?25l  442  442,0-129%[?12l[?25h[?25l  443 gl::GenVertexArrays(1, &mut vao); 443,129%[?12l[?25h[?25l  444 gl::GenBuffers(1, &mut vbo); 444,129%[?12l[?25h[?25l  445 gl::GenBuffers(1, &mut ebo); 445,129%[?12l[?25h[?25l  446 gl::GenBuffers(1, &mut vbo_instance); 446,130%[?12l[?25h[?25l  447 gl::BindVertexArray(vao); 447,130%[?12l[?25h[?25l  448  448,0-130%[?12l[?25h[?25l  449 // ---------------------------- 449,130%[?12l[?25h[?25l  450 // setup vertex position buffer 450,130%[?12l[?25h[?25l  451 // ---------------------------- 451,130%[?12l[?25h[?25l  452 // Top right, Bottom right, Bottom left, Top left 452,130%[?12l[?25h[?25l  453 let vertices = [ 453,130%[?12l[?25h[?25l  454 PackedVertex { x: 1.0, y: 1.0 }, 454,130%[?12l[?25h[?25l  455 PackedVertex { x: 1.0, y: 0.0 }, 455,130%[?12l[?25h[?25l  456 PackedVertex { x: 0.0, y: 0.0 }, 456,130%[?12l[?25h[?25l  457 PackedVertex { x: 0.0, y: 1.0 }, 457,130%[?12l[?25h[?25l  458 ]; 458,130%[?12l[?25h[?25l  459  459,0-131%[?12l[?25h[?25l  460 gl::BindBuffer(gl::ARRAY_BUFFER, vbo); 460,131%[?12l[?25h[?25l  461  461,0-131%[?12l[?25h[?25l  462 gl::VertexAttribPointer(0, 2, 462,131%[?12l[?25h[?25l  463 gl::FLOAT, gl::FALSE, 463,131%[?12l[?25h[?25l  464 size_of::<PackedVertex>() as i32, 464,131%[?12l[?25h[?25l  465 ptr::null()); 465,131%[?12l[?25h[?25l  466 gl::EnableVertexAttribArray(0); 466,131%[?12l[?25h[?25l  467  467,0-131%[?12l[?25h[?25l  468 gl::BufferData(gl::ARRAY_BUFFER, 468,131%[?12l[?25h[?25l  469 (size_of::<PackedVertex>() * vertices.len()) as GLsizeiptr, 469,131%[?12l[?25h[?25l  470 vertices.as_ptr() as *const _, 470,131%[?12l[?25h[?25l  471 gl::STATIC_DRAW); 471,131%[?12l[?25h[?25l  472  472,0-132%[?12l[?25h[?25l  473 // --------------------- 473,132%[?12l[?25h[?25l  474 // Set up element buffer 474,132%[?12l[?25h[?25l  475 // --------------------- 475,132%[?12l[?25h[?25l  476 let indices: [u32; 6] = [0, 1, 3, 476,132%[?12l[?25h[?25l  477 1, 2, 3]; 477,132%[?12l[?25h[?25l  478  478,0-132%[?12l[?25h[?25l  479 gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo); 479,132%[?12l[?25h[?25l  480 gl::BufferData(gl::ELEMENT_ARRAY_BUFFER, 480,132%[?12l[?25h[?25l  481 (6 * size_of::<u32>()) as isize, 481,132%[?12l[?25h[?25l  482 indices.as_ptr() as *const _, 482,132%[?12l[?25h[?25l  483 gl::STATIC_DRAW); 483,132%[?12l[?25h[?25l  484  484,0-132%[?12l[?25h[?25l  485 // ---------------------------- 485,133%[?12l[?25h[?25l  486 // Setup vertex instance buffer 486,133%[?12l[?25h[?25l  487 // ---------------------------- 487,133%[?12l[?25h[?25l  488 gl::BindBuffer(gl::ARRAY_BUFFER, vbo_instance); 488,133%[?12l[?25h[?25l  489 gl::BufferData(gl::ARRAY_BUFFER, 489,133%[?12l[?25h[?25l  490 (BATCH_MAX * size_of::<InstanceData>()) as isize, 490,133%[?12l[?25h[?25l  491 ptr::null(), gl::STREAM_DRAW); 491,133%[?12l[?25h[?25l  492 // coords 492,133%[?12l[?25h[?25l  493 gl::VertexAttribPointer(1, 2, 493,133%[?12l[?25h[?25l  494 gl::FLOAT, gl::FALSE, 494,133%[?12l[?25h[?25l  495 size_of::<InstanceData>() as i32, 495,133%[?12l[?25h[?25l  496 ptr::null()); 496,133%[?12l[?25h[?25l  497 gl::EnableVertexAttribArray(1); 497,133%[?12l[?25h[?25l  498 gl::VertexAttribDivisor(1, 1); 498,134%[?12l[?25h[?25l  499 // glyphoffset 499,134%[?12l[?25h[?25l  500 gl::VertexAttribPointer(2, 4, 500,134%[?12l[?25h[?25l  501 gl::FLOAT, gl::FALSE, 501,134%[?12l[?25h[?25l  502 size_of::<InstanceData>() as i32, 502,134%[?12l[?25h[?25l  503 (2 * size_of::<f32>()) as *const _); 503,134%[?12l[?25h[?25l  504 gl::EnableVertexAttribArray(2); 504,134%[?12l[?25h[?25l  505 gl::VertexAttribDivisor(2, 1); 505,134%[?12l[?25h[?25l  506 // uv 506,134%[?12l[?25h[?25l  507 gl::VertexAttribPointer(3, 4, 507,134%[?12l[?25h[?25l  508 gl::FLOAT, gl::FALSE, 508,134%[?12l[?25h[?25l  509 size_of::<InstanceData>() as i32, 509,134%[?12l[?25h[?25l  510 (6 * size_of::<f32>()) as *const _); 510,134%[?12l[?25h[?25l  511 gl::EnableVertexAttribArray(3); 511,135%[?12l[?25h[?25l  512 gl::VertexAttribDivisor(3, 1); 512,135%[?12l[?25h[?25l  513 // color 513,135%[?12l[?25h[?25l  514 gl::VertexAttribPointer(4, 3, 514,135%[?12l[?25h[?25l  515 gl::FLOAT, gl::FALSE, 515,135%[?12l[?25h[?25l  516 size_of::<InstanceData>() as i32, 516,135%[?12l[?25h[?25l  517 (10 * size_of::<f32>()) as *const _); 517,135%[?12l[?25h[?25l  518 gl::EnableVertexAttribArray(4); 518,135%[?12l[?25h[?25l  519 gl::VertexAttribDivisor(4, 1); 519,135%[?12l[?25h[?25l  520 // color 520,135%[?12l[?25h[?25l  521 gl::VertexAttribPointer(5, 3, 521,135%[?12l[?25h[?25l  522 gl::FLOAT, gl::FALSE, 522,135%[?12l[?25h[?25l  523 size_of::<InstanceData>() as i32, 523,135%[?12l[?25h[?25l  524 (13 * size_of::<f32>()) as *const _); 524,136%[?12l[?25h[?25l  525 gl::EnableVertexAttribArray(5); 525,136%[?12l[?25h[?25l  526 gl::VertexAttribDivisor(5, 1); 526,136%[?12l[?25h[?25l  527  527,0-136%[?12l[?25h[?25l  528 gl::BindVertexArray(0); 528,136%[?12l[?25h[?25l  529 gl::BindBuffer(gl::ARRAY_BUFFER, 0); 529,136%[?12l[?25h[?25l  530 } 530,136%[?12l[?25h[?25l  531  531,0-136%[?12l[?25h[?25l  532 let (msg_tx, msg_rx) = mpsc::channel(); 532,136%[?12l[?25h[?25l  533  533,0-136%[?12l[?25h[?25l  534 if cfg!(feature = "live-shader-reload") { 534,136%[?12l[?25h[?25l  535 ::std::thread::spawn(move || { 535,136%[?12l[?25h[?25l  536 let (tx, rx) = ::std::sync::mpsc::channel(); 536,136%[?12l[?25h[?25l  537 let mut watcher = Watcher::new(tx).expect("create file watcher"); 537,137%[?12l[?25h[?25l  538 watcher.watch(TEXT_SHADER_F_PATH).expect("watch fragment shader"); 538,137%[?12l[?25h[?25l  539 watcher.watch(TEXT_SHADER_V_PATH).expect("watch vertex shader"); 539,137%[?12l[?25h[?25l  540  540,0-137%[?12l[?25h[?25l  541 loop { 541,137%[?12l[?25h[?25l  542 let event = rx.recv().expect("watcher event"); 542,137%[?12l[?25h[?25l  543 let ::notify::Event { path, op } = event; 543,137%[?12l[?25h[?25l  544  544,0-137%[?12l[?25h[?25l  545 if let Ok(op) = op { 545,137%[?12l[?25h[?25l  546 if op.contains(op::RENAME) { 546,137%[?12l[?25h[?25l  547 continue; 547,137%[?12l[?25h[?25l  548 } 548,137%[?12l[?25h[?25l  549  549,0-137%[?12l[?25h[?25l  550 if op.contains(op::IGNORED) { 550,138%[?12l[?25h[?25l  551 if let Some(path) = path.as_ref() { 551,138%[?12l[?25h[?25l  552 if let Err(err) = watcher.watch(path) { 552,138%[?12l[?25h[?25l  553 warn!("failed to establish watch on {:?}: {:?}", path, err);  553,138%[?12l[?25h[?25l  554 } 554,138%[?12l[?25h[?25l  555 } 555,138%[?12l[?25h[?25l  556  556,0-138%[?12l[?25h[?25l  557 msg_tx.send(Msg::ShaderReload) 557,138%[?12l[?25h[?25l  558 .expect("msg send ok"); 558,138%[?12l[?25h[?25l  559 } 559,138%[?12l[?25h[?25l  560 } 560,138%[?12l[?25h[?25l  561 } 561,138%[?12l[?25h[?25l  562 }); 562,138%[?12l[?25h[?25l  563 } 563,139%[?12l[?25h[?25l  564  564,0-139%[?12l[?25h[?25l  565 let mut renderer = QuadRenderer { 565,139%[?12l[?25h[?25l  566 program: program, 566,139%[?12l[?25h[?25l  567 vao: vao, 567,139%[?12l[?25h[?25l  568 vbo: vbo, 568,139%[?12l[?25h[?25l  569 ebo: ebo, 569,139%[?12l[?25h[?25l  570 vbo_instance: vbo_instance, 570,139%[?12l[?25h[?25l  571 atlas: Vec::new(), 571,139%[?12l[?25h[?25l  572 active_tex: 0, 572,139%[?12l[?25h[?25l  573 batch: Batch::new(), 573,139%[?12l[?25h[?25l  574 rx: msg_rx, 574,139%[?12l[?25h[?25l  575 }; 575,139%[?12l[?25h[?25l  576  576,0-140%[?12l[?25h[?25l  577 let atlas = Atlas::new(ATLAS_SIZE); 577,140%[?12l[?25h[?25l  578 renderer.atlas.push(atlas); 578,140%[?12l[?25h[?25l  579  579,0-140%[?12l[?25h[?25l  580 Ok(renderer) 580,140%[?12l[?25h[?25l  581  } 581,140%[?12l[?25h[?25l  582  582,0-140%[?12l[?25h[?25l  583  pub fn with_api<F, T>( 583,140%[?12l[?25h[?25l  584 &mut self, 584,140%[?12l[?25h[?25l  585 config: &Config, 585,140%[?12l[?25h[?25l  586 props: &term::SizeInfo, 586,140%[?12l[?25h[?25l  587 visual_bell_intensity: f64, 587,140%[?12l[?25h[?25l  588 func: F 588,140%[?12l[?25h[?25l  589  ) -> T 589,141%[?12l[?25h[?25l  590 where F: FnOnce(RenderApi) -> T 590,141%[?12l[?25h[?25l  591  { 591,141%[?12l[?25h[?25l  592 while let Ok(msg) = self.rx.try_recv() { 592,141%[?12l[?25h[?25l  593 match msg { 593,141%[?12l[?25h[?25l  594 Msg::ShaderReload => { 594,141%[?12l[?25h[?25l  595 self.reload_shaders(&config, Size { 595,141%[?12l[?25h[?25l  596 width: Pixels(props.width as u32), 596,141%[?12l[?25h[?25l  597 height: Pixels(props.height as u32) 597,141%[?12l[?25h[?25l  598 }); 598,141%[?12l[?25h[?25l  599 } 599,141%[?12l[?25h[?25l  600 } 600,141%[?12l[?25h[?25l  601 } 601,141%[?12l[?25h[?25l  602  602,0-142%[?12l[?25h[?25l  603 unsafe { 603,142%[?12l[?25h[?25l  604 self.program.activate(); 604,142%[?12l[?25h[?25l  605 self.program.set_term_uniforms(props); 605,142%[?12l[?25h[?25l  606 self.program.set_visual_bell(visual_bell_intensity as _); 606,142%[?12l[?25h[?25l  607  607,0-142%[?12l[?25h[?25l  608 gl::BindVertexArray(self.vao); 608,142%[?12l[?25h[?25l  609 gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo); 609,142%[?12l[?25h[?25l  610 gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo_instance); 610,142%[?12l[?25h[?25l  611 gl::ActiveTexture(gl::TEXTURE0); 611,142%[?12l[?25h[?25l  612 } 612,142%[?12l[?25h[?25l  613  613,0-142%[?12l[?25h[?25l  614 let res = func(RenderApi { 614,142%[?12l[?25h[?25l  615 active_tex: &mut self.active_tex, 615,143%[?12l[?25h[?25l  616 batch: &mut self.batch, 616,143%[?12l[?25h[?25l  617 atlas: &mut self.atlas, 617,143%[?12l[?25h[?25l  618 program: &mut self.program, 618,143%[?12l[?25h[?25l  619 visual_bell_intensity: visual_bell_intensity as _, 619,143%[?12l[?25h[?25l  620 config: config, 620,143%[?12l[?25h[?25l  621 }); 621,143%[?12l[?25h[?25l  622  622,0-143%[?12l[?25h[?25l  623 unsafe { 623,143%[?12l[?25h[?25l  624 gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, 0); 624,143%[?12l[?25h[?25l  625 gl::BindBuffer(gl::ARRAY_BUFFER, 0); 625,143%[?12l[?25h[?25l  626 gl::BindVertexArray(0); 626,143%[?12l[?25h[?25l  627  627,0-143%[?12l[?25h[?25l  628 self.program.deactivate(); 628,144%[?12l[?25h[?25l  629 } 629,144%[?12l[?25h[?25l  630  630,0-144%[?12l[?25h[?25l  631 res 631,144%[?12l[?25h[?25l  632  } 632,144%[?12l[?25h[?25l  633  633,0-144%[?12l[?25h[?25l  634  pub fn with_loader<F, T>(&mut self, func: F) -> T 634,144%[?12l[?25h[?25l  635 where F: FnOnce(LoaderApi) -> T 635,144%[?12l[?25h[?25l  636  { 636,144%[?12l[?25h[?25l  637 unsafe { 637,144%[?12l[?25h[?25l  638 gl::ActiveTexture(gl::TEXTURE0); 638,144%[?12l[?25h[?25l  639 } 639,144%[?12l[?25h[?25l  640  640,0-144%[?12l[?25h[?25l  641 func(LoaderApi { 641,145%[?12l[?25h[?25l  642 active_tex: &mut self.active_tex, 642,145%[?12l[?25h[?25l  643 atlas: &mut self.atlas, 643,145%[?12l[?25h[?25l  644 }) 644,145%[?12l[?25h[?25l  645  } 645,145%[?12l[?25h[?25l  646  646,0-145%[?12l[?25h[?25l  647  pub fn reload_shaders(&mut self, config: &Config, size: Size<Pixels<u32>>) { 647,145%[?12l[?25h[?25l  648 info!("Reloading shaders"); 648,145%[?12l[?25h[?25l  649 let program = match ShaderProgram::new(config, size) { 649,145%[?12l[?25h[?25l  650 Ok(program) => program, 650,145%[?12l[?25h[?25l  651 Err(err) => { 651,145%[?12l[?25h[?25l  652 match err { 652,145%[?12l[?25h[?25l  653 ShaderCreationError::Io(err) => { 653,145%[?12l[?25h[?25l  654 error!("Error reading shader file: {}", err); 654,146%[?12l[?25h[?25l  655 }, 655,146%[?12l[?25h[?25l  656 ShaderCreationError::Compile(path, log) => { 656,146%[?12l[?25h[?25l  657 error!("Error compiling shader at {:?}", path); 657,146%[?12l[?25h[?25l  658 let _ = io::copy(&mut log.as_bytes(), &mut io::stdout()); 658,146%[?12l[?25h[?25l  659 } 659,146%[?12l[?25h[?25l  660 } 660,146%[?12l[?25h[?25l  661  661,0-146%[?12l[?25h[?25l  662 return; 662,146%[?12l[?25h[?25l  663 } 663,146%[?12l[?25h[?25l  664 }; 664,146%[?12l[?25h[?25l  665  665,0-146%[?12l[?25h[?25l  666 self.active_tex = 0; 666,146%[?12l[?25h[?25l  667 self.program = program; 667,147%[?12l[?25h[?25l  668  } 668,147%[?12l[?25h[?25l  669  669,0-147%[?12l[?25h[?25l  670  pub fn resize(&mut self, width: i32, height: i32) { 670,147%[?12l[?25h[?25l  671 let padding_x = self.program.padding_x as i32; 671,147%[?12l[?25h[?25l  672 let padding_y = self.program.padding_y as i32; 672,147%[?12l[?25h[?25l  673  673,0-147%[?12l[?25h[?25l  674 // viewport 674,147%[?12l[?25h[?25l  675 unsafe { 675,147%[?12l[?25h[?25l  676 gl::Viewport(padding_x, padding_y, width - 2 * padding_x, height - 2 * padding_y);  676,147%[?12l[?25h[?25l  677 } 677,147%[?12l[?25h[?25l  678  678,0-147%[?12l[?25h[?25l  679 // update projection 679,147%[?12l[?25h[?25l  680 self.program.activate(); 680,148%[?12l[?25h[?25l  681 self.program.update_projection(width as f32, height as f32); 681,148%[?12l[?25h[?25l  682 self.program.deactivate(); 682,148%[?12l[?25h[?25l  683  } 683,148%[?12l[?25h[?25l  684 } 684,148%[?12l[?25h[?25l  685  685,0-148%[?12l[?25h[?25l  686 impl<'a> RenderApi<'a> { 686,148%[?12l[?25h[?25l  687  pub fn clear(&self, color: Rgb) { 687,148%[?12l[?25h[?25l  688 unsafe { 688,148%[?12l[?25h[?25l  689 gl::ClearColor( 689,148%[?12l[?25h[?25l  690 (self.visual_bell_intensity + color.r as f32 / 255.0).min(1.0), 690,148%[?12l[?25h[?25l  691 (self.visual_bell_intensity + color.g as f32 / 255.0).min(1.0), 691,148%[?12l[?25h[?25l  692 (self.visual_bell_intensity + color.b as f32 / 255.0).min(1.0), 692,148%[?12l[?25h[?25l  693 1.0 693,149%[?12l[?25h[?25l  694 ); 694,149%[?12l[?25h[?25l  695 gl::Clear(gl::COLOR_BUFFER_BIT); 695,149%[?12l[?25h[?25l  696 } 696,149%[?12l[?25h[?25l  697  } 697,149%[?12l[?25h[?25l  698  698,0-149%[?12l[?25h[?25l  699  fn render_batch(&mut self) { 699,149%[?12l[?25h[?25l  700 unsafe { 700,149%[?12l[?25h[?25l  701 gl::BufferSubData(gl::ARRAY_BUFFER, 0, self.batch.size() as isize, 701,149%[?12l[?25h[?25l  702 self.batch.instances.as_ptr() as *const _); 702,149%[?12l[?25h[?25l  703 } 703,149%[?12l[?25h[?25l  704  704,0-149%[?12l[?25h[?25l  705 // Bind texture if necessary 705,150%[?12l[?25h[?25l  706 if *self.active_tex != self.batch.tex { 706,150%[?12l[?25h[?25l  707 unsafe { 707,150%[?12l[?25h[?25l  708 gl::BindTexture(gl::TEXTURE_2D, self.batch.tex); 708,150%[?12l[?25h[?25l  709 } 709,150%[?12l[?25h[?25l  710 *self.active_tex = self.batch.tex; 710,150%[?12l[?25h[?25l  711 } 711,150%[?12l[?25h[?25l  712  712,0-150%[?12l[?25h[?25l  713 unsafe { 713,150%[?12l[?25h[?25l  714 self.program.set_background_pass(true); 714,150%[?12l[?25h[?25l  715 gl::DrawElementsInstanced(gl::TRIANGLES, 715,150%[?12l[?25h[?25l  716 6, gl::UNSIGNED_INT, ptr::null(), 716,150%[?12l[?25h[?25l  717 self.batch.len() as GLsizei); 717,150%[?12l[?25h[?25l  718 self.program.set_background_pass(false); 718,151%[?12l[?25h[?25l  719 gl::DrawElementsInstanced(gl::TRIANGLES, 719,151%[?12l[?25h[?25l  720 6, gl::UNSIGNED_INT, ptr::null(), 720,151%[?12l[?25h[?25l  721 self.batch.len() as GLsizei); 721,151%[?12l[?25h[?25l  722 } 722,151%[?12l[?25h[?25l  723  723,0-151%[?12l[?25h[?25l  724 self.batch.clear(); 724,151%[?12l[?25h[?25l  725  } 725,151%[?12l[?25h[?25l  726  /// Render a string in a predefined location. Used for printing render time for profiling and  726,151%[?12l[?25h[?25l  727  /// optimization. 727,151%[?12l[?25h[?25l  728  pub fn render_string( 728,151%[?12l[?25h[?25l  729 &mut self, 729,151%[?12l[?25h[?25l  730 string: &str, 730,151%[?12l[?25h[?25l  731 glyph_cache: &mut GlyphCache, 731,152%[?12l[?25h[?25l  732 color: Rgb, 732,152%[?12l[?25h[?25l  733  ) { 733,152%[?12l[?25h[?25l  734 let line = Line(23); 734,152%[?12l[?25h[?25l  735 let col = Column(0); 735,152%[?12l[?25h[?25l  736  736,0-152%[?12l[?25h[?25l  737 let cells = string.chars() 737,152%[?12l[?25h[?25l  738 .enumerate() 738,152%[?12l[?25h[?25l  739 .map(|(i, c)| RenderableCell { 739,152%[?12l[?25h[?25l  740 line: line, 740,152%[?12l[?25h[?25l  741 column: col + i, 741,152%[?12l[?25h[?25l  742 c: c, 742,152%[?12l[?25h[?25l  743 bg: color, 743,152%[?12l[?25h[?25l  744 fg: Rgb { r: 0, g: 0, b: 0 }, 744,153%[?12l[?25h[?25l  745 flags: cell::Flags::empty(), 745,153%[?12l[?25h[?25l  746 }) 746,153%[?12l[?25h[?25l  747 .collect::<Vec<_>>(); 747,153%[?12l[?25h[?25l  748  748,0-153%[?12l[?25h[?25l  749 self.render_cells(cells.into_iter(), glyph_cache); 749,153%[?12l[?25h[?25l  750  } 750,153%[?12l[?25h[?25l  751  751,0-153%[?12l[?25h[?25l  752  #[inline] 752,153%[?12l[?25h[?25l  753  fn add_render_item(&mut self, cell: &RenderableCell, glyph: &Glyph) { 753,153%[?12l[?25h[?25l  754 // Flush batch if tex changing 754,153%[?12l[?25h[?25l  755 if !self.batch.is_empty() && self.batch.tex != glyph.tex_id { 755,153%[?12l[?25h[?25l  756 self.render_batch(); 756,153%[?12l[?25h[?25l  757 } 757,154%[?12l[?25h[?25l  758  758,0-154%[?12l[?25h[?25l  759 self.batch.add_item(cell, glyph); 759,154%[?12l[?25h[?25l  760  760,0-154%[?12l[?25h[?25l  761 // Render batch and clear if it's full 761,154%[?12l[?25h[?25l  762 if self.batch.full() { 762,154%[?12l[?25h[?25l  763 self.render_batch(); 763,154%[?12l[?25h[?25l  764 } 764,154%[?12l[?25h[?25l  765  } 765,154%[?12l[?25h[?25l  766  766,0-154%[?12l[?25h[?25l  767  pub fn render_cells<I>( 767,154%[?12l[?25h[?25l  768 &mut self, 768,154%[?12l[?25h[?25l  769 cells: I, 769,154%[?12l[?25h[?25l  770 glyph_cache: &mut GlyphCache 770,155%[?12l[?25h[?25l  771  ) 771,155%[?12l[?25h[?25l  772 where I: Iterator<Item=RenderableCell> 772,155%[?12l[?25h[?25l  773  { 773,155%[?12l[?25h[?25l  774 for cell in cells { 774,155%[?12l[?25h[?25l  775 // Get font key for cell 775,155%[?12l[?25h[?25l  776 // FIXME this is super inefficient. 776,155%[?12l[?25h[?25l  777 let mut font_key = glyph_cache.font_key; 777,155%[?12l[?25h[?25l  778 if cell.flags.contains(cell::BOLD) { 778,155%[?12l[?25h[?25l  779 font_key = glyph_cache.bold_key; 779,155%[?12l[?25h[?25l  780 } else if cell.flags.contains(cell::ITALIC) { 780,155%[?12l[?25h[?25l  781 font_key = glyph_cache.italic_key; 781,155%[?12l[?25h[?25l  782 } 782,155%[?12l[?25h[?25l  783  783,0-156%[?12l[?25h[?25l  784 let glyph_key = GlyphKey { 784,156%[?12l[?25h[?25l  785 font_key: font_key, 785,156%[?12l[?25h[?25l  786 size: glyph_cache.font_size, 786,156%[?12l[?25h[?25l  787 c: cell.c 787,156%[?12l[?25h[?25l  788 }; 788,156%[?12l[?25h[?25l  789  789,0-156%[?12l[?25h[?25l  790 // Add cell to batch 790,156%[?12l[?25h[?25l  791 { 791,156%[?12l[?25h[?25l  792 let glyph = glyph_cache.get(&glyph_key, self); 792,156%[?12l[?25h[?25l  793 self.add_render_item(&cell, glyph); 793,156%[?12l[?25h[?25l  794 } 794,156%[?12l[?25h[?25l  795  795,0-156%[?12l[?25h[?25l  796 // FIXME This is a super hacky way to do underlined text. During 796,157%[?12l[?25h[?25l  797 // a time crunch to release 0.1, this seemed like a really 797,157%[?12l[?25h[?25l  798 // easy, clean hack. 798,157%[?12l[?25h[?25l  799 if cell.flags.contains(cell::UNDERLINE) { 799,157%[?12l[?25h[?25l  800 let glyph_key = GlyphKey { 800,157%[?12l[?25h[?25l  801 font_key: font_key, 801,157%[?12l[?25h[?25l  802 size: glyph_cache.font_size, 802,157%[?12l[?25h[?25l  803 c: '_' 803,157%[?12l[?25h[?25l  804 }; 804,157%[?12l[?25h[?25l  805  805,0-157%[?12l[?25h[?25l  806 let underscore = glyph_cache.get(&glyph_key, self); 806,157%[?12l[?25h[?25l  807 self.add_render_item(&cell, underscore); 807,157%[?12l[?25h[?25l  808 } 808,157%[?12l[?25h[?25l  809 } 809,158%[?12l[?25h[?25l  810  } 810,158%[?12l[?25h[?25l  811 } 811,158%[?12l[?25h[?25l  812  812,0-158%[?12l[?25h[?25l  813 impl<'a> LoadGlyph for LoaderApi<'a> { 813,158%[?12l[?25h[?25l  814  /// Load a glyph into a texture atlas 814,158%[?12l[?25h[?25l  815  /// 815,158%[?12l[?25h[?25l  816  /// If the current atlas is full, a new one will be created. 816,158%[?12l[?25h[?25l  817  fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph { 817,158%[?12l[?25h[?25l  818 // At least one atlas is guaranteed to be in the `self.atlas` list; thus 818,158%[?12l[?25h[?25l  819 // the unwrap should always be ok. 819,158%[?12l[?25h[?25l  820 match self.atlas.last_mut().unwrap().insert(rasterized, &mut self.active_tex) { 820,158%[?12l[?25h[?25l  821 Ok(glyph) => glyph, 821,158%[?12l[?25h[?25l  822 Err(_) => { 822,159%[?12l[?25h[?25l  823 let atlas = Atlas::new(ATLAS_SIZE); 823,159%[?12l[?25h[?25l  824 *self.active_tex = 0; // Atlas::new binds a texture. Ugh this is sloppy. 824,159%[?12l[?25h[?25l  825 self.atlas.push(atlas); 825,159%[?12l[?25h[?25l  826 self.load_glyph(rasterized) 826,159%[?12l[?25h[?25l  827 } 827,159%[?12l[?25h[?25l  828 } 828,159%[?12l[?25h[?25l  829  } 829,159%[?12l[?25h[?25l { 830 } 830,159%[?12l[?25h[?25l {}  831  831,0-159%[?12l[?25h[?25l  832 impl<'a> LoadGlyph for RenderApi<'a> { 832,159%[?12l[?25h[?25l  833  /// Load a glyph into a texture atlas 833,159%[?12l[?25h[?25l  834  /// 834,159%[?12l[?25h[?25l  835  /// If the current atlas is full, a new one will be created. 835,160%[?12l[?25h[?25l  836  fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph { 836,160%[?12l[?25h[?25l  837 // At least one atlas is guaranteed to be in the `self.atlas` list; thus 837,160%[?12l[?25h[?25l  838 // the unwrap. 838,160%[?12l[?25h[?25l  839 match self.atlas.last_mut().unwrap().insert(rasterized, &mut self.active_tex) { 839,160%[?12l[?25h[?25l  840 Ok(glyph) => glyph, 840,160%[?12l[?25h[?25l  841 Err(_) => { 841,160%[?12l[?25h[?25l  842 let atlas = Atlas::new(ATLAS_SIZE); 842,160%[?12l[?25h[?25l  843 *self.active_tex = 0; // Atlas::new binds a texture. Ugh this is sloppy. 843,160%[?12l[?25h[?25l  844 self.atlas.push(atlas); 844,160%[?12l[?25h[?25l  845 self.load_glyph(rasterized) 845,160%[?12l[?25h[?25l  846 } 846,160%[?12l[?25h[?25l  847 } 847,160%[?12l[?25h[?25l  848  } 848,161%[?12l[?25h[?25l { 849 } 849,161%[?12l[?25h[?25l {}  850  850,0-161%[?12l[?25h[?25l  851 impl<'a> Drop for RenderApi<'a> { 851,161%[?12l[?25h[?25l  852  fn drop(&mut self) { 852,161%[?12l[?25h[?25l  853 if !self.batch.is_empty() { 853,161%[?12l[?25h[?25l  854 self.render_batch(); 854,161%[?12l[?25h[?25l  855 } 855,161%[?12l[?25h[?25l  856  } 856,161%[?12l[?25h[?25l { 857 } 857,161%[?12l[?25h[?25l {}  858  858,0-161%[?12l[?25h[?25l  859 impl ShaderProgram { 859,161%[?12l[?25h[?25l  860  pub fn activate(&self) { 860,161%[?12l[?25h[?25l  861 unsafe { 861,162%[?12l[?25h[?25l  862 gl::UseProgram(self.id); 862,162%[?12l[?25h[?25l  863 } 863,162%[?12l[?25h[?25l  864  } 864,162%[?12l[?25h[?25l  865  865,0-162%[?12l[?25h[?25l  866  pub fn deactivate(&self) { 866,162%[?12l[?25h[?25l  867 unsafe { 867,162%[?12l[?25h[?25l  868 gl::UseProgram(0); 868,162%[?12l[?25h[?25l  869 } 869,162%[?12l[?25h[?25l  870  } 870,162%[?12l[?25h[?25l  871  871,0-162%[?12l[?25h[?25l  872  pub fn new( 872,162%[?12l[?25h[?25l  873 config: &Config, 873,162%[?12l[?25h[?25l  874 size: Size<Pixels<u32>> 874,163%[?12l[?25h[?25l  875  ) -> Result<ShaderProgram, ShaderCreationError> { 875,163%[?12l[?25h[?25l  876 let vertex_source = if cfg!(feature = "live-shader-reload") { 876,163%[?12l[?25h[?25l  877 None 877,163%[?12l[?25h[?25l  878 } else { 878,163%[?12l[?25h[?25l  879 Some(TEXT_SHADER_V) 879,163%[?12l[?25h[?25l  880 }; 880,163%[?12l[?25h[?25l  881 let vertex_shader = ShaderProgram::create_shader( 881,163%[?12l[?25h[?25l  882 TEXT_SHADER_V_PATH, 882,163%[?12l[?25h[?25l  883 gl::VERTEX_SHADER, 883,163%[?12l[?25h[?25l  884 vertex_source 884,163%[?12l[?25h[?25l  885 )?; 885,163%[?12l[?25h[?25l  886 let frag_source = if cfg!(feature = "live-shader-reload") { 886,163%[?12l[?25h[?25l  887 None 887,164%[?12l[?25h[?25l  888 } else { 888,164%[?12l[?25h[?25l  889 Some(TEXT_SHADER_F) 889,164%[?12l[?25h[?25l  890 }; 890,164%[?12l[?25h[?25l  891 let fragment_shader = ShaderProgram::create_shader( 891,164%[?12l[?25h