All pastes #934641 Raw Edit

Miscellany

public cpp v1 · immutable
·published 2008-03-08 23:47 UTC
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);	}}