<commit_before>// Copyright 2016 <NAME>, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! Exports the `Term` type which is a high-level API for the Grid
use std::mem;
use std::ops::{Deref, Range};
use std::ptr;

use ansi::{self, Attr, Handler};
use grid::{Grid, ClearRegion};
use index::{Cursor, Column, Line};
use tty;
use ansi::Color;

/// RAII type which manages grid state for render
///
/// This manages the cursor during a render. The cursor location is inverted to
/// draw it, and reverted after drawing to maintain state.
pub struct RenderGrid<'a> {
    inner: &'a mut Grid<Cell>,
    cursor: &'a Cursor,
    mode: TermMode,
}

impl<'a> RenderGrid<'a> {
    fn new<'b>(grid: &'b mut Grid<Cell>, cursor: &'b Cursor, mode: TermMode) -> RenderGrid<'b> {
        if mode.contains(mode::SHOW_CURSOR) && grid.contains(cursor) {
            let cell = &mut grid[cursor];
            mem::swap(&mut cell.fg, &mut cell.bg);
        }

        RenderGrid {
            inner: grid,
            cursor: cursor,
            mode: mode,
        }
    }
}

impl<'a> Drop for RenderGrid<'a> {
    fn drop(&mut self) {
        if self.mode.contains(mode::SHOW_CURSOR) && self.inner.contains(self.cursor) {
            let cell = &mut self.inner[self.cursor];
            mem::swap(&mut cell.fg, &mut cell.bg);
        }
    }
}

impl<'a> Deref for RenderGrid<'a> {
    type Target = Grid<Cell>;

    fn deref(&self) -> &Self::Target {
        self.inner
    }
}

/// coerce val to be between min and max
fn limit<T: PartialOrd>(val: T, min: T, max: T) -> T {
    if val < min {
        min
    } else if val > max {
        max
    } else {
        val
    }
}

pub mod cell {
    use ::Rgb;

    bitflags! {
        pub flags Flags: u32 {
            const INVERSE   = 0b00000001,
            const BOLD      = 0b00000010,
            const ITALIC    = 0b00000100,
            const UNDERLINE = 0b00001000,
        }
    }

    #[derive(Debug, Clone, PartialEq, Eq)]
    pub enum Color {
        Rgb(Rgb),
        Ansi(::ansi::Color),
    }

    #[derive(Clone, Debug)]
    pub struct Cell {
        pub c: char,
        pub fg: Color,
        pub bg: Color,
        pub flags: Flags,
    }

    impl Cell {
        pub fn bold(&self) -> bool {
            self.flags.contains(BOLD)
        }

        pub fn new(c: char, fg: Color, bg: Color) -> Cell {
            Cell {
                c: c.into(),
                bg: bg,
                fg: fg,
                flags: Flags::empty(),
            }
        }

        #[inline]
        pub fn reset(&mut self, template: &Cell) {
            // memcpy template to self
            *self = template.clone();
        }
    }

    #[cfg(test)]
    mod tests {
        use super::Color;
        use std::mem;

        // Ensure memory layout is well defined so components like renderer
        // can exploit it.
        //
        // Thankfully, everything is just a u8 for now so no endianness
        // considerations are needed.
        #[test]
        fn color_memory_layout() {
            let rgb_color = Color::Rgb(::Rgb { r: 1, g: 2, b: 3 });
            let ansi_color = Color::Ansi(::ansi::Color::Foreground);

            unsafe {
                // Color::Rgb
                // [discriminant(0), red, green ,blue]
                let bytes: [u8; 4] = mem::transmute_copy(&rgb_color);
                assert_eq!(bytes[0], 0);
                assert_eq!(bytes[1], 1);
                assert_eq!(bytes[2], 2);
                assert_eq!(bytes[3], 3);

                // Color::Ansi
                // [discriminant(1), ansi::Color, 0, 0]
                let bytes: [u8; 4] = mem::transmute_copy(&ansi_color);
                assert_eq!(bytes[0], 1);
                assert_eq!(bytes[1], ::ansi::Color::Foreground as u8);
                assert_eq!(bytes[2], 0);
                assert_eq!(bytes[3], 0);
            }
        }
    }
}

pub use self::cell::Cell;

pub mod mode {
    bitflags! {
        pub flags TermMode: u8 {
            const SHOW_CURSOR = 0b00000001,
            const APP_CURSOR  = 0b00000010,
            const APP_KEYPAD  = 0b00000100,
            const ANY         = 0b11111111,
            const NONE        = 0b00000000,
        }
    }

