scheme.rs 5.89 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
    active: usize,
    pub screens: BTreeMap<usize, Box<Screen>>
Jeremy Soller's avatar
Jeremy Soller committed
13 14 15
}

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

        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
28 29

        DisplayScheme {
30 31
            active: 1,
            screens: screens
Jeremy Soller's avatar
Jeremy Soller committed
32 33 34 35
        }
    }

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

44 45
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
46
        if path == b"input" {
Jeremy Soller's avatar
Jeremy Soller committed
47 48 49 50 51
            if uid == 0 {
                Ok(0)
            } else {
                Err(Error::new(EACCES))
            }
Jeremy Soller's avatar
Jeremy Soller committed
52
        } else {
53 54 55
            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);
56
            if self.screens.contains_key(&id) {
57 58 59 60 61
                for cmd in parts {
                    if cmd == "activate" {
                        self.active = id;
                    }
                }
Jeremy Soller's avatar
Jeremy Soller committed
62 63 64 65 66 67 68
                Ok(id)
            } else {
                Err(Error::new(ENOENT))
            }
        }
    }

Jeremy Soller's avatar
Jeremy Soller committed
69
    fn dup(&mut self, id: usize, _buf: &[u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
70 71 72
        Ok(id)
    }

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

81 82 83 84 85 86 87 88
    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))
        }
    }

89
    fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
90 91
        let path_str = if id == 0 {
            format!("display:input")
92
        } else if let Some(screen) = self.screens.get(&id) {
Jeremy Soller's avatar
Jeremy Soller committed
93
            format!("display:{}/{}/{}", id, screen.width(), screen.height())
Jeremy Soller's avatar
Jeremy Soller committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
        } 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)
    }

109 110 111
    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
112 113 114 115 116 117 118 119
                screen.sync();
            }
            Ok(0)
        } else {
            Err(Error::new(EBADF))
        }
    }

120 121
    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
122 123 124 125 126 127
            screen.read(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

128
    fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
129 130 131
        if id == 0 {
            if buf.len() == 1 && buf[0] >= 0xF4 {
                let new_active = (buf[0] - 0xF4) as usize + 1;
132 133
                if let Some(mut screen) = self.screens.get_mut(&new_active) {
                    self.active = new_active;
Jeremy Soller's avatar
Jeremy Soller committed
134 135 136 137
                    screen.redraw();
                }
                Ok(1)
            } else {
Jeremy Soller's avatar
Jeremy Soller committed
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
                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 {
159 160
                        if let Some(mut screen) = self.screens.get_mut(&new_active) {
                            self.active = new_active;
Jeremy Soller's avatar
Jeremy Soller committed
161 162 163
                            screen.redraw();
                        }
                    } else {
164
                        if let Some(mut screen) = self.screens.get_mut(&self.active) {
Jeremy Soller's avatar
Jeremy Soller committed
165 166 167
                            screen.input(event);
                        }
                    }
Jeremy Soller's avatar
Jeremy Soller committed
168
                }
Jeremy Soller's avatar
Jeremy Soller committed
169 170

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

179 180
    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
181 182 183 184 185 186
            screen.seek(pos, whence)
        } else {
            Err(Error::new(EBADF))
        }
    }

187
    fn close(&mut self, _id: usize) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
188 189 190
        Ok(0)
    }
}