URI: 
       mod.rs - 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
       ---
       mod.rs (32114B)
       ---
            1 use std::{
            2     cmp::{max, min},
            3     ffi::OsStr,
            4     fs::File,
            5     io::Write,
            6     path::{Path, PathBuf},
            7     sync::Arc,
            8 };
            9 
           10 use eframe::{
           11     egui::{self, Id, Key, Response},
           12     epaint::{mutex::Mutex, Vec2},
           13 };
           14 use i18n_embed_fl::fl;
           15 use icy_engine::{
           16     attribute,
           17     editor::{AtomicUndoGuard, UndoState},
           18     util::{pop_data, pop_sixel_image, push_data, BUFFER_DATA},
           19     AttributedChar, Buffer, EngineResult, Line, Position, Rectangle, SaveOptions, TextAttribute, TextPane,
           20 };
           21 
           22 use icy_engine_egui::{show_terminal_area, BufferView, CaretShape, TerminalCalc};
           23 
           24 use crate::{
           25     model::{DragPos, MKey, MModifiers, Tool},
           26     paint::ColorMode,
           27     ClipboardHandler, Commands, Document, DocumentOptions, Message, SavingError, TerminalResult, UndoHandler, SETTINGS,
           28 };
           29 
           30 pub enum Event {
           31     None,
           32     CursorPositionChange(Position, Position),
           33 }
           34 
           35 pub struct AnsiEditor {
           36     pub id: usize,
           37     pub drag_pos: DragPos,
           38     pub half_block_click_pos: Position,
           39     drag_started: bool,
           40     pub buffer_view: Arc<eframe::epaint::mutex::Mutex<BufferView>>,
           41     pub is_inactive: bool,
           42 
           43     pub outline_font_mode: bool,
           44     last_selected_tool: usize,
           45 
           46     pub reference_image: Option<PathBuf>,
           47     // pub outline_changed: std::boxed::Box<dyn Fn(&Editor)>,
           48     //pub request_refresh: Box<dyn Fn ()>,
           49     pub egui_id: Id,
           50     pub next_scroll_x_position: Option<f32>,
           51     pub next_scroll_y_position: Option<f32>,
           52     pub guide: Option<Vec2>,
           53     pub raster: Option<Vec2>, //pub pos_changed: std::boxed::Box<dyn Fn(&Editor, Position)>,
           54     //pub attr_changed: std::boxed::Box<dyn Fn(TextAttribute)>
           55     pub request_focus: bool,
           56     pub color_mode: ColorMode,
           57 }
           58 
           59 impl UndoHandler for AnsiEditor {
           60     fn undo_description(&self) -> Option<String> {
           61         self.buffer_view.lock().get_edit_state().undo_description()
           62     }
           63 
           64     fn can_undo(&self) -> bool {
           65         self.buffer_view.lock().get_edit_state().can_undo()
           66     }
           67 
           68     fn undo(&mut self) -> EngineResult<Option<Message>> {
           69         self.buffer_view.lock().get_edit_state_mut().undo()?;
           70         Ok(None)
           71     }
           72 
           73     fn redo_description(&self) -> Option<String> {
           74         self.buffer_view.lock().get_edit_state().redo_description()
           75     }
           76 
           77     fn can_redo(&self) -> bool {
           78         self.buffer_view.lock().get_edit_state().can_redo()
           79     }
           80 
           81     fn redo(&mut self) -> EngineResult<Option<Message>> {
           82         self.buffer_view.lock().get_edit_state_mut().redo()?;
           83         Ok(None)
           84     }
           85 }
           86 
           87 impl ClipboardHandler for AnsiEditor {
           88     fn can_cut(&self) -> bool {
           89         self.buffer_view.lock().get_selection().is_some()
           90     }
           91     fn cut(&mut self) -> EngineResult<()> {
           92         let _cut = self.begin_atomic_undo(fl!(crate::LANGUAGE_LOADER, "undo-cut"));
           93         self.copy()?;
           94         self.buffer_view.lock().get_edit_state_mut().erase_selection()?;
           95         Ok(())
           96     }
           97 
           98     fn can_copy(&self) -> bool {
           99         self.buffer_view.lock().get_selection().is_some()
          100     }
          101 
          102     fn copy(&mut self) -> EngineResult<()> {
          103         if let Some(data) = self.buffer_view.lock().get_edit_state_mut().get_clipboard_data() {
          104             push_data(BUFFER_DATA, &data)?;
          105         } else {
          106             log::error!("can't get clipboard data!");
          107         }
          108         Ok(())
          109     }
          110 
          111     fn can_paste(&self) -> bool {
          112         pop_data(BUFFER_DATA).is_some() || pop_sixel_image().is_some()
          113     }
          114 
          115     fn paste(&mut self) -> EngineResult<()> {
          116         if self.buffer_view.lock().get_edit_state_mut().has_floating_layer() {
          117             return Ok(());
          118         }
          119 
          120         if let Some(data) = pop_data(BUFFER_DATA) {
          121             self.buffer_view.lock().get_edit_state_mut().paste_clipboard_data(&data)?;
          122         } else if let Some(sixel) = pop_sixel_image() {
          123             self.buffer_view.lock().get_edit_state_mut().paste_sixel(sixel)?;
          124         }
          125         Ok(())
          126     }
          127 }
          128 const ICED_EXT: &str = "icy";
          129 
          130 impl Document for AnsiEditor {
          131     fn default_extension(&self) -> &'static str {
          132         ICED_EXT
          133     }
          134 
          135     fn undo_stack_len(&self) -> usize {
          136         if let Ok(stack) = self.buffer_view.lock().get_edit_state().get_undo_stack().lock() {
          137             for i in (0..stack.len()).rev() {
          138                 if stack[i].changes_data() {
          139                     return i + 1;
          140                 }
          141             }
          142         }
          143         0
          144     }
          145 
          146     fn get_bytes(&mut self, path: &Path) -> TerminalResult<Vec<u8>> {
          147         let ext = if let Some(ext) = path.extension() {
          148             OsStr::to_str(ext).unwrap_or(ICED_EXT).to_lowercase()
          149         } else {
          150             ICED_EXT.to_string()
          151         };
          152         let mut options = SaveOptions::new();
          153         options.compress = false;
          154         options.lossles_output = true;
          155         let bytes = self.buffer_view.lock().get_buffer().to_bytes(&ext, &options)?;
          156         Ok(bytes)
          157     }
          158 
          159     fn show_ui(&mut self, ui: &mut egui::Ui, cur_tool: &mut Box<dyn Tool>, selected_tool: usize, options: &DocumentOptions) -> Option<Message> {
          160         let mut message = None;
          161 
          162         // clear tool overlays on tool change
          163         if self.last_selected_tool != selected_tool {
          164             self.last_selected_tool = selected_tool;
          165             self.buffer_view.lock().get_edit_state_mut().get_tool_overlay_mask_mut().clear();
          166             self.buffer_view.lock().get_edit_state_mut().set_is_buffer_dirty();
          167         }
          168 
          169         let mut scale = unsafe { SETTINGS.get_scale() };
          170         let is_visible = cur_tool.use_caret(self);
          171         self.buffer_view.lock().get_caret_mut().set_is_visible(is_visible);
          172         if self.buffer_view.lock().get_buffer().use_aspect_ratio() {
          173             if self.buffer_view.lock().get_buffer().use_letter_spacing() {
          174                 scale.y *= 1.2;
          175             } else {
          176                 scale.y *= 1.35;
          177             }
          178         }
          179         let opt = icy_engine_egui::TerminalOptions {
          180             stick_to_bottom: false,
          181             scale: Some(scale),
          182             fit_width: options.fit_width,
          183             monitor_settings: unsafe { SETTINGS.monitor_settings.clone() },
          184             marker_settings: unsafe { SETTINGS.marker_settings.clone() },
          185             id: Some(Id::new(self.id + 10000)),
          186             raster: self.raster,
          187             guide: self.guide,
          188             scroll_offset_y: self.next_scroll_y_position.take(),
          189             scroll_offset_x: self.next_scroll_x_position.take(),
          190             show_layer_borders: unsafe { SETTINGS.show_layer_borders },
          191             show_line_numbers: unsafe { SETTINGS.show_line_numbers },
          192             request_focus: self.request_focus,
          193             caret_shape: CaretShape::Block,
          194             ..Default::default()
          195         };
          196         let (mut response, calc) = show_terminal_area(ui, self.buffer_view.clone(), opt);
          197 
          198         if calc.has_focus {
          199             self.request_focus = false;
          200         }
          201         let response_opt = response.context_menu(|ui| {
          202             message = terminal_context_menu(self, &options.commands, ui);
          203         });
          204         if let Some(response_opt) = response_opt {
          205             response = response_opt.response;
          206         }
          207         self.handle_response(ui, response, calc, cur_tool, &mut message);
          208 
          209         message
          210     }
          211 
          212     fn get_ansi_editor_mut(&mut self) -> Option<&mut AnsiEditor> {
          213         Some(self)
          214     }
          215 
          216     fn get_ansi_editor(&self) -> Option<&AnsiEditor> {
          217         Some(self)
          218     }
          219 
          220     fn destroy(&self, gl: &glow::Context) -> Option<Message> {
          221         self.buffer_view.lock().destroy(gl);
          222         None
          223     }
          224 }
          225 
          226 impl AnsiEditor {
          227     pub fn new(gl: &Arc<glow::Context>, id: usize, buf: Buffer) -> Self {
          228         let buffer_view = Arc::new(Mutex::new(BufferView::from_buffer(gl, buf)));
          229         // let buffer_parser = ansi::Parser::default();
          230         AnsiEditor {
          231             id,
          232             buffer_view,
          233             is_inactive: false,
          234             reference_image: None,
          235             drag_started: false,
          236             drag_pos: DragPos::default(),
          237             egui_id: Id::new(id),
          238             guide: None,
          239             raster: None,
          240             outline_font_mode: false,
          241             next_scroll_x_position: Some(0.0),
          242             next_scroll_y_position: Some(0.0),
          243             half_block_click_pos: Position::default(),
          244             last_selected_tool: 0,
          245             request_focus: false,
          246             color_mode: ColorMode::Both,
          247         }
          248     }
          249 
          250     pub fn get_cur_layer_index(&self) -> TerminalResult<usize> {
          251         self.buffer_view.lock().get_edit_state_mut().get_current_layer()
          252     }
          253 
          254     pub fn set_cur_layer_index(&self, layer: usize) {
          255         self.buffer_view.lock().get_edit_state_mut().set_current_layer(layer);
          256     }
          257 
          258     pub fn output_string(&mut self, str: &str) {
          259         for ch in str.chars() {
          260             self.type_key(ch);
          261         }
          262     }
          263 
          264     pub fn get_caret_position(&self) -> Position {
          265         self.buffer_view.lock().get_caret().get_position()
          266     }
          267 
          268     pub fn set_caret_position(&mut self, pos: Position) {
          269         let buffer_view = &mut self.buffer_view.lock();
          270         let pos = Position::new(
          271             min(buffer_view.get_width() - 1, max(0, pos.x)),
          272             min(buffer_view.get_buffer().get_height() - 1, max(0, pos.y)),
          273         );
          274         buffer_view.get_caret_mut().set_position(pos);
          275         buffer_view.reset_caret_blink();
          276         //(self.pos_changed)(self, pos);
          277     }
          278 
          279     pub fn set_caret_attribute(&mut self, attr: TextAttribute) {
          280         if attr == self.buffer_view.lock().get_caret().get_attribute() {
          281             return;
          282         }
          283 
          284         self.buffer_view.lock().get_caret_mut().set_attr(attr);
          285         // (self.attr_changed)(attr);
          286     }
          287 
          288     pub fn join_overlay(&mut self, description: impl Into<String>) {
          289         let _undo = self.begin_atomic_undo(description.into());
          290         let opt_layer = self.buffer_view.lock().get_buffer_mut().remove_overlay();
          291         let use_selection = self.buffer_view.lock().get_edit_state().is_something_selected();
          292 
          293         if let Some(layer) = &opt_layer {
          294             for y in 0..layer.lines.len() {
          295                 let line = &layer.lines[y];
          296                 for x in 0..line.chars.len() {
          297                     let ch = line.chars[x];
          298                     let pos = Position::new(x as i32, y as i32);
          299                     if ch.is_visible() && (!use_selection || self.buffer_view.lock().get_edit_state().get_is_selected(pos + layer.get_offset())) {
          300                         self.set_char(pos, ch);
          301                     }
          302                 }
          303             }
          304         }
          305     }
          306 
          307     pub fn delete_line(&mut self, line: i32) {
          308         // TODO: Undo
          309         let mut lock = self.buffer_view.lock();
          310         if let Ok(cur_layer) = self.get_cur_layer_index() {
          311             let layer = &mut lock.get_buffer_mut().layers[cur_layer];
          312             layer.remove_line(line);
          313         } else {
          314             log::error!("can't get current layer!");
          315         }
          316     }
          317 
          318     pub fn insert_line(&mut self, line: i32) {
          319         // TODO: Undo
          320         let mut binding = self.buffer_view.lock();
          321         if let Ok(cur_layer) = self.get_cur_layer_index() {
          322             let layer = &mut binding.get_buffer_mut().layers[cur_layer];
          323             layer.insert_line(line, Line::new());
          324         } else {
          325             log::error!("can't get current layer!");
          326         }
          327     }
          328 
          329     pub fn pickup_color(&mut self, pos: Position) {
          330         let ch = self.buffer_view.lock().get_buffer().get_char(pos);
          331         if ch.is_visible() {
          332             self.buffer_view.lock().get_caret_mut().set_attr(ch.attribute);
          333         }
          334     }
          335 
          336     pub fn set_caret(&mut self, x: i32, y: i32) -> Event {
          337         let old = self.buffer_view.lock().get_caret().get_position();
          338         let mut w = self.buffer_view.lock().get_buffer().get_width() - 1;
          339         let mut h = self.buffer_view.lock().get_buffer().get_height() - 1;
          340         let offset: Position = if let Some(layer) = self.buffer_view.lock().get_edit_state().get_cur_layer() {
          341             w = layer.get_width() - 1;
          342             h = layer.get_height() - 1;
          343             layer.get_offset()
          344         } else {
          345             Position::default()
          346         };
          347 
          348         let char_scroll_position = self.buffer_view.lock().calc.char_scroll_position;
          349         let terminal_rect = self.buffer_view.lock().calc.terminal_rect;
          350         let terminal_width = terminal_rect.width();
          351         let terminal_height = terminal_rect.height();
          352         let rect = self.buffer_view.lock().calc.buffer_rect;
          353         let buffer_width = rect.width().min(terminal_width);
          354         let buffer_height = rect.height().min(terminal_height);
          355         let buffer_char_width = buffer_width / self.buffer_view.lock().calc.scale.x;
          356         let buffer_char_height = buffer_height / self.buffer_view.lock().calc.scale.y;
          357 
          358         let y = min(max(0, y), h);
          359         self.set_caret_position(Position::new(min(max(0, x), w), y));
          360 
          361         let font_dim = self.buffer_view.lock().get_buffer().get_font_dimensions();
          362 
          363         let pos = self.buffer_view.lock().get_caret().get_position();
          364         let x = (offset.x + pos.x) as f32 * font_dim.width as f32;
          365         let y = (offset.y + pos.y) as f32 * font_dim.height as f32;
          366         let mut next_y = None;
          367         let mut next_x = None;
          368         if y < char_scroll_position.y {
          369             next_y = Some(y);
          370         }
          371         if x < char_scroll_position.x {
          372             next_x = Some(x);
          373         }
          374         if y > (char_scroll_position.y + buffer_char_height - font_dim.height as f32) {
          375             next_y = Some((y - buffer_char_height + font_dim.height as f32).max(0.0));
          376         }
          377         if x > (char_scroll_position.x + buffer_char_width - font_dim.width as f32) {
          378             next_x = Some((x - buffer_char_width + font_dim.width as f32).max(0.0));
          379         }
          380         self.next_scroll_x_position = next_x;
          381         self.next_scroll_y_position = next_y;
          382         Event::CursorPositionChange(old, self.buffer_view.lock().get_caret().get_position())
          383     }
          384 
          385     pub fn save_content(&self, file_name: &Path, options: &SaveOptions) -> EngineResult<bool> {
          386         match File::create(file_name) {
          387             Ok(mut f) => {
          388                 let content = if let Some(ext) = file_name.extension() {
          389                     let ext = OsStr::to_string_lossy(ext).to_lowercase();
          390                     self.buffer_view.lock().get_buffer().to_bytes(ext.as_str(), options)?
          391                 } else {
          392                     self.buffer_view.lock().get_buffer().to_bytes(ICED_EXT, options)?
          393                 };
          394                 if let Err(err) = f.write_all(&content) {
          395                     return Err(SavingError::ErrorWritingFile(format!("{err}")).into());
          396                 }
          397             }
          398             Err(err) => {
          399                 return Err(SavingError::ErrorCreatingFile(format!("{err}")).into());
          400             }
          401         }
          402 
          403         Ok(true)
          404     }
          405 
          406     pub fn get_char_set_key(&self, i: usize) -> char {
          407         unsafe {
          408             let lock = self.buffer_view.lock();
          409             let font_page = lock.get_caret().get_font_page();
          410 
          411             let checksum = if let Some(font) = lock.get_buffer().get_font(font_page) {
          412                 font.get_checksum()
          413             } else {
          414                 0
          415             };
          416 
          417             SETTINGS.get_character_set_char(checksum, i)
          418         }
          419     }
          420 
          421     pub fn type_char_set_key(&mut self, character_set: usize) {
          422         self.buffer_view.lock().clear_selection();
          423         let ch = self.get_char_set_key(character_set);
          424         self.type_key(unsafe { char::from_u32_unchecked(ch as u32) });
          425     }
          426 
          427     pub fn get_char(&self, pos: Position) -> AttributedChar {
          428         self.buffer_view.lock().get_buffer().get_char(pos)
          429     }
          430 
          431     pub fn get_char_from_cur_layer(&self, pos: Position) -> AttributedChar {
          432         if let Ok(cur_layer) = self.get_cur_layer_index() {
          433             if cur_layer >= self.buffer_view.lock().get_buffer().layers.len() {
          434                 return AttributedChar::invisible();
          435             }
          436             self.buffer_view.lock().get_buffer().layers[cur_layer].get_char(pos)
          437         } else {
          438             log::error!("can't get current layer!");
          439             AttributedChar::invisible()
          440         }
          441     }
          442 
          443     pub fn set_char(&mut self, pos: impl Into<Position>, attributed_char: AttributedChar) {
          444         let _ = self.buffer_view.lock().get_edit_state_mut().set_char(pos, attributed_char);
          445     }
          446 
          447     #[must_use]
          448     pub fn begin_atomic_undo(&mut self, description: impl Into<String>) -> AtomicUndoGuard {
          449         self.buffer_view.lock().get_edit_state_mut().begin_atomic_undo(description.into())
          450     }
          451 
          452     pub fn fill(&mut self, rect: Rectangle, dos_char: AttributedChar) {
          453         let mut pos = rect.start;
          454         let _undo = self.begin_atomic_undo("Fill");
          455         for _ in 0..rect.size.height {
          456             for _ in 0..rect.size.width {
          457                 self.set_char(pos, dos_char);
          458                 pos.x += 1;
          459             }
          460             pos.y += 1;
          461             pos.x = rect.start.x;
          462         }
          463     }
          464 
          465     pub fn type_key(&mut self, char_code: char) {
          466         let pos = self.buffer_view.lock().get_caret().get_position();
          467         self.buffer_view.lock().clear_selection();
          468         if self.buffer_view.lock().get_caret().insert_mode {
          469             let end = self.buffer_view.lock().get_buffer().get_width();
          470             for i in (pos.x..end).rev() {
          471                 let next = self.get_char_from_cur_layer(Position::new(i - 1, pos.y));
          472                 self.set_char(Position::new(i, pos.y), next);
          473             }
          474         }
          475         let mut attr = self.get_char(pos).attribute;
          476         let caret_attr = self.buffer_view.lock().get_caret().get_attribute();
          477         attr.set_font_page(caret_attr.get_font_page());
          478         attr.attr = caret_attr.attr & !attribute::INVISIBLE;
          479         if self.color_mode.use_fore() {
          480             attr.set_foreground(caret_attr.get_foreground());
          481         }
          482         if self.color_mode.use_back() {
          483             attr.set_background(caret_attr.get_background());
          484         }
          485 
          486         self.set_char(pos, AttributedChar::new(char_code, attr));
          487         self.set_caret(pos.x + 1, pos.y);
          488         self.request_focus = true;
          489     }
          490 
          491     pub fn switch_fg_bg_color(&mut self) {
          492         let mut attr = self.buffer_view.lock().get_caret().get_attribute();
          493         let bg = attr.get_background();
          494         attr.set_background(attr.get_foreground());
          495         attr.set_foreground(bg);
          496         self.set_caret_attribute(attr);
          497     }
          498 
          499     pub fn erase_line(&mut self) {
          500         let _undo = self.begin_atomic_undo("Erase line");
          501         // TODO
          502     }
          503 
          504     pub fn erase_line_to_start(&mut self) {
          505         let _undo = self.begin_atomic_undo("Erase line to start");
          506         // TODO
          507     }
          508 
          509     pub fn erase_line_to_end(&mut self) {
          510         let _undo = self.begin_atomic_undo("Erase line to end");
          511         // TODO
          512     }
          513 
          514     pub fn erase_column(&mut self) {
          515         let _undo = self.begin_atomic_undo("Erase column");
          516         // TODO
          517     }
          518 
          519     pub fn erase_column_to_start(&mut self) {
          520         let _undo = self.begin_atomic_undo("Erase column to start");
          521         // TODO
          522     }
          523 
          524     pub fn erase_column_to_end(&mut self) {
          525         let _undo = self.begin_atomic_undo("Erase column to end");
          526         // TODO
          527     }
          528 
          529     pub fn delete_row(&mut self) {
          530         let _undo = self.begin_atomic_undo("Delete row");
          531         // TODO
          532     }
          533 
          534     pub fn insert_row(&mut self) {
          535         let _undo = self.begin_atomic_undo("Insert row");
          536         // TODO
          537     }
          538 
          539     pub fn delete_column(&mut self) {
          540         let _undo = self.begin_atomic_undo("Delete column");
          541         // TODO
          542     }
          543 
          544     pub fn insert_column(&mut self) {
          545         let _undo = self.begin_atomic_undo("Insert column");
          546         // TODO
          547     }
          548 
          549     fn handle_response(
          550         &mut self,
          551         ui: &egui::Ui,
          552         mut response: Response,
          553         calc: TerminalCalc,
          554         cur_tool: &mut Box<dyn Tool>,
          555         message: &mut Option<Message>,
          556     ) -> Response {
          557         if response.has_focus() {
          558             let events = ui.input(|i| i.events.clone());
          559             for e in &events {
          560                 match e {
          561                     egui::Event::Copy => {}
          562                     egui::Event::Cut => {}
          563                     egui::Event::Paste(text) => {
          564                         self.output_string(text);
          565                     }
          566 
          567                     egui::Event::CompositionEnd(text) | egui::Event::Text(text) => {
          568                         if !ui.input(|i| i.modifiers.ctrl || i.modifiers.command || i.modifiers.alt) {
          569                             for c in text.chars() {
          570                                 cur_tool.handle_key(self, MKey::Character(c as u16), MModifiers::None);
          571                             }
          572                         }
          573                     }
          574 
          575                     egui::Event::Key {
          576                         key, pressed: true, modifiers, ..
          577                     } => {
          578                         let mut key_code = *key as u32;
          579                         if modifiers.shift {
          580                             key_code |= SHIFT_MOD;
          581                         }
          582 
          583                         let mut modifier: MModifiers = MModifiers::None;
          584                         if modifiers.ctrl || modifiers.command {
          585                             modifier = MModifiers::Control;
          586                         }
          587 
          588                         if modifiers.shift {
          589                             modifier = MModifiers::Shift;
          590                         }
          591 
          592                         if modifiers.alt {
          593                             modifier = MModifiers::Alt;
          594                         }
          595                         for (k, m) in EDITOR_KEY_MAP {
          596                             if *k == key_code {
          597                                 cur_tool.handle_key(self, *m, modifier);
          598                                 break;
          599                             }
          600                         }
          601                     }
          602                     _ => {}
          603                 }
          604             }
          605         }
          606 
          607         if response.clicked_by(egui::PointerButton::Primary) {
          608             if let Some(mouse_pos) = response.hover_pos() {
          609                 if calc.buffer_rect.contains(mouse_pos) && !calc.vert_scrollbar_rect.contains(mouse_pos) && !calc.horiz_scrollbar_rect.contains(mouse_pos) {
          610                     let click_pos = calc.calc_click_pos(mouse_pos);
          611                     let cp_abs = Position::new(click_pos.x as i32, click_pos.y as i32);
          612                     let layer_offset = self.get_cur_click_offset();
          613                     let cp = cp_abs - layer_offset;
          614                     let click_pos2 = calc.calc_click_pos_half_block(mouse_pos);
          615                     self.half_block_click_pos = Position::new(click_pos2.x as i32 - layer_offset.x, click_pos2.y as i32 - layer_offset.y);
          616 
          617                     /*
          618                     let b: i32 = match responsee.b {
          619                                      PointerButton::Primary => 1,
          620                                      PointerButton::Secondary => 2,
          621                                      PointerButton::Middle => 3,
          622                                      PointerButton::Extra1 => 4,
          623                                      PointerButton::Extra2 => 5,
          624                                  }; */
          625                     let msg = cur_tool.handle_click(self, 1, cp, cp_abs, &response);
          626                     if message.is_none() {
          627                         *message = msg;
          628                     }
          629                 }
          630             }
          631         }
          632 
          633         if response.drag_started_by(egui::PointerButton::Primary) {
          634             if let Some(mouse_pos) = response.hover_pos() {
          635                 if calc.buffer_rect.contains(mouse_pos) && !calc.vert_scrollbar_rect.contains(mouse_pos) && !calc.horiz_scrollbar_rect.contains(mouse_pos) {
          636                     let click_pos = calc.calc_click_pos(mouse_pos);
          637                     let cp_abs = Position::new(click_pos.x as i32, click_pos.y as i32);
          638 
          639                     let layer_offset = self.get_cur_click_offset();
          640                     let cp = cp_abs - layer_offset;
          641                     let click_pos2 = calc.calc_click_pos_half_block(mouse_pos);
          642                     let click_pos2 = Position::new(click_pos2.x as i32, click_pos2.y as i32);
          643                     let half_block_layer_offset = Position::new(layer_offset.x, layer_offset.y * 2);
          644                     let half_block_click_pos = click_pos2 - half_block_layer_offset;
          645                     self.half_block_click_pos = half_block_click_pos;
          646 
          647                     self.drag_pos.start_abs = cp_abs;
          648                     self.drag_pos.start = cp;
          649 
          650                     self.drag_pos.cur_abs = cp_abs;
          651                     self.drag_pos.cur = cp;
          652                     self.drag_pos.start_half_block = half_block_click_pos;
          653                     self.drag_started = true;
          654 
          655                     cur_tool.handle_drag_begin(self, &response);
          656                 }
          657             }
          658         }
          659 
          660         if response.dragged_by(egui::PointerButton::Primary) && self.drag_started {
          661             if let Some(mouse_pos) = response.hover_pos() {
          662                 let layer_offset = self.get_cur_click_offset();
          663                 let click_pos2 = calc.calc_click_pos_half_block(mouse_pos);
          664                 let click_pos2 = Position::new(click_pos2.x as i32, click_pos2.y as i32);
          665 
          666                 let half_block_layer_offset = Position::new(layer_offset.x, layer_offset.y * 2);
          667                 let half_block_click_pos = click_pos2 - half_block_layer_offset;
          668 
          669                 let mut c_abs = self.half_block_click_pos;
          670                 while c_abs != half_block_click_pos {
          671                     let s = (half_block_click_pos - c_abs).signum();
          672                     c_abs += s;
          673                     self.half_block_click_pos = c_abs;
          674 
          675                     self.drag_pos.cur_abs = Position::new(c_abs.x, c_abs.y / 2) + layer_offset;
          676                     self.drag_pos.cur = self.drag_pos.cur_abs - layer_offset;
          677                     response = cur_tool.handle_drag(ui, response, self, &calc);
          678                 }
          679             }
          680         }
          681         if response.hovered() {
          682             if let Some(mouse_pos) = response.hover_pos() {
          683                 if calc.buffer_rect.contains(mouse_pos) && !calc.vert_scrollbar_rect.contains(mouse_pos) && !calc.horiz_scrollbar_rect.contains(mouse_pos) {
          684                     let click_pos = calc.calc_click_pos(mouse_pos);
          685                     let cp_abs = Position::new(click_pos.x as i32, click_pos.y as i32);
          686                     let cp = cp_abs - self.get_cur_click_offset();
          687                     response = cur_tool.handle_hover(ui, response, self, cp, cp_abs);
          688                 } else {
          689                     cur_tool.handle_no_hover(self);
          690                 }
          691             } else {
          692                 cur_tool.handle_no_hover(self);
          693             }
          694         } else {
          695             cur_tool.handle_no_hover(self);
          696         }
          697 
          698         if response.drag_released_by(egui::PointerButton::Primary) {
          699             let msg = cur_tool.handle_drag_end(self);
          700             if msg.is_some() {
          701                 *message = msg;
          702             }
          703 
          704             self.drag_started = false;
          705         }
          706 
          707         response
          708     }
          709 
          710     fn get_cur_click_offset(&mut self) -> Position {
          711         if let Some(layer) = self.buffer_view.lock().get_edit_state().get_cur_layer() {
          712             return layer.get_offset();
          713         }
          714         Position::default()
          715     }
          716 
          717     pub(crate) fn clear_overlay_layer(&self) {
          718         let cur_offset = self.buffer_view.lock().get_edit_state().get_cur_layer().unwrap().get_offset();
          719 
          720         if let Some(layer) = self.buffer_view.lock().get_edit_state_mut().get_overlay_layer() {
          721             layer.set_offset(cur_offset);
          722             layer.clear();
          723         }
          724         self.buffer_view.lock().get_edit_state_mut().set_is_buffer_dirty();
          725     }
          726 
          727     pub fn backspace(&mut self) {
          728         let _op: AtomicUndoGuard = self
          729             .buffer_view
          730             .lock()
          731             .get_edit_state_mut()
          732             .begin_atomic_undo(fl!(crate::LANGUAGE_LOADER, "undo-backspace"));
          733         self.buffer_view.lock().clear_selection();
          734         let pos = self.get_caret_position();
          735         if pos.x > 0 {
          736             self.set_caret_position(pos + Position::new(-1, 0));
          737             if self.buffer_view.lock().get_caret().insert_mode {
          738                 let end = self.buffer_view.lock().get_width() - 1;
          739                 for i in pos.x..end {
          740                     let next = self.get_char_from_cur_layer(Position::new(i + 1, pos.y));
          741                     self.set_char(Position::new(i, pos.y), next);
          742                 }
          743                 let last_pos = Position::new(self.buffer_view.lock().get_width() - 1, pos.y);
          744                 self.set_char(last_pos, AttributedChar::invisible());
          745             } else {
          746                 let pos = self.get_caret_position();
          747                 self.set_char(pos, AttributedChar::invisible());
          748             }
          749         }
          750     }
          751 
          752     pub fn delete(&mut self) {
          753         let _op: AtomicUndoGuard = self
          754             .buffer_view
          755             .lock()
          756             .get_edit_state_mut()
          757             .begin_atomic_undo(fl!(crate::LANGUAGE_LOADER, "undo-delete"));
          758         self.buffer_view.lock().clear_selection();
          759         let pos = self.get_caret_position();
          760         if pos.x >= 0 {
          761             let end = self.buffer_view.lock().get_width() - 1;
          762             for i in pos.x..end {
          763                 let next = self.get_char_from_cur_layer(Position::new(i + 1, pos.y));
          764                 self.set_char(Position::new(i, pos.y), next);
          765             }
          766             let last_pos = Position::new(self.buffer_view.lock().get_width() - 1, pos.y);
          767             self.set_char(last_pos, AttributedChar::invisible());
          768         }
          769     }
          770 }
          771 
          772 pub const DEFAULT_CHAR_SET_TABLE: [[u8; 10]; 15] = [
          773     [218, 191, 192, 217, 196, 179, 195, 180, 193, 194],
          774     [201, 187, 200, 188, 205, 186, 204, 185, 202, 203],
          775     [213, 184, 212, 190, 205, 179, 198, 181, 207, 209],
          776     [214, 183, 211, 189, 196, 186, 199, 182, 208, 210],
          777     [197, 206, 216, 215, 232, 233, 155, 156, 153, 239],
          778     [176, 177, 178, 219, 223, 220, 221, 222, 254, 250],
          779     [1, 2, 3, 4, 5, 6, 240, 127, 14, 15],
          780     [24, 25, 30, 31, 16, 17, 18, 29, 20, 21],
          781     [174, 175, 242, 243, 169, 170, 253, 246, 171, 172],
          782     [227, 241, 244, 245, 234, 157, 228, 248, 251, 252],
          783     [224, 225, 226, 229, 230, 231, 235, 236, 237, 238],
          784     [128, 135, 165, 164, 152, 159, 247, 249, 173, 168],
          785     [131, 132, 133, 160, 166, 134, 142, 143, 145, 146],
          786     [136, 137, 138, 130, 144, 140, 139, 141, 161, 158],
          787     [147, 148, 149, 162, 167, 150, 129, 151, 163, 154],
          788 ];
          789 
          790 pub fn terminal_context_menu(editor: &AnsiEditor, commands: &Commands, ui: &mut egui::Ui) -> Option<Message> {
          791     ui.style_mut().wrap = Some(false);
          792     let mut result = None;
          793     ui.input_mut(|i| i.events.clear());
          794 
          795     commands.cut.ui(ui, &mut result);
          796     commands.copy.ui(ui, &mut result);
          797     commands.paste.ui(ui, &mut result);
          798 
          799     let sel = editor.buffer_view.lock().get_selection();
          800 
          801     if let Some(_sel) = sel {
          802         commands.erase_selection.ui(ui, &mut result);
          803         commands.flip_x.ui(ui, &mut result);
          804         commands.flip_y.ui(ui, &mut result);
          805         commands.justifycenter.ui(ui, &mut result);
          806         commands.justifyleft.ui(ui, &mut result);
          807         commands.justifyright.ui(ui, &mut result);
          808         commands.crop.ui(ui, &mut result);
          809     }
          810     result
          811 }
          812 
          813 pub const CTRL_MOD: u32 = 0b1000_0000_0000_0000_0000;
          814 pub const SHIFT_MOD: u32 = 0b0100_0000_0000_0000_0000;
          815 
          816 pub static EDITOR_KEY_MAP: &[(u32, MKey)] = &[
          817     (Key::Escape as u32, MKey::Escape),
          818     (Key::Home as u32, MKey::Home),
          819     (Key::End as u32, MKey::End),
          820     (Key::Home as u32 | CTRL_MOD, MKey::Home),
          821     (Key::End as u32 | CTRL_MOD, MKey::End),
          822     (Key::Insert as u32, MKey::Insert),
          823     (Key::Backspace as u32, MKey::Backspace),
          824     (Key::Enter as u32, MKey::Return),
          825     (Key::Tab as u32, MKey::Tab),
          826     (Key::Tab as u32 | SHIFT_MOD, MKey::Tab),
          827     (Key::Delete as u32, MKey::Delete),
          828     (Key::PageUp as u32, MKey::PageUp),
          829     (Key::PageDown as u32, MKey::PageDown),
          830     (Key::ArrowUp as u32, MKey::Up),
          831     (Key::ArrowDown as u32, MKey::Down),
          832     (Key::ArrowRight as u32, MKey::Right),
          833     (Key::ArrowLeft as u32, MKey::Left),
          834     (Key::ArrowUp as u32 | SHIFT_MOD, MKey::Up),
          835     (Key::ArrowDown as u32 | SHIFT_MOD, MKey::Down),
          836     (Key::ArrowRight as u32 | SHIFT_MOD, MKey::Right),
          837     (Key::ArrowLeft as u32 | SHIFT_MOD, MKey::Left),
          838     (Key::F1 as u32, MKey::F1),
          839     (Key::F2 as u32, MKey::F2),
          840     (Key::F3 as u32, MKey::F3),
          841     (Key::F4 as u32, MKey::F4),
          842     (Key::F5 as u32, MKey::F5),
          843     (Key::F6 as u32, MKey::F6),
          844     (Key::F7 as u32, MKey::F7),
          845     (Key::F8 as u32, MKey::F8),
          846     (Key::F9 as u32, MKey::F9),
          847     (Key::F10 as u32, MKey::F10),
          848     (Key::F11 as u32, MKey::F11),
          849     (Key::F12 as u32, MKey::F12),
          850 ];