1 /* 2 * Copyright 2007, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Author: 6 * François Revol, revol@free.fr. 7 */ 8 9 #include <SupportDefs.h> 10 #include <string.h> 11 #include "toscalls.h" 12 #include <util/kernel_cpp.h> 13 14 #include "Handle.h" 15 #include "console.h" 16 #include "keyboard.h" 17 18 19 // TOS emulates a VT52 20 21 class ConsoleHandle : public CharHandle { 22 public: 23 ConsoleHandle(); 24 25 virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, 26 size_t bufferSize); 27 virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, 28 size_t bufferSize); 29 }; 30 31 class InputConsoleHandle : public ConsoleHandle { 32 public: 33 InputConsoleHandle(); 34 35 virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, 36 size_t bufferSize); 37 38 void PutChar(char c); 39 void PutChars(const char *buffer, int count); 40 char GetChar(); 41 42 private: 43 enum { BUFFER_SIZE = 32 }; 44 45 char fBuffer[BUFFER_SIZE]; 46 int fStart; 47 int fCount; 48 }; 49 50 51 static InputConsoleHandle sInput; 52 static ConsoleHandle sOutput; 53 FILE *stdin, *stdout, *stderr; 54 55 56 ConsoleHandle::ConsoleHandle() 57 : CharHandle() 58 { 59 } 60 61 62 ssize_t 63 ConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *buffer, 64 size_t bufferSize) 65 { 66 // don't seek in character devices 67 // not implemented (and not yet? needed) 68 return B_ERROR; 69 } 70 71 72 ssize_t 73 ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer, 74 size_t bufferSize) 75 { 76 const char *string = (const char *)buffer; 77 size_t i; 78 79 // be nice to our audience and replace single "\n" with "\r\n" 80 81 for (i = 0; i < bufferSize; i++) { 82 if (string[i] == '\n') 83 Bconout(fHandle, '\r'); 84 Bconout(fHandle, string[i]); 85 } 86 87 return bufferSize; 88 } 89 90 91 // #pragma mark - 92 93 94 InputConsoleHandle::InputConsoleHandle() 95 : ConsoleHandle() 96 , fStart(0) 97 , fCount(0) 98 { 99 } 100 101 102 ssize_t 103 InputConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer, 104 size_t bufferSize) 105 { 106 char *buffer = (char*)_buffer; 107 108 // copy buffered bytes first 109 int bytesTotal = 0; 110 while (bufferSize > 0 && fCount > 0) { 111 *buffer++ = GetChar(); 112 bytesTotal++; 113 bufferSize--; 114 } 115 116 // read from console 117 if (bufferSize > 0) { 118 ssize_t bytesRead = ConsoleHandle::ReadAt(NULL, 0, buffer, bufferSize); 119 if (bytesRead < 0) 120 return bytesRead; 121 bytesTotal += bytesRead; 122 } 123 124 return bytesTotal; 125 } 126 127 128 void 129 InputConsoleHandle::PutChar(char c) 130 { 131 if (fCount >= BUFFER_SIZE) 132 return; 133 134 int pos = (fStart + fCount) % BUFFER_SIZE; 135 fBuffer[pos] = c; 136 fCount++; 137 } 138 139 140 void 141 InputConsoleHandle::PutChars(const char *buffer, int count) 142 { 143 for (int i = 0; i < count; i++) 144 PutChar(buffer[i]); 145 } 146 147 148 char 149 InputConsoleHandle::GetChar() 150 { 151 if (fCount == 0) 152 return 0; 153 154 fCount--; 155 char c = fBuffer[fStart]; 156 fStart = (fStart + 1) % BUFFER_SIZE; 157 return c; 158 } 159 160 161 // #pragma mark - 162 163 164 status_t 165 console_init(void) 166 { 167 sInput.SetHandle(DEV_CONSOLE); 168 sOutput.SetHandle(DEV_CONSOLE); 169 170 // now that we're initialized, enable stdio functionality 171 stdin = (FILE *)&sInput; 172 stdout = stderr = (FILE *)&sOutput; 173 174 return B_OK; 175 } 176 177 178 // #pragma mark - 179 180 181 void 182 console_clear_screen(void) 183 { 184 sInput.WriteAt(NULL, 0LL, "\033E", 2); 185 } 186 187 188 int32 189 console_width(void) 190 { 191 int columnCount = 80; //XXX: check video mode 192 return columnCount; 193 } 194 195 196 int32 197 console_height(void) 198 { 199 int lineCount = 25; //XXX: check video mode 200 return lineCount; 201 } 202 203 204 void 205 console_set_cursor(int32 x, int32 y) 206 { 207 char buff[] = "\033Y "; 208 x = MIN(79,MAX(0,x)); 209 y = MIN(24,MAX(0,y)); 210 buff[3] += (char)x; 211 buff[2] += (char)y; 212 sInput.WriteAt(NULL, 0LL, buff, 4); 213 } 214 215 216 static int 217 translate_color(int32 color) 218 { 219 /* 220 r g b 221 0: 0 0 0 // black 222 1: 0 0 aa // dark blue 223 2: 0 aa 0 // dark green 224 3: 0 aa aa // cyan 225 4: aa 0 0 // dark red 226 5: aa 0 aa // purple 227 6: aa 55 0 // brown 228 7: aa aa aa // light gray 229 8: 55 55 55 // dark gray 230 9: 55 55 ff // light blue 231 a: 55 ff 55 // light green 232 b: 55 ff ff // light cyan 233 c: ff 55 55 // light red 234 d: ff 55 ff // magenta 235 e: ff ff 55 // yellow 236 f: ff ff ff // white 237 */ 238 if (color >= 0 && color < 16) 239 return color; 240 return 0; 241 } 242 243 244 void 245 console_set_color(int32 foreground, int32 background) 246 { 247 char buff[] = "\033b \033c "; 248 buff[2] = (char)translate_color(foreground); 249 buff[5] = (char)translate_color(background); 250 sInput.WriteAt(NULL, 0LL, buff, 6); 251 } 252 253 254 int 255 console_wait_for_key(void) 256 { 257 #if 0 258 // XXX: do this way and remove keyboard.cpp ? 259 // wait for a key 260 char buffer[3]; 261 ssize_t bytesRead; 262 do { 263 bytesRead = sInput.ReadAt(NULL, 0, buffer, 3); 264 if (bytesRead < 0) 265 return 0; 266 } while (bytesRead == 0); 267 #endif 268 union key key = wait_for_key(); 269 270 if (key.code.ascii == 0) { 271 switch (key.code.bios) { 272 case BIOS_KEY_UP: 273 return TEXT_CONSOLE_KEY_UP; 274 case BIOS_KEY_DOWN: 275 return TEXT_CONSOLE_KEY_DOWN; 276 case BIOS_KEY_PAGE_UP: 277 return TEXT_CONSOLE_KEY_PAGE_UP; 278 case BIOS_KEY_PAGE_DOWN: 279 return TEXT_CONSOLE_KEY_PAGE_DOWN; 280 case BIOS_KEY_HOME: 281 return TEXT_CONSOLE_KEY_HOME; 282 case BIOS_KEY_END: 283 return TEXT_CONSOLE_KEY_END; 284 default: 285 return 0; 286 } 287 } else 288 return key.code.ascii; 289 } 290 291