URI: 
       Track API changes. - icy_draw - icy_draw is the successor to mystic draw. fork / mirror
  HTML git clone https://git.drkhsh.at/icy_draw.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 06798e3045807e9ec78245d1fa8ac82c018f8e2d
   DIR parent 36762c37cf4cb5dd094f14db0b316445e55492ad
  HTML Author: Mike Krüger <mkrueger@posteo.de>
       Date:   Sun,  3 Sep 2023 07:47:10 +0200
       
       Track API changes.
       
       Diffstat:
         M src/model/tools/brush_imp.rs        |      12 ++++++------
         M src/model/tools/draw_ellipse_fille… |       9 +++++++--
         M src/model/tools/draw_ellipse_imp.rs |      11 ++++++++---
         M src/model/tools/draw_rectangle_fil… |       9 +++++++--
         M src/model/tools/draw_rectangle_imp… |      11 ++++++++---
         M src/model/tools/fill_imp.rs         |      14 +++++++-------
         M src/model/tools/font_imp.rs         |      22 +++++++++++-----------
         M src/model/tools/line_imp.rs         |     106 +++++++++++++++++++++++++------
         M src/model/tools/mod.rs              |      74 ++++++++++++++++++++-----------
         M src/model/tools/move_layer_imp.rs   |      12 +++++++++---
         M src/model/tools/pencil_imp.rs       |      12 ++++++------
         M src/ui/dialogs/edit_layer_dialog.rs |       3 ++-
         M src/ui/dialogs/edit_sauce_dialog.rs |      14 ++++++++------
         M src/ui/dialogs/select_character_di… |       4 ++--
         M src/ui/dialogs/set_canvas_size_dia… |       2 +-
         M src/ui/editor/ansi/mod.rs           |     199 +++++++++++++++++++------------
         M src/ui/editor/charfont/mod.rs       |       3 ++-
         M src/ui/messages.rs                  |      84 +++++++++++++++++++++----------
         M src/ui/old/buffer_view.rs           |       4 ++--
         M src/ui/old/mod.rs                   |       4 ++--
         M src/ui/old/render.rs                |      38 ++++++++++++++++----------------
         M src/ui/palette_editor.rs            |      36 +++++++++++++++++++++-----------
         M src/ui/tools/bitfont_selector.rs    |       4 ++--
         M src/ui/tools/char_table.rs          |       4 ++--
         M src/ui/tools/layer_view.rs          |       7 ++++---
       
       25 files changed, 456 insertions(+), 242 deletions(-)
       ---
   DIR diff --git a/src/model/tools/brush_imp.rs b/src/model/tools/brush_imp.rs
       @@ -41,7 +41,7 @@ impl BrushTool {
                            BrushType::Shade => {
                                let ch = editor.get_char_from_cur_layer(center + Position::new(x, y));
        
       -                        let attribute = editor.buffer_view.lock().caret.get_attribute();
       +                        let attribute = editor.buffer_view.lock().get_caret().get_attribute();
        
                                let mut char_code = gradient[0];
                                if ch.ch == gradient[gradient.len() - 1] {
       @@ -60,7 +60,7 @@ impl BrushTool {
                                );
                            }
                            BrushType::Solid => {
       -                        let attribute = editor.buffer_view.lock().caret.get_attribute();
       +                        let attribute = editor.buffer_view.lock().get_caret().get_attribute();
                                editor.set_char(
                                    center + Position::new(x, y),
                                    AttributedChar::new(*self.char_code.borrow(), attribute),
       @@ -74,7 +74,7 @@ impl BrushTool {
                                        editor
                                            .buffer_view
                                            .lock()
       -                                    .caret
       +                                    .get_caret()
                                            .get_attribute()
                                            .get_foreground(),
                                    );
       @@ -84,7 +84,7 @@ impl BrushTool {
                                        editor
                                            .buffer_view
                                            .lock()
       -                                    .caret
       +                                    .get_caret()
                                            .get_attribute()
                                            .get_background(),
                                    );
       @@ -191,8 +191,8 @@ pub fn draw_glyph(
            editor: &AnsiEditor,
            ch: &Rc<RefCell<char>>,
        ) -> Option<Message> {
       -    let font_page = editor.buffer_view.lock().caret.get_font_page();
       -    if let Some(font) = editor.buffer_view.lock().buf.get_font(font_page) {
       +    let font_page = editor.buffer_view.lock().get_caret().get_font_page();
       +    if let Some(font) = editor.buffer_view.lock().get_buffer().get_font(font_page) {
                let scale = 1.5;
                let (id, stroke_rect) = ui.allocate_space(Vec2::new(
                    scale * font.size.width as f32,
   DIR diff --git a/src/model/tools/draw_ellipse_filled_imp.rs b/src/model/tools/draw_ellipse_filled_imp.rs
       @@ -96,7 +96,12 @@ impl Tool for DrawEllipseFilledTool {
            }
        
            fn handle_drag(&mut self, editor: &mut AnsiEditor, start: Position, cur: Position) -> Event {
       -        if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +        if let Some(layer) = editor
       +            .buffer_view
       +            .lock()
       +            .get_buffer_mut()
       +            .get_overlay_layer()
       +        {
                    layer.clear();
                }
        
       @@ -130,7 +135,7 @@ impl Tool for DrawEllipseFilledTool {
                cur: Position,
            ) -> Event {
                if start == cur {
       -            editor.buffer_view.lock().buf.remove_overlay();
       +            editor.buffer_view.lock().get_buffer_mut().remove_overlay();
                } else {
                    editor.join_overlay();
                }
   DIR diff --git a/src/model/tools/draw_ellipse_imp.rs b/src/model/tools/draw_ellipse_imp.rs
       @@ -102,7 +102,12 @@ impl Tool for DrawEllipseTool {
                mut start: Position,
                mut cur: Position,
            ) -> Event {
       -        if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +        if let Some(layer) = editor
       +            .buffer_view
       +            .lock()
       +            .get_buffer_mut()
       +            .get_overlay_layer()
       +        {
                    layer.clear();
                }
        
       @@ -122,7 +127,7 @@ impl Tool for DrawEllipseTool {
                let col = editor
                    .buffer_view
                    .lock()
       -            .caret
       +            .get_caret()
                    .get_attribute()
                    .get_foreground();
                for rect in lines.outline() {
       @@ -146,7 +151,7 @@ impl Tool for DrawEllipseTool {
                cur: Position,
            ) -> Event {
                if start == cur {
       -            editor.buffer_view.lock().buf.remove_overlay();
       +            editor.buffer_view.lock().get_buffer_mut().remove_overlay();
                } else {
                    editor.join_overlay();
                }
   DIR diff --git a/src/model/tools/draw_rectangle_filled_imp.rs b/src/model/tools/draw_rectangle_filled_imp.rs
       @@ -95,7 +95,12 @@ impl Tool for DrawRectangleFilledTool {
            }
        
            fn handle_drag(&mut self, editor: &mut AnsiEditor, start: Position, cur: Position) -> Event {
       -        if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +        if let Some(layer) = editor
       +            .buffer_view
       +            .lock()
       +            .get_buffer_mut()
       +            .get_overlay_layer()
       +        {
                    layer.clear();
                }
        
       @@ -125,7 +130,7 @@ impl Tool for DrawRectangleFilledTool {
                cur: Position,
            ) -> Event {
                if start == cur {
       -            editor.buffer_view.lock().buf.remove_overlay();
       +            editor.buffer_view.lock().get_buffer_mut().remove_overlay();
                } else {
                    editor.join_overlay();
                }
   DIR diff --git a/src/model/tools/draw_rectangle_imp.rs b/src/model/tools/draw_rectangle_imp.rs
       @@ -102,7 +102,12 @@ impl Tool for DrawRectangleTool {
                mut start: Position,
                mut cur: Position,
            ) -> Event {
       -        if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +        if let Some(layer) = editor
       +            .buffer_view
       +            .lock()
       +            .get_buffer_mut()
       +            .get_overlay_layer()
       +        {
                    layer.clear();
                }
        
       @@ -117,7 +122,7 @@ impl Tool for DrawRectangleTool {
                let col = editor
                    .buffer_view
                    .lock()
       -            .caret
       +            .get_caret()
                    .get_attribute()
                    .get_foreground();
                for rect in lines.outline() {
       @@ -142,7 +147,7 @@ impl Tool for DrawRectangleTool {
                cur: Position,
            ) -> Event {
                if start == cur {
       -            editor.buffer_view.lock().buf.remove_overlay();
       +            editor.buffer_view.lock().get_buffer_mut().remove_overlay();
                } else {
                    editor.join_overlay();
                }
   DIR diff --git a/src/model/tools/fill_imp.rs b/src/model/tools/fill_imp.rs
       @@ -32,14 +32,14 @@ impl FillTool {
                old_ch: AttributedChar,
                new_ch: AttributedChar,
            ) {
       -        if pos.x >= editor.buffer_view.lock().buf.get_width() as i32
       -            || pos.y >= editor.buffer_view.lock().buf.get_height() as i32
       +        if pos.x >= editor.buffer_view.lock().get_buffer().get_width() as i32
       +            || pos.y >= editor.buffer_view.lock().get_buffer().get_height() as i32
                    || !visited.insert(pos)
                {
                    return;
                }
        
       -        let cur_char = editor.buffer_view.lock().buf.get_char(pos);
       +        let cur_char = editor.buffer_view.lock().get_buffer().get_char(pos);
                if matches!(self.fill_type, FillType::Character) && self.use_fore && self.use_back {
                    if cur_char != old_ch || cur_char == new_ch {
                        return;
       @@ -102,7 +102,7 @@ impl FillTool {
                    editor
                        .buffer_view
                        .lock()
       -                .caret
       +                .get_caret()
                        .get_attribute()
                        .get_font_page(),
                );
       @@ -174,11 +174,11 @@ impl Tool for FillTool {
        
            fn handle_click(&mut self, editor: &mut AnsiEditor, button: i32, pos: Position) -> Event {
                if button == 1 {
       -            if editor.cur_layer >= editor.buffer_view.lock().buf.layers.len() {
       +            if editor.get_cur_layer() >= editor.buffer_view.lock().get_buffer().layers.len() {
                        return Event::None;
                    }
       -            let attr = editor.buffer_view.lock().caret.get_attribute();
       -            let ch = editor.buffer_view.lock().buf.get_char(pos);
       +            let attr = editor.buffer_view.lock().get_caret().get_attribute();
       +            let ch = editor.buffer_view.lock().get_buffer().get_char(pos);
                    if self.use_back || self.use_fore || matches!(self.fill_type, FillType::Character) {
                        editor.begin_atomic_undo();
                        let mut visited = HashSet::new();
   DIR diff --git a/src/model/tools/font_imp.rs b/src/model/tools/font_imp.rs
       @@ -232,7 +232,7 @@ impl Tool for FontTool {
                    return Event::None;
                }
                let font = &self.fonts.lock().unwrap()[selected_font as usize];
       -        let pos = editor.buffer_view.lock().caret.get_position();
       +        let pos = editor.buffer_view.lock().get_caret().get_position();
        
                match key {
                    MKey::Down => {
       @@ -250,7 +250,7 @@ impl Tool for FontTool {
        
                    MKey::Home => {
                        if let MModifiers::Control = modifier {
       -                    let end = editor.buffer_view.lock().buf.get_width() as i32;
       +                    let end = editor.buffer_view.lock().get_buffer().get_width() as i32;
                            for i in 0..end {
                                if !editor
                                    .get_char_from_cur_layer(pos.with_x(i))
       @@ -266,7 +266,7 @@ impl Tool for FontTool {
        
                    MKey::End => {
                        if let MModifiers::Control = modifier {
       -                    let end = editor.buffer_view.lock().buf.get_width() as i32;
       +                    let end = editor.buffer_view.lock().get_buffer().get_width() as i32;
                            for i in (0..end).rev() {
                                if !editor
                                    .get_char_from_cur_layer(pos.with_x(i))
       @@ -277,7 +277,7 @@ impl Tool for FontTool {
                                }
                            }
                        }
       -                let w = editor.buffer_view.lock().buf.get_width() as i32;
       +                let w = editor.buffer_view.lock().get_buffer().get_width() as i32;
                        editor.set_caret(w - 1, pos.y);
                    }
        
       @@ -298,9 +298,9 @@ impl Tool for FontTool {
                        let pos = editor.get_caret_position();
                        if pos.x > 0 {
                            editor.set_caret_position(pos + Position::new(-(letter_size.width as i32), 0));
       -                    if editor.buffer_view.lock().caret.insert_mode {
       -                        let end = (editor.buffer_view.lock().buf.get_width() - (letter_size.width))
       -                            as i32;
       +                    if editor.buffer_view.lock().get_caret().insert_mode {
       +                        let end = (editor.buffer_view.lock().get_buffer().get_width()
       +                            - (letter_size.width)) as i32;
                                for i in pos.x..end {
                                    let next = editor.get_char_from_cur_layer(Position::new(
                                        i + letter_size.width as i32,
       @@ -309,8 +309,8 @@ impl Tool for FontTool {
                                    editor.set_char(Position::new(i, pos.y), next);
                                }
                                let last_pos = Position::new(
       -                            (editor.buffer_view.lock().buf.get_width() - (letter_size.width))
       -                                as i32,
       +                            (editor.buffer_view.lock().get_buffer().get_width()
       +                                - (letter_size.width)) as i32,
                                    pos.y,
                                );
                                editor.fill(
       @@ -336,9 +336,9 @@ impl Tool for FontTool {
                    MKey::Character(ch) => {
                        let c_pos = editor.get_caret_position();
                        editor.begin_atomic_undo();
       -                let attr = editor.buffer_view.lock().caret.get_attribute();
       +                let attr = editor.buffer_view.lock().get_caret().get_attribute();
                        let opt_size: Option<Size> = font.render(
       -                    &mut editor.buffer_view.lock().buf,
       +                    &mut editor.buffer_view.lock().get_buffer_mut(),
                            0,
                            c_pos.as_uposition(),
                            attr,
   DIR diff --git a/src/model/tools/line_imp.rs b/src/model/tools/line_imp.rs
       @@ -245,7 +245,12 @@ impl Tool for LineTool {
            }
        
            fn handle_drag(&mut self, editor: &mut AnsiEditor, start: Position, cur: Position) -> Event {
       -        if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +        if let Some(layer) = editor
       +            .buffer_view
       +            .lock()
       +            .get_buffer_mut()
       +            .get_overlay_layer()
       +        {
                    layer.clear();
                }
        
       @@ -258,7 +263,7 @@ impl Tool for LineTool {
                    let col = editor
                        .buffer_view
                        .lock()
       -                .caret
       +                .get_caret()
                        .get_attribute()
                        .get_foreground();
                    let draw = move |rect: Rectangle| {
       @@ -299,7 +304,7 @@ impl Tool for LineTool {
                cur: Position,
            ) -> Event {
                if start == cur {
       -            editor.buffer_view.lock().buf.remove_overlay();
       +            editor.buffer_view.lock().get_buffer_mut().remove_overlay();
                } else {
                    editor.join_overlay();
                }
       @@ -390,8 +395,8 @@ fn get_half_block(
        }
        
        pub fn set_half_block(editor: &AnsiEditor, pos: Position, col: u32) {
       -    let w = editor.buffer_view.lock().buf.get_width() as i32;
       -    let h = editor.buffer_view.lock().buf.get_line_count() as i32;
       +    let w = editor.buffer_view.lock().get_buffer().get_width() as i32;
       +    let h = editor.buffer_view.lock().get_buffer().get_line_count() as i32;
        
            if pos.x < 0 || pos.x >= w || pos.y < 0 || pos.y >= h * 2 {
                return;
       @@ -414,33 +419,58 @@ pub fn set_half_block(editor: &AnsiEditor, pos: Position, col: u32) {
            let pos = Position::new(pos.x, text_y);
            if is_blocky {
                if (is_top && lower_block_color == col) || (!is_top && upper_block_color == col) {
       -            if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +            if let Some(layer) = editor
       +                .buffer_view
       +                .lock()
       +                .get_buffer_mut()
       +                .get_overlay_layer()
       +            {
                        layer.set_char(
                            pos,
                            AttributedChar::new('\u{00DB}', TextAttribute::new(col, 0)),
                        );
                    }
                } else if is_top {
       -            if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +            if let Some(layer) = editor
       +                .buffer_view
       +                .lock()
       +                .get_buffer_mut()
       +                .get_overlay_layer()
       +            {
                        layer.set_char(
                            pos,
                            AttributedChar::new('\u{00DF}', TextAttribute::new(col, lower_block_color)),
                        );
                    }
       -        } else if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +        } else if let Some(layer) = editor
       +            .buffer_view
       +            .lock()
       +            .get_buffer_mut()
       +            .get_overlay_layer()
       +        {
                    layer.set_char(
                        pos,
                        AttributedChar::new('\u{00DC}', TextAttribute::new(col, upper_block_color)),
                    );
                }
            } else if is_top {
       -        if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +        if let Some(layer) = editor
       +            .buffer_view
       +            .lock()
       +            .get_buffer_mut()
       +            .get_overlay_layer()
       +        {
                    layer.set_char(
                        pos,
                        AttributedChar::new('\u{00DF}', TextAttribute::new(col, block_back)),
                    );
                }
       -    } else if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +    } else if let Some(layer) = editor
       +        .buffer_view
       +        .lock()
       +        .get_buffer_mut()
       +        .get_overlay_layer()
       +    {
                layer.set_char(
                    pos,
                    AttributedChar::new('\u{00DC}', TextAttribute::new(col, block_back)),
       @@ -450,7 +480,12 @@ pub fn set_half_block(editor: &AnsiEditor, pos: Position, col: u32) {
        }
        
        fn optimize_block(editor: &AnsiEditor, pos: Position) {
       -    let block = if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +    let block = if let Some(layer) = editor
       +        .buffer_view
       +        .lock()
       +        .get_buffer_mut()
       +        .get_overlay_layer()
       +    {
                layer.get_char(pos)
            } else {
                AttributedChar::default()
       @@ -458,13 +493,23 @@ fn optimize_block(editor: &AnsiEditor, pos: Position) {
        
            if block.attribute.get_foreground() == 0 {
                if block.attribute.get_background() == 0 || block.ch == '\u{00DB}' {
       -            if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +            if let Some(layer) = editor
       +                .buffer_view
       +                .lock()
       +                .get_buffer_mut()
       +                .get_overlay_layer()
       +            {
                        layer.set_char(pos, AttributedChar::default());
                    }
                } else {
                    match block.ch as u8 {
                        220 => {
       -                    if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +                    if let Some(layer) = editor
       +                        .buffer_view
       +                        .lock()
       +                        .get_buffer_mut()
       +                        .get_overlay_layer()
       +                    {
                                layer.set_char(
                                    pos,
                                    AttributedChar::new(
       @@ -478,7 +523,12 @@ fn optimize_block(editor: &AnsiEditor, pos: Position) {
                            }
                        }
                        223 => {
       -                    if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +                    if let Some(layer) = editor
       +                        .buffer_view
       +                        .lock()
       +                        .get_buffer_mut()
       +                        .get_overlay_layer()
       +                    {
                                layer.set_char(
                                    pos,
                                    AttributedChar::new(
       @@ -501,7 +551,12 @@ fn optimize_block(editor: &AnsiEditor, pos: Position) {
                if is_blocky {
                    match block.ch as u8 {
                        220 => {
       -                    if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +                    if let Some(layer) = editor
       +                        .buffer_view
       +                        .lock()
       +                        .get_buffer_mut()
       +                        .get_overlay_layer()
       +                    {
                                layer.set_char(
                                    pos,
                                    AttributedChar::new(
       @@ -515,7 +570,12 @@ fn optimize_block(editor: &AnsiEditor, pos: Position) {
                            }
                        }
                        223 => {
       -                    if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +                    if let Some(layer) = editor
       +                        .buffer_view
       +                        .lock()
       +                        .get_buffer_mut()
       +                        .get_overlay_layer()
       +                    {
                                layer.set_char(
                                    pos,
                                    AttributedChar::new(
       @@ -533,7 +593,12 @@ fn optimize_block(editor: &AnsiEditor, pos: Position) {
                } else if is_vertically_blocky {
                    match block.ch as u8 {
                        221 => {
       -                    if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +                    if let Some(layer) = editor
       +                        .buffer_view
       +                        .lock()
       +                        .get_buffer_mut()
       +                        .get_overlay_layer()
       +                    {
                                layer.set_char(
                                    pos,
                                    AttributedChar::new(
       @@ -547,7 +612,12 @@ fn optimize_block(editor: &AnsiEditor, pos: Position) {
                            }
                        }
                        222 => {
       -                    if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +                    if let Some(layer) = editor
       +                        .buffer_view
       +                        .lock()
       +                        .get_buffer_mut()
       +                        .get_overlay_layer()
       +                    {
                                layer.set_char(
                                    pos,
                                    AttributedChar::new(
   DIR diff --git a/src/model/tools/mod.rs b/src/model/tools/mod.rs
       @@ -102,14 +102,14 @@ pub trait Tool {
        
                // ctrl+pgup  - upper left corner
                // ctrl+pgdn  - lower left corner
       -        let pos = editor.buffer_view.lock().caret.get_position();
       +        let pos = editor.buffer_view.lock().get_caret().get_position();
                match key {
                    MKey::Down => {
                        if let MModifiers::Control = modifier {
                            let fg = (editor
                                .buffer_view
                                .lock()
       -                        .caret
       +                        .get_caret()
                                .get_attribute()
                                .get_foreground()
                                + 14)
       @@ -117,7 +117,7 @@ pub trait Tool {
                            editor
                                .buffer_view
                                .lock()
       -                        .caret
       +                        .get_caret()
                                .get_attribute()
                                .set_foreground(fg);
                        } else {
       @@ -129,7 +129,7 @@ pub trait Tool {
                            let fg = (editor
                                .buffer_view
                                .lock()
       -                        .caret
       +                        .get_caret()
                                .get_attribute()
                                .get_foreground()
                                + 1)
       @@ -137,7 +137,7 @@ pub trait Tool {
                            editor
                                .buffer_view
                                .lock()
       -                        .caret
       +                        .get_caret()
                                .get_attribute()
                                .set_foreground(fg);
                        } else {
       @@ -150,7 +150,7 @@ pub trait Tool {
                            let bg = (editor
                                .buffer_view
                                .lock()
       -                        .caret
       +                        .get_caret()
                                .get_attribute()
                                .get_background()
                                + 7)
       @@ -158,7 +158,7 @@ pub trait Tool {
                            editor
                                .buffer_view
                                .lock()
       -                        .caret
       +                        .get_caret()
                                .get_attribute()
                                .set_background(bg);
                        } else {
       @@ -171,7 +171,7 @@ pub trait Tool {
                            let bg = (editor
                                .buffer_view
                                .lock()
       -                        .caret
       +                        .get_caret()
                                .get_attribute()
                                .get_background()
                                + 1)
       @@ -179,7 +179,7 @@ pub trait Tool {
                            editor
                                .buffer_view
                                .lock()
       -                        .caret
       +                        .get_caret()
                                .get_attribute()
                                .set_background(bg);
                        } else {
       @@ -203,13 +203,13 @@ pub trait Tool {
                            editor.set_caret(next_tab, pos.y);
                        } else {
                            let tabs = 1 + pos.x / tab_size;
       -                    let next_tab = min(editor.buf.width as i32 - 1, tabs * tab_size);
       +                    let next_tab = min(editor.get_buffer().width as i32 - 1, tabs * tab_size);
                            editor.set_caret(next_tab, pos.y);
                        }
                    }
                    MKey::Home  => {
                        if let MModifiers::Control = modifier {
       -                    for i in 0..editor.buf.width {
       +                    for i in 0..editor.get_buffer().width {
                                if !editor.get_char_from_cur_layer(pos.with_x(i as i32)).unwrap_or_default().is_transparent() {
                                    editor.set_caret(i as i32, pos.y);
                                    return Event::None;
       @@ -220,14 +220,14 @@ pub trait Tool {
                    }
                    MKey::End => {
                        if let MModifiers::Control = modifier {
       -                    for i in (0..editor.buf.width).rev()  {
       +                    for i in (0..editor.get_buffer().width).rev()  {
                                if !editor.get_char_from_cur_layer(pos.with_x(i as i32)).unwrap_or_default().is_transparent() {
                                    editor.set_caret(i as i32, pos.y);
                                    return Event::None;
                                }
                            }
                        }
       -                let w = editor.buf.width as i32;
       +                let w = editor.get_buffer().width as i32;
                        editor.set_caret(w - 1, pos.y);
                    }*/
                    MKey::Return => {
       @@ -238,19 +238,21 @@ pub trait Tool {
                            editor.delete_selection();
                        } else {
                            let pos = editor.get_caret_position();
       -                    let end = editor.buffer_view.lock().buf.get_width() as i32 - 1;
       +                    let end = editor.buffer_view.lock().get_buffer().get_width() as i32 - 1;
                            for i in pos.x..end {
                                let next = editor.get_char_from_cur_layer(Position::new(i + 1, pos.y));
                                editor.set_char(Position::new(i, pos.y), next);
                            }
       -                    let last_pos =
       -                        Position::new(editor.buffer_view.lock().buf.get_width() as i32 - 1, pos.y);
       +                    let last_pos = Position::new(
       +                        editor.buffer_view.lock().get_buffer().get_width() as i32 - 1,
       +                        pos.y,
       +                    );
                            editor.set_char(last_pos, AttributedChar::invisible());
                        }
                    }
                    MKey::Insert => {
       -                editor.buffer_view.lock().caret.insert_mode =
       -                    !editor.buffer_view.lock().caret.insert_mode;
       +                editor.buffer_view.lock().get_caret_mut().insert_mode =
       +                    !editor.buffer_view.lock().get_caret().insert_mode;
                    }
                    MKey::Backspace => {
                        editor.buffer_view.lock().clear_selection();
       @@ -266,14 +268,14 @@ pub trait Tool {
                                cpos--;
                            } else {*/
                            editor.set_caret_position(pos + Position::new(-1, 0));
       -                    if editor.buffer_view.lock().caret.insert_mode {
       -                        let end = editor.buffer_view.lock().buf.get_width() as i32 - 1;
       +                    if editor.buffer_view.lock().get_caret().insert_mode {
       +                        let end = editor.buffer_view.lock().get_buffer().get_width() as i32 - 1;
                                for i in pos.x..end {
                                    let next = editor.get_char_from_cur_layer(Position::new(i + 1, pos.y));
                                    editor.set_char(Position::new(i, pos.y), next);
                                }
                                let last_pos = Position::new(
       -                            editor.buffer_view.lock().buf.get_width() as i32 - 1,
       +                            editor.buffer_view.lock().get_buffer().get_width() as i32 - 1,
                                    pos.y,
                                );
                                editor.set_char(last_pos, AttributedChar::invisible());
       @@ -409,7 +411,7 @@ trait Plottable {
        
        fn plot_point(editor: &AnsiEditor, tool: &dyn Plottable, pos: Position) {
            let ch = editor.get_char_from_cur_layer(pos);
       -    let editor_attr = editor.buffer_view.lock().caret.get_attribute();
       +    let editor_attr = editor.buffer_view.lock().get_caret().get_attribute();
            let mut attribute = ch.attribute;
            if !ch.is_visible() {
                attribute = TextAttribute::default();
       @@ -425,7 +427,12 @@ fn plot_point(editor: &AnsiEditor, tool: &dyn Plottable, pos: Position) {
        
            match tool.get_draw_mode() {
                DrawMode::Line => {
       -            if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +            if let Some(layer) = editor
       +                .buffer_view
       +                .lock()
       +                .get_buffer_mut()
       +                .get_overlay_layer()
       +            {
                        layer.set_char(
                            pos,
                            AttributedChar::new(unsafe { char::from_u32_unchecked(219) }, attribute),
       @@ -433,7 +440,12 @@ fn plot_point(editor: &AnsiEditor, tool: &dyn Plottable, pos: Position) {
                    }
                }
                DrawMode::Char => {
       -            if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +            if let Some(layer) = editor
       +                .buffer_view
       +                .lock()
       +                .get_buffer_mut()
       +                .get_overlay_layer()
       +            {
                        layer.set_char(pos, AttributedChar::new(tool.get_char_code(), attribute));
                    }
                }
       @@ -449,12 +461,22 @@ fn plot_point(editor: &AnsiEditor, tool: &dyn Plottable, pos: Position) {
                            }
                        }
                    }
       -            if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +            if let Some(layer) = editor
       +                .buffer_view
       +                .lock()
       +                .get_buffer_mut()
       +                .get_overlay_layer()
       +            {
                        layer.set_char(pos, AttributedChar::new(char_code, attribute));
                    }
                }
                DrawMode::Colorize => {
       -            if let Some(layer) = editor.buffer_view.lock().buf.get_overlay_layer() {
       +            if let Some(layer) = editor
       +                .buffer_view
       +                .lock()
       +                .get_buffer_mut()
       +                .get_overlay_layer()
       +            {
                        layer.set_char(pos, AttributedChar::new(ch.ch, attribute));
                    }
                }
   DIR diff --git a/src/model/tools/move_layer_imp.rs b/src/model/tools/move_layer_imp.rs
       @@ -31,7 +31,13 @@ impl Tool for MoveLayer {
                _start: Position,
                _cur: Position,
            ) -> Event {
       -        if let Some(layer) = editor.buffer_view.lock().buf.layers.get(editor.cur_layer) {
       +        if let Some(layer) = editor
       +            .buffer_view
       +            .lock()
       +            .get_buffer()
       +            .layers
       +            .get(editor.get_cur_layer())
       +        {
                    self.pos = layer.get_offset();
                }
                Event::None
       @@ -41,9 +47,9 @@ impl Tool for MoveLayer {
                if let Some(layer) = editor
                    .buffer_view
                    .lock()
       -            .buf
       +            .get_buffer_mut()
                    .layers
       -            .get_mut(editor.cur_layer)
       +            .get_mut(editor.get_cur_layer())
                {
                    layer.set_offset(self.pos + cur - start);
                }
   DIR diff --git a/src/model/tools/pencil_imp.rs b/src/model/tools/pencil_imp.rs
       @@ -42,7 +42,7 @@ impl PencilTool {
                            let col = editor
                                .buffer_view
                                .lock()
       -                        .caret
       +                        .get_caret()
                                .get_attribute()
                                .get_foreground();
                            for y in 0..(rect.size.height as i32) {
       @@ -59,7 +59,7 @@ impl PencilTool {
                    }
                    PencilType::Shade => {
                        let ch = editor.get_char_from_cur_layer(center);
       -                let attribute = editor.buffer_view.lock().caret.get_attribute();
       +                let attribute = editor.buffer_view.lock().get_caret().get_attribute();
        
                        let mut char_code = gradient[0];
                        if ch.ch == gradient[gradient.len() - 1] {
       @@ -75,7 +75,7 @@ impl PencilTool {
                        editor.set_char(center, AttributedChar::new(char_code, attribute));
                    }
                    PencilType::Solid => {
       -                let attribute = editor.buffer_view.lock().caret.get_attribute();
       +                let attribute = editor.buffer_view.lock().get_caret().get_attribute();
                        editor.set_char(
                            center,
                            AttributedChar::new(*self.char_code.borrow(), attribute),
       @@ -89,7 +89,7 @@ impl PencilTool {
                                editor
                                    .buffer_view
                                    .lock()
       -                            .caret
       +                            .get_caret()
                                    .get_attribute()
                                    .get_foreground(),
                            );
       @@ -99,7 +99,7 @@ impl PencilTool {
                                editor
                                    .buffer_view
                                    .lock()
       -                            .caret
       +                            .get_caret()
                                    .get_attribute()
                                    .get_background(),
                            );
       @@ -198,7 +198,7 @@ impl Tool for PencilTool {
        pub fn draw_glyph_plain(editor: &AnsiEditor, ch: char, font_page: usize) -> impl egui::Widget {
            let bv = editor.buffer_view.clone();
            move |ui: &mut egui::Ui| {
       -        if let Some(font) = bv.lock().buf.get_font(font_page) {
       +        if let Some(font) = bv.lock().get_buffer().get_font(font_page) {
                    let scale = 1.8;
                    let padding = 2.;
                    let (id, stroke_rect) = ui.allocate_space(Vec2::new(
   DIR diff --git a/src/ui/dialogs/edit_layer_dialog.rs b/src/ui/dialogs/edit_layer_dialog.rs
       @@ -203,7 +203,8 @@ impl ModalDialog for EditLayerDialog {
            }
        
            fn commit(&self, editor: &mut AnsiEditor) -> TerminalResult<bool> {
       -        let layer = &mut editor.buffer_view.lock().buf.layers[self.layer];
       +        let mut bv = editor.buffer_view.lock();
       +        let layer = &mut bv.get_buffer_mut().layers[self.layer];
                layer.title = self.title.clone();
                layer.color = self.color;
                layer.is_visible = self.is_visible;
   DIR diff --git a/src/ui/dialogs/edit_sauce_dialog.rs b/src/ui/dialogs/edit_sauce_dialog.rs
       @@ -150,12 +150,14 @@ impl ModalDialog for EditSauceDialog {
            }
        
            fn commit(&self, editor: &mut AnsiEditor) -> TerminalResult<bool> {
       -        editor.buffer_view.lock().buf.title = self.title.clone();
       -        editor.buffer_view.lock().buf.author = self.author.clone();
       -        editor.buffer_view.lock().buf.group = self.group.clone();
       -        editor.buffer_view.lock().buf.comments = self.comments.clone();
       -        editor.buffer_view.lock().buf.use_letter_spacing = self.use_letter_spacing;
       -        editor.buffer_view.lock().buf.use_aspect_ratio = self.use_aspect_ratio;
       +        let bv = &mut editor.buffer_view.lock();
       +        let buf = bv.get_buffer_mut();
       +        buf.title = self.title.clone();
       +        buf.author = self.author.clone();
       +        buf.group = self.group.clone();
       +        buf.comments = self.comments.clone();
       +        buf.use_letter_spacing = self.use_letter_spacing;
       +        buf.use_aspect_ratio = self.use_aspect_ratio;
                Ok(true)
            }
        }
   DIR diff --git a/src/ui/dialogs/select_character_dialog.rs b/src/ui/dialogs/select_character_dialog.rs
       @@ -37,8 +37,8 @@ impl ModalDialog for SelectCharacterDialog {
                modal.show(|ui| {
                    modal.title(ui, fl!(crate::LANGUAGE_LOADER, "select-character-title"));
                    let buffer_view = self.buf.lock();
       -            let font_page = buffer_view.caret.get_font_page();
       -            let font = buffer_view.buf.get_font(font_page).unwrap();
       +            let font_page = buffer_view.get_caret().get_font_page();
       +            let font = buffer_view.get_buffer().get_font(font_page).unwrap();
                    let scale = 4.;
        
                    //   ui.with_layout(Layout::right_to_left(egui::Align::Center), |ui| {
   DIR diff --git a/src/ui/dialogs/set_canvas_size_dialog.rs b/src/ui/dialogs/set_canvas_size_dialog.rs
       @@ -77,7 +77,7 @@ impl ModalDialog for SetCanvasSizeDialog {
                editor
                    .buffer_view
                    .lock()
       -            .buf
       +            .get_buffer_mut()
                    .set_buffer_size(Size::new(self.width, self.height));
                Ok(true)
            }
   DIR diff --git a/src/ui/editor/ansi/mod.rs b/src/ui/editor/ansi/mod.rs
       @@ -37,19 +37,15 @@ pub enum Event {
        
        pub struct AnsiEditor {
            pub id: usize,
       -
            is_dirty: bool,
            drag_start: Option<Vec2>,
            last_pos: Position,
        
            pub buffer_view: Arc<eframe::epaint::mutex::Mutex<BufferView>>,
       -    pub buffer_parser: Box<dyn BufferParser>,
       -
            pub cur_outline: usize,
            pub is_inactive: bool,
        
            pub reference_image: Option<PathBuf>,
       -    pub cur_layer: usize,
            // pub outline_changed: std::boxed::Box<dyn Fn(&Editor)>,
            //pub request_refresh: Box<dyn Fn ()>,
            atomic_undo_stack: Vec<usize>,
       @@ -64,7 +60,7 @@ pub struct AnsiEditor {
        
        impl Document for AnsiEditor {
            fn get_title(&self) -> String {
       -        if let Some(file_name) = &self.buffer_view.lock().buf.file_name {
       +        if let Some(file_name) = &self.buffer_view.lock().get_buffer().file_name {
                    file_name.file_name().unwrap().to_str().unwrap().to_string()
                } else {
                    "Untitled".to_string()
       @@ -81,7 +77,7 @@ impl Document for AnsiEditor {
                let bytes = self
                    .buffer_view
                    .lock()
       -            .buf
       +            .get_buffer()
                    .to_bytes(file.extension().unwrap().to_str().unwrap(), &options)?;
                fs::write(file_name, bytes)?;
                self.is_dirty = false;
       @@ -95,7 +91,7 @@ impl Document for AnsiEditor {
                options: &DocumentOptions,
            ) {
                let mut scale = options.scale;
       -        if self.buffer_view.lock().buf.use_aspect_ratio {
       +        if self.buffer_view.lock().get_buffer().use_aspect_ratio {
                    scale.y *= 1.35;
                }
                ui.allocate_ui(
       @@ -142,8 +138,6 @@ impl AnsiEditor {
                    glow::NEAREST as i32,
                )));
                // let buffer_parser = ansi::Parser::default();
       -        let buffer_parser = ansi::Parser::default();
       -
                AnsiEditor {
                    id,
                    buffer_view,
       @@ -152,7 +146,6 @@ impl AnsiEditor {
                    reference_image: None,
                    //outline_changed: Box::new(|_| {}),
                    // request_refresh: Box::new(|| {}),
       -            cur_layer: 0,
                    atomic_undo_stack: Vec::new(),
                    //pos_changed: Box::new(|_, _| {}),
                    //attr_changed: Box::new(|_| {}),
       @@ -162,14 +155,32 @@ impl AnsiEditor {
                    is_dirty: false,
                    drag_start: None,
                    last_pos: Position::default(),
       -            buffer_parser: Box::new(buffer_parser),
                    egui_id: Id::new(id),
                }
            }
        
       +    pub fn get_cur_layer(&self) -> usize {
       +        self.buffer_view
       +            .lock()
       +            .get_edit_state_mut()
       +            .get_current_layer()
       +    }
       +
       +    pub fn set_cur_layer(&self, layer: usize) {
       +        self.buffer_view
       +            .lock()
       +            .get_edit_state_mut()
       +            .set_current_layer(layer);
       +    }
       +
            pub fn output_string(&mut self, str: &str) {
                for ch in str.chars() {
       -            let translated_char = self.buffer_parser.convert_from_unicode(ch, 0);
       +            let translated_char = self
       +                .buffer_view
       +                .lock()
       +                .get_edit_state()
       +                .get_parser()
       +                .convert_from_unicode(ch, 0);
                    if let Err(err) = self.print_char(translated_char as u8) {
                        eprintln!("{}", err);
                    }
       @@ -179,37 +190,42 @@ impl AnsiEditor {
            pub fn print_char(&mut self, c: u8) -> Result<(), Box<dyn std::error::Error>> {
                self.buffer_view
                    .lock()
       -            .print_char(&mut self.buffer_parser, unsafe {
       -                char::from_u32_unchecked(c as u32)
       -            })?;
       +            .print_char(unsafe { char::from_u32_unchecked(c as u32) })?;
                self.buffer_view.lock().redraw_view();
                Ok(())
            }
            pub fn get_caret_position(&self) -> Position {
       -        self.buffer_view.lock().caret.get_position()
       +        self.buffer_view.lock().get_caret().get_position()
            }
        
            pub fn set_caret_position(&mut self, pos: Position) {
                let buffer_view = &mut self.buffer_view.lock();
                let pos = Position::new(
       -            min(buffer_view.buf.get_width() as i32 - 1, max(0, pos.x)),
       -            min(buffer_view.buf.get_line_count() as i32 - 1, max(0, pos.y)),
       +            min(
       +                buffer_view.get_buffer().get_width() as i32 - 1,
       +                max(0, pos.x),
       +            ),
       +            min(
       +                buffer_view.get_buffer().get_line_count() as i32 - 1,
       +                max(0, pos.y),
       +            ),
                );
       -        buffer_view.caret.set_position(pos);
       +        buffer_view.get_caret_mut().set_position(pos);
                //(self.pos_changed)(self, pos);
            }
        
            pub fn set_caret_attribute(&mut self, attr: TextAttribute) {
       -        if attr == self.buffer_view.lock().caret.get_attribute() {
       +        if attr == self.buffer_view.lock().get_caret().get_attribute() {
                    return;
                }
        
       -        self.buffer_view.lock().caret.set_attr(attr);
       +        self.buffer_view.lock().get_caret_mut().set_attr(attr);
                // (self.attr_changed)(attr);
            }
        
            pub fn clear_layer(&mut self, layer_num: usize) -> ClearLayerOperation {
       -        let layers = std::mem::take(&mut self.buffer_view.lock().buf.layers[layer_num].lines);
       +        let layers =
       +            std::mem::take(&mut self.buffer_view.lock().get_buffer_mut().layers[layer_num].lines);
                ClearLayerOperation {
                    layer_num,
                    lines: layers,
       @@ -218,7 +234,7 @@ impl AnsiEditor {
        
            pub fn join_overlay(&mut self) {
                self.begin_atomic_undo();
       -        let opt_layer = self.buffer_view.lock().buf.remove_overlay();
       +        let opt_layer = self.buffer_view.lock().get_buffer_mut().remove_overlay();
        
                if let Some(layer) = &opt_layer {
                    for y in 0..layer.lines.len() {
       @@ -236,29 +252,38 @@ impl AnsiEditor {
        
            pub fn delete_line(&mut self, line: i32) {
                // TODO: Undo
       -        let layer = &mut self.buffer_view.lock().buf.layers[self.cur_layer];
       +        let mut lock = self.buffer_view.lock();
       +        let cur_layer = self.get_cur_layer();
       +
       +        let layer = &mut lock.get_buffer_mut().layers[cur_layer];
                layer.remove_line(line);
            }
        
            pub fn insert_line(&mut self, line: i32) {
                // TODO: Undo
       -        let layer = &mut self.buffer_view.lock().buf.layers[self.cur_layer];
       +        let mut binding = self.buffer_view.lock();
       +        let cur_layer = self.get_cur_layer();
       +
       +        let layer = &mut binding.get_buffer_mut().layers[cur_layer];
                layer.insert_line(line, Line::new());
            }
        
            pub fn pickup_color(&mut self, pos: Position) {
       -        let ch = self.buffer_view.lock().buf.get_char(pos);
       +        let ch = self.buffer_view.lock().get_buffer().get_char(pos);
                if ch.is_visible() {
       -            self.buffer_view.lock().caret.set_attr(ch.attribute);
       +            self.buffer_view
       +                .lock()
       +                .get_caret_mut()
       +                .set_attr(ch.attribute);
                }
            }
        
            pub fn set_caret(&mut self, x: i32, y: i32) -> Event {
       -        let old = self.buffer_view.lock().caret.get_position();
       -        let w = self.buffer_view.lock().buf.get_width() as i32 - 1;
       -        let h = self.buffer_view.lock().buf.get_line_count() as i32 - 1;
       +        let old = self.buffer_view.lock().get_caret().get_position();
       +        let w = self.buffer_view.lock().get_buffer().get_width() as i32 - 1;
       +        let h = self.buffer_view.lock().get_buffer().get_line_count() as i32 - 1;
                self.set_caret_position(Position::new(min(max(0, x), w), min(max(0, y), h)));
       -        Event::CursorPositionChange(old, self.buffer_view.lock().caret.get_position())
       +        Event::CursorPositionChange(old, self.buffer_view.lock().get_caret().get_position())
            }
        
            pub fn get_cur_outline(&self) -> usize {
       @@ -277,10 +302,13 @@ impl AnsiEditor {
                    let ext = OsStr::to_str(ext).unwrap().to_lowercase();
                    self.buffer_view
                        .lock()
       -                .buf
       +                .get_buffer()
                        .to_bytes(ext.as_str(), options)?
                } else {
       -            self.buffer_view.lock().buf.to_bytes("icd", options)?
       +            self.buffer_view
       +                .lock()
       +                .get_buffer()
       +                .to_bytes("icd", options)?
                };
                f.write_all(&content)?;
                Ok(true)
       @@ -308,24 +336,27 @@ impl AnsiEditor {
            }
        
            pub fn get_char(&self, pos: Position) -> AttributedChar {
       -        self.buffer_view.lock().buf.get_char(pos)
       +        self.buffer_view.lock().get_buffer().get_char(pos)
            }
        
            pub fn get_char_from_cur_layer(&self, pos: Position) -> AttributedChar {
       -        if self.cur_layer >= self.buffer_view.lock().buf.layers.len() {
       +        if self.get_cur_layer() >= self.buffer_view.lock().get_buffer().layers.len() {
                    return AttributedChar::invisible();
                }
       -        self.buffer_view.lock().buf.layers[self.cur_layer].get_char(pos)
       +        let cur_layer = self.get_cur_layer();
       +        self.buffer_view.lock().get_buffer().layers[cur_layer].get_char(pos)
            }
        
            pub fn set_char(&mut self, pos: impl Into<UPosition>, attributed_char: AttributedChar) {
                let pos = pos.into();
                self.redo_stack.clear();
       -        let old = self.buffer_view.lock().buf.layers[self.cur_layer].get_char(pos);
       -        self.buffer_view.lock().buf.layers[self.cur_layer].set_char(pos, attributed_char);
       +        let cur_layer = self.get_cur_layer();
       +
       +        let old = self.buffer_view.lock().get_buffer().layers[cur_layer].get_char(pos);
       +        self.buffer_view.lock().get_buffer_mut().layers[cur_layer].set_char(pos, attributed_char);
                self.undo_stack.push(Box::new(UndoSetChar {
                    pos,
       -            layer: self.cur_layer,
       +            layer: self.get_cur_layer(),
                    old,
                    new: attributed_char,
                }));
       @@ -351,14 +382,14 @@ impl AnsiEditor {
        
            pub fn undo(&mut self) {
                if let Some(op) = self.undo_stack.pop() {
       -            op.undo(&mut self.buffer_view.lock().buf);
       +            op.undo(&mut self.buffer_view.lock().get_buffer_mut());
                    self.redo_stack.push(op);
                }
            }
        
            pub fn redo(&mut self) {
                if let Some(op) = self.redo_stack.pop() {
       -            op.redo(&mut self.buffer_view.lock().buf);
       +            op.redo(&mut self.buffer_view.lock().get_buffer_mut());
                    self.undo_stack.push(op);
                }
            }
       @@ -385,15 +416,15 @@ impl AnsiEditor {
            }
        
            pub fn type_key(&mut self, char_code: char) {
       -        let pos = self.buffer_view.lock().caret.get_position();
       -        if self.buffer_view.lock().caret.insert_mode {
       -            let start = self.buffer_view.lock().buf.get_width() as i32 - 1;
       +        let pos = self.buffer_view.lock().get_caret().get_position();
       +        if self.buffer_view.lock().get_caret().insert_mode {
       +            let start = self.buffer_view.lock().get_buffer().get_width() as i32 - 1;
                    for i in start..=pos.x {
                        let next = self.get_char_from_cur_layer(Position::new(i - 1, pos.y));
                        self.set_char(Position::new(i, pos.y), next);
                    }
                }
       -        let attr = self.buffer_view.lock().caret.get_attribute();
       +        let attr = self.buffer_view.lock().get_caret().get_attribute();
                self.set_char(pos, AttributedChar::new(char_code, attr));
                self.set_caret(pos.x + 1, pos.y);
            }
       @@ -415,7 +446,7 @@ impl AnsiEditor {
            }
        
            pub fn clear_cur_layer(&mut self) {
       -        let b = Box::new(self.clear_layer(self.cur_layer));
       +        let b = Box::new(self.clear_layer(self.get_cur_layer()));
                self.undo_stack.push(b);
            }
        
       @@ -425,7 +456,7 @@ impl AnsiEditor {
                    let max = selection.max();
                    (min.x, min.y, max.x, max.y)
                } else {
       -            let size = self.buffer_view.lock().buf.get_buffer_size();
       +            let size = self.buffer_view.lock().get_buffer().get_buffer_size();
                    (0, 0, size.width as i32 - 1, size.height as i32 - 1)
                }
            }
       @@ -433,9 +464,12 @@ impl AnsiEditor {
            pub fn justify_left(&mut self) {
                self.begin_atomic_undo();
                let (x1, y1, x2, y2) = self.get_blockaction_rectangle();
       -        let is_bg_layer = self.cur_layer == self.buffer_view.lock().buf.layers.len() - 1;
       +        let is_bg_layer =
       +            self.get_cur_layer() == self.buffer_view.lock().get_buffer().layers.len() - 1;
                {
       -            let layer = &mut self.buffer_view.lock().buf.layers[self.cur_layer];
       +            let lock = &mut self.buffer_view.lock();
       +            let cur_layer = self.get_cur_layer();
       +            let layer = &mut lock.get_buffer_mut().layers[cur_layer];
                    for y in y1..=y2 {
                        let mut removed_chars = 0;
                        let len = x2 - x1 + 1;
       @@ -463,7 +497,7 @@ impl AnsiEditor {
                            layer.set_char(pos, ch);
                            self.undo_stack.push(Box::new(UndoSetChar {
                                pos,
       -                        layer: self.cur_layer,
       +                        layer: self.get_cur_layer(),
                                old,
                                new: ch,
                            }));
       @@ -478,9 +512,13 @@ impl AnsiEditor {
                self.justify_left();
        
                let (x1, y1, x2, y2) = self.get_blockaction_rectangle();
       -        let is_bg_layer = self.cur_layer == self.buffer_view.lock().buf.layers.len() - 1;
       +        let is_bg_layer =
       +            self.get_cur_layer() == self.buffer_view.lock().get_buffer().layers.len() - 1;
                {
       -            let layer = &mut self.buffer_view.lock().buf.layers[self.cur_layer];
       +            let mut lock: eframe::epaint::mutex::MutexGuard<'_, BufferView> =
       +                self.buffer_view.lock();
       +            let cur_layer = self.get_cur_layer();
       +            let layer = &mut lock.get_buffer_mut().layers[cur_layer];
                    for y in y1..=y2 {
                        let mut removed_chars = 0;
                        let len = x2 - x1 + 1;
       @@ -510,7 +548,7 @@ impl AnsiEditor {
                            layer.set_char(pos, ch);
                            self.undo_stack.push(Box::new(UndoSetChar {
                                pos,
       -                        layer: self.cur_layer,
       +                        layer: self.get_cur_layer(),
                                old,
                                new: ch,
                            }));
       @@ -523,9 +561,13 @@ impl AnsiEditor {
            pub fn justify_right(&mut self) {
                self.begin_atomic_undo();
                let (x1, y1, x2, y2) = self.get_blockaction_rectangle();
       -        let is_bg_layer = self.cur_layer == self.buffer_view.lock().buf.layers.len() - 1;
       +        let is_bg_layer =
       +            self.get_cur_layer() == self.buffer_view.lock().get_buffer().layers.len() - 1;
                {
       -            let layer = &mut self.buffer_view.lock().buf.layers[self.cur_layer];
       +            let mut lock: eframe::epaint::mutex::MutexGuard<'_, BufferView> =
       +                self.buffer_view.lock();
       +            let cur_layer = self.get_cur_layer();
       +            let layer = &mut lock.get_buffer_mut().layers[cur_layer];
                    for y in y1..=y2 {
                        let mut removed_chars = 0;
                        let len = x2 - x1 + 1;
       @@ -554,7 +596,7 @@ impl AnsiEditor {
                            layer.set_char(pos, ch);
                            self.undo_stack.push(Box::new(UndoSetChar {
                                pos,
       -                        layer: self.cur_layer,
       +                        layer: self.get_cur_layer(),
                                old,
                                new: ch,
                            }));
       @@ -568,14 +610,17 @@ impl AnsiEditor {
                self.begin_atomic_undo();
                let (x1, y1, x2, y2) = self.get_blockaction_rectangle();
                {
       -            let layer = &mut self.buffer_view.lock().buf.layers[self.cur_layer];
       +            let mut lock: eframe::epaint::mutex::MutexGuard<'_, BufferView> =
       +                self.buffer_view.lock();
       +            let cur_layer = self.get_cur_layer();
       +            let layer = &mut lock.get_buffer_mut().layers[cur_layer];
                    for y in y1..=y2 {
                        for x in 0..=(x2 - x1) / 2 {
                            let pos1 = Position::new(x1 + x, y);
                            let pos2 = Position::new(x2 - x, y);
                            layer.swap_char(pos1, pos2);
                            self.undo_stack.push(Box::new(UndoSwapChar {
       -                        layer: self.cur_layer,
       +                        layer: self.get_cur_layer(),
                                pos1,
                                pos2,
                            }));
       @@ -593,14 +638,17 @@ impl AnsiEditor {
                self.begin_atomic_undo();
                let (x1, y1, x2, y2) = self.get_blockaction_rectangle();
                {
       -            let layer = &mut self.buffer_view.lock().buf.layers[self.cur_layer];
       +            let mut lock: eframe::epaint::mutex::MutexGuard<'_, BufferView> =
       +                self.buffer_view.lock();
       +            let cur_layer = self.get_cur_layer();
       +            let layer = &mut lock.get_buffer_mut().layers[cur_layer];
                    for x in x1..=x2 {
                        for y in 0..=(y2 - y1) / 2 {
                            let pos1 = Position::new(x, y1 + y);
                            let pos2 = Position::new(x, y2 - y);
                            layer.swap_char(pos1, pos2);
                            self.undo_stack.push(Box::new(UndoSwapChar {
       -                        layer: self.cur_layer,
       +                        layer: self.get_cur_layer(),
                                pos1,
                                pos2,
                            }));
       @@ -616,16 +664,17 @@ impl AnsiEditor {
                let new_height = y2 - y1;
                let new_width = x2 - x1;
        
       -        if new_height == self.buffer_view.lock().buf.get_line_count() as i32
       -            && new_width == self.buffer_view.lock().buf.get_width() as i32
       +        if new_height == self.buffer_view.lock().get_buffer().get_line_count() as i32
       +            && new_width == self.buffer_view.lock().get_buffer().get_width() as i32
                {
                    return;
                }
        
                let mut new_layers = Vec::new();
       -        let max = self.buffer_view.lock().buf.layers.len();
       +        let max = self.buffer_view.lock().get_buffer().layers.len();
                for l in 0..max {
       -            let old_layer = &self.buffer_view.lock().buf.layers[l];
       +            let lock = &self.buffer_view.lock();
       +            let old_layer = &lock.get_buffer().layers[l];
                    let mut new_layer = Layer::default();
                    new_layer.title = old_layer.title.clone();
                    new_layer.is_visible = old_layer.is_visible;
       @@ -648,28 +697,28 @@ impl AnsiEditor {
                /* TODO
                self.undo_stack.push(Box::new(super::UndoReplaceLayers {
        
       -            old_layer: self.buffer_view.lock().buf.layers.clone(),
       +            old_layer: self.buffer_view.lock().get_buffer().layers.clone(),
                    new_layer: new_layers.clone(),
                    old_size: Size::new(
       -                self.buffer_view.lock().buf.get_width(),
       -                self.buffer_view.lock().buf.get_line_count(),
       +                self.buffer_view.lock().get_buffer().get_width(),
       +                self.buffer_view.lock().get_buffer().get_line_count(),
                    ),
                    new_size: Size::new(new_width, new_height),
                })); */
        
       -        self.buffer_view.lock().buf.layers = new_layers;
       +        self.buffer_view.lock().get_buffer_mut().layers = new_layers;
                self.buffer_view
                    .lock()
       -            .buf
       +            .get_buffer_mut()
                    .set_buffer_width(new_width as usize);
                self.buffer_view
                    .lock()
       -            .buf
       +            .get_buffer_mut()
                    .set_buffer_height(new_height as usize);
                self.end_atomic_undo();
            }
            pub fn switch_fg_bg_color(&mut self) {
       -        let mut attr = self.buffer_view.lock().caret.get_attribute();
       +        let mut attr = self.buffer_view.lock().get_caret().get_attribute();
                let bg = attr.get_background();
                attr.set_background(attr.get_foreground());
                attr.set_foreground(bg);
       @@ -738,7 +787,7 @@ impl AnsiEditor {
        
            fn show_toolbar(&mut self, ui: &mut egui::Ui) {
                ui.horizontal(|ui| {
       -            let pos = self.buffer_view.lock().caret.get_position();
       +            let pos = self.buffer_view.lock().get_caret().get_position();
        
                    let label_font_size = 20.0;
        
       @@ -757,7 +806,7 @@ impl AnsiEditor {
        
                    let r = ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
                        let cur_outline = self.cur_outline;
       -                let cur_font_page = self.buffer_view.lock().caret.get_font_page();
       +                let cur_font_page = self.buffer_view.lock().get_caret().get_font_page();
        
                        let button_font_size = 16.0;
                        if ui
       @@ -817,7 +866,7 @@ impl AnsiEditor {
                            egui::Event::Copy => {
                                let buffer_view = self.buffer_view.clone();
                                let mut l = buffer_view.lock();
       -                        if let Some(txt) = l.get_copy_text(&*self.buffer_parser) {
       +                        if let Some(txt) = l.get_copy_text() {
                                    ui.output_mut(|o| o.copied_text = txt);
                                }
                            }
       @@ -952,7 +1001,7 @@ impl AnsiEditor {
            }
        
            pub(crate) fn set_file_name(&self, file_name: impl Into<PathBuf>) {
       -        self.buffer_view.lock().buf.file_name = Some(file_name.into());
       +        self.buffer_view.lock().get_buffer_mut().file_name = Some(file_name.into());
            }
        }
        
   DIR diff --git a/src/ui/editor/charfont/mod.rs b/src/ui/editor/charfont/mod.rs
       @@ -133,7 +133,8 @@ impl CharFontEditor {
            }
        
            fn show_selected_char(&mut self) {
       -        let buffer = &mut self.ansi_editor.buffer_view.lock().buf;
       +        let lock = &mut self.ansi_editor.buffer_view.lock();
       +        let buffer = &mut lock.get_buffer_mut();
                buffer.layers[0].clear();
        
                if let Some(ch) = self.selected_char_opt {
   DIR diff --git a/src/ui/messages.rs b/src/ui/messages.rs
       @@ -94,7 +94,7 @@ impl MainWindow {
                    Message::ExportFile => {
                        self.run_editor_command(0, |window, editor, _| {
                            let view = editor.buffer_view.clone();
       -                    window.open_dialog(crate::ExportFileDialog::new(&view.lock().buf));
       +                    window.open_dialog(crate::ExportFileDialog::new(&view.lock().get_buffer()));
                            None
                        });
                        if let Some(editor) = self
       @@ -105,7 +105,7 @@ impl MainWindow {
                            .get_ansi_editor()
                        {
                            let view = editor.buffer_view.clone();
       -                    self.open_dialog(crate::ExportFileDialog::new(&view.lock().buf));
       +                    self.open_dialog(crate::ExportFileDialog::new(&view.lock().get_buffer()));
                        }
                    }
                    Message::ShowOutlineDialog => {
       @@ -145,8 +145,8 @@ impl MainWindow {
                            .get_ansi_editor()
                        {
                            let buf = &mut editor.buffer_view.lock();
       -                    let w = buf.buf.get_width();
       -                    let h = buf.buf.get_line_count();
       +                    let w = buf.get_buffer().get_width();
       +                    let h = buf.get_buffer().get_line_count();
        
                            buf.set_selection(Selection::from_rectangle(0.0, 0.0, w as f32, h as f32));
                        }
       @@ -204,7 +204,7 @@ impl MainWindow {
                            .get_ansi_editor()
                        {
                            let view = editor.buffer_view.clone();
       -                    self.open_dialog(crate::EditSauceDialog::new(&view.lock().buf));
       +                    self.open_dialog(crate::EditSauceDialog::new(&view.lock().get_buffer()));
                        }
                    }
                    Message::SetCanvasSize => {
       @@ -216,7 +216,7 @@ impl MainWindow {
                            .get_ansi_editor()
                        {
                            let view = editor.buffer_view.clone();
       -                    self.open_dialog(crate::SetCanvasSizeDialog::new(&view.lock().buf));
       +                    self.open_dialog(crate::SetCanvasSizeDialog::new(&view.lock().get_buffer()));
                        }
                    }
        
       @@ -229,7 +229,7 @@ impl MainWindow {
                            .get_ansi_editor()
                        {
                            let view = editor.buffer_view.clone();
       -                    self.open_dialog(crate::EditLayerDialog::new(&view.lock().buf, i));
       +                    self.open_dialog(crate::EditLayerDialog::new(&view.lock().get_buffer(), i));
                        }
                    }
                    Message::NewLayer => {
       @@ -240,7 +240,8 @@ impl MainWindow {
                            .unwrap()
                            .get_ansi_editor_mut()
                        {
       -                    let buf = &mut editor.buffer_view.lock().buf;
       +                    let mut lock = editor.buffer_view.lock();
       +                    let buf = lock.get_buffer_mut();
                            let size = buf.get_buffer_size();
                            let mut new_layer = icy_engine::Layer::new("New Layer", size);
                            new_layer.has_alpha_channel = true;
       @@ -262,10 +263,10 @@ impl MainWindow {
                            editor
                                .buffer_view
                                .lock()
       -                        .buf
       +                        .get_buffer_mut()
                                .layers
                                .swap(cur_layer, cur_layer - 1);
       -                    editor.cur_layer -= 1;
       +                    editor.set_cur_layer(editor.get_cur_layer() - 1);
                        }
                    }
                    Message::MoveLayerDown(cur_layer) => {
       @@ -279,40 +280,62 @@ impl MainWindow {
                            editor
                                .buffer_view
                                .lock()
       -                        .buf
       +                        .get_buffer_mut()
                                .layers
                                .swap(cur_layer, cur_layer + 1);
       -                    editor.cur_layer += 1;
       +                    editor.set_cur_layer(editor.get_cur_layer() + 1);
                        }
                    }
                    Message::DeleteLayer(cur_layer) => {
                        self.run_editor_command(cur_layer, |_, editor, cur_layer| {
       -                    editor.buffer_view.lock().buf.layers.remove(cur_layer);
       -                    editor.cur_layer = editor.cur_layer.clamp(
       -                        0,
       -                        editor.buffer_view.lock().buf.layers.len().saturating_sub(1),
       +                    editor
       +                        .buffer_view
       +                        .lock()
       +                        .get_buffer_mut()
       +                        .layers
       +                        .remove(cur_layer);
       +                    editor.set_cur_layer(
       +                        editor.get_cur_layer().clamp(
       +                            0,
       +                            editor
       +                                .buffer_view
       +                                .lock()
       +                                .get_buffer()
       +                                .layers
       +                                .len()
       +                                .saturating_sub(1),
       +                        ),
                            );
                            None
                        });
                    }
                    Message::DuplicateLayer(cur_layer) => {
                        self.run_editor_command(cur_layer, |_, editor, cur_layer| {
       -                    let layer = editor.buffer_view.lock().buf.layers[cur_layer].clone();
       +                    let layer = editor.buffer_view.lock().get_buffer().layers[cur_layer].clone();
                            editor
                                .buffer_view
                                .lock()
       -                        .buf
       +                        .get_buffer_mut()
                                .layers
                                .insert(cur_layer + 1, layer);
       -                    editor.cur_layer += 1;
       +                    editor.set_cur_layer(editor.get_cur_layer() + 1);
                            None
                        });
                    }
                    Message::MergeLayer(cur_layer) => {
                        self.run_editor_command(cur_layer, |_, editor, cur_layer| {
       -                    let layer = editor.buffer_view.lock().buf.layers.remove(cur_layer);
       -                    if let Some(layer_below) =
       -                        editor.buffer_view.lock().buf.layers.get_mut(cur_layer)
       +                    let layer = editor
       +                        .buffer_view
       +                        .lock()
       +                        .get_buffer_mut()
       +                        .layers
       +                        .remove(cur_layer);
       +                    if let Some(layer_below) = editor
       +                        .buffer_view
       +                        .lock()
       +                        .get_buffer_mut()
       +                        .layers
       +                        .get_mut(cur_layer)
                            {
                                for y in 0..layer.get_height() {
                                    for x in 0..layer.get_width() {
       @@ -336,8 +359,10 @@ impl MainWindow {
                            .unwrap()
                            .get_ansi_editor_mut()
                        {
       -                    let is_visible = editor.buffer_view.lock().buf.layers[cur_layer].is_visible;
       -                    editor.buffer_view.lock().buf.layers[cur_layer].is_visible = !is_visible;
       +                    let is_visible =
       +                        editor.buffer_view.lock().get_buffer().layers[cur_layer].is_visible;
       +                    editor.buffer_view.lock().get_buffer_mut().layers[cur_layer].is_visible =
       +                        !is_visible;
                        }
                    }
                    Message::SelectLayer(cur_layer) => {
       @@ -348,7 +373,7 @@ impl MainWindow {
                            .unwrap()
                            .get_ansi_editor_mut()
                        {
       -                    editor.cur_layer = cur_layer;
       +                    editor.set_cur_layer(cur_layer);
                        }
                    }
        
       @@ -360,9 +385,14 @@ impl MainWindow {
                            .unwrap()
                            .get_ansi_editor_mut()
                        {
       -                    editor.buffer_view.lock().caret.set_font_page(page);
       +                    editor
       +                        .buffer_view
       +                        .lock()
       +                        .get_caret_mut()
       +                        .set_font_page(page);
        
       -                    let buf = &mut editor.buffer_view.lock().buf;
       +                    let lock = &mut editor.buffer_view.lock();
       +                    let buf = &mut lock.get_buffer_mut();
                            if buf.get_font(page).is_none() {
                                if let Some(font_name) =
                                    icy_engine::parsers::ansi::constants::ANSI_FONT_NAMES.get(page)
   DIR diff --git a/src/ui/old/buffer_view.rs b/src/ui/old/buffer_view.rs
       @@ -472,7 +472,7 @@ void main() {
            }
        
            pub fn clear(&mut self) {
       -        self.editor.caret.ff(&mut self.editor.buf);
       +        self.editor.get_caret().ff(&mut self.editor.buf);
            }
        
            pub fn get_copy_text(&mut self, buffer_parser: &dyn BufferParser) -> Option<String> {
       @@ -513,7 +513,7 @@ void main() {
                parser: &mut Box<dyn BufferParser>,
                c: char,
            ) -> EngineResult<CallbackAction> {
       -        let res = parser.print_char(&mut self.editor.buf, &mut self.editor.caret, c);
       +        let res = parser.print_char(&mut self.editor.buf, &mut self.editor.get_caret(), c);
                self.redraw_view();
                res
            }
   DIR diff --git a/src/ui/old/mod.rs b/src/ui/old/mod.rs
       @@ -52,7 +52,7 @@ impl AnsiEditor {
        
        impl Document for AnsiEditor {
            fn get_title(&self) -> String {
       -        if let Some(file_name) = &self.buffer_view.lock().editor.buf.file_name {
       +        if let Some(file_name) = &self.buffer_view.lock().editor.get_buffer().file_name {
                    file_name.file_name().unwrap().to_str().unwrap().to_string()
                } else {
                    "Untitled".to_string()
       @@ -360,7 +360,7 @@ impl Document for AnsiEditor {
                    });
        
                ui.horizontal(|ui| {
       -            let pos = self.buffer_view.lock().editor.caret.get_position();
       +            let pos = self.buffer_view.lock().editor.get_caret().get_position();
        
                    let label_font_size = 20.0;
        
   DIR diff --git a/src/ui/old/render.rs b/src/ui/old/render.rs
       @@ -74,18 +74,18 @@ impl BufferView {
                        0.0,
                    );
        
       -            let sbl = (self.editor.buf.get_first_visible_line() - self.scroll_first_line) as f32;
       +            let sbl = (self.editor.get_buffer().get_first_visible_line() - self.scroll_first_line) as f32;
                    gl.uniform_4_f32(
                        gl.get_uniform_location(self.program, "u_caret_position")
                            .as_ref(),
       -                self.editor.caret.get_position().x as f32,
       -                self.editor.caret.get_position().y as f32 + sbl,
       -                if self.caret_blink.is_on() && self.editor.caret.is_visible {
       +                self.editor.get_caret().get_position().x as f32,
       +                self.editor.get_caret().get_position().y as f32 + sbl,
       +                if self.caret_blink.is_on() && self.editor.get_caret().is_visible {
                            1.0
                        } else {
                            0.0
                        },
       -                if self.editor.caret.insert_mode {
       +                if self.editor.get_caret().insert_mode {
                            1.0
                        } else {
                            0.0
       @@ -104,8 +104,8 @@ impl BufferView {
                    gl.uniform_2_f32(
                        gl.get_uniform_location(self.program, "u_terminal_size")
                            .as_ref(),
       -                self.editor.buf.get_width() as f32 - 0.0001,
       -                self.editor.buf.get_height() as f32 - 0.0001,
       +                self.editor.get_buffer().get_width() as f32 - 0.0001,
       +                self.editor.get_buffer().get_height() as f32 - 0.0001,
                    );
        
                    gl.uniform_1_i32(gl.get_uniform_location(self.program, "u_fonts").as_ref(), 0);
       @@ -234,8 +234,8 @@ impl BufferView {
                                        self.render_buffer_size.y,
                                    );
        
       -                            let x = sixel.pos.x as f32 * self.editor.buf.get_font_dimensions().width as f32;
       -                            let y = sixel.pos.y as f32 * self.editor.buf.get_font_dimensions().height as f32;
       +                            let x = sixel.pos.x as f32 * self.editor.get_buffer().get_font_dimensions().width as f32;
       +                            let y = sixel.pos.y as f32 * self.editor.get_buffer().get_font_dimensions().height as f32;
        
                                    let w = sixel.size.width as f32 * sixel.x_scale as f32;
                                    let h = sixel.size.height as f32 * sixel.y_scale as f32;
       @@ -328,7 +328,7 @@ impl BufferView {
                    self.redraw_view = true;
                }
        
       -        if self.redraw_font || self.editor.buf.is_font_table_updated() {
       +        if self.redraw_font || self.editor.get_buffer().is_font_table_updated() {
                    self.redraw_font = false;
                    self.font_lookup_table =
                        create_font_texture(gl, &mut self.editor.buf, &self.font_texture);
       @@ -345,16 +345,16 @@ impl BufferView {
                    );
                }
        
       -        if self.redraw_palette || self.colors != self.editor.buf.palette.colors.len() {
       +        if self.redraw_palette || self.colors != self.editor.get_buffer().palette.colors.len() {
                    self.redraw_palette = false;
                    create_palette_texture(gl, &self.editor.buf, self.palette_texture);
       -            self.colors = self.editor.buf.palette.colors.len();
       +            self.colors = self.editor.get_buffer().palette.colors.len();
                }
        
                let editor = &self.editor;
                let render_buffer_size = Vec2::new(
       -            editor.buf.get_font_dimensions().width as f32 * editor.buf.get_width() as f32,
       -            editor.buf.get_font_dimensions().height as f32 * editor.buf.get_height() as f32,
       +            editor.get_buffer().get_font_dimensions().width as f32 * editor.get_buffer().get_width() as f32,
       +            editor.get_buffer().get_font_dimensions().height as f32 * editor.get_buffer().get_height() as f32,
                );
        
                if render_buffer_size != self.render_buffer_size {
       @@ -461,7 +461,7 @@ pub fn create_palette_texture(
            palette_texture: NativeTexture,
        ) {
            let mut palette_data = Vec::new();
       -    for i in 0..buf.palette.colors.len() {
       +    for i in 0..get_buffer().palette.colors.len() {
                let (r, g, b) = buf.palette.colors[i].get_rgb();
                palette_data.push(r);
                palette_data.push(g);
       @@ -579,7 +579,7 @@ pub fn create_buffer_texture(
            while y < buf.get_height() {
                let mut is_double_height = false;
        
       -        for x in 0..buf.get_width() {
       +        for x in 0..get_buffer().get_width() {
                    let ch = buf.get_char_xy(x, first_line - scroll_back_line + y);
                    if ch.attribute.is_double_height() {
                        is_double_height = true;
       @@ -604,7 +604,7 @@ pub fn create_buffer_texture(
                }
        
                if is_double_height {
       -            for x in 0..buf.get_width() {
       +            for x in 0..get_buffer().get_width() {
                        let ch = buf.get_char_xy(x, first_line - scroll_back_line + y);
        
                        if ch.attribute.is_double_height() {
       @@ -640,7 +640,7 @@ pub fn create_buffer_texture(
            while y < buf.get_height() {
                let mut is_double_height = false;
        
       -        for x in 0..buf.get_width() {
       +        for x in 0..get_buffer().get_width() {
                    let ch = buf.get_char_xy(x, first_line - scroll_back_line + y);
        
                    let mut attr = if ch.attribute.is_double_underlined() {
       @@ -664,7 +664,7 @@ pub fn create_buffer_texture(
                }
        
                if is_double_height {
       -            for x in 0..buf.get_width() {
       +            for x in 0..get_buffer().get_width() {
                        let ch = buf.get_char_xy(x, first_line - scroll_back_line + y);
                        let mut attr = if ch.attribute.is_double_underlined() {
                            3
   DIR diff --git a/src/ui/palette_editor.rs b/src/ui/palette_editor.rs
       @@ -7,8 +7,8 @@ use std::cmp::min;
        
        pub fn palette_switcher(ctx: &egui::Context, editor: &AnsiEditor) -> impl egui::Widget {
            let tex_id = SWAP_SVG.texture_id(ctx);
       -    let caret_attr = editor.buffer_view.lock().caret.get_attribute();
       -    let palette = editor.buffer_view.lock().buf.palette.clone();
       +    let caret_attr = editor.buffer_view.lock().get_caret().get_attribute();
       +    let palette = editor.buffer_view.lock().get_buffer().palette.clone();
        
            let buffer_view = editor.buffer_view.clone();
        
       @@ -138,7 +138,9 @@ pub fn palette_switcher(ctx: &egui::Context, editor: &AnsiEditor) -> impl egui::
        
                    if response.clicked() {
                        if pos.x > rect_height && pos.y < rect_height {
       -                    let caret = &mut buffer_view.lock().caret;
       +                    let mut bv: eframe::epaint::mutex::MutexGuard<'_, icy_engine_egui::BufferView> =
       +                        buffer_view.lock();
       +                    let caret = bv.get_caret_mut();
                            let fg = caret.get_attribute().get_foreground();
                            let bg = caret.get_attribute().get_background();
                            caret.set_foreground(bg);
       @@ -147,7 +149,9 @@ pub fn palette_switcher(ctx: &egui::Context, editor: &AnsiEditor) -> impl egui::
                        }
        
                        if pos.x < rect_height && pos.y > rect_height {
       -                    let caret = &mut buffer_view.lock().caret;
       +                    let mut bv: eframe::epaint::mutex::MutexGuard<'_, icy_engine_egui::BufferView> =
       +                        buffer_view.lock();
       +                    let caret = bv.get_caret_mut();
                            caret.set_foreground(7);
                            caret.set_background(0);
                            response.mark_changed();
       @@ -159,8 +163,8 @@ pub fn palette_switcher(ctx: &egui::Context, editor: &AnsiEditor) -> impl egui::
        }
        
        pub fn palette_editor_16(ui: &mut egui::Ui, editor: &AnsiEditor) {
       -    let caret_attr = editor.buffer_view.lock().caret.get_attribute();
       -    let palette = editor.buffer_view.lock().buf.palette.clone();
       +    let caret_attr = editor.buffer_view.lock().get_caret().get_attribute();
       +    let palette = editor.buffer_view.lock().get_buffer().palette.clone();
            let buffer_view = editor.buffer_view.clone();
        
            ui.horizontal(|ui| {
       @@ -248,11 +252,11 @@ pub fn palette_editor_16(ui: &mut egui::Ui, editor: &AnsiEditor) {
                    let pos = (hp.to_vec2() - stroke_rect.left_top().to_vec2()) / Vec2::new(height, height);
                    let color = min(palette.len() - 1, pos.x as u32 + pos.y as u32 * 8);
                    if response.clicked() {
       -                buffer_view.lock().caret.set_foreground(color);
       +                buffer_view.lock().get_caret_mut().set_foreground(color);
                        response.mark_changed();
                    }
                    if response.secondary_clicked() {
       -                buffer_view.lock().caret.set_background(color);
       +                buffer_view.lock().get_caret_mut().set_background(color);
                        response.mark_changed();
                    }
                }
       @@ -331,14 +335,22 @@ pub fn show_extended_palette(ui: &mut Ui, editor: &AnsiEditor) {
        
                            let buffer_view = editor.buffer_view.clone();
                            if response.clicked() {
       -                        let color = buffer_view.lock().buf.palette.insert_color_rgb(r, g, b);
       -                        buffer_view.lock().caret.set_foreground(color);
       +                        let color = buffer_view
       +                            .lock()
       +                            .get_buffer_mut()
       +                            .palette
       +                            .insert_color_rgb(r, g, b);
       +                        buffer_view.lock().get_caret_mut().set_foreground(color);
                                response.mark_changed();
                            }
        
                            if response.secondary_clicked() {
       -                        let color = buffer_view.lock().buf.palette.insert_color_rgb(r, g, b);
       -                        buffer_view.lock().caret.set_background(color);
       +                        let color = buffer_view
       +                            .lock()
       +                            .get_buffer_mut()
       +                            .palette
       +                            .insert_color_rgb(r, g, b);
       +                        buffer_view.lock().get_caret_mut().set_background(color);
                                response.mark_changed();
                            }
                            response
   DIR diff --git a/src/ui/tools/bitfont_selector.rs b/src/ui/tools/bitfont_selector.rs
       @@ -35,7 +35,7 @@ fn show_font_list(ui: &mut egui::Ui, editor: &AnsiEditor) -> Option<Message> {
            let mut result = None;
        
            /*
       -    for (id, font) in editor.buffer_view.lock().buf.font_iter() {
       +    for (id, font) in editor.buffer_view.lock().get_buffer().font_iter() {
        
                if id >= 100 {
                    // TODO
       @@ -43,7 +43,7 @@ fn show_font_list(ui: &mut egui::Ui, editor: &AnsiEditor) -> Option<Message> {
            }*/
            let row_height = 23.0;
        
       -    let cur_font_page = editor.buffer_view.lock().caret.get_font_page();
       +    let cur_font_page = editor.buffer_view.lock().get_caret().get_font_page();
        
            egui::ScrollArea::vertical()
                .id_source("bitfont_scroll_area")
   DIR diff --git a/src/ui/tools/char_table.rs b/src/ui/tools/char_table.rs
       @@ -34,11 +34,11 @@ impl ToolWindow for CharTableToolWindow {
        pub fn show_char_table(ui: &mut egui::Ui, editor: &AnsiEditor) -> Option<Message> {
            let mut result = None;
        
       -    let font_page = editor.buffer_view.lock().caret.get_font_page();
       +    let font_page = editor.buffer_view.lock().get_caret().get_font_page();
            let font_length = editor
                .buffer_view
                .lock()
       -        .buf
       +        .get_buffer()
                .get_font(font_page)
                .unwrap()
                .length;
   DIR diff --git a/src/ui/tools/layer_view.rs b/src/ui/tools/layer_view.rs
       @@ -40,8 +40,8 @@ fn show_layer_view(ui: &mut egui::Ui, editor: &AnsiEditor) -> Option<Message> {
            let row_height = 24.0;
            let mut result = None;
        
       -    let max = editor.buffer_view.lock().buf.layers.len();
       -    let cur_layer = editor.cur_layer;
       +    let max = editor.buffer_view.lock().get_buffer().layers.len();
       +    let cur_layer = editor.get_cur_layer();
            let uv = Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0));
            ui.set_height(row_height * 6.0);
            egui::ScrollArea::vertical()
       @@ -52,7 +52,8 @@ fn show_layer_view(ui: &mut egui::Ui, editor: &AnsiEditor) -> Option<Message> {
                        ui.horizontal(|ui| {
                            ui.add_space(4.0);
                            let (is_visible, title, color) = {
       -                        let layer = &editor.buffer_view.lock().buf.layers[i];
       +                        let lock = editor.buffer_view.lock();
       +                        let layer = &lock.get_buffer().layers[i];
                                (layer.is_visible, layer.title.clone(), layer.color)
                            };
                            let width = ui.available_width();