1use std;
4use std::sync;
5use {log, easycurses, pancurses, nsys};
6use lazy_static::lazy_static;
7
8use crate::{Application, Interface, Tree};
9use crate::math::Vector2;
10use crate::geometry::integer::Aabb2;
11use crate::geometry::intersect::integer as intersect;
12use crate::interface::{view, View};
13use crate::widget;
14use crate::tree::NodeId;
15use super::{Graphics, Presentation};
16
17lazy_static!{
18 pub static ref INIT_COLORS : sync::Mutex <Option <[[u8; 3]; 8]>> =
19 sync::Mutex::new (None);
20}
21
22#[derive(Debug)]
24pub struct Curses {
25 inner : nsys::curses::Curses,
26 release_buttons : Vec <view::input::Button>
30}
31
32pub fn border_acs_lines() -> view::Border {
33 view::Border {
34 top: pancurses::ACS_HLINE() as u32,
35 bottom: pancurses::ACS_HLINE() as u32,
36 left: pancurses::ACS_VLINE() as u32,
37 right: pancurses::ACS_VLINE() as u32,
38 top_left: pancurses::ACS_ULCORNER() as u32,
39 top_right: pancurses::ACS_URCORNER() as u32,
40 bottom_left: pancurses::ACS_LLCORNER() as u32,
41 bottom_right: pancurses::ACS_LRCORNER() as u32,
42 thickness_top: 1,
43 thickness_bottom: 1,
44 thickness_left: 1,
45 thickness_right: 1
46 }
47}
48
49impl Curses {
50 #[inline]
51 pub fn inner (&self) -> &nsys::curses::Curses {
52 &self.inner
53 }
54 #[inline]
55 pub fn inner_mut (&mut self) -> &mut nsys::curses::Curses {
56 &mut self.inner
57 }
58 #[inline]
59 pub fn dimensions (&self) -> view::dimensions::Tile {
60 let (rows, columns) = self.inner.dimensions_rc();
61 debug_assert!(rows > 0);
62 debug_assert!(columns > 0);
63 Vector2::new (rows as u32, columns as u32).into()
64 }
65}
66
67impl Default for Curses {
68 fn default() -> Self {
69 let init_colors = INIT_COLORS.lock().unwrap();
70 let mut inner = nsys::curses::Curses::new (init_colors.as_ref());
71 inner.un_get_input (pancurses::Input::KeyResize);
73 Curses { inner, release_buttons: Vec::new() }
74 }
75}
76
77impl Graphics for Curses { }
78impl Presentation for Curses {
79 fn with_root (_root : View, _id : NodeId) -> Self {
80 Self::default()
81 }
82
83 fn make_interface <A : Application> () -> Interface <A, Self> {
85 use widget::BuildElement;
86 let screen = widget::frame::screen::TileBuilder::<A>::new().build_element();
89 let mut interface = Interface::<A, Self>::with_root (screen);
90 let dimensions = interface.presentation.dimensions();
91 let mut actions = vec![];
92 widget::frame::screen::resize (
93 &view::input::System::Resized {
94 width: dimensions.columns(),
95 height: dimensions.rows()
96 },
97 interface.elements(),
98 interface.root_id(),
99 &mut actions
100 );
101 let _ = interface.actions (actions);
102 interface
103 }
104
105 fn get_input (&mut self, input_buffer : &mut Vec <view::Input>) {
106 use view::{input, Input};
107 log::trace!("get input...");
108 input_buffer.extend (self.release_buttons.drain (..)
109 .map (|button|{
110 let input = Input::Button (button, input::button::State::Released);
111 log::debug!("input: {:?}", input);
112 input
113 }));
114 if let Some (pancurses_input) = self.inner.getch_nowait() {
115 log::trace!("pancurses input: {:?}", pancurses_input);
116 let input = match pancurses_input.into() {
117 Input::System (input::System::Resized { width: 0, height: 0 }) => {
120 let (width, height) = {
122 let (rows, columns) = self.inner.dimensions_rc();
123 debug_assert!(rows >= 0);
124 debug_assert!(columns >= 0);
125 (columns as u32, rows as u32)
130 };
131 input::System::Resized { width, height }.into()
132 }
133 Input::Button (button, pressed) => {
134 debug_assert_eq!(pressed, input::button::State::Pressed);
135 self.release_buttons.push (button);
137 Input::Button (button, pressed)
138 }
139 Input::Text (input::Text::Char (ch)) => {
140 let button = {
142 let (keycode, modifiers) = char_to_keycode (ch);
143 input::Button { variant: keycode.into(), modifiers }
144 };
145 let input = Input::Text (input::Text::Char (ch));
146 log::debug!("input: {:?}", input);
147 input_buffer.push (input);
148 self.release_buttons.push (button);
150 (button.clone(), input::button::State::Pressed).into()
151 }
152 input => input
153 };
154 log::debug!("input: {:?}", input);
155 input_buffer.push (input);
156 }
157 log::trace!("...get input");
158 }
159
160 fn display_view <V : AsRef <View>> (&mut self,
161 view_tree : &Tree <V>,
162 _display_values : std::vec::Drain <(NodeId, view::Display)>
163 ) {
164 use std::collections::VecDeque;
165 use pancurses::chtype;
166 use nsys::curses::{color_pair_attr, pancurses_ok, pancurses_warn_ok};
167 use view::component::{canvas, Body, Canvas, Image, Kind};
168 log::trace!("display view...");
169 let (attrs, colors) = self.inner.win().attrget();
171 let bkgd = self.inner.win().getbkgd();
172 log::trace!(" window: attributes: {:064b}", attrs);
173 log::trace!(" window: color pair: {}", colors);
174 log::trace!(" window: background: {:064b}", bkgd);
175 let screen_id = view_tree.root_node_id().unwrap();
177 let screen = view_tree.get (screen_id).unwrap().data().as_ref();
178 let screen_canvas = Canvas::try_ref (&screen.component).unwrap();
179 let (clear, bg_color) = {
182 let color = match screen_canvas.clear_color {
183 canvas::ClearColor::Appearance =>
184 screen.appearance.style.as_ref().map(|style| style.bg),
185 canvas::ClearColor::Fixed (clear_color) => clear_color
186 };
187 ( color.is_some(),
188 color.map(|color| {
189 let bg = convert_color (color).unwrap();
190 color_pair_attr (easycurses::Color::White, bg)
191 }).unwrap_or (0x00) )
193 };
194 self.inner.win().bkgdset (' ' as chtype | bg_color);
195 if clear {
196 pancurses_ok!(self.inner.win().erase());
197 }
198 let style = screen.appearance.style.clone().unwrap_or_default();
200 if let Some (border) = screen_canvas.border.as_ref() {
202 let rc_min = (0,0);
203 let rc_max = (
204 screen_canvas.coordinates.dimensions().vec().numcast().unwrap()
205 - Vector2::new (1,1)
206 ).into_tuple();
207 let color = color_pair_attr (
208 convert_color (style.fg).unwrap(),
209 convert_color (style.bg).unwrap());
210 pancurses_warn_ok!(self.inner.draw_border (
211 border.left as chtype | color,
212 border.right as chtype | color,
213 border.top as chtype | color,
214 border.bottom as chtype | color,
215 border.top_left as chtype | color,
216 border.top_right as chtype | color,
217 border.bottom_left as chtype | color,
218 border.bottom_right as chtype | color,
219 rc_min, rc_max,
220 border.thickness_top as u32,
221 border.thickness_bottom as u32,
222 border.thickness_left as u32,
223 border.thickness_right as u32
224 ));
225 }
226 let screen_aabb = screen_canvas.coordinates.into();
228 let mut canvases = VecDeque::new();
229 for child_id in view_tree.children_ids (screen_id).unwrap() {
230 let child = view_tree.get (child_id).unwrap().data().as_ref();
231 let style = child.appearance.style.as_ref().unwrap_or (&style);
232 if let Some (child_canvas) = Canvas::try_ref (&child.component) {
233 if let Some ((canvas, body_aabb)) =
234 canvas_and_body_aabb (&child_canvas, &screen_aabb)
235 {
236 canvases.push_back ((child_id, canvas, style, body_aabb));
237 }
238 }
239 }
240 while canvases.len() > 0 {
241 let (node_id, canvas, style, body_aabb) = canvases.pop_front().unwrap();
242 let node = view_tree.get (node_id).unwrap();
243 let mut text = None;
244 let mut image = None;
245 for child_id in node.children().iter().rev() {
246 let child = view_tree.get (child_id).unwrap().data().as_ref();
247 let style = child.appearance.style.as_ref().unwrap_or (&style);
248 if let Some (child_canvas) = Canvas::try_ref (&child.component) {
249 if let Some ((canvas, body_aabb)) =
250 canvas_and_body_aabb (&child_canvas, &screen_aabb)
251 {
252 canvases.push_front ((child_id, canvas, style, body_aabb));
253 }
254 } else if let Some (child_text) = Body::try_ref (&child.component) {
255 debug_assert!(text.is_none());
256 let skip = body_aabb.min().0.x as usize;
259 let take = body_aabb.max().0.x as usize - skip;
260 let start = body_aabb.min().0.y as usize;
261 let end = body_aabb.max().0.y as usize;
262 text = Some ((
263 child_text.0.lines().skip (skip).take (take).map (
264 move |line| &line[start.min (line.len())..end.min (line.len())]),
265 child.appearance.style.clone()
266 ));
267 } else if let Some (child_image) = Image::try_ref (&child.component) {
268 debug_assert!(image.is_none());
269 match child_image {
270 Image::Raw64 (pixmap) => {
271 let skip = body_aabb.min().0.x as usize;
272 let take = body_aabb.max().0.x as usize - skip;
273 let start = body_aabb.min().0.y as usize;
274 let end = body_aabb.max().0.y as usize;
275 image = Some (pixmap.rows().skip (skip).take (take).map (
276 move |row| &row[start.min (row.len())..end.min (row.len())]
277 ));
278 }
279 Image::Raw8(_) | Image::Raw16(_) | Image::Raw32(_) |
280 Image::Texture(_) => {
281 image = None;
283 }
284 }
285 }
286 }
287 self.draw_canvas (&canvas, &style, text, image, true);
288 }
289 log::trace!("...display view");
292
293 fn canvas_and_body_aabb (child_canvas : &Canvas, screen_aabb : &Aabb2 <i32>)
294 -> Option <(Canvas, Aabb2 <i32>)>
295 {
296 let child_aabb = child_canvas.coordinates.into();
297 intersect::continuous_aabb2_aabb2 (screen_aabb, &child_aabb).map (
298 |intersection| {
299 let coordinates = view::Coordinates::tile_from_aabb (intersection);
300 let mut canvas = Canvas {
301 coordinates, .. child_canvas.clone()
302 };
303 let (body_width, body_height) = child_canvas.body_wh();
304 let (mut body_min_row, mut body_min_col) = (0, 0);
305 let (mut body_max_row, mut body_max_col) =
306 (body_height as i32, body_width as i32);
307 if let Some (border) = canvas.border.as_mut() {
308 let outside_top = screen_aabb.min().0.x - child_aabb.min().0.x;
309 if outside_top > 0 {
310 body_min_row = (outside_top as u32)
311 .saturating_sub (border.thickness_top as u32) as i32;
312 border.thickness_top = border.thickness_top
313 .saturating_sub (outside_top as u16);
314 }
315 let outside_bottom = child_aabb.max().0.x - screen_aabb.max().0.x;
316 if outside_bottom > 0 {
317 body_max_row = body_max_row - (outside_bottom as u32)
318 .saturating_sub (border.thickness_bottom as u32) as i32;
319 border.thickness_bottom = border.thickness_bottom
320 .saturating_sub (outside_bottom as u16);
321 }
322 let outside_left = screen_aabb.min().0.y - child_aabb.min().0.y;
323 if outside_left > 0 {
324 body_min_col = (outside_left as u32)
325 .saturating_sub (border.thickness_left as u32) as i32;
326 border.thickness_left = border.thickness_left
327 .saturating_sub (outside_left as u16);
328 }
329 let outside_right = child_aabb.max().0.y - screen_aabb.max().0.y;
330 if outside_right > 0 {
331 body_max_col = body_max_col - (outside_right as u32)
332 .saturating_sub (border.thickness_right as u32) as i32;
333 border.thickness_right = border.thickness_right
334 .saturating_sub (outside_right as u16);
335 }
336 }
337 ( canvas,
338 Aabb2::with_minmax (
339 [body_min_row, body_min_col].into(),
340 [body_max_row, body_max_col].into()
341 )
342 )
343 }
344 )
345 }
346 }
347}
348
349impl Curses {
350 fn draw_canvas <'a> (&mut self,
352 canvas : &view::component::Canvas,
353 style : &view::Style,
354 text : Option <(impl Iterator <Item=&'a str>, Option <view::Style>)>,
355 image : Option <impl Iterator <Item=&'a [u64]>>,
356 _debug : bool
357 ) {
358 use std::convert::TryInto;
359 use nsys::curses::{chtype_color_pair, color_pair_attr, pancurses_ok,
360 pancurses_warn_ok};
361 use pancurses::chtype;
362 use crate::interface::view::component::canvas;
363 log::trace!("draw_canvas...");
364 let curses = &mut self.inner;
365 let (position, dimensions)
366 : (view::position::Tile, view::dimensions::Tile)
367 = canvas.coordinates.try_into().unwrap();
368 let (rc_min, rc_max) = {
369 let (row, col) = (position.row(), position.column());
370 let (rows, cols) = (dimensions.rows() as i32, dimensions.columns() as i32);
371 ( (row, col),
372 (row + rows-1, col + cols-1) )
373 };
374 let clear_color = match canvas.clear_color {
376 canvas::ClearColor::Appearance => Some (style.bg),
377 canvas::ClearColor::Fixed (color) => color
378 };
379 clear_color.map (|color|{
380 let border = ' ' as chtype;
381 let bgcolor = convert_color (color).unwrap();
382 let fill_color = color_pair_attr (easycurses::Color::White, bgcolor);
383 let fill = ' ' as chtype | fill_color;
384 curses.draw_rect (border, fill, rc_min, rc_max, 0,0); });
386 let color = color_pair_attr (
387 convert_color (style.fg).unwrap(),
388 convert_color (style.bg).unwrap());
389 let color_pair = chtype_color_pair (color);
390 pancurses_ok!(curses.win().color_set (color_pair));
391 curses.win().bkgdset (b' ' as chtype | color);
392 let (border_thickness_top, border_thickness_left) =
394 canvas.border.as_ref().map (|border|{
395 pancurses_warn_ok!(curses.draw_border (
396 border.left as chtype | color,
397 border.right as chtype | color,
398 border.top as chtype | color,
399 border.bottom as chtype | color,
400 border.top_left as chtype | color,
401 border.top_right as chtype | color,
402 border.bottom_left as chtype | color,
403 border.bottom_right as chtype | color,
404 rc_min, rc_max,
405 border.thickness_top as u32,
406 border.thickness_bottom as u32,
407 border.thickness_left as u32,
408 border.thickness_right as u32
409 ));
410 ( border.thickness_top as i32,
411 border.thickness_left as i32 )
412 }).unwrap_or_default();
413 text.map (|(text, style)|{
415 style.map (|style|{
416 let color = color_pair_attr (
417 convert_color (style.fg).unwrap(),
418 convert_color (style.bg).unwrap());
419 let color_pair = chtype_color_pair (color);
420 pancurses_ok!(curses.win().color_set (color_pair));
421 curses.win().bkgdset (b' ' as chtype | color);
422 });
423 for (i, line) in text.enumerate() {
424 let printable = line.trim_start_matches ('\0');
425 let skip = line.len() - printable.len();
426 let row = rc_min.0 + border_thickness_top + i as i32;
427 let col = rc_min.1 + border_thickness_left + skip as i32;
428 if line.len() > 0 {
429 let _ = curses.win().mvaddstr (row, col, printable);
430 }
431 }
432 });
433 image.map (|image|{
435 for (i, line) in image.enumerate() {
436 let row = rc_min.0 + border_thickness_top + i as i32;
437 let col = rc_min.1 + border_thickness_left;
438 for (j, ch) in line.iter().enumerate() {
439 if *ch != 0x0 {
440 let _ = curses.win().mvaddch (row, col+j as i32, *ch as chtype);
441 }
442 }
443 }
444 });
445 log::trace!("...draw_canvas");
446 }
447}
448
449impl From <pancurses::Input> for view::Input {
450
451 fn from (input : pancurses::Input) -> Self {
457 use pancurses::Input::*;
458 use view::input::{self, button::Keycode, Modifiers};
459 const ALT : Modifiers = Modifiers::ALT;
460 const CTRL : Modifiers = Modifiers::CTRL;
461 const SHIFT : Modifiers = Modifiers::SHIFT;
462 const EMPTY : Modifiers = Modifiers::empty();
463 let unhandled = |input| {
464 log::warn!("curses unhandled input: {:?}", input);
465 (Keycode::NonConvert, EMPTY)
466 };
467 let (keycode, modifiers) = match input {
468 Character (ch) => match ch {
469 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' |
470 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' |
471 'y' | 'z' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '0' |
472 '-' | '=' | '`' | '[' | ']' | '\\'| ';' | '\''| ',' | '.' | '/' | 'A' |
473 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' |
474 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' |
475 'Z' | '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '(' | ')' | '_' |
476 '+' | '~' | '{' | '}' | '|' | ':' | '"' | '<' | '>' | '?' | ' ' | '\n'|
477 '\t' => return view::input::Text::Char (ch).into(),
478 special => {
479 let unhandled = |ch| {
480 log::warn!("curses unhandled special character: {:?}", ch);
481 (Keycode::NonConvert, EMPTY)
482 };
483 let keyname = pancurses::keyname (special as i32).unwrap_or_else (||{
484 log::error!("pancurses keyname failed for special char {:?}",
485 special);
486 unreachable!()
487 });
488 log::trace!("keyname: {:?}", keyname);
489 match keyname.as_str() {
490 "^A" => (Keycode::A, CTRL),
491 "^B" => (Keycode::B, CTRL),
492 "^C" => (Keycode::C, CTRL),
493 "^D" => (Keycode::D, CTRL),
494 "^E" => (Keycode::E, CTRL),
495 "^F" => (Keycode::F, CTRL),
496 "^G" => (Keycode::G, CTRL),
497 "^H" => (Keycode::Backspace, EMPTY),
499 "^I" => (Keycode::I, CTRL),
500 "^J" => (Keycode::J, CTRL),
501 "^K" => (Keycode::K, CTRL),
502 "^L" => (Keycode::L, CTRL),
503 "^M" => (Keycode::M, CTRL),
504 "^N" => (Keycode::N, CTRL),
505 "^O" => (Keycode::O, CTRL),
506 "^P" => (Keycode::P, CTRL),
507 "^Q" => (Keycode::Q, CTRL),
508 "^R" => (Keycode::R, CTRL),
509 "^S" => (Keycode::S, CTRL),
510 "^T" => (Keycode::T, CTRL),
511 "^U" => (Keycode::U, CTRL),
512 "^V" => (Keycode::V, CTRL),
513 "^W" => (Keycode::W, CTRL),
514 "^X" => (Keycode::X, CTRL),
515 "^Y" => (Keycode::Y, CTRL),
516 "^Z" => (Keycode::Z, CTRL),
517 "^_" => (Keycode::Minus, SHIFT | CTRL),
518 "^?" => (Keycode::Backspace, EMPTY),
519 "^[" => (Keycode::Escape, EMPTY), "^@" => (Keycode::Key2, CTRL),
522 "KEY_PAUSE" => (Keycode::Pause, EMPTY),
524 "KEY_SCROLLLOCK" => (Keycode::ScrollLock, EMPTY),
525 "KEY_SDOWN" => (Keycode::Down, SHIFT),
526 "KEY_SUP" => (Keycode::Up, SHIFT),
527 "KEY_B2" => (Keycode::Numpad5, SHIFT),
528 "SHF_PADENTER" => (Keycode::NumpadEnter, SHIFT),
529 "SHF_PADMINUS" => (Keycode::NumpadSubtract, SHIFT),
530 "SHF_PADPLUS" => (Keycode::NumpadAdd, SHIFT),
531 "SHF_PADSLASH" => (Keycode::NumpadDivide, SHIFT),
532 "SHF_PADSTAR" => (Keycode::NumpadMultiply, SHIFT),
533 "KEY_F(25)" => (Keycode::F1, CTRL),
534 "KEY_F(26)" => (Keycode::F2, CTRL),
535 "KEY_F(27)" => (Keycode::F3, CTRL),
536 "KEY_F(28)" => (Keycode::F4, CTRL),
537 "KEY_F(29)" => (Keycode::F5, CTRL),
538 "KEY_F(30)" => (Keycode::F6, CTRL),
539 "KEY_F(31)" => (Keycode::F7, CTRL),
540 "KEY_F(32)" => (Keycode::F8, CTRL),
541 "KEY_F(33)" => (Keycode::F9, CTRL),
542 "KEY_F(34)" => (Keycode::F10, CTRL),
543 "KEY_F(35)" => (Keycode::F11, CTRL),
544 "KEY_F(36)" => (Keycode::F12, CTRL),
545 "KEY_F(37)" => (Keycode::F1, ALT),
546 "KEY_F(38)" => (Keycode::F2, ALT),
547 "KEY_F(39)" => (Keycode::F3, ALT),
548 "KEY_F(40)" => (Keycode::F4, ALT),
549 "KEY_F(41)" => (Keycode::F5, ALT),
550 "KEY_F(42)" => (Keycode::F6, ALT),
551 "KEY_F(43)" => (Keycode::F7, ALT),
552 "KEY_F(44)" => (Keycode::F8, ALT),
553 "KEY_F(45)" => (Keycode::F9, ALT),
554 "KEY_F(46)" => (Keycode::F10, ALT),
555 "KEY_F(47)" => (Keycode::F11, ALT),
556 "KEY_F(48)" => (Keycode::F12, ALT),
557 "CTL_0" => (Keycode::Key0, CTRL),
558 "CTL_1" => (Keycode::Key1, CTRL),
559 "CTL_2" => (Keycode::Key2, CTRL),
560 "CTL_3" => (Keycode::Key3, CTRL),
561 "CTL_4" => (Keycode::Key4, CTRL),
562 "CTL_5" => (Keycode::Key5, CTRL),
563 "CTL_6" => (Keycode::Key6, CTRL),
564 "CTL_7" => (Keycode::Key7, CTRL),
565 "CTL_8" => (Keycode::Key8, CTRL),
566 "CTL_9" => (Keycode::Key9, CTRL),
567 "CTL_DOWN" => (Keycode::Down, CTRL),
568 "CTL_LEFT" => (Keycode::Left, CTRL),
569 "CTL_RIGHT" => (Keycode::Right, CTRL),
570 "CTL_UP" => (Keycode::Up, CTRL),
571 "CTL_PAD0" => (Keycode::Numpad0, CTRL),
572 "CTL_PAD1" => (Keycode::Numpad1, CTRL),
573 "CTL_PAD2" => (Keycode::Numpad2, CTRL),
574 "CTL_PAD3" => (Keycode::Numpad3, CTRL),
575 "CTL_PAD4" => (Keycode::Numpad4, CTRL),
576 "CTL_PAD5" => (Keycode::Numpad5, CTRL),
577 "CTL_PAD6" => (Keycode::Numpad6, CTRL),
578 "CTL_PAD7" => (Keycode::Numpad7, CTRL),
579 "CTL_PAD8" => (Keycode::Numpad8, CTRL),
580 "CTL_PAD9" => (Keycode::Numpad9, CTRL),
581 "CTL_PADENTER" => (Keycode::NumpadEnter, CTRL),
582 "CTL_PADMINUS" => (Keycode::NumpadSubtract, CTRL),
583 "CTL_PADPLUS" => (Keycode::NumpadAdd, CTRL),
584 "CTL_PADSLASH" => (Keycode::NumpadDivide, CTRL),
585 "CTL_PADSTOP" => (Keycode::NumpadDecimal, CTRL),
586 "CTL_PADSTAR" => (Keycode::NumpadMultiply, CTRL),
587 "CTL_BQUOTE" => (Keycode::Grave, CTRL),
588 "CTL_DEL" => (Keycode::Delete, CTRL),
589 "CTL_END" => (Keycode::End, CTRL),
590 "CTL_FLASH" => (Keycode::Slash, CTRL),
591 "CTL_HOME" => (Keycode::Home, CTRL),
592 "CTL_INS" => (Keycode::Insert, CTRL),
593 "CTL_PAUSE" => (Keycode::Pause, CTRL),
594 "CTL_PGDN" => (Keycode::PageDown, CTRL),
595 "CTL_PGUP" => (Keycode::PageUp, CTRL),
596 "CTL_SEMICOLON" => (Keycode::Semicolon, CTRL),
597 "CTL_STOP" => (Keycode::Period, CTRL),
598 "CTL_TAB" => (Keycode::Tab, CTRL),
599 "ALT_0" => (Keycode::Key0, ALT),
600 "ALT_1" => (Keycode::Key1, ALT),
601 "ALT_2" => (Keycode::Key2, ALT),
602 "ALT_3" => (Keycode::Key3, ALT),
603 "ALT_4" => (Keycode::Key4, ALT),
604 "ALT_5" => (Keycode::Key5, ALT),
605 "ALT_6" => (Keycode::Key6, ALT),
606 "ALT_7" => (Keycode::Key7, ALT),
607 "ALT_8" => (Keycode::Key8, ALT),
608 "ALT_9" => (Keycode::Key9, ALT),
609 "ALT_A" => (Keycode::A, ALT),
610 "ALT_B" => (Keycode::B, ALT),
611 "ALT_C" => (Keycode::C, ALT),
612 "ALT_D" => (Keycode::D, ALT),
613 "ALT_E" => (Keycode::E, ALT),
614 "ALT_F" => (Keycode::F, ALT),
615 "ALT_G" => (Keycode::G, ALT),
616 "ALT_H" => (Keycode::H, ALT),
617 "ALT_I" => (Keycode::I, ALT),
618 "ALT_J" => (Keycode::J, ALT),
619 "ALT_K" => (Keycode::K, ALT),
620 "ALT_L" => (Keycode::L, ALT),
621 "ALT_M" => (Keycode::M, ALT),
622 "ALT_N" => (Keycode::N, ALT),
623 "ALT_O" => (Keycode::O, ALT),
624 "ALT_P" => (Keycode::P, ALT),
625 "ALT_Q" => (Keycode::Q, ALT),
626 "ALT_R" => (Keycode::R, ALT),
627 "ALT_S" => (Keycode::S, ALT),
628 "ALT_T" => (Keycode::T, ALT),
629 "ALT_U" => (Keycode::U, ALT),
630 "ALT_V" => (Keycode::V, ALT),
631 "ALT_W" => (Keycode::W, ALT),
632 "ALT_X" => (Keycode::X, ALT),
633 "ALT_Y" => (Keycode::Y, ALT),
634 "ALT_Z" => (Keycode::Z, ALT),
635 "ALT_BKSP" => (Keycode::Backspace, ALT),
636 "ALT_BQUOTE" => (Keycode::Grave, ALT),
637 "ALT_BSLASH" => (Keycode::Backslash, ALT),
638 "^\\" => (Keycode::LBracket, ALT),
639 "ALT_COMMA" => (Keycode::Comma, ALT),
640 "ALT_DEL" => (Keycode::Delete, ALT),
641 "ALT_END" => (Keycode::End, ALT),
642 "ALT_ENTER" => (Keycode::Enter, ALT),
643 "ALT_EQUALS" => (Keycode::Equal, ALT),
644 "ALT_HOME" => (Keycode::Home, ALT),
645 "ALT_INS" => (Keycode::Insert, ALT),
646 "ALT_FQUOTE" => (Keycode::Quote, ALT),
647 "ALT_FSLASH" => (Keycode::Slash, ALT),
648 "ALT_MINUS" => (Keycode::Minus, ALT),
649 "ALT_PGDN" => (Keycode::PageDown, ALT),
650 "ALT_PGUP" => (Keycode::PageUp, ALT),
651 "ALT_RBRACKET" => (Keycode::RBracket, ALT),
652 "ALT_SCROLLLOCK" => (Keycode::ScrollLock, ALT),
653 "ALT_SEMICOLON" => (Keycode::Semicolon, ALT),
654 "ALT_STOP" => (Keycode::Period, ALT),
655 "ALT_PADENTER" => (Keycode::NumpadEnter, ALT),
656 "ALT_PADMINUS" => (Keycode::NumpadSubtract, ALT),
657 "ALT_PADSLASH" => (Keycode::NumpadDivide, ALT),
658 "ALT_PADSTAR" => (Keycode::NumpadMultiply, ALT),
659 "ALT_PADSTOP" => (Keycode::NumpadDecimal, ALT),
660 ch => unhandled (ch)
661 }
662 }
663 },
664 Unknown(_) => unhandled (input),
665 KeyCodeYes => unhandled (input),
666
667 KeyBreak => (Keycode::Pause, EMPTY),
668 KeyDown => (Keycode::Down, EMPTY),
669 KeyUp => (Keycode::Up, EMPTY),
670 KeyLeft => (Keycode::Left, EMPTY),
671 KeyRight => (Keycode::Right, EMPTY),
672 KeyHome => (Keycode::Home, EMPTY),
673 KeyBackspace => (Keycode::Backspace, EMPTY),
674 KeyF0 => unhandled (input),
675 KeyF1 => (Keycode::F1, EMPTY),
676 KeyF2 => (Keycode::F2, EMPTY),
677 KeyF3 => (Keycode::F3, EMPTY),
678 KeyF4 => (Keycode::F4, EMPTY),
679 KeyF5 => (Keycode::F5, EMPTY),
680 KeyF6 => (Keycode::F6, EMPTY),
681 KeyF7 => (Keycode::F7, EMPTY),
682 KeyF8 => (Keycode::F8, EMPTY),
683 KeyF9 => (Keycode::F9, EMPTY),
684 KeyF10 => (Keycode::F10, EMPTY),
685 KeyF11 => (Keycode::F11, EMPTY),
686 KeyF12 => (Keycode::F12, EMPTY),
687 KeyF13 => (Keycode::F13, EMPTY),
688 KeyF14 => (Keycode::F14, EMPTY),
689 KeyF15 => (Keycode::F15, EMPTY),
690
691 KeyDL => unhandled (input),
692 KeyIL => unhandled (input),
693 KeyDC => (Keycode::Delete, EMPTY),
694 KeyIC => (Keycode::Insert, EMPTY),
695 KeyEIC => unhandled (input),
696 KeyClear => unhandled (input),
697 KeyEOS => unhandled (input),
698 KeyEOL => unhandled (input),
699 KeySF => (Keycode::Down, SHIFT),
700 KeySR => (Keycode::Up, SHIFT),
701 KeyNPage => (Keycode::PageDown, EMPTY),
702 KeyPPage => (Keycode::PageUp, EMPTY),
703 KeySTab => unhandled (input), KeyCTab => unhandled (input),
705 KeyCATab => unhandled (input),
706 KeyEnter => (Keycode::Enter, EMPTY),
707 KeySReset => unhandled (input),
708 KeyReset => unhandled (input),
709 KeyPrint => unhandled (input),
710 KeyLL => unhandled (input),
711 KeyAbort => unhandled (input),
712 KeySHelp => unhandled (input),
713 KeyLHelp => unhandled (input),
714 KeyBTab => (Keycode::Tab, SHIFT),
715 KeyBeg => unhandled (input),
716 KeyCancel => unhandled (input),
717 KeyClose => unhandled (input),
718 KeyCommand => unhandled (input),
719 KeyCopy => (Keycode::Copy, EMPTY),
720 KeyCreate => unhandled (input),
721 KeyEnd => (Keycode::End, EMPTY),
722 KeyExit => unhandled (input),
723 KeyFind => unhandled (input),
724 KeyHelp => unhandled (input),
725 KeyMark => unhandled (input),
726 KeyMessage => unhandled (input),
727 KeyMove => unhandled (input),
728 KeyNext => unhandled (input),
729 KeyOpen => unhandled (input),
730 KeyOptions => unhandled (input),
731 KeyPrevious => unhandled (input),
732 KeyRedo => unhandled (input),
733 KeyReference => unhandled (input),
734 KeyRefresh => unhandled (input),
735 KeyReplace => unhandled (input),
736 KeyRestart => unhandled (input),
737 KeyResume => unhandled (input),
738 KeySave => unhandled (input),
739 KeySBeg => unhandled (input),
740 KeySCancel => unhandled (input),
741 KeySCommand => unhandled (input),
742 KeySCopy => unhandled (input),
743 KeySCreate => unhandled (input),
744 KeySDC => (Keycode::Delete, SHIFT),
745 KeySDL => unhandled (input),
746 KeySelect => unhandled (input),
747 KeySEnd => (Keycode::End, SHIFT),
748 KeySEOL => unhandled (input),
749 KeySExit => unhandled (input),
750 KeySFind => unhandled (input),
751 KeySHome => (Keycode::Home, SHIFT),
752 KeySIC => (Keycode::Insert, SHIFT),
753
754 KeySLeft | KeySMessage => (Keycode::Left, SHIFT),
756 KeySMove => unhandled (input),
757 KeySNext => (Keycode::PageDown, SHIFT),
758 KeySOptions => unhandled (input),
759 KeySPrevious => (Keycode::PageUp, SHIFT),
760 KeySPrint => unhandled (input),
761 KeySRedo => unhandled (input),
762 KeySReplace => unhandled (input),
763 KeySRight | KeySResume => (Keycode::Right, SHIFT),
765 KeySSave => unhandled (input),
766 KeySSuspend => unhandled (input),
767 KeySUndo => unhandled (input),
768 KeySuspend => unhandled (input),
769 KeyUndo => unhandled (input),
770
771 KeyResize => return input::System::Resized { width: 0, height: 0 }.into(),
776 KeyEvent => unhandled (input),
777 KeyMouse => unhandled (input),
778
779 KeyA1 => unhandled (input),
780 KeyA3 => unhandled (input),
781 KeyB2 => unhandled (input),
782 KeyC1 => unhandled (input),
783 KeyC3 => unhandled (input)
784 };
785 ( input::Button {
786 variant: keycode.into(),
787 modifiers
788 },
789 input::button::State::Pressed
790 ).into()
791 }
792}
793
794fn char_to_keycode (ch : char)
798 -> (view::input::button::Keycode, view::input::Modifiers)
799{
800 use view::input::Modifiers;
801 use view::input::button::Keycode;
802 const EMPTY : Modifiers = Modifiers::empty();
803 const SHIFT : Modifiers = Modifiers::SHIFT;
804 match ch {
805 'a' => (Keycode::A, EMPTY),
806 'b' => (Keycode::B, EMPTY),
807 'c' => (Keycode::C, EMPTY),
808 'd' => (Keycode::D, EMPTY),
809 'e' => (Keycode::E, EMPTY),
810 'f' => (Keycode::F, EMPTY),
811 'g' => (Keycode::G, EMPTY),
812 'h' => (Keycode::H, EMPTY),
813 'i' => (Keycode::I, EMPTY),
814 'j' => (Keycode::J, EMPTY),
815 'k' => (Keycode::K, EMPTY),
816 'l' => (Keycode::L, EMPTY),
817 'm' => (Keycode::M, EMPTY),
818 'n' => (Keycode::N, EMPTY),
819 'o' => (Keycode::O, EMPTY),
820 'p' => (Keycode::P, EMPTY),
821 'q' => (Keycode::Q, EMPTY),
822 'r' => (Keycode::R, EMPTY),
823 's' => (Keycode::S, EMPTY),
824 't' => (Keycode::T, EMPTY),
825 'u' => (Keycode::U, EMPTY),
826 'v' => (Keycode::V, EMPTY),
827 'w' => (Keycode::W, EMPTY),
828 'x' => (Keycode::X, EMPTY),
829 'y' => (Keycode::Y, EMPTY),
830 'z' => (Keycode::Z, EMPTY),
831 '1' => (Keycode::Key1, EMPTY),
832 '2' => (Keycode::Key2, EMPTY),
833 '3' => (Keycode::Key3, EMPTY),
834 '4' => (Keycode::Key4, EMPTY),
835 '5' => (Keycode::Key5, EMPTY),
836 '6' => (Keycode::Key6, EMPTY),
837 '7' => (Keycode::Key7, EMPTY),
838 '8' => (Keycode::Key8, EMPTY),
839 '9' => (Keycode::Key9, EMPTY),
840 '0' => (Keycode::Key0, EMPTY),
841 '-' => (Keycode::Minus, EMPTY),
842 '=' => (Keycode::Equal, EMPTY),
843 '`' => (Keycode::Grave, EMPTY),
844 '[' => (Keycode::LBracket, EMPTY),
845 ']' => (Keycode::RBracket, EMPTY),
846 '\\' => (Keycode::Backslash, EMPTY),
847 ';' => (Keycode::Semicolon, EMPTY),
848 '\'' => (Keycode::Quote, EMPTY),
849 ',' => (Keycode::Comma, EMPTY),
850 '.' => (Keycode::Period, EMPTY),
851 '/' => (Keycode::Slash, EMPTY),
852 'A' => (Keycode::A, SHIFT),
853 'B' => (Keycode::B, SHIFT),
854 'C' => (Keycode::C, SHIFT),
855 'D' => (Keycode::D, SHIFT),
856 'E' => (Keycode::E, SHIFT),
857 'F' => (Keycode::F, SHIFT),
858 'G' => (Keycode::G, SHIFT),
859 'H' => (Keycode::H, SHIFT),
860 'I' => (Keycode::I, SHIFT),
861 'J' => (Keycode::J, SHIFT),
862 'K' => (Keycode::K, SHIFT),
863 'L' => (Keycode::L, SHIFT),
864 'M' => (Keycode::M, SHIFT),
865 'N' => (Keycode::N, SHIFT),
866 'O' => (Keycode::O, SHIFT),
867 'P' => (Keycode::P, SHIFT),
868 'Q' => (Keycode::Q, SHIFT),
869 'R' => (Keycode::R, SHIFT),
870 'S' => (Keycode::S, SHIFT),
871 'T' => (Keycode::T, SHIFT),
872 'U' => (Keycode::U, SHIFT),
873 'V' => (Keycode::V, SHIFT),
874 'W' => (Keycode::W, SHIFT),
875 'X' => (Keycode::X, SHIFT),
876 'Y' => (Keycode::Y, SHIFT),
877 'Z' => (Keycode::Z, SHIFT),
878 '!' => (Keycode::Key1, SHIFT),
879 '@' => (Keycode::Key2, SHIFT),
880 '#' => (Keycode::Key3, SHIFT),
881 '$' => (Keycode::Key4, SHIFT),
882 '%' => (Keycode::Key5, SHIFT),
883 '^' => (Keycode::Key6, SHIFT),
884 '&' => (Keycode::Key7, SHIFT),
885 '*' => (Keycode::Key8, SHIFT),
886 '(' => (Keycode::Key9, SHIFT),
887 ')' => (Keycode::Key0, SHIFT),
888 '_' => (Keycode::Minus, SHIFT),
889 '+' => (Keycode::Equal, SHIFT),
890 '~' => (Keycode::Grave, SHIFT),
891 '{' => (Keycode::LBracket, SHIFT),
892 '}' => (Keycode::RBracket, SHIFT),
893 '|' => (Keycode::Backslash, SHIFT),
894 ':' => (Keycode::Semicolon, SHIFT),
895 '"' => (Keycode::Quote, SHIFT),
896 '<' => (Keycode::Comma, SHIFT),
897 '>' => (Keycode::Period, SHIFT),
898 '?' => (Keycode::Slash, SHIFT),
899 ' ' => (Keycode::Space, EMPTY),
900 '\n' => (Keycode::Enter, EMPTY),
901 '\t' => (Keycode::Tab, EMPTY),
902 _ => unreachable!()
903 }
904}
905
906fn convert_color (color : view::Color)
907 -> Result <easycurses::Color, view::Color>
908{
909 use view::color::*;
910 let color = match color {
911 Color::Named (named) => match named {
912 Named::Monochrome (Monochrome::White) => easycurses::Color::White,
913 Named::Monochrome (Monochrome::Grey) => return Err (color),
914 Named::Monochrome (Monochrome::Black) => easycurses::Color::Black,
915 Named::Hue (hue) => match hue {
916 Hue::Primary (Primary::Red) => easycurses::Color::Red,
917 Hue::Primary (Primary::Green) => easycurses::Color::Green,
918 Hue::Primary (Primary::Blue) => easycurses::Color::Blue,
919 Hue::Secondary (Secondary::Cyan) => easycurses::Color::Cyan,
920 Hue::Secondary (Secondary::Yellow) => easycurses::Color::Yellow,
921 Hue::Secondary (Secondary::Magenta) => easycurses::Color::Magenta,
922 _ => return Err (color)
923 }
924 },
925 _ => return Err (color)
926 };
927 Ok (color)
928}