aboutsummaryrefslogtreecommitdiff
path: root/src/utils.rs
blob: 6819e719c7a79b6b863a9948a275d2261a3d2bd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use crate::{
    app::AppState,
    consts::FONT_PATH,
    lisp::{
        error::{EvalError, LispError, ParseError},
        eval::Evaluator,
        lex::Lexer,
        parse::Parser,
    },
    message::Message,
};

use std::{
    fs::OpenOptions,
    io::{self, Cursor, Read},
    path::Path,
};

use log::info;
use obi::Image;
use sdl2::{
    keyboard::{Keycode, Mod},
    pixels::Color,
    render::Canvas,
    ttf::Sdl2TtfContext,
    video::Window,
};

#[macro_export]
macro_rules! rect(
    ($x:expr, $y:expr, $w:expr, $h:expr) => (
        ::sdl2::rect::Rect::new($x as i32, $y as i32, $w as u32, $h as u32)
    )
);

pub fn draw_text<S: AsRef<str>>(
    canvas: &mut Canvas<Window>,
    ttf_context: &Sdl2TtfContext,
    text: S,
    color: Color,
    (x, y): (i32, i32),
) -> u32 {
    let text = text.as_ref();
    let texture_creator = canvas.texture_creator();
    let mut font = ttf_context.load_font(FONT_PATH, 17).unwrap();
    font.set_style(sdl2::ttf::FontStyle::NORMAL);
    font.set_hinting(sdl2::ttf::Hinting::Mono);
    let surface = font
        .render(if text.is_empty() { " " } else { text.as_ref() })
        .blended(color)
        .unwrap();
    let texture = texture_creator
        .create_texture_from_surface(&surface)
        .unwrap();
    let (width, height) = font.size_of(&text).unwrap();
    let area = rect!(x, y, width, height);
    canvas.copy(&texture, None, area).unwrap();
    width
}

pub fn is_copy_event(keycode: Option<Keycode>, keymod: Mod) -> bool {
    keycode == Some(Keycode::C) && (keymod == Mod::LCTRLMOD || keymod == Mod::RCTRLMOD)
}

pub fn is_paste_event(keycode: Option<Keycode>, keymod: Mod) -> bool {
    keycode == Some(Keycode::V) && (keymod == Mod::LCTRLMOD || keymod == Mod::RCTRLMOD)
}

pub fn handle_error(err: ParseError, src: &str, file_name: &str) -> Message {
    let mut message = Message::new();
    message.set_error(err.display(&src, file_name));
    message
}

pub fn load_script<P: AsRef<Path>>(path: P, app: &mut AppState) -> Result<(), LispError> {
    let mut script = OpenOptions::new()
        .read(true)
        .write(false)
        .create(false)
        .open(path.as_ref())
        .map_err(EvalError::ScriptLoadError)?;
    let mut buf = String::new();
    script
        .read_to_string(&mut buf)
        .map_err(EvalError::ScriptLoadError)?;

    let mut parser = Parser::new(Lexer::new(&buf, 0));
    let mut evaluator = Evaluator {
        app,
        context: Vec::new(),
    };
    for expr in parser.parse_exprs().map_err(|err| {
        LispError::Stringified(err.display(&buf, path.as_ref().to_str().unwrap_or("<unknown>")))
    })? {
        evaluator.eval(&expr)?;
    }
    return Ok(());
}

pub fn load_file<P: AsRef<Path>>(path: P) -> Result<Image, io::Error> {
    info!("loading existing file `{:?}`", path.as_ref());
    let mut image = OpenOptions::new()
        .read(true)
        .write(false)
        .create(false)
        .open(&path)?;
    let mut buf = Vec::new();
    image.read_to_end(&mut buf)?;
    Ok(Image::decode(&mut (Cursor::new(buf))).unwrap()) // TODO: obi erro
}