rendered paste body/* Copyright 2007 Mike Smith * Redistribution is allowed under the conditions of the * Creative Commons Attribution-NonCommercial-NoDerivs 3.0 license. * You can find a copy of this license at the following URL: * http://creativecommons.org/licenses/by-nc-nd/3.0/ */#include <lib/TextIO.hpp>#include <lib/PortIO.hpp>#include <lib/Varargs.hpp>#include <lib/String.hpp>#include <lib/Misc.hpp>#define PR_LJ 0x01#define PR_CA 0x02#define PR_SG 0x04#define PR_32 0x08#define PR_16 0x10#define PR_WS 0x20#define PR_LZ 0x40#define PR_BUFLEN 37namespace TextIO{ uint_8 attributes = 0x07; uint_8 cx, cy; void scroll() { if (cy >= 25) { Misc::copy <uint_16> ((uint_16 *)(0xB8000 + 80 * 2), (uint_16 *)(0xB8000), (24 * 80 * 2)); Misc::set <uint_16> ((uint_16 *)(0xB8000 + (24 * 80 * 2)), 0, 80); cy = 24; cx = 0; } } void move_cursor() { uint_16 position = (cy * 80) + cx; PortIO::outportb(0x3D4, 0x0F); PortIO::outportb(0x3D5, (uint_8)(position & 0xFF)); PortIO::outportb(0x3D4, 0x0E); PortIO::outportb(0x3D5, (uint_8)((position >> 8) & 0xFF)); } void clear_screen() { for (int i = 0; i < 80 * 25; i++) { *(uint_8 *)(0xB8000 + i * 2) = '\0'; *(uint_8 *)(0xB8000 + i * 2 + 1) = attributes; } cx = cy = 0; } void goto_x(uint_8 x) { if (x < 80) cx = x; } void goto_y(uint_8 y) { if (y < 25) cy = y; } void foreground(uint_8 fg) { attributes = (attributes & 0xF0) | fg; } void background(uint_8 bg) { attributes = (attributes & 0x0F) | (bg << 4); } void putchar(char c) { switch (c) { case '\n': cx = 0; cy++; break; case '\r': cx = 0; break; case '\t': for (int i = 0; i < cx % 8; i++) putchar(' '); break; default: *(uint_8 *)(0xB8000 + (80 * cy + cx) * 2) = c; *(uint_8 *)(0xB8000 + (80 * cy + cx) * 2 + 1) = attributes; cx++; } if (cx >= 80) { cx = 0; cy++; } move_cursor(); scroll(); } void do_print(const char *fmt, va_list args) { uint_32 flags, actual_wd, given_wd; char *where, buf[PR_BUFLEN]; uint_8 state, radix; long num; state = flags = given_wd = 0; for(; *fmt; fmt++) { switch(state) { case 0: if(*fmt != '%') { putchar(*fmt); break; } state++; fmt++; case 1: if(*fmt == '%') { putchar('%'); state = flags = given_wd = 0; break; } if(*fmt == '-') { if(flags & PR_LJ) state = flags = given_wd = 0; else flags |= PR_LJ; break; } state++; if(*fmt == '0') { flags |= PR_LZ; fmt++; } case 2: if(*fmt >= '0' && *fmt <= '9') { given_wd = 10 * given_wd + (*fmt - '0'); break; } state++; case 3: if(*fmt == 'F') { // far pointers? what do you think this is, DOS? break; } if(*fmt == 'N') break; if(*fmt == 'l') { flags |= PR_32; break; } if(*fmt == 'h') { flags |= PR_16; break; } state++; case 4: where = buf + PR_BUFLEN - 1; *where = '\0'; switch(*fmt) { case 'X': flags |= PR_CA; case 'x': case 'p': case 'n': radix = 16; goto DO_NUM; case 'd': case 'i': flags |= PR_SG; case 'u': radix = 10; goto DO_NUM; case 'b': radix = 2; goto DO_NUM; case 'o': radix = 8;DO_NUM: if(flags & PR_32) num = va_arg(*(uint_8 **)&args, uint_32); else if(flags & PR_16) { if(flags & PR_SG) num = va_arg(*(uint_8 **)&args, short); else num = va_arg(*(uint_8 **)&args, uint_16); } else { if(flags & PR_SG) num = va_arg(*(uint_8 **)&args, int); else num = va_arg(*(uint_8 **)&args, uint_32); } if(flags & PR_SG) { if(num < 0) { flags |= PR_WS; num = -num; } } do { uint_32 temp; temp = (uint_32)num % radix; where--; if(temp < 10) *where = temp + '0'; else if(flags & PR_CA) *where = temp - 10 + 'A'; else *where = temp - 10 + 'a'; num = (uint_32)num / radix; } while(num != 0); goto EMIT; case 'c': flags &= ~PR_LZ; where--; *where = (uint_8)va_arg(*(uint_8 **)&args, char); actual_wd = 1; goto EMIT2; case 's': flags &= ~PR_LZ; where = va_arg(*(uint_8 **)&args, char *);EMIT: actual_wd = String::length(where); if(flags & PR_WS) actual_wd++; if((flags & (PR_WS | PR_LZ)) == (PR_WS | PR_LZ)) { putchar('-'); }EMIT2: if((flags & PR_LJ) == 0) { while(given_wd > actual_wd) { putchar(flags & PR_LZ ? '0' : ' '); given_wd--; } } if((flags & (PR_WS | PR_LZ)) == PR_WS) { putchar('-'); } while(*where != '\0') { putchar(*where++); } if(given_wd < actual_wd) given_wd = 0; else given_wd -= actual_wd; for(; given_wd; given_wd--) { putchar(' '); } break; default: break; } default: state = flags = given_wd = 0; break; } } } void print(const char *fmt, ...) { va_list args; va_start(args, fmt); do_print(fmt, args); va_end(args); }}