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

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

use display::Display;
Jeremy Soller's avatar
Jeremy Soller committed
9
use screen::{Screen, GraphicScreen, TextScreen};
Jeremy Soller's avatar
Jeremy Soller committed
10 11 12 13 14 15

pub struct DisplayScheme {
    width: usize,
    height: usize,
    onscreen: usize,
    active: Cell<usize>,
Jeremy Soller's avatar
Jeremy Soller committed
16
    next_screen: Cell<usize>,
17
    pub screens: RefCell<BTreeMap<usize, Box<Screen>>>
Jeremy Soller's avatar
Jeremy Soller committed
18 19 20
}

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

        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
33 34 35 36 37 38

        DisplayScheme {
            width: width,
            height: height,
            onscreen: onscreen,
            active: Cell::new(1),
Jeremy Soller's avatar
Jeremy Soller committed
39
            next_screen: Cell::new(screen_i),
Jeremy Soller's avatar
Jeremy Soller committed
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
            screens: RefCell::new(screens)
        }
    }

    pub fn will_block(&self, id: usize) -> bool {
        let screens = self.screens.borrow();
        if let Some(screen) = screens.get(&id) {
            screen.will_block()
        } else {
            false
        }
    }
}

impl Scheme for DisplayScheme {
Jeremy Soller's avatar
Jeremy Soller committed
55
    fn open(&self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
56
        if path == b"input" {
Jeremy Soller's avatar
Jeremy Soller committed
57 58 59 60 61
            if uid == 0 {
                Ok(0)
            } else {
                Err(Error::new(EACCES))
            }
Jeremy Soller's avatar
Jeremy Soller committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
        } else {
            let path_str = str::from_utf8(path).unwrap_or("");
            let id = path_str.parse::<usize>().unwrap_or(0);
            if self.screens.borrow().contains_key(&id) {
                Ok(id)
            } else {
                Err(Error::new(ENOENT))
            }
        }
    }

    fn dup(&self, id: usize) -> Result<usize> {
        Ok(id)
    }

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

    fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
        let screens = self.screens.borrow();
        let path_str = if id == 0 {
            format!("display:input")
        } else if let Some(screen) = screens.get(&id) {
Jeremy Soller's avatar
Jeremy Soller committed
91
            format!("display:{}/{}/{}", id, screen.width(), screen.height())
Jeremy Soller's avatar
Jeremy Soller committed
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
        } 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)
    }

    fn fsync(&self, id: usize) -> Result<usize> {
        let mut screens = self.screens.borrow_mut();
        if let Some(mut screen) = screens.get_mut(&id) {
            if id == self.active.get() {
                screen.sync();
            }
            Ok(0)
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
        let mut screens = self.screens.borrow_mut();
        if let Some(mut screen) = screens.get_mut(&id) {
            screen.read(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

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

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

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

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