1 /* 2 * Copyright 2007-2010, 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 static bool sForceBW = false; // force black & white for Milan 20 21 22 // TOS emulates a VT52 23 24 class ConsoleHandle : public CharHandle { 25 public: 26 ConsoleHandle(); 27 28 virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, 29 size_t bufferSize); 30 virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, 31 size_t bufferSize); 32 }; 33 34 class InputConsoleHandle : public ConsoleHandle { 35 public: 36 InputConsoleHandle(); 37 38 virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, 39 size_t bufferSize); 40 41 void PutChar(char c); 42 void PutChars(const char *buffer, int count); 43 char GetChar(); 44 45 private: 46 enum { BUFFER_SIZE = 32 }; 47 48 char fBuffer[BUFFER_SIZE]; 49 int fStart; 50 int fCount; 51 }; 52 53 54 static InputConsoleHandle sInput; 55 static ConsoleHandle sOutput; 56 FILE *stdin, *stdout, *stderr; 57 58 59 ConsoleHandle::ConsoleHandle() 60 : CharHandle() 61 { 62 } 63 64 65 ssize_t 66 ConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *buffer, 67 size_t bufferSize) 68 { 69 // don't seek in character devices 70 // not implemented (and not yet? needed) 71 return B_ERROR; 72 } 73 74 75 ssize_t 76 ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer, 77 size_t bufferSize) 78 { 79 const char *string = (const char *)buffer; 80 size_t i; 81 82 // be nice to our audience and replace single "\n" with "\r\n" 83 84 for (i = 0; i < bufferSize; i++) { 85 if (string[i] == '\0') 86 break; 87 if (string[i] == '\n') 88 Bconout(fHandle, '\r'); 89 Bconout(fHandle, string[i]); 90 } 91 92 return bufferSize; 93 } 94 95 96 // #pragma mark - 97 98 99 InputConsoleHandle::InputConsoleHandle() 100 : ConsoleHandle() 101 , fStart(0) 102 , fCount(0) 103 { 104 } 105 106 107 ssize_t 108 InputConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer, 109 size_t bufferSize) 110 { 111 char *buffer = (char*)_buffer; 112 113 // copy buffered bytes first 114 int bytesTotal = 0; 115 while (bufferSize > 0 && fCount > 0) { 116 *buffer++ = GetChar(); 117 bytesTotal++; 118 bufferSize--; 119 } 120 121 // read from console 122 if (bufferSize > 0) { 123 ssize_t bytesRead = ConsoleHandle::ReadAt(NULL, 0, buffer, bufferSize); 124 if (bytesRead < 0) 125 return bytesRead; 126 bytesTotal += bytesRead; 127 } 128 129 return bytesTotal; 130 } 131 132 133 void 134 InputConsoleHandle::PutChar(char c) 135 { 136 if (fCount >= BUFFER_SIZE) 137 return; 138 139 int pos = (fStart + fCount) % BUFFER_SIZE; 140 fBuffer[pos] = c; 141 fCount++; 142 } 143 144 145 void 146 InputConsoleHandle::PutChars(const char *buffer, int count) 147 { 148 for (int i = 0; i < count; i++) 149 PutChar(buffer[i]); 150 } 151 152 153 char 154 InputConsoleHandle::GetChar() 155 { 156 if (fCount == 0) 157 return 0; 158 159 fCount--; 160 char c = fBuffer[fStart]; 161 fStart = (fStart + 1) % BUFFER_SIZE; 162 return c; 163 } 164 165 166 // #pragma mark - 167 168 169 static void 170 dump_colors() 171 { 172 int bg, fg; 173 dprintf("colors:\n"); 174 for (bg = 0; bg < 16; bg++) { 175 for (fg = 0; fg < 16; fg++) { 176 console_set_color(fg, bg); 177 dprintf("#"); 178 } 179 console_set_color(0, 15); 180 dprintf("\n"); 181 } 182 } 183 184 185 static int32 186 dump_milan_modes(SCREENINFO *info, uint32 flags) 187 { 188 dprintf("mode: %d '%s':\n flags %08lx @%08lx %dx%d (%dx%d)\n%d planes %d colors fmt %08lx\n", 189 info->devID, info->name, info->scrFlags, info->frameadr, 190 info->scrWidth, info->scrHeight, 191 info->virtWidth, info->virtHeight, 192 info->scrPlanes, info->scrColors, info->scrFormat); 193 return ENUMMODE_CONT; 194 } 195 196 status_t 197 console_init(void) 198 { 199 sInput.SetHandle(DEV_CONSOLE); 200 sOutput.SetHandle(DEV_CONSOLE); 201 202 // now that we're initialized, enable stdio functionality 203 stdin = (FILE *)&sInput; 204 stdout = stderr = (FILE *)&sOutput; 205 206 if (tos_find_cookie('_MIL')) { 207 dprintf("Milan detected... forcing black & white\n"); 208 /* 209 dprintf("Getrez() = %d\n", Getrez()); 210 Setscreen(-1, &dump_milan_modes, MI_MAGIC, CMD_ENUMMODES); 211 Setscreen((void*)-1, (void*)-1, 0, 0); 212 */ 213 sForceBW = true; 214 } 215 //dump_colors(); 216 217 return B_OK; 218 } 219 220 221 // #pragma mark - 222 223 224 void 225 console_clear_screen(void) 226 { 227 sInput.WriteAt(NULL, 0LL, "\033E", 2); 228 } 229 230 231 int32 232 console_width(void) 233 { 234 int columnCount = 80; //XXX: check video mode 235 return columnCount; 236 } 237 238 239 int32 240 console_height(void) 241 { 242 int lineCount = 25; //XXX: check video mode 243 return lineCount; 244 } 245 246 247 void 248 console_set_cursor(int32 x, int32 y) 249 { 250 char buff[] = "\033Y "; 251 x = MIN(79,MAX(0,x)); 252 y = MIN(24,MAX(0,y)); 253 buff[3] += (char)x; 254 buff[2] += (char)y; 255 sInput.WriteAt(NULL, 0LL, buff, 4); 256 } 257 258 259 static int 260 translate_color(int32 color) 261 { 262 /* 263 r g b 264 0: 0 0 0 // black 265 1: 0 0 aa // dark blue 266 2: 0 aa 0 // dark green 267 3: 0 aa aa // cyan 268 4: aa 0 0 // dark red 269 5: aa 0 aa // purple 270 6: aa 55 0 // brown 271 7: aa aa aa // light gray 272 8: 55 55 55 // dark gray 273 9: 55 55 ff // light blue 274 a: 55 ff 55 // light green 275 b: 55 ff ff // light cyan 276 c: ff 55 55 // light red 277 d: ff 55 ff // magenta 278 e: ff ff 55 // yellow 279 f: ff ff ff // white 280 */ 281 // cf. http://www.fortunecity.com/skyscraper/apple/308/html/chap4.htm 282 static const char cmap[] = { 283 15, 4, 2, 6, 1, 5, 3, 7, 284 8, 12, 10, 14, 9, 13, 11, 0 }; 285 286 if (color < 0 && color >= 16) 287 return 0; 288 return cmap[color]; 289 //return color; 290 } 291 292 293 void 294 console_set_color(int32 foreground, int32 background) 295 { 296 char buff[] = "\033b \033c "; 297 if (sForceBW) { 298 if (background == 0) 299 foreground = 15; 300 else { 301 background = 15; 302 foreground = 0; 303 } 304 305 } 306 buff[2] += (char)translate_color(foreground); 307 buff[5] += (char)translate_color(background); 308 sInput.WriteAt(NULL, 0LL, buff, 6); 309 } 310 311 312 void 313 console_show_cursor(void) 314 { 315 } 316 317 318 void 319 console_hide_cursor(void) 320 { 321 } 322 323 324 int 325 console_wait_for_key(void) 326 { 327 #if 0 328 // XXX: do this way and remove keyboard.cpp ? 329 // wait for a key 330 char buffer[3]; 331 ssize_t bytesRead; 332 do { 333 bytesRead = sInput.ReadAt(NULL, 0, buffer, 3); 334 if (bytesRead < 0) 335 return 0; 336 } while (bytesRead == 0); 337 #endif 338 union key key = wait_for_key(); 339 340 if (key.code.ascii == 0) { 341 switch (key.code.bios) { 342 case BIOS_KEY_UP: 343 return TEXT_CONSOLE_KEY_UP; 344 case BIOS_KEY_DOWN: 345 return TEXT_CONSOLE_KEY_DOWN; 346 case BIOS_KEY_PAGE_UP: 347 return TEXT_CONSOLE_KEY_PAGE_UP; 348 case BIOS_KEY_PAGE_DOWN: 349 return TEXT_CONSOLE_KEY_PAGE_DOWN; 350 case BIOS_KEY_HOME: 351 return TEXT_CONSOLE_KEY_HOME; 352 case BIOS_KEY_END: 353 return TEXT_CONSOLE_KEY_END; 354 default: 355 return 0; 356 } 357 } else 358 return key.code.ascii; 359 } 360 361