www.pudn.com > COS0.0.1.rar > vtext.c
/*
vtext.c - Text mode vga stuff
Author: Paul Barker
Part of: COS
Created: 28/10/04
Last Modified: 05/11/04
Copyright (C) 2004 Paul Barker
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
(See file "Copying")
*/
#include
#include
#include
#include
#include
static vtext_cursor_t position;
static vtext_cursor_t extent;
static u8_t attrib;
/* current cursor position */
#define CURRENT_POSN() (VGA_START + 2 * (position.x + (extent.x * position.y)))
#define TAB_SPACES 8
void vtext_set_hw_cursor()
{
u16_t pos = (position.y * extent.x) + position.x;
u8_t orig;
// Save original contents of CRT address register.
orig = inb_p(VGA_AREG);
// Set the high cursor location byte
outb_p(VGA_CURSOR_LOC_HIGH_REG, VGA_AREG);
outb_p((pos>>8) & 0xff, VGA_DREG);
// Set the low cursor location byte
outb_p(VGA_CURSOR_LOC_LOW_REG, VGA_AREG);
outb_p(pos & 0xff, VGA_DREG);
// Restore contents of the CRT address register
outb(orig, VGA_AREG);
}
void vtext_get_hw_cursor()
{
u8_t orig;
u16_t pos;
// Save original contents of CRT address register.
orig = inb_p(VGA_AREG);
// Get the high cursor location byte
outb_p(VGA_CURSOR_LOC_HIGH_REG, VGA_AREG);
pos = (inb_p(VGA_DREG) << 8);
// Get the low cursor location byte
outb_p(VGA_CURSOR_LOC_LOW_REG, VGA_AREG);
pos += inb_p(VGA_DREG);
// Restore contents of the CRT address register
outb(orig, VGA_AREG);
position.x = pos % extent.x;
position.y = pos / extent.x;
}
void vtext_set_cursor(vtext_cursor_t cur)
{
position = cur;
vtext_set_hw_cursor();
}
vtext_cursor_t vtext_get_cursor()
{
return position;
}
vtext_cursor_t vtext_get_extent()
{
return extent;
}
void vtext_set_attrib(u8_t at)
{
attrib = at;
}
u8_t vtext_get_attrib()
{
return attrib;
}
void vtext_init()
{
position.x = position.y = 0;
extent.x = VGA_NCOLS;
extent.y = VGA_NROWS;
}
/* clear video memory */
count_t vtext_clear()
{
char_t* p = VGA_START;
count_t x, y;
count_t i = 0;
for (y = 0; y < extent.y; y++)
{
for (x = 0; x < extent.x; x++)
{
*p++ = ' '; /* clear character */
*p++ = attrib; /* set current attribute */
++i; /* increment counter */
}
}
position.x = position.y = 0;
vtext_set_hw_cursor();
return i;
}
/* scroll video memory */
void vtext_scroll()
{
count_t x;
char_t* p = (char_t*)(2 * extent.x * (extent.y - 1));
memcpy(VGA_START, VGA_START + 2 * extent.x,
(count_t)p);
p += (iptr_t)VGA_START;
for (x = 0; x < extent.x; x++)
{
*p++ = ' '; /* clear character */
*p++ = attrib; /* set current attribute */
}
}
/* moves the cursor to the next position */
void vtext_next()
{
position.x++;
if (position.x >= extent.x)
{
position.x = 0;
position.y++;
if (position.y >= extent.y)
{
vtext_scroll();
position.y--;
}
}
vtext_set_hw_cursor();
}
/* raw output - no ctrl character parsing */
void vtext_output(char_t ch)
{
char_t* p = CURRENT_POSN();
*p++ = ch;
*p = attrib;
vtext_next();
}
/*------------------------------------------------------------------------
control characters
------------------------------------------------------------------------*/
void vtext_ht()
{
count_t tomove = TAB_SPACES - (position.x % TAB_SPACES);
char_t* p = CURRENT_POSN();
if ((position.x + tomove) < extent.x)
{
while (tomove--)
{
*p++ = ' ';
*p++ = attrib;
}
position.x += tomove;
}
}
void vtext_bs()
{
char_t* p = CURRENT_POSN() - 2;
if (position.x)
{
*p++ = ' ';
*p = attrib;
--(position.x);
}
}
/* vertical tab starts a new line at the current position */
void vtext_vt()
{
char_t* p = CURRENT_POSN();
count_t n;
position.y++;
/* handle scrolling */
if (position.y >= extent.y)
{
vtext_scroll();
position.y -= 2;
p = CURRENT_POSN();
position.y++;
}
/* fill a blank line upto the same place on the next line */
for (n = 0; n < extent.y; n++)
{
*p++ = ' ';
*p++ = attrib;
}
}
void vtext_lf()
{
char_t* p = CURRENT_POSN();
/* pad to end of line */
while (position.x < extent.x)
{
*p++ = ' ';
*p++ = attrib;
position.x++;
}
/* start a new line */
position.x = 0;
position.y++;
if (position.y >= extent.y)
{
vtext_scroll();
position.y--;
}
}
void vtext_write(char_t ch)
{
switch (ch)
{
case ASCII_NUL: /* padding character */
case ASCII_SOH: /* all these aren't handled yet */
case ASCII_STX:
case ASCII_ETX:
case ASCII_EOT:
case ASCII_ENQ:
case ASCII_ACK:
case ASCII_BEL:
case ASCII_CR:
case ASCII_SO:
case ASCII_SI:
case ASCII_DLE:
case ASCII_DC1:
case ASCII_DC2:
case ASCII_DC3:
case ASCII_DC4:
case ASCII_NAK:
case ASCII_SYN:
case ASCII_ETB:
case ASCII_CAN:
case ASCII_EM:
case ASCII_FS:
case ASCII_GS:
case ASCII_RS:
case ASCII_US:
case ASCII_FF:
case ASCII_SUB:
case ASCII_ESC: /* should be handled by caller */
break;
case ASCII_LF: /* line feed (new line) */
vtext_lf();
break;
case ASCII_BS: /* backspace */
vtext_bs();
break;
case ASCII_HT: /* horizontal tab */
vtext_ht();
break;
case ASCII_VT: /* vertical tab */
vtext_vt();
break;
default: /* all other characters */
vtext_output(ch);
}
}
/* pos.x = 0xFF means read current position */
int_t vtext_read(vtext_cursor_t pos)
{
if (pos.x == 0xFF)
pos = position;
if ((pos.x >= extent.x) || (pos.y >= extent.y))
return -1;
return *( (char_t*)(VGA_START + 2 * (pos.x + (extent.x * pos.y))) );
}
/*
TODO: Header file.
When this is finished, write printk()
*/