    impl Default for TermMode {
        fn default() -> TermMode {
            SHOW_CURSOR<commit_msg>Fix test for Cell layout<commit_after>// Copyright 2016 <NAME>, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! Exports the `Term` type which is a high-level API for the Grid
use std::mem;
use std::ops::{Deref, Range};
use std::ptr;

use ansi::{self, Attr, Handler};
use grid::{Grid, ClearRegion};
use index::{Cursor, Column, Line};
use tty;
use ansi::Color;

/// RAII type which manages grid state for render
///
/// This manages the cursor during a render. The cursor location is inverted to
/// draw it, and reverted after drawing to maintain state.
pub struct RenderGrid<'a> {
    inner: &'a mut Grid<Cell>,
    cursor: &'a Cursor,
    mode: TermMode,
}

impl<'a> RenderGrid<'a> {
    fn new<'b>(grid: &'b mut Grid<Cell>, cursor: &'b Cursor, mode: TermMode) -> RenderGrid<'b> {
        if mode.contains(mode::SHOW_CURSOR) && grid.contains(cursor) {
            let cell = &mut grid[cursor];
            mem::swap(&mut cell.fg, &mut cell.bg);
        }

        RenderGrid {
            inner: grid,
            cursor: cursor,
            mode: mode,
        }
    }
}

impl<'a> Drop for RenderGrid<'a> {
    fn drop(&mut self) {
        if self.mode.contains(mode::SHOW_CURSOR) && self.inner.contains(self.cursor) {
            let cell = &mut self.inner[self.cursor];
            mem::swap(&mut cell.fg, &mut cell.bg);
        }
    }
}

impl<'a> Deref for RenderGrid<'a> {
    type Target = Grid<Cell>;

    fn deref(&self) -> &Self::Target {
        self.inner
    }
}

/// coerce val to be between min and max
fn limit<T: PartialOrd>(val: T, min: T, max: T) -> T {
    if val < min {
        min
    } else if val > max {
        max
    } else {
        val
    }
}

pub mod cell {
    use ::Rgb;

    bitflags! {
        pub flags Flags: u32 {
            const INVERSE   = 0b00000001,
            const BOLD      = 0b00000010,
            const ITALIC    = 0b00000100,
            const UNDERLINE = 0b00001000,
        }
    }

    #[derive(Debug, Clone, PartialEq, Eq)]
    pub enum Color {
        Rgb(Rgb),
        Ansi(::ansi::Color),
    }

    #[derive(Clone, Debug)]
    pub struct Cell {
        pub c: char,
        pub fg: Color,
        pub bg: Color,
        pub flags: Flags,
    }

    impl Cell {
        pub fn bold(&self) -> bool {
            self.flags.contains(BOLD)
        }

        pub fn new(c: char, fg: Color, bg: Color) -> Cell {
            Cell {
                c: c.into(),
                bg: bg,
                fg: fg,
                flags: Flags::empty(),
            }
        }

        #[inline]
        pub fn reset(&mut self, template: &Cell) {
            // memcpy template to self
            *self = template.clone();
        }
    }

    #[cfg(test)]
    mod tests {
        use super::Color;
        use std::mem;

        // Ensure memory layout is well defined so components like renderer
        // can exploit it.
        //
        // Thankfully, everything is just a u8 for now so no endianness
        // considerations are needed.
        #[test]
        fn color_memory_layout() {
            let rgb_color = Color::Rgb(::Rgb { r: 1, g: 2, b: 3 });
            let ansi_color = Color::Ansi(::ansi::Color::Foreground);

            unsafe {
                // Color::Rgb
                // [discriminant(0), red, green ,blue]
                let bytes: [u8; 4] = mem::transmute_copy(&rgb_color);
                assert_eq!(bytes[0], 0);
                assert_eq!(bytes[1], 1);
                assert_eq!(bytes[2], 2);
                assert_eq!(bytes[3], 3);

                // Color::Ansi
                // [discriminant(1), ansi::Color, 0, 0]
                let bytes: [u8; 4] = mem::transmute_copy(&ansi_color);
                assert_eq!(bytes[0], 1);
                assert_eq!(bytes[1], ::ansi::Color::Foreground as u8);
            }
        }
    }
}

pub use self::cell::Cell;

pub mod mode {
    bitflags! {
        pub flags TermMode: u8 {
            const SHOW_CURSOR = 0b00000001,
            const APP_CURSOR  = 0b00000010,
            const APP_KEYPAD  = 0b00000100,
            const ANY         = 0b11111111,
            const NONE        = 0b00000000,
        }
    }

    impl Default for TermMode {
        fn default() -> TermMode {
            SHOW_CURSOR
{'fraction_non_alphanumeric': 0.12465116279069767, 'fraction_numerical': 0.02439276485788114, 'mean_word_length': 1.7685264663805436, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 8, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3974520', 'n_tokens_mistral': 3187, 'n_tokens_neox': 2972, 'n_words': 915}