blob: 0ed858e25f52c9d5b12f5f1eb119674122d8895a [file] [log] [blame]
/*
* Simple text console
*
* (C) Copyright 2002 Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
#include <stdarg.h>
#include <stdio.h>
#include "types.h"
#include "font.h"
#include "console.h"
#include "fb.h"
#include "drawops.h"
#include "visual.h"
#include "clut.h"
#include "util.h"
#define PRINTF_BUFFER_SIZE 1024
#define BITMAP_SIZE 1024
static char printf_buffer[PRINTF_BUFFER_SIZE];
static const struct font *con_font;
static unsigned int con_pitch, con_charsize;
static unsigned int con_cols, con_rows;
static unsigned int con_x, con_y;
static pixel_t con_fgcolor, con_bgcolor;
static unsigned char bitmap[BITMAP_SIZE];
static unsigned int bitmap_width, bitmap_pitch, bitmap_max_width;
static unsigned int bitmap_x;
static void con_flush(void)
{
if (bitmap_width) {
expand_bitmap(bitmap_x*con_font->width, con_y*con_font->height,
bitmap_width, con_font->height, (const u8 *)bitmap,
bitmap_pitch, con_bgcolor, con_fgcolor);
bitmap_width = 0;
}
}
static void con_clear(void)
{
con_flush();
fill_rect(0, 0, con_cols*con_font->width, con_rows*con_font->height,
con_bgcolor);
}
static void con_reset(void)
{
con_flush();
con_x = 0;
con_y = 0;
con_fgcolor = idx_pixel[7];
con_bgcolor = idx_pixel[0];
con_clear();
}
static void con_scrollup(void)
{
con_flush();
copy_rect(0, 0, con_cols*con_font->width, (con_rows-1)*con_font->height,
0, con_font->height);
fill_rect(0, (con_rows-1)*con_font->height, con_cols*con_font->width,
con_font->height, con_bgcolor);
}
void con_init(const struct font *font)
{
int i;
fill_rect(0, 0, fb_var.xres, fb_var.yres, 0);
con_font = font;
con_pitch = (font->width+7)/8;
con_charsize = con_pitch*font->height;
con_cols = fb_var.xres/font->width;
con_rows = fb_var.yres/font->height;
for (i = 0; i < 16; i++)
clut[i] = clut_console[i];
clut_update();
bitmap_pitch = (sizeof(bitmap)/(font->height*sizeof(unsigned long)))*
sizeof(unsigned long);
bitmap_max_width = bitmap_pitch*8;
bitmap_width = 0;
bitmap_x = 0;
con_reset();
}
static void con_newline(void)
{
con_flush();
con_x = 0;
con_y++;
if (con_y == con_rows) {
con_y--;
con_scrollup();
}
}
static void con_store_char(unsigned char c)
{
const unsigned char *src;
unsigned char *dst;
int y;
if (bitmap_width+con_font->width > bitmap_max_width)
con_flush();
if (!bitmap_width)
bitmap_x = con_x;
src = con_font->data+c*con_charsize;
switch (con_font->width) {
case 4:
dst = bitmap+bitmap_width/8;
if (bitmap_width & 4) {
for (y = 0; y < con_font->height; y++) {
*dst |= *src++ & 0x0f;
dst += bitmap_pitch;
}
} else {
for (y = 0; y < con_font->height; y++) {
*dst = *src++ & 0xf0;
dst += bitmap_pitch;
}
}
break;
case 8:
dst = bitmap+bitmap_width/8;
for (y = 0; y < con_font->height; y++) {
*dst = *src++;
dst += bitmap_pitch;
}
break;
case 12:
dst = bitmap+bitmap_width/8;
if (bitmap_width & 4) {
for (y = 0; y < con_font->height; y++) {
unsigned char d = *src++;
dst[0] |= d >> 4;
dst[1] = d << 4 | *src++ >> 4;
dst += bitmap_pitch;
}
} else {
for (y = 0; y < con_font->height; y++) {
dst[0] = *src++;
dst[1] = *src++ & 0xf0;
dst += bitmap_pitch;
}
}
break;
case 16:
dst = bitmap+bitmap_width/8;
for (y = 0; y < con_font->height; y++) {
dst[0] = *src++;
dst[1] = *src++;
dst += bitmap_pitch;
}
break;
default:
Fatal("Fontwidth %d is not yet supported\n", con_font->width);
}
bitmap_width += con_font->width;
}
static void con_do_putc(unsigned char c)
{
switch (c) {
case '\n':
con_newline();
break;
default:
con_store_char(c);
con_x++;
if (con_x == con_cols)
con_newline();
break;
}
}
void con_putc(char c)
{
con_do_putc(c);
con_flush();
}
void con_puts(const char *s)
{
unsigned char c;
while ((c = *s++))
con_do_putc(c);
con_flush();
}
void con_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap);
va_end(ap);
con_puts(printf_buffer);
}