luxos/SysCore/lib/conio.c

694 lines
19 KiB
C

#include <stdarg.h>
#include <conio.h>
#include <hal.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "../memory/mmngr_ph.h"
unsigned char ColorDefault;
unsigned char ConsoleScreenInstalled = 0;
/*char hex[] = "0123456789ABCDEF"; */
/* External routines the user must specify */
void (*_console_cursor)(int x, int y);
void (*_console_putc)(int x, int y, unsigned char c);
unsigned char (*_console_getc) (int x, int y);
void (*_console_putcolor)(int x, int y, unsigned char color);
unsigned char (*_console_getcolor)(int x, int y);
/* Other external routines */
extern void *memset(void *dest, char val, int count);
/* Important variables */
UPoint ScreenSize, Cursor;
void ConsoleInstall(ConsoleScreen screen)
{
_console_cursor = screen.cursor;
_console_putc = screen.putc;
_console_getc = screen.getc;
_console_putcolor = screen.putcolor;
_console_getcolor = screen.getcolor;
ScreenSize.X = screen.width;
ScreenSize.Y = screen.height;
ColorDefault = screen.defcolors;
Cursor.X = 0; Cursor.Y = 0;
ConsoleUpdateCursor (Cursor, _NORMALCURSOR);
ConsoleScreenInstalled = 1;
}
unsigned char _cuc_ex_type;
UPoint _cuc_ex_pos;
void ConsoleUpdateCursor(UPoint position, unsigned char type)
{
if (_cuc_ex_type == _SOLIDCURSOR)
(*_console_putcolor) (
_cuc_ex_pos.X,
_cuc_ex_pos.Y,
0xFF - (*_console_getcolor)(_cuc_ex_pos.X, _cuc_ex_pos.Y)
);
if (_cuc_ex_type == _NORMALCURSOR && type != _NORMALCURSOR)
(*_console_cursor)(ScreenSize.X, ScreenSize.Y);
switch (type) {
case _NORMALCURSOR:
(*_console_cursor)(position.X, position.Y);
break;
case _SOLIDCURSOR:
(*_console_putcolor) (
position.X, position.Y,
0xFF - (*_console_getcolor)(position.X, position.Y)
); break;
case _NOCURSOR:
(*_console_cursor)(ScreenSize.X, ScreenSize.Y); break;
}
_cuc_ex_type = type;
_cuc_ex_pos.X = position.X;
_cuc_ex_pos.Y = position.Y;
}
void ConsoleScroll(unsigned lines)
{
movetext(0, (int)lines, ScreenSize.X, ScreenSize.Y, 0, 0);
}
void ConsoleSetDefaultColors (unsigned char background, unsigned char foreground)
{
ColorDefault = (foreground & 0xF) | (background<<4);
}
void ConsoleSetCursorPosition (Point rel, unsigned char display)
{
Point abs = { (int)(Cursor.X) + rel.X,
(int)(Cursor.Y) + rel.Y };
while (abs.X < 0) { abs.X += (int)ScreenSize.X; abs.Y--; }
while (abs.X >= (int)ScreenSize.X) { abs.X -= (int)ScreenSize.X; abs.Y++; }
if (abs.Y < 0) abs.Y = 0;
if (abs.Y >= (int)ScreenSize.Y) {
ConsoleScroll((unsigned)abs.Y - ScreenSize.Y + 1);
abs.Y = (int)ScreenSize.Y - 1;
}
Cursor.X = (unsigned)abs.X;
Cursor.Y = (unsigned)abs.Y;
if (display) ConsoleUpdateCursor(Cursor, _cuc_ex_type);
}
/**Inline function to return the index of next word\n
Parameters:\n
- const char* string = string to check for words\n
- int len = length of string\n
- int current = current cursor position\n
- int plus = direction (0:back, 1:foward)\n*/
inline int __cgets__skip_word(const char* string, int len, int current, int plus)
{
int tmp = current;
if (!plus) {
--tmp;
while ((isspace((unsigned char)string[tmp]) || ispunct((unsigned char)string[tmp])) && tmp > 0) --tmp;
while (isalnum((unsigned char)string[tmp]) && tmp > 0) --tmp;
}
else {
++tmp;
while (isalnum((unsigned char)string[tmp]) && tmp < len) ++tmp;
while ((isspace((unsigned char)string[tmp]) || ispunct((unsigned char)string[tmp])) && tmp < len) ++tmp;
}
if (tmp != 0 && plus==0) tmp++;
return tmp;
}
/**Macro which defines the INSERT key behaviour (overwrite/insert mode)*/
#define __cgets__key_insert() OverWrite = 1 - OverWrite
/**Macro which defines the ENTER key behaviour*/
#define __cgets__key_enter() { ConsoleSetCursorPosition((Point){Len, 0}, 1); return Len; }
/**Move the cursor to the left/right\n
Parameters:\n
- const char* string = the character string to work with\n
- int direction = direction to go (0: backward, 1:foward)\n
- int len = length of string\n
- int* cursor = pointer to cursor integer\n
- int word = move one word (1) or just one character(0)\n */
inline void __cgets__move_cursor(const char* string, int direction, int len, int* cursor, int word)
{
int dtmp = (direction) ? 1 : -1;
if ((*cursor <= 0 && direction == 0) || (*cursor >= len && direction == 1)) return;
// Skip one word (e.g. CTRL is pressed)
if (word) {
int tmp = __cgets__skip_word(string, len, *cursor+dtmp, direction);
*cursor = tmp;
}
else {
*cursor += dtmp;
}
}
/**Deletes the substring between index_start and index_end-1, also updates string length\n
Parameters:\n
- char* string = the character string to work with\n
- int index_start = where to start\n
- int index_end = where to stop\n
- int* len = pointer to length of string\n*/
inline void __cgets__delete (char* string, int index_start, int index_end, int* len)
{
for (; index_end <= *len+1; index_start++, index_end++)
string[index_start] = string[index_end];
*len = strlen(string);
}
/**Inserts a char in position of index, also updates string length\n
Parameters:\n
- char* string = the character string to work with\n
- int index = where to insert\n
- char c = characer to insert\n
- int* len = pointer to length of string\n*/
inline void __cgets__insert (char* string, int index, char c, int* len)
{
*len = *len+1;
int i;
for (i = *len-1; i > index; i--)
string[i] = string[i-1];
string[index] = c;
string[*len] = 0;
}
int cgets(char* string, int maxlen)
{
unsigned char OverWrite = 0;
memset ((void*)string, 0, maxlen);
int Len = 0, CurPos = 0;
kb_key Key;
UPoint CursorSave;
while (Len < maxlen)
{
// Display string on the screen
CursorSave = Cursor;
ConsoleUpdateCursor(Cursor, _NOCURSOR);
cputs(string); clreol();
// Display cursor in right position
Cursor = CursorSave;
ConsoleSetCursorPosition((Point){CurPos, 0}, 0);
ConsoleUpdateCursor(Cursor, (OverWrite) ? _SOLIDCURSOR : _NORMALCURSOR);
// Restore cursor
Cursor = CursorSave;
// Get key and process
Key = getkey();
switch (Key.scancode) {
// Switch overwrite/insert
case KB_KEY_INSERT: __cgets__key_insert(); break;
// Finish writing (return)
case KB_KEY_ENTER: __cgets__key_enter(); break;
case KB_KEY_NUMPAD_ENTER: __cgets__key_enter(); break;
// Left
case KB_KEY_LEFT:
__cgets__move_cursor(string, 0, Len, &CurPos, ((Key.status & KB_KEY_LCTRL) || (Key.status & KB_KEY_RCTRL)));
break;
// Right
case KB_KEY_RIGHT:
__cgets__move_cursor(string, 1, Len, &CurPos, ((Key.status & KB_KEY_LCTRL) || (Key.status & KB_KEY_RCTRL)));
break;
case KB_KEY_HOME:
CurPos = 0;
break;
case KB_KEY_END:
CurPos = Len;
break;
case KB_KEY_BACKSPACE:
if (CurPos > 0) {
int tmp;
if ((Key.status & KB_KEY_LCTRL) || (Key.status & KB_KEY_RCTRL))
tmp = __cgets__skip_word(string, Len, CurPos, 0);
else tmp = CurPos-1;
__cgets__delete(string, tmp, CurPos, &Len);
CurPos = tmp;
};
break;
// Delete
case KB_KEY_DELETE:
if (CurPos < Len) {
int tmp;
// If CTRL is pressed, foward one word
if ((Key.status & KB_KEY_LCTRL) || (Key.status & KB_KEY_RCTRL))
tmp = __cgets__skip_word(string, Len, CurPos, 1);
else tmp = CurPos+1;
__cgets__delete(string, CurPos, tmp, &Len);
}
break;
// Text character
default:
if (isprint(Key.character)) {
// fix CAPS bug
if ((Key.lights & KB_KEY_CAPS) && islower((unsigned char)Key.character))
Key.character = toupper(Key.character);
// Cursor is at the end of the string
if (CurPos == Len) {
Len++; string[Len-1] = Key.character;
string[Len] = 0;
}
// Cursor is not at the end in OverWrite mode
else if (OverWrite) string[CurPos] = Key.character;
// Cursor is not at the end in Insert mode
else __cgets__insert(string, CurPos, Key.character, &Len);
// Increase cursor position
CurPos++;
}
break;
}
}
__cgets__key_enter();
}
void clreol()
{
int counter = Cursor.X;
while (counter < ScreenSize.X) {
(*_console_putc)(counter, Cursor.Y, 0);
++counter;
}
}
void clrscr()
{
for (Cursor.Y = 0; Cursor.Y < ScreenSize.Y; Cursor.Y++)
for (Cursor.X = 0; Cursor.X < ScreenSize.X; Cursor.X++) {
_console_putc(Cursor.X, Cursor.Y, 0);
_console_putcolor(Cursor.X, Cursor.Y, ColorDefault);
}
Cursor.X = 0; Cursor.Y = 0;
}
void getpass (char* string)
{}
int gettext (int left, int top, int right, int bottom, unsigned char* dest)
{
if (left < 0 || top < 0 || (unsigned)right > ScreenSize.X || (unsigned)bottom > ScreenSize.Y)
return 0;
int i, j;
for (i = top; i < bottom; i++)
for (j = left; j < right; j++) {
*dest++ = (*_console_getc)(j, i);
*dest++ = (*_console_getcolor)(j, i);
}
return 1;
}
void gotoxy (int x, int y)
{
Cursor.X = x; Cursor.Y = y;
ConsoleUpdateCursor(Cursor, _cuc_ex_type);
}
int cputs(const char* str)
{
while (*str != 0) {
putch(*str); str++;
}
return (int)*str;
}
int getch()
{
kb_key k;
k = getkey();
if ((k.lights & KB_KEY_CAPS) && k.character >= 'a' && k.character <= 'z')
return (int)(k.character - 'a' + 'A');
return k.character;
}
int getche()
{
int ret = getch();
putch((char)ret);
return ret;
}
/*TODO: kbhit()*/
void movetext(int left, int top, int right, int bottom, int destleft, int desttop)
{
int destright = destleft + right - left;
int destbottom = desttop + bottom - top;
// Sanity check
if (left < 0 || top < 0 || (unsigned)right > ScreenSize.X ||
(unsigned)bottom > ScreenSize.Y || destleft < 0 || desttop < 0)
return;
// Allocate memory
int needed_mem = ((right-left) * (bottom - top) * 2) / pmmngr_get_block_size();
unsigned char* map = (unsigned char*) pmmngr_alloc_blocks(needed_mem);
// Save box in a buffer
gettext(left, top, right, bottom, map);
// Empty box
int i, j;
for (i = top; i < bottom; i++)
for (j = left; j < right; j++) {
(*_console_putc)(j, i, 0);
(*_console_putcolor)(j, i, ColorDefault);
}
// Put new text
puttext(destleft, desttop, destright, destbottom, map);
// Free used memory
pmmngr_free_blocks((unsigned)map, needed_mem * pmmngr_get_block_size());
}
int putch(const char c)
{
switch(c)
{
case '\n': ConsoleSetCursorPosition((Point){0, 1}, 0);
break;
case '\r': Cursor.X = 0;
break;
case '\t': ConsoleSetCursorPosition((Point){6 - (Cursor.X % 6), 0}, 0);
break;
case '\b': ConsoleSetCursorPosition((Point){-1, 0}, 0);
(*_console_putc)(Cursor.X, Cursor.Y, 0);
break;
default:
(*_console_putc)(Cursor.X, Cursor.Y, c);
(*_console_putcolor)(Cursor.X, Cursor.Y, ColorDefault);
ConsoleSetCursorPosition((Point){1,0}, 0);
break;
}
return c;
}
int puttext(int left, int top, int right, int bottom, unsigned char* src)
{
if (left < 0 || top < 0 || (unsigned)right > ScreenSize.X || (unsigned)bottom > ScreenSize.Y)
return 0;
int i,j;
for (i = top; i < bottom; i++)
for (j = left; j < right; j++) {
(*_console_putc)(j, i, *src++);
(*_console_putcolor)(j, i, *src++);
}
return 1;
}
void _setcursortype (int cursor)
{
ConsoleUpdateCursor(Cursor, cursor);
}
int wherex() { return (int)Cursor.X; };
int wherey() { return (int)Cursor.Y; };
int cprintf(const char* str, ...)
{
if (!ConsoleScreenInstalled) return -1;
if (!str || !*str) return 0;
va_list args;
va_start (args, str);
unsigned i, len = strlen(str);
unsigned char temp_col = ColorDefault;
for (i = 0; i < len; i++)
switch (str[i]) {
case '%':
switch (str[i+1]) {
// Character
case 'c': {char c = va_arg (args, char);
putch(c); i++; break;}
// String
case 's': {int* c = (int*) va_arg (args, char*);
cputs((const char*)c); i++; break;}
// Integers
case 'd':
case 'i': {int c = va_arg(args, int);
char temp[32];
itoa(c, temp, 10);
cputs(temp);
i++; break;}
// Integers - hex
case 'X':
case 'x': {int c = va_arg(args, int);
char temp[32];
uitoa(c, temp, 16);
cputs(temp);
i++; break;}
// Integers - unsigned
case 'u': { int c = va_arg(args, unsigned int);
char temp[32];
uitoa(c, temp, 10);
cputs(temp);
i++; break;
}
case '#': { char temp[] = {str[i+2], str[i+3], 0};
ColorDefault = (unsigned char) atox(temp);
i+=3;
break; }
default: va_end(args); return 1;
};
break;
default: putch(str[i]); break;
}
va_end(args);
ColorDefault = temp_col;
return i;
}
/*
void graphics_init()
{
}
// Change cursor position
void text_mode_cursor(int x, int y)
{
unsigned temp = y*current_mode_width + x;
outportb (0x3D4, 14);
outportb (0x3D5, temp >> 8);
outportb (0x3D4, 15);
outportb (0x3D5, temp);
}
// Set the default colors; max is 0x0F
void set_default_colors(unsigned char back, unsigned char fore)
{
if (back < 0x10) ColorDefaultBack = back;
if (fore < 0x10) ColorDefaultFore = fore;
}
// Clear screen, and set font to default font
void clrscr()
{
unsigned char font = ColorDefaultFore | (ColorDefaultBack<<4);
int i = 0;
for (i = 0; i < current_mode_width*current_mode_height; i++)
{ TextVideoRam[2*i] = 0;
TextVideoRam[2*i+1] = font;
}
cursor_x = 0; cursor_y = 0;
}
void scroll(int n)
{
memcpy(TextVideoRam,
TextVideoRam+(current_mode_width*n*2),
2*current_mode_width*(current_mode_height - n));
unsigned char blank = ColorDefaultFore | (ColorDefaultBack<<4);
int i;
for (i = current_mode_width*(current_mode_height-n);
i < current_mode_width*current_mode_height; i++){
TextVideoRam[2*i] = 0;
TextVideoRam[2*i+1] = blank;
}
}
void prev_line()
{
cursor_x = 79;
if (--cursor_y < 0) {
cursor_y = 0; cursor_x=0;
}
}
void next_line()
{
cursor_x = 0;
if (++cursor_y >=25) {
cursor_y = 24; scroll(1);
}
}
// Put character on screen in specified position; can use different font colors
void putc_pos_font(int x, int y, char c, unsigned char back, unsigned char fore)
{
TextVideoRam[2*(y*current_mode_width+x)] = c;
TextVideoRam[2*(y*current_mode_width+x)+1] = fore|(back<<4);
}
// Put character on screen in specified position; use default font colors
void putc_pos(int x, int y, char c)
{
TextVideoRam[2*(y*current_mode_width+x)] = c;
}
// Put character on screen in the current cursor position; different font colors
void putc_font(char c, unsigned char back, unsigned char fore)
{
if (cursor_x >= current_mode_width) next_line();
if (c == '\n') {next_line(); return;};
TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)] = c;
TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)+1] = fore|(back<<4);
cursor_x++;
}
// Put character on screen in the current cursor position; default font colors
void putc(char c)
{
if (cursor_x >= current_mode_width) next_line();
if (c == '\n') {next_line(); return;};
if (c == '\r') {cursor_x = 0; return; };
TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)] = c;
cursor_x++;
}
// Put string on screen in specified position; can use different font colors
void puts_pos_font(int x, int y, const char *str, unsigned char back, unsigned char fore)
{
int i;
for (i = 0; str[i] != 0; i++)
putc_pos_font(x+i, y, str[i], back, fore);
}
// Put string on screen in specified position; use default font colors
void puts_pos(int x, int y, const char *str)
{
int i;
for (i = 0; str[i] != 0; i++)
putc_pos(x+i, y, str[i]);
}
void puts(const char *str)
{
int i;
for (i = 0; str[i] != 0; i++)
putc(str[i]);
}
void puts_font(const char *str, unsigned char back, unsigned char fore)
{
int i;
for (i = 0; str[i] != 0; i++)
putc_font(str[i], back, fore);
}
void put_hex(unsigned int alpha)
{
char nr[9];
int i;
for (i = 7; i >= 0; i--) {
nr[i] = hex[alpha%16];
alpha /= 16;
}
nr[8] = 0;
puts(nr);
}
void put_hex_pos(int x, int y, unsigned int alpha)
{
char nr[9];
int i;
for (i = 7; i >= 0; i--) {
nr[i] = hex[alpha%16];
alpha /= 16;
}
nr[8] = 0;
puts_pos(x,y,nr);
}
void put_bin (int x, int y, unsigned char xz)
{
int i;
char arr[9] = {0,0,0,0,0,0,0,0,0};
for(i=7; i>=0; i--) {
arr[i] = (xz%2) + '0'; xz/=2;
}
puts_pos (x, y, arr);
}
*/