URI: 
       Worked on font tool. - 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 f8f7b318c76c53b4048108adcef89e2f7084db3a
   DIR parent 8988825b86bddb19387334389450c09afeea2446
  HTML Author: Mike Krüger <mkrueger@posteo.de>
       Date:   Sun, 23 Jul 2023 20:50:46 +0200
       
       Worked on font tool.
       
       + Fonts basically work now.
       
       Diffstat:
         M Cargo.toml                          |       1 +
         M src/model/tool/font_imp.rs          |     269 +++++++++++++++++--------------
         M src/model/tool/mod.rs               |     343 ++++++++++++++++---------------
         M src/ui/ansi_editor/key_maps.rs      |     126 ++++++++++++++++---------------
         M src/ui/ansi_editor/mod.rs           |      27 ++++++++++++++++++---------
         M src/ui/main_window.rs               |       8 ++++++++
       
       6 files changed, 413 insertions(+), 361 deletions(-)
       ---
   DIR diff --git a/Cargo.toml b/Cargo.toml
       @@ -18,6 +18,7 @@ icy_engine = { path = "../icy_engine" }
        walkdir = "2"
        serde = { version = "1", features = ["derive"], optional = true }
        lazy_static = "1.4.0"
       +directories = "5.0.1"
        
        i18n-embed = { version = "0.13.4", features = ["fluent-system", "desktop-requester"]} 
        i18n-embed-fl = "0.6.4"
   DIR diff --git a/src/model/tool/font_imp.rs b/src/model/tool/font_imp.rs
       @@ -1,8 +1,11 @@
       -use std::{cell::RefCell, rc::Rc};
       +use std::{cell::RefCell, rc::Rc, fs, sync::{Arc, Mutex}};
       +
       +use crate::ansi_editor::BufferView;
        
        use super::{Editor, Event, MKey, MKeyCode, MModifiers, Position, Tool};
       -use eframe::egui;
       -use icy_engine::{Size, TheDrawFont};
       +use directories::ProjectDirs;
       +use eframe::egui::{self, ComboBox};
       +use icy_engine::{Size, TheDrawFont, Rectangle, TextAttribute};
        use walkdir::{DirEntry, WalkDir};
        pub struct FontTool {
            pub selected_font: i32,
       @@ -21,38 +24,46 @@ impl FontTool {
                    .to_str()
                    .map_or(false, |s| s.starts_with('.'))
            }
       -    /*
       -        pub fn load_fonts(&mut self)
       -        {
       -            if let Some(path) = unsafe { &WORKSPACE.settings.font_path } {
       -                let walker = WalkDir::new(path).into_iter();
       -                for entry in walker.filter_entry(|e| !FontTool::is_hidden(e)) {
       -                    if let Err(e) = entry {
       -                        eprintln!("Can't load tdf font library: {}", e);
       -                        break;
       -                    }
       -                    let entry = entry.unwrap();
       -                    let path = entry.path();
        
       -                    if path.is_dir() {
       -                        continue;
       -                    }
       -                    let extension = path.extension();
       -                    if extension.is_none() { continue; }
       -                    let extension = extension.unwrap().to_str();
       -                    if extension.is_none() { continue; }
       -                    let extension = extension.unwrap().to_lowercase();
       -
       -                    if extension == "tdf" {
       -                        if let Some(font) = TheDrawFont::load(path) {
       -                            self.fonts.push(font);
       -                        }
       +    pub fn load_fonts(&mut self)
       +    {
       +        if let Some(proj_dirs) = ProjectDirs::from("com", "GitHub", "icy_draw") {
       +
       +            let tdf_dir = proj_dirs.config_dir().join("tdf");
       +            if !tdf_dir.exists() {
       +                fs::create_dir_all(&tdf_dir).expect(&format!(
       +                    "Can't create tdf font directory {:?}",
       +                    proj_dirs.config_dir()
       +                ));
       +            }
       +            self.fonts.clear();
       +            let walker = WalkDir::new(tdf_dir).into_iter();
       +            for entry in walker.filter_entry(|e| !FontTool::is_hidden(e)) {
       +                if let Err(e) = entry {
       +                    eprintln!("Can't load tdf font library: {}", e);
       +                    break;
       +                }
       +                let entry = entry.unwrap();
       +                let path = entry.path();
       +
       +                if path.is_dir() {
       +                    continue;
       +                }
       +                let extension = path.extension();
       +                if extension.is_none() { continue; }
       +                let extension = extension.unwrap().to_str();
       +                if extension.is_none() { continue; }
       +                let extension = extension.unwrap().to_lowercase();
       +
       +                if extension == "tdf" {
       +                    if let Some(font) = TheDrawFont::load(path) {
       +                        self.fonts.push(font);
                            }
                        }
                    }
                }
       +    }
        
       -    */
        }
        
        impl Tool for FontTool {
       @@ -69,116 +80,136 @@ impl Tool for FontTool {
                ui: &mut egui::Ui,
                buffer_opt: Option<std::sync::Arc<std::sync::Mutex<crate::ui::ansi_editor::BufferView>>>,
            ) {
       -    }
       -    /*
       -        fn handle_click(&mut self, editor: Rc<RefCell<Editor>>, button: u32, pos: Position) -> Event {
       -            if button == 1 {
       -                editor.borrow_mut().set_caret_position(pos);
       +
       +        ui.vertical_centered(|ui| {
       +            let mut selected_text = "<none>".to_string();
       +
       +            if self.selected_font >= 0 && (self.selected_font as usize) < self.fonts.len() {
       +                if let Some(font) = self.fonts.get(self.selected_font as usize) {
       +                    selected_text = font.name.clone();
       +                }
                    }
       -            let mut editor = editor.borrow_mut();
       -            self.sizes.clear();
       + 
       +            ComboBox::from_label("Font")
       +            .selected_text(selected_text)
       +            .show_ui(ui, |ui| {
       +                for i in 0..self.fonts.len() {
       +                    ui.selectable_value(&mut self.selected_font, i as i32,  &self.fonts[i].name);
       +                }
       +            });
       +        });
       +    }
       +
       +    fn handle_click(
       +        &mut self,
       +        buffer_view: Arc<Mutex<BufferView>>,
       +        button: i32,
       +        pos: Position,
       +    ) -> Event {
       +        if button == 1 {
       +            let editor = &mut buffer_view.lock().unwrap().editor;
       +            editor.set_caret_position(pos);
                    editor.cur_selection = None;
       -            Event::None
                }
       +        Event::None
       +    }
        
       -        fn handle_key(&mut self, editor: Rc<RefCell<Editor>>, key: MKey, _key_code: MKeyCode, modifier: MModifiers) -> Event
       -        {
       -            if self.selected_font < 0 || self.selected_font >= self.fonts.len() as i32 {
       -                return Event::None;
       -            }
       -            let font = &self.fonts[self.selected_font as usize];
       -            let pos = editor.borrow().get_caret_position();
       -            let mut editor = editor.borrow_mut();
       +    fn handle_key(&mut self, buffer_view: Arc<Mutex<BufferView>>, key: MKey, modifier: MModifiers) -> Event
       +    {
       +        if self.selected_font < 0 || self.selected_font >= self.fonts.len() as i32 {
       +            return Event::None;
       +        }
       +        let font = &self.fonts[self.selected_font as usize];
       +        let editor= &mut buffer_view.lock().unwrap().editor;
       +        let pos = editor.caret.get_position();
        
       -            match key {
       -                MKey::Down => {
       -                    editor.set_caret(pos.x, pos.y + 1);
       -                }
       -                MKey::Up => {
       -                    editor.set_caret(pos.x, pos.y - 1);
       -                }
       -                MKey::Left => {
       -                    editor.set_caret(pos.x - 1, pos.y);
       -                }
       -                MKey::Right => {
       -                    editor.set_caret(pos.x + 1, pos.y);
       -                }
       +        match key {
       +            MKey::Down => {
       +                editor.set_caret(pos.x, pos.y + 1);
       +            }
       +            MKey::Up => {
       +                editor.set_caret(pos.x, pos.y - 1);
       +            }
       +            MKey::Left => {
       +                editor.set_caret(pos.x - 1, pos.y);
       +            }
       +            MKey::Right => {
       +                editor.set_caret(pos.x + 1, pos.y);
       +            }
        
       -                MKey::Home  => {
       -                    if let MModifiers::Control = modifier {
       -                        for i in 0..editor.buf.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;
       -                            }
       +            MKey::Home  => {
       +                if let MModifiers::Control = modifier {
       +                    for i in 0..editor.buf.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;
                                }
                            }
       -                    editor.set_caret(0, pos.y);
                        }
       +                editor.set_caret(0, pos.y);
       +            }
        
       -                MKey::End => {
       -                    if let MModifiers::Control = modifier {
       -                        for i in (0..editor.buf.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;
       -                            }
       +            MKey::End => {
       +                if let MModifiers::Control = modifier {
       +                    for i in (0..editor.buf.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;
       -                    editor.set_caret(w - 1, pos.y);
                        }
       +                let w = editor.buf.get_buffer_width() as i32;
       +                editor.set_caret(w - 1, pos.y);
       +            }
        
       -                MKey::Return => {
       -                    editor.set_caret(0,pos.y + font.get_font_height() as i32);
       -    /*
       -                    if let Some(size) = self.sizes.last() {
       -                        editor.set_caret(0,pos.y + size.height as i32);
       -                    } else {
       -                        editor.set_caret(0,pos.y + 1);
       -                    }*/
       -                    self.sizes.clear();
       -                }
       +            MKey::Return => {
       +                editor.set_caret(0,pos.y + font.get_font_height() as i32);
       +/*
       +                if let Some(size) = self.sizes.last() {
       +                    editor.set_caret(0,pos.y + size.height as i32);
       +                } else {
       +                    editor.set_caret(0,pos.y + 1);
       +                }*/
       +                self.sizes.clear();
       +            }
        
       -                MKey::Backspace => {
       -                    let letter_size= self.sizes.pop().unwrap_or_else(|| Size::from(1,1));
       -                    editor.cur_selection = None;
       -                    let pos = editor.get_caret_position();
       -                    if pos.x > 0 {
       -                        editor.set_caret_position(pos + Position::from(-(letter_size.width as i32), 0));
       -                        if editor.caret.insert_mode {
       -                            for i in pos.x..(editor.buf.width as i32 - (letter_size.width as i32)) {
       -                                let next = editor.get_char_from_cur_layer( Position::from(i + (letter_size.width as i32), pos.y));
       -                                editor.set_char(Position::from(i, pos.y), next);
       -                            }
       -                            let last_pos = Position::from(editor.buf.width as i32 - (letter_size.width as i32), pos.y);
       -                            editor.fill(Rectangle{ start: last_pos, size: letter_size }, Some(super::DosChar { char_code: b' ' as u16, attribute: TextAttribute::DEFAULT }));
       -                        } else {
       -                            let pos = editor.get_caret_position();
       -                            editor.fill(Rectangle{ start: pos, size: letter_size }, Some(super::DosChar { char_code: b' ' as u16, attribute: TextAttribute::DEFAULT }));
       +            MKey::Backspace => {
       +                let letter_size= self.sizes.pop().unwrap_or_else(|| Size::new(1,1));
       +                editor.cur_selection = None;
       +                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.caret.insert_mode {
       +                        for i in pos.x..(editor.buf.get_buffer_width() as i32 - (letter_size.width as i32)) {
       +                            let next = editor.get_char_from_cur_layer( Position::new(i + (letter_size.width as i32), pos.y));
       +                            editor.set_char(Position::new(i, pos.y), next);
                                }
       +                        let last_pos = Position::new(editor.buf.get_buffer_width() as i32 - (letter_size.width as i32), pos.y);
       +                        editor.fill(Rectangle { start: last_pos, size: letter_size }, Some(super::AttributedChar::new(' ', TextAttribute::default())));
       +                    } else {
       +                        let pos = editor.get_caret_position();
       +                        editor.fill(Rectangle{ start: pos, size: letter_size }, Some(super::AttributedChar::new(' ', TextAttribute::default())));
                            }
                        }
       +            }
        
       -                MKey::Character(ch) => {
       -                    let c_pos = editor.get_caret_position();
       -                    editor.begin_atomic_undo();
       -                    let attr = editor.caret.get_attribute();
       -                    let opt_size = font.render(&mut editor, c_pos, attr, ch as u8);
       -                    if let Some(size) = opt_size  {
       -                        editor.set_caret(c_pos.x + size.width as i32 + font.spaces, c_pos.y);
       -                        let new_pos = editor.get_caret_position();
       -                        self.sizes.push(Size { width: (new_pos.x - c_pos.x), height: size.height });
       -                    } else {
       -                        editor.type_key(ch);
       -                        self.sizes.push(Size::from(1, 1));
       -                    }
       -                    editor.end_atomic_undo();
       +            MKey::Character(ch) => {
       +                let c_pos = editor.get_caret_position();
       +                editor.begin_atomic_undo();
       +                let attr = editor.caret.get_attribute();
       +                let opt_size = font.render(&mut editor.buf, 0, c_pos, attr, 0, ch as u8);
       +                if let Some(size) = opt_size  {
       +                    editor.set_caret(c_pos.x + size.width as i32 + font.spaces, c_pos.y);
       +                    let new_pos = editor.get_caret_position();
       +                    self.sizes.push(Size { width: (new_pos.x - c_pos.x), height: size.height });
       +                } else {
       +                    editor.type_key(unsafe { char::from_u32_unchecked(ch as u32) });
       +                    self.sizes.push(Size::new(1, 1));
                        }
       -                _ => {}
       +                editor.end_atomic_undo();
                    }
       -            Event::None
       +            _ => {}
                }
       -
       -    */
       +        Event::None
       +    }
        }
   DIR diff --git a/src/model/tool/mod.rs b/src/model/tool/mod.rs
       @@ -105,197 +105,198 @@ pub trait Tool {
                buffer_opt: Option<std::sync::Arc<std::sync::Mutex<crate::ui::ansi_editor::BufferView>>>,
            );
        
       -    /*
       -        fn handle_key(&mut self, editor: Rc<RefCell<Editor>>, key: MKey, key_code: MKeyCode, modifier: MModifiers) -> Event
       -        {
       -            // TODO Keys:
       +    fn handle_key(&mut self, buffer_view: Arc<Mutex<BufferView>>, key: MKey, modifier: MModifiers) -> Event
       +    {
       +        // TODO Keys:
        
       -            // Tab - Next tab
       -            // Shift+Tab - Prev tab
       +        // Tab - Next tab
       +        // Shift+Tab - Prev tab
        
       -            // ctrl+pgup  - upper left corner
       -            // ctrl+pgdn  - lower left corner
       -            let pos = editor.borrow().get_caret_position();
       -            let mut editor = editor.borrow_mut();
       -            match key {
       -                MKey::Down => {
       -                    if let MModifiers::Control = modifier {
       -                        let fg = (editor.caret.get_attribute().get_foreground() + 14) % 16;
       -                        editor.caret.get_attribute().set_foreground(fg);
       -                    } else {
       -                        editor.set_caret(pos.x, pos.y + 1);
       -                    }
       -                }
       -                MKey::Up => {
       -                    if let MModifiers::Control = modifier {
       -                        let fg = (editor.caret.get_attribute().get_foreground() + 1) % 16;
       -                        editor.caret.get_attribute().set_foreground(fg);
       -                    } else {
       -                        editor.set_caret(pos.x, pos.y - 1);
       -                    }
       -                }
       -                MKey::Left => {
       -                    // TODO: ICE Colors
       -                    if let MModifiers::Control = modifier {
       -                        let bg = (editor.caret.get_attribute().get_background() + 7) % 8;
       -                        editor.caret.get_attribute().set_background(bg);
       -                    } else {
       -                        editor.set_caret(pos.x - 1, pos.y);
       -                    }
       +        // ctrl+pgup  - upper left corner
       +        // ctrl+pgdn  - lower left corner
       +        let editor: &mut Editor = &mut buffer_view.lock().unwrap().editor;
       +        let pos = editor.caret.get_position();
       +        match key {
       +            MKey::Down => {
       +                if let MModifiers::Control = modifier {
       +                    let fg = (editor.caret.get_attribute().get_foreground() + 14) % 16;
       +                    editor.caret.get_attribute().set_foreground(fg);
       +                } else {
       +                    editor.set_caret(pos.x, pos.y + 1);
                        }
       -                MKey::Right => {
       -                    // TODO: ICE Colors
       -                    if let MModifiers::Control = modifier {
       -                        let bg = (editor.caret.get_attribute().get_background() + 1) % 8;
       -                        editor.caret.get_attribute().set_background(bg);
       -                    } else {
       -                        editor.set_caret(pos.x + 1, pos.y);
       -                    }
       +            }
       +            MKey::Up => {
       +                if let MModifiers::Control = modifier {
       +                    let fg = (editor.caret.get_attribute().get_foreground() + 1) % 16;
       +                    editor.caret.get_attribute().set_foreground(fg);
       +                } else {
       +                    editor.set_caret(pos.x, pos.y - 1);
                        }
       -                MKey::PageDown => {
       -                    // TODO
       -                    println!("pgdn");
       +            }
       +            MKey::Left => {
       +                // TODO: ICE Colors
       +                if let MModifiers::Control = modifier {
       +                    let bg = (editor.caret.get_attribute().get_background() + 7) % 8;
       +                    editor.caret.get_attribute().set_background(bg);
       +                } else {
       +                    editor.set_caret(pos.x - 1, pos.y);
                        }
       -                MKey::PageUp => {
       -                    // TODO
       -                    println!("pgup");
       +            }
       +            MKey::Right => {
       +                // TODO: ICE Colors
       +                if let MModifiers::Control = modifier {
       +                    let bg = (editor.caret.get_attribute().get_background() + 1) % 8;
       +                    editor.caret.get_attribute().set_background(bg);
       +                } else {
       +                    editor.set_caret(pos.x + 1, pos.y);
                        }
       -
       -                MKey::Tab => {
       -                    let tab_size = unsafe { crate::WORKSPACE.settings.tab_size } ;
       -                    if let MModifiers::Control = modifier {
       -                        let tabs = max(0, (pos.x / tab_size) - 1);
       -                        let next_tab = tabs * tab_size;
       -                        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);
       -                        editor.set_caret(next_tab, pos.y);
       -                    }
       +            }
       +            MKey::PageDown => {
       +                // TODO
       +                println!("pgdn");
       +            }
       +            MKey::PageUp => {
       +                // TODO
       +                println!("pgup");
       +            }
       +/* 
       +            MKey::Tab => {
       +                let tab_size = unsafe { crate::WORKSPACE.settings.tab_size } ;
       +                if let MModifiers::Control = modifier {
       +                    let tabs = max(0, (pos.x / tab_size) - 1);
       +                    let next_tab = tabs * tab_size;
       +                    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);
       +                    editor.set_caret(next_tab, pos.y);
                        }
       -                MKey::Home  => {
       -                    if let MModifiers::Control = modifier {
       -                        for i in 0..editor.buf.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;
       -                            }
       +            }
       +            MKey::Home  => {
       +                if let MModifiers::Control = modifier {
       +                    for i in 0..editor.buf.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;
                                }
                            }
       -                    editor.set_caret(0, pos.y);
                        }
       -                MKey::End => {
       -                    if let MModifiers::Control = modifier {
       -                        for i in (0..editor.buf.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;
       -                            }
       +                editor.set_caret(0, pos.y);
       +            }
       +            MKey::End => {
       +                if let MModifiers::Control = modifier {
       +                    for i in (0..editor.buf.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;
       -                    editor.set_caret(w - 1, pos.y);
       -                }
       -                MKey::Return => {
       -                    editor.set_caret(0,pos.y + 1);
                        }
       -                MKey::Delete => {
       -                    if editor.cur_selection.is_some() {
       -                        editor.delete_selection();
       -                    } else {
       -                        let pos = editor.get_caret_position();
       -                        for i in pos.x..(editor.buf.width as i32 - 1) {
       -                            let next = editor.get_char_from_cur_layer( Position::from(i + 1, pos.y));
       -                            editor.set_char(Position::from(i, pos.y), next);
       -                        }
       -                        let last_pos = Position::from(editor.buf.width as i32 - 1, pos.y);
       -                        editor.set_char(last_pos, None);
       +                let w = editor.buf.width as i32;
       +                editor.set_caret(w - 1, pos.y);
       +            }*/
       +            MKey::Return => {
       +                editor.set_caret(0,pos.y + 1);
       +            }
       +            MKey::Delete => {
       +                if editor.cur_selection.is_some() {
       +                    editor.delete_selection();
       +                } else {
       +                    let pos = editor.get_caret_position();
       +                    for i in pos.x..(editor.buf.get_buffer_width() as i32 - 1) {
       +                        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.buf.get_buffer_width() as i32 - 1, pos.y);
       +                    editor.set_char(last_pos, None);
                        }
       -                MKey::Insert => {
       -                    editor.caret.insert_mode = !editor.caret.insert_mode;
       -                }
       -                MKey::Backspace => {
       -                    editor.cur_selection = None;
       -                    let pos = editor.get_caret_position();
       -                    if pos.x> 0 {
       -                       /* if (caret.fontMode() && FontTyped && cpos > 0)  {
       -                            caret.getX() -= CursorPos[cpos] - 1;
       -                            for (a=0;a<=CursorPos[cpos];a++)
       -                            for (b=0;b<=FontLibrary::getInstance().maxY;b++) {
       -                                getCurrentBuffer()->getCharacter(caret.getLogicalY() + b, caret.getLogicalX()+a) = getUndoBuffer()->getCharacter(caret.getLogicalY() + b, caret.getLogicalX()+a);
       -                                getCurrentBuffer()->getAttribute(caret.getLogicalY() + b, caret.getLogicalX()+a) = getUndoBuffer()->getAttribute(caret.getLogicalY() + b, caret.getLogicalX()+a);
       -                            }
       -                            cpos--;
       -                        } else {*/
       -                            editor.set_caret_position(pos + Position::from(-1, 0));
       -                        if editor.caret.insert_mode {
       -                            for i in pos.x..(editor.buf.width as i32 - 1) {
       -                                let next = editor.get_char_from_cur_layer( Position::from(i + 1, pos.y));
       -                                editor.set_char(Position::from(i, pos.y), next);
       -                            }
       -                            let last_pos = Position::from(editor.buf.width as i32 - 1, pos.y);
       -                            editor.set_char(last_pos, None);
       -                        } else  {
       -                            let pos = editor.get_caret_position();
       -                            editor.set_char(pos, None);
       +            }
       +            MKey::Insert => {
       +                editor.caret.insert_mode = !editor.caret.insert_mode;
       +            }
       +            MKey::Backspace => {
       +                editor.cur_selection = None;
       +                let pos = editor.get_caret_position();
       +                if pos.x> 0 {
       +                    /* if (caret.fontMode() && FontTyped && cpos > 0)  {
       +                        caret.getX() -= CursorPos[cpos] - 1;
       +                        for (a=0;a<=CursorPos[cpos];a++)
       +                        for (b=0;b<=FontLibrary::getInstance().maxY;b++) {
       +                            getCurrentBuffer()->getCharacter(caret.getLogicalY() + b, caret.getLogicalX()+a) = getUndoBuffer()->getCharacter(caret.getLogicalY() + b, caret.getLogicalX()+a);
       +                            getCurrentBuffer()->getAttribute(caret.getLogicalY() + b, caret.getLogicalX()+a) = getUndoBuffer()->getAttribute(caret.getLogicalY() + b, caret.getLogicalX()+a);
                                }
       +                        cpos--;
       +                    } else {*/
       +                        editor.set_caret_position(pos + Position::new(-1, 0));
       +                    if editor.caret.insert_mode {
       +                        for i in pos.x..(editor.buf.get_buffer_width() as i32 - 1) {
       +                            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.buf.get_buffer_width() as i32 - 1, pos.y);
       +                        editor.set_char(last_pos, None);
       +                    } else  {
       +                        let pos = editor.get_caret_position();
       +                        editor.set_char(pos, None);
                            }
                        }
       +            }
        
       -                MKey::Character(ch) => {
       -                    editor.cur_selection = None;
       -                    if let MModifiers::Alt = modifier {
       -                        match key_code {
       -                            MKeyCode::KeyI => editor.insert_line(pos.y),
       -                            MKeyCode::KeyU => editor.pickup_color(pos),
       -                            MKeyCode::KeyY => editor.delete_line(pos.y),
       -                            MKeyCode::Unknown => {}
       -                        }
       -                        return Event::None;
       +            MKey::Character(ch) => {
       +                editor.cur_selection = None;
       +        /*        if let MModifiers::Alt = modifier {
       +                    match key_code {
       +                        MKeyCode::KeyI => editor.insert_line(pos.y),
       +                        MKeyCode::KeyU => editor.pickup_color(pos),
       +                        MKeyCode::KeyY => editor.delete_line(pos.y),
       +                        MKeyCode::Unknown => {}
                            }
       +                    return Event::None;
       +                }*/
        
       -                    editor.type_key(ch);
       -                }
       +                println!("{} - {}", ch, unsafe { char::from_u32_unchecked(ch as u32) });
        
       -                MKey::F1 => {
       -                    handle_outline_insertion(&mut editor, modifier, 0);
       -                }
       -                MKey::F2 => {
       -                    handle_outline_insertion(&mut editor, modifier, 1);
       -                }
       -                MKey::F3 => {
       -                    handle_outline_insertion(&mut editor, modifier, 2);
       -                }
       -                MKey::F4 => {
       -                    handle_outline_insertion(&mut editor, modifier, 3);
       -                }
       -                MKey::F5 => {
       -                    handle_outline_insertion(&mut editor, modifier, 4);
       -                }
       -                MKey::F6 => {
       -                    handle_outline_insertion(&mut editor, modifier, 5);
       -                }
       -                MKey::F7 => {
       -                    handle_outline_insertion(&mut editor, modifier, 6);
       -                }
       -                MKey::F8 => {
       -                    handle_outline_insertion(&mut editor, modifier, 7);
       -                }
       -                MKey::F9 => {
       -                    handle_outline_insertion(&mut editor, modifier, 8);
       -                }
       -                MKey::F10 => {
       -                    handle_outline_insertion(&mut editor, modifier, 9);
       -                }
       -                MKey::Escape => {
       -                    editor.cur_selection = None;
       -                }
       -                _ => {}
       +                editor.type_key(unsafe { char::from_u32_unchecked(ch as u32) });
       +            }
       + 
       +            MKey::F1 => {
       +                handle_outline_insertion(editor, modifier, 0);
                    }
       -            Event::None
       +            MKey::F2 => {
       +                handle_outline_insertion(editor, modifier, 1);
       +            }
       +            MKey::F3 => {
       +                handle_outline_insertion(editor, modifier, 2);
       +            }
       +            MKey::F4 => {
       +                handle_outline_insertion(editor, modifier, 3);
       +            }
       +            MKey::F5 => {
       +                handle_outline_insertion(editor, modifier, 4);
       +            }
       +            MKey::F6 => {
       +                handle_outline_insertion(editor, modifier, 5);
       +            }
       +            MKey::F7 => {
       +                handle_outline_insertion(editor, modifier, 6);
       +            }
       +            MKey::F8 => {
       +                handle_outline_insertion(editor, modifier, 7);
       +            }
       +            MKey::F9 => {
       +                handle_outline_insertion(editor, modifier, 8);
       +            }
       +            MKey::F10 => {
       +                handle_outline_insertion(editor, modifier, 9);
       +            }
       +            MKey::Escape => {
       +                editor.cur_selection = None;
       +            }
       +            _ => {}
                }
       -    */
       +        Event::None
       +    }
       +
            fn handle_click(
                &mut self,
                _buffer_view: Arc<Mutex<BufferView>>,
       @@ -331,8 +332,8 @@ pub trait Tool {
            }
        }
        
       -/*
       -fn handle_outline_insertion(editor: &mut RefMut<Editor>, modifier: MModifiers, outline: i32) {
       +
       +fn handle_outline_insertion(editor: &mut Editor, modifier: MModifiers, outline: i32) {
            if let MModifiers::Control = modifier {
                editor.set_cur_outline(outline);
                return;
       @@ -347,9 +348,9 @@ fn handle_outline_insertion(editor: &mut RefMut<Editor>, modifier: MModifiers, o
            editor.cur_selection = None;
            let ch = editor.get_outline_char_code(outline);
            if let Ok(ch) = ch {
       -        editor.type_key(ch);
       +        editor.type_key(unsafe { char::from_u32_unchecked(ch as u32) });
            }
       -} */
       +} 
        
        #[derive(Clone, Copy, Debug, PartialEq)]
        pub enum DrawMode {
   DIR diff --git a/src/ui/ansi_editor/key_maps.rs b/src/ui/ansi_editor/key_maps.rs
       @@ -1,67 +1,68 @@
        use eframe::egui::Key;
        
       +use crate::model::MKey;
       +
        pub const CTRL_MOD: u32 = 0b1000_0000_0000_0000_0000;
        pub const SHIFT_MOD: u32 = 0b0100_0000_0000_0000_0000;
        
       -pub static ANSI_KEY_MAP: &[(u32, &[u8])] = &[
       -    (Key::Escape as u32, &[0x1B]),
       -    (Key::Home as u32, b"\x1b[H"),
       -    (Key::Insert as u32, b"\x1b[@"),
       -    (Key::Backspace as u32, &[8]),
       -    (Key::Enter as u32, &[b'\r']),
       -    (Key::Tab as u32, &[9]),
       -    (Key::Tab as u32 | SHIFT_MOD, b"\x1b[Z"),
       -    (Key::Delete as u32, &[127]),
       -    (Key::Insert as u32, b"\x1b[@"),
       -    (Key::End as u32, b"\x1b[K"),
       -    (Key::PageUp as u32, b"\x1b[V"),
       -    (Key::PageDown as u32, b"\x1b[U"),
       -    (Key::F1 as u32, b"\x1b[OP"),
       -    (Key::F2 as u32, b"\x1b[OQ"),
       -    (Key::F3 as u32, b"\x1b[OR"),
       -    (Key::F4 as u32, b"\x1b[OS"),
       -    (Key::F5 as u32, b"\x1b[OT"),
       -    (Key::F6 as u32, b"\x1b[17~"),
       -    (Key::F7 as u32, b"\x1b[18~"),
       -    (Key::F8 as u32, b"\x1b[19~"),
       -    (Key::F9 as u32, b"\x1b[20~"),
       -    (Key::F10 as u32, b"\x1b[21~"),
       -    (Key::F11 as u32, b"\x1b[23~"),
       -    (Key::F12 as u32, b"\x1b[24~"),
       -    (Key::ArrowUp as u32, b"\x1b[A"),
       -    (Key::ArrowDown as u32, b"\x1b[B"),
       -    (Key::ArrowRight as u32, b"\x1b[C"),
       -    (Key::ArrowLeft as u32, b"\x1b[D"),
       -    (Key::A as u32 | CTRL_MOD, &[1]),
       -    (Key::B as u32 | CTRL_MOD, &[2]),
       -    (Key::C as u32 | CTRL_MOD, &[3]),
       -    (Key::D as u32 | CTRL_MOD, &[4]),
       -    (Key::E as u32 | CTRL_MOD, &[5]),
       -    (Key::F as u32 | CTRL_MOD, &[6]),
       -    (Key::G as u32 | CTRL_MOD, &[7]),
       -    (Key::H as u32 | CTRL_MOD, &[8]),
       -    (Key::I as u32 | CTRL_MOD, &[9]),
       -    (Key::J as u32 | CTRL_MOD, &[10]),
       -    (Key::K as u32 | CTRL_MOD, &[11]),
       -    (Key::L as u32 | CTRL_MOD, &[12]),
       -    (Key::M as u32 | CTRL_MOD, &[13]),
       -    (Key::N as u32 | CTRL_MOD, &[14]),
       -    (Key::O as u32 | CTRL_MOD, &[15]),
       -    (Key::P as u32 | CTRL_MOD, &[16]),
       -    (Key::Q as u32 | CTRL_MOD, &[17]),
       -    (Key::R as u32 | CTRL_MOD, &[18]),
       -    (Key::S as u32 | CTRL_MOD, &[19]),
       -    (Key::T as u32 | CTRL_MOD, &[20]),
       -    (Key::U as u32 | CTRL_MOD, &[21]),
       -    (Key::V as u32 | CTRL_MOD, &[22]),
       -    (Key::W as u32 | CTRL_MOD, &[23]),
       -    (Key::X as u32 | CTRL_MOD, &[24]),
       -    (Key::Y as u32 | CTRL_MOD, &[25]),
       -    (Key::Z as u32 | CTRL_MOD, &[26]),
       -    (Key::Num2 as u32 | CTRL_MOD, &[0]),
       -    (Key::Num3 as u32 | CTRL_MOD, &[0x1B]),
       -    (Key::Num4 as u32 | CTRL_MOD, &[0x1C]),
       -    (Key::Num5 as u32 | CTRL_MOD, &[0x1D]),
       -    (Key::Num6 as u32 | CTRL_MOD, &[0x1E]),
       -    (Key::Num7 as u32 | CTRL_MOD, &[0x1F]),
       -];
       +pub static ANSI_KEY_MAP: &[(u32, MKey)] = &[
       +    (Key::Escape as u32, MKey::Escape),
       +    (Key::Home as u32, MKey::Home),
       +    (Key::Insert as u32, MKey::Insert),
       +    (Key::Backspace as u32, MKey::Backspace),
       +    (Key::Enter as u32, MKey::Return),
       +    (Key::Tab as u32, MKey::Tab),
       +    (Key::Delete as u32, MKey::Delete),
       +    (Key::End as u32, MKey::End),
       +    (Key::PageUp as u32, MKey::PageUp),
       +    (Key::PageDown as u32, MKey::PageDown),
       +    (Key::F1 as u32, MKey::F1),
       +    (Key::F2 as u32, MKey::F2),
       +    (Key::F3 as u32, MKey::F3),
       +    (Key::F4 as u32, MKey::F4),
       +    (Key::F5 as u32, MKey::F5),
       +    (Key::F6 as u32, MKey::F6),
       +    (Key::F7 as u32, MKey::F7),
       +    (Key::F8 as u32, MKey::F8),
       +    (Key::F9 as u32, MKey::F9),
       +    (Key::F10 as u32, MKey::F10),
       +    (Key::F11 as u32, MKey::F11),
       +    (Key::F12 as u32, MKey::F12),
       +    (Key::ArrowUp as u32, MKey::Up),
       +    (Key::ArrowDown as u32, MKey::Down),
       +    (Key::ArrowRight as u32, MKey::Right),
       +    (Key::ArrowLeft as u32, MKey::Left),
       +    
       +    (Key::A as u32 | CTRL_MOD, MKey::Character(1)),
       +    (Key::B as u32 | CTRL_MOD, MKey::Character(2)),
       +    (Key::C as u32 | CTRL_MOD, MKey::Character(3)),
       +    (Key::D as u32 | CTRL_MOD, MKey::Character(4)),
       +    (Key::E as u32 | CTRL_MOD, MKey::Character(5)),
       +    (Key::F as u32 | CTRL_MOD, MKey::Character(6)),
       +    (Key::G as u32 | CTRL_MOD, MKey::Character(7)),
       +    (Key::H as u32 | CTRL_MOD, MKey::Character(8)),
       +    (Key::I as u32 | CTRL_MOD, MKey::Character(9)),
       +    (Key::J as u32 | CTRL_MOD, MKey::Character(10)),
       +    (Key::K as u32 | CTRL_MOD, MKey::Character(11)),
       +    (Key::L as u32 | CTRL_MOD, MKey::Character(12)),
       +    (Key::M as u32 | CTRL_MOD, MKey::Character(13)),
       +    (Key::N as u32 | CTRL_MOD, MKey::Character(14)),
       +    (Key::O as u32 | CTRL_MOD, MKey::Character(15)),
       +    (Key::P as u32 | CTRL_MOD, MKey::Character(16)),
       +    (Key::Q as u32 | CTRL_MOD, MKey::Character(17)),
       +    (Key::R as u32 | CTRL_MOD, MKey::Character(18)),
       +    (Key::S as u32 | CTRL_MOD, MKey::Character(19)),
       +    (Key::T as u32 | CTRL_MOD, MKey::Character(20)),
       +    (Key::U as u32 | CTRL_MOD, MKey::Character(21)),
       +    (Key::V as u32 | CTRL_MOD, MKey::Character(22)),
       +    (Key::W as u32 | CTRL_MOD, MKey::Character(23)),
       +    (Key::X as u32 | CTRL_MOD, MKey::Character(24)),
       +    (Key::Y as u32 | CTRL_MOD, MKey::Character(25)),
       +    (Key::Z as u32 | CTRL_MOD, MKey::Character(26)),
       +    (Key::Num2 as u32 | CTRL_MOD, MKey::Character(0)),
       +    (Key::Num3 as u32 | CTRL_MOD, MKey::Character(0x1B)),
       +    (Key::Num4 as u32 | CTRL_MOD, MKey::Character(0x1C)),
       +    (Key::Num5 as u32 | CTRL_MOD, MKey::Character(0x1D)),
       +    (Key::Num6 as u32 | CTRL_MOD, MKey::Character(0x1E)),
       +    (Key::Num7 as u32 | CTRL_MOD, MKey::Character(0x1F))
       +];
       +\ No newline at end of file
   DIR diff --git a/src/ui/ansi_editor/mod.rs b/src/ui/ansi_editor/mod.rs
       @@ -24,7 +24,7 @@ pub mod key_maps;
        pub use key_maps::*;
        
        use crate::{
       -    model::{brush_imp::draw_glyph, Tool, DEFAULT_OUTLINE_TABLE},
       +    model::{brush_imp::draw_glyph, Tool, DEFAULT_OUTLINE_TABLE, MModifiers, MKey},
            Document, TerminalResult,
        };
        
       @@ -246,8 +246,12 @@ impl Document for AnsiEditor {
                                    egui::Event::Paste(text) => {
                                        self.output_string(&text);
                                    }
       +
                                    egui::Event::CompositionEnd(text) | egui::Event::Text(text) => {
       -                                self.output_string(&text);
       +                                for c in text.chars() {
       +                                    let buffer_view = self.buffer_view.clone();
       +                                    cur_tool.handle_key(buffer_view, MKey::Character(c as u16), MModifiers::None);
       +                                }
                                        response.mark_changed();
                                    }
        
       @@ -322,6 +326,7 @@ impl Document for AnsiEditor {
                                        }
                                    }
        
       +
                                    /*egui::Event::KeyRepeat { key, modifiers }
                                    | */
                                    egui::Event::Key {
       @@ -337,14 +342,19 @@ impl Document for AnsiEditor {
                                        if modifiers.shift {
                                            key_code |= SHIFT_MOD;
                                        }
       +
       +                                let mut modifier: MModifiers = MModifiers::None;
       +                                if modifiers.ctrl || modifiers.command {
       +                                    modifier = MModifiers::Control;
       +                                }
       +
       +                                if modifiers.shift {
       +                                    modifier = MModifiers::Shift;
       +                                }
                                        for (k, m) in ANSI_KEY_MAP {
                                            if *k == key_code {
       -                                        //self.handled_char = true;
       -                                        for c in *m {
       -                                            if let Err(err) = self.print_char(*c) {
       -                                                eprintln!("{}", err);
       -                                            }
       -                                        }
       +                                        let buffer_view = self.buffer_view.clone();
       +                                        cur_tool.handle_key(buffer_view, *m, modifier);
                                                response.mark_changed();
                                                ui.input_mut(|i| i.consume_key(*modifiers, *key));
                                                break;
       @@ -362,7 +372,6 @@ impl Document for AnsiEditor {
                                        ui.output_mut(|o| o.cursor_icon = CursorIcon::Text);
                                    }
                                }
       -
                            }
        
                            response.dragged = false;
   DIR diff --git a/src/ui/main_window.rs b/src/ui/main_window.rs
       @@ -155,6 +155,14 @@ impl MainWindow {
                    attr: icy_engine::TextAttribute::default(),
                }));
        
       +        let mut fnt = crate::model::font_imp::FontTool {
       +            selected_font: 0,
       +            fonts: Vec::new(),
       +            sizes: Vec::new()
       +        };
       +        fnt.load_fonts();
       +        tools.push(Box::new(fnt));
       +
                tools.push(Box::new(crate::model::move_layer_imp::MoveLayer {
                    pos: icy_engine::Position { x: 0, y: 0 },
                }));