scheme.rs 6.01 KB
Newer Older
Jeremy Soller's avatar
Jeremy Soller committed
1
use std::collections::BTreeMap;
Jeremy Soller's avatar
Jeremy Soller committed
2
use std::{mem, slice, str};
Jeremy Soller's avatar
Jeremy Soller committed
3

Jeremy Soller's avatar
Jeremy Soller committed
4
use orbclient::{Event, EventOption};
5
use syscall::{Result, Error, EACCES, EBADF, ENOENT, SchemeMut};
Jeremy Soller's avatar
Jeremy Soller committed
6 7

use display::Display;
Jeremy Soller's avatar
Jeremy Soller committed
8
use screen::{Screen, GraphicScreen, TextScreen};
Jeremy Soller's avatar
Jeremy Soller committed
9 10

pub struct DisplayScheme {
11 12
    width: usize,
    height: usize,
13 14
    active: usize,
    pub screens: BTreeMap<usize, Box<Screen>>
Jeremy Soller's avatar
Jeremy Soller committed
15 16 17
}

impl DisplayScheme {
Jeremy Soller's avatar
Jeremy Soller committed
18
    pub fn new(width: usize, height: usize, onscreen: usize, spec: &[bool]) -> DisplayScheme {
Jeremy Soller's avatar
Jeremy Soller committed
19
        let mut screens: BTreeMap<usize, Box<Screen>> = BTreeMap::new();
Jeremy Soller's avatar
Jeremy Soller committed
20 21 22 23 24 25 26 27 28 29

        let mut screen_i = 1;
        for &screen_type in spec.iter() {
            if screen_type {
                screens.insert(screen_i, Box::new(GraphicScreen::new(Display::new(width, height, onscreen))));
            } else {
                screens.insert(screen_i, Box::new(TextScreen::new(Display::new(width, height, onscreen))));
            }
            screen_i += 1;
        }
Jeremy Soller's avatar
Jeremy Soller committed
30 31

        DisplayScheme {
32 33
            width: width,
            height: height,
34 35
            active: 1,
            screens: screens
Jeremy Soller's avatar
Jeremy Soller committed
36 37 38 39
        }
    }

    pub fn will_block(&self, id: usize) -> bool {
40
        if let Some(screen) = self.screens.get(&id) {
Jeremy Soller's avatar
Jeremy Soller committed
41 42 43 44 45 46 47
            screen.will_block()
        } else {
            false
        }
    }
}

