#include <stdlib.h>
#include <kernel/kernel.h>
#include <printf.h>
#include <wchar.h>
#include <kernel/serial.h>
#include <kernel/sys.h>
#include <kernel/console.h>
//! Determines the destination of kernel debugging messages, written using
//! _cputws() or wprintf()
/*!
* Initially this is set to modeBlue, so that the first kernel messages are
* written directly to the screen. After the first kernel driver is
* loaded, this is changed to modeConsole, so that the next _cputws()
* will try to open the console driver and write to there.
*/
enum PrintfMode printf_mode = modeBlue;
#ifdef BUFFER
static wchar_t printf_buffer[80], *ch;
#endif
int text_width, text_height;
//! Pointer to a console driver object, used once the console driver is loaded
//IStream* console;
textwin_t spew, checks;
//! Set to true when wprintf is executing
bool wprintf_lock;
textwin_t *wprintf_window = &spew;
console_t *con;
void conSetMode(enum PrintfMode mode)
{
printf_mode = mode;
//if (mode == modeBlue && console)
//console->vtbl->Release(console);
}
void conClear()
{
con->conScroll(wprintf_window, 0, wprintf_window->top - wprintf_window->bottom);
}
//! Writes a string directly to the kernel console (in "blue-screen" mode)
/*!
* \param str The string to be written
* \return Zero
*/
int _cputws_blue(textwin_t* win, const wchar_t* str)
{
while (*str)
{
switch (*str)
{
case L'\n':
win->x = win->left;
win->y++;
break;
case L'\r':
win->x = win->left;
break;
case L'\t':
win->x = (win->x + 4) & ~3;
break;
case L'\b':
if (win->x > 0)
win->x--;
break;
default:
con->conWriteChar(win, win->x, win->y, win->attrib, *str);
win->x++;
}
if (win->x >= win->right)
{
win->x = win->left;
win->y++;
}
while (win->y >= win->bottom)
con->conScroll(win, 0, -1);
//ioWriteByte(NULL, *str);
str++;
}
con->conUpdateCursor(win);
return 0;
}
void _cputws_check(const wchar_t* str)
{
_cputws_blue(&checks, str);
con->conUpdateCursor(&spew);
}
//! Writes a string directly to either the kernel console (in "blue-screen"
//! mode) or the console driver
/*!
* The value of printf_mode decides where the string will be written.
*
* \param str The string to be written
* \return Zero
*/
int _cputws(const wchar_t* str)
{
return _cputws_blue(&spew, str);
}
wint_t putwchar(wint_t c)
{
wchar_t str[2] = { c, 0 };
_cputws(str);
return c;
}
static bool kprintfhelp(void* pContext, const wchar_t* str, dword len)
{
#ifdef BUFFER
if (ch + len > printf_buffer + countof(printf_buffer) ||
*str == L'\r' || *str == L'\n')
{
_cputws_blue(wprintf_window, printf_buffer);
ch = printf_buffer;
}
wcscpy(ch, str);
ch += len;
#else
_cputws_blue(wprintf_window, str);
#endif
return true;
}
int vwprintf(const wchar_t* fmt, va_list ptr)
{
int ret;
#ifdef BUFFER
ch = printf_buffer;
#endif
ret = dowprintf(kprintfhelp, NULL, fmt, ptr);
#ifdef BUFFER
_cputws_blue(wprintf_window, printf_buffer);
#endif
return ret;
}
int wprintf(const wchar_t* fmt, ...)
{
va_list ptr;
int ret;
//while (wprintf_lock)
//;
wprintf_lock = true;
va_start(ptr, fmt);
ret = vwprintf(fmt, ptr);
va_end(ptr);
wprintf_lock = false;
return ret;
}
void conInit(int nMode)
{
con = vgaInit();
wprintf(L"Screen is %dx%d\n", text_width, text_height);
}