48 49
impl SchemeMut for DisplayScheme {
    fn open(&mut self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
50
        if path == b"input" {
Jeremy Soller's avatar
Jeremy Soller committed
51 52 53 54 55
            if uid == 0 {
                Ok(0)
            } else {
                Err(Error::new(EACCES))
            }
Jeremy Soller's avatar
Jeremy Soller committed
56
        } else {
57 58 59
            let path_str = str::from_utf8(path).unwrap_or("").trim_matches('/');
            let mut parts = path_str.split('/');
            let id = parts.next().unwrap_or("").parse::<usize>().unwrap_or(0);
60
            if self.screens.contains_key(&id) {
61 62 63 64 65
                for cmd in parts {
                    if cmd == "activate" {
                        self.active = id;
                    }
                }
Jeremy Soller's avatar
Jeremy Soller committed
66 67 68 69 70 71 72
                Ok(id)
            } else {
                Err(Error::new(ENOENT))
            }
        }
    }

Jeremy Soller's avatar
Jeremy Soller committed
73
    fn dup(&mut self, id: usize, _buf: &[u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
74 75 76
        Ok(id)
    }

77 78
    fn fevent(&mut self, id: usize, flags: usize) -> Result<usize> {
        if let Some(mut screen) = self.screens.get_mut(&id) {
79
            screen.event(flags).and(Ok(id))
Jeremy Soller's avatar
Jeremy Soller committed
80 81 82 83 84
        } else {
            Err(Error::new(EBADF))
        }
    }

85 86 87 88 89 90 91 92
    fn fmap(&mut self, id: usize, offset: usize, size: usize) -> Result<usize> {
        if let Some(screen) = self.screens.get(&id) {
            screen.map(offset, size)
        } else {
            Err(Error::new(EBADF))
        }
    }

93
    fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
94
        let path_str = if id == 0 {
95
            format!("display:input/{}/{}", self.width, self.height)
96
        } else if let Some(screen) = self.screens.get(&id) {
Jeremy Soller's avatar
Jeremy Soller committed
97
            format!("display:{}/{}/{}", id, screen.width(), screen.height())
Jeremy Soller's avatar
Jeremy Soller committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
        } else {
            return Err(Error::new(EBADF));
        };

        let path = path_str.as_bytes();

        let mut i = 0;
        while i < buf.len() && i < path.len() {
            buf[i] = path[i];
            i += 1;
        }

        Ok(i)
    }

113 114 115
    fn fsync(&mut self, id: usize) -> Result<usize> {
        if let Some(mut screen) = self.screens.get_mut(&id) {
            if id == self.active {
Jeremy Soller's avatar
Jeremy Soller committed
116 117 118 119 120 121 122 123
                screen.sync();
            }
            Ok(0)
        } else {
            Err(Error::new(EBADF))
        }
    }

124 125
    fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
        if let Some(mut screen) = self.screens.get_mut(&id) {
Jeremy Soller's avatar
Jeremy Soller committed
126 127 128 129 130 131
            screen.read(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

132
    fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
133 134 135
        if id == 0 {
            if buf.len() == 1 && buf[0] >= 0xF4 {
                let new_active = (buf[0] - 0xF4) as usize + 1;
136 137
                if let Some(mut screen) = self.screens.get_mut(&new_active) {
                    self.active = new_active;
Jeremy Soller's avatar
Jeremy Soller committed
138 139 140 141
                    screen.redraw();
                }
                Ok(1)
            } else {
Jeremy Soller's avatar
Jeremy Soller committed
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
                let events = unsafe { slice::from_raw_parts(buf.as_ptr() as *const Event, buf.len()/mem::size_of::<Event>()) };

                for event in events.iter() {
                    let new_active_opt = if let EventOption::Key(key_event) = event.to_option() {
                        match key_event.scancode {
                            f @ 0x3B ... 0x44 => { // F1 through F10
                                Some((f - 0x3A) as usize)
                            },
                            0x57 => { // F11
                                Some(11)
                            },
                            0x58 => { // F12
                                Some(12)
                            },
                            _ => None
                        }
                    } else {
                        None
                    };

                    if let Some(new_active) = new_active_opt {
163 164
                        if let Some(mut screen) = self.screens.get_mut(&new_active) {
                            self.active = new_active;
Jeremy Soller's avatar
Jeremy Soller committed
165 166 167
                            screen.redraw();
                        }
                    } else {
168
                        if let Some(mut screen) = self.screens.get_mut(&self.active) {
Jeremy Soller's avatar
Jeremy Soller committed
169 170 171
                            screen.input(event);
                        }
                    }
Jeremy Soller's avatar
Jeremy Soller committed
172
                }
Jeremy Soller's avatar
Jeremy Soller committed
173 174

                Ok(events.len() * mem::size_of::<Event>())
Jeremy Soller's avatar
Jeremy Soller committed
175
            }
176 177
        } else if let Some(mut screen) = self.screens.get_mut(&id) {
            screen.write(buf, id == self.active)
Jeremy Soller's avatar
Jeremy Soller committed
178 179 180 181 182
        } else {
            Err(Error::new(EBADF))
        }
    }

183 184
    fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result<usize> {
        if let Some(mut screen) = self.screens.get_mut(&id) {
Jeremy Soller's avatar
Jeremy Soller committed
185 186 187 188 189 190
            screen.seek(pos, whence)
        } else {
            Err(Error::new(EBADF))
        }
    }

191
    fn close(&mut self, _id: usize) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
192 193 194
        Ok(0)
    }
}