⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tui.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  FreeLoader
 *  Copyright (C) 1998-2003  Brian Palmer  <brianp@sginet.com>
 *
 *  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.
 */

#include <freeldr.h>

PVOID	TextVideoBuffer = NULL;
extern BOOLEAN UiMinimal;

/*
 * printf() - prints formatted text to stdout
 * originally from GRUB
 */
int printf(const char *format, ... )
{
	va_list ap;
	va_start(ap,format);
	char c, *ptr, str[16];

	while ((c = *(format++)))
	{
		if (c != '%')
		{
			MachConsPutChar(c);
		}
		else
		{
			switch (c = *(format++))
			{
			case 'd': case 'u': case 'x':
                if (c == 'x')
                    _itoa(va_arg(ap, unsigned long), str, 16);
                else
                    _itoa(va_arg(ap, unsigned long), str, 10);

				ptr = str;

				while (*ptr)
				{
					MachConsPutChar(*(ptr++));
				}
				break;

			case 'c': MachConsPutChar((va_arg(ap,int))&0xff); break;

			case 's':
				ptr = va_arg(ap,char *);

				while ((c = *(ptr++)))
				{
					MachConsPutChar(c);
				}
				break;
			case '%':
				MachConsPutChar(c);
				break;
			default:
				printf("\nprintf() invalid format specifier - %%%c\n", c);
				break;
			}
		}
	}

	va_end(ap);

	return 0;
}

BOOLEAN TuiInitialize(VOID)
{
	MachVideoClearScreen(ATTR(COLOR_WHITE, COLOR_BLACK));
	MachVideoHideShowTextCursor(FALSE);

	TextVideoBuffer = VideoAllocateOffScreenBuffer();
	if (TextVideoBuffer == NULL)
	{
		return FALSE;
	}

	return TRUE;
}

VOID TuiUnInitialize(VOID)
{
	if (UiUseSpecialEffects)
	{
		TuiFadeOut();
	}
	else
	{
		MachVideoSetDisplayMode(NULL, FALSE);
	}

	//VideoClearScreen();
	MachVideoHideShowTextCursor(TRUE);
}

VOID TuiDrawBackdrop(VOID)
{
    if (UiMinimal)
    {
        //
        // Fill in a black background
        //
        TuiFillArea(0,
                    0,
                    UiScreenWidth - 1,
                    UiScreenHeight - 1,
                    0,
                    0);

        //
        // Update the screen buffer
        //
        VideoCopyOffScreenBufferToVRAM();
        return;
    }

	//
	// Fill in the background (excluding title box & status bar)
	//
	TuiFillArea(0,
			TUI_TITLE_BOX_CHAR_HEIGHT,
			UiScreenWidth - 1,
			UiScreenHeight - 2,
			UiBackdropFillStyle,
			ATTR(UiBackdropFgColor, UiBackdropBgColor));

	//
	// Draw the title box
	//
	TuiDrawBox(0,
			0,
			UiScreenWidth - 1,
			TUI_TITLE_BOX_CHAR_HEIGHT - 1,
			D_VERT,
			D_HORZ,
			TRUE,
			FALSE,
			ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));

	//
	// Draw version text
	//
	TuiDrawText(2,
			1,
			GetFreeLoaderVersionString(),
			ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));

	//
	// Draw copyright
	//
	TuiDrawText(2,
			2,
			BY_AUTHOR,
			ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
	TuiDrawText(2,
			3,
			AUTHOR_EMAIL,
			ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));

	//
	// Draw help text
	//
	TuiDrawText(UiScreenWidth - 16, 3, /*"F1 for Help"*/"F8 for Options", ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));

	//
	// Draw title text
	//
	TuiDrawText( (UiScreenWidth / 2) - (strlen(UiTitleBoxTitleText) / 2),
			2,
			UiTitleBoxTitleText,
			ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));

	//
	// Draw status bar
	//
	TuiDrawStatusText("Welcome to FreeLoader!");

	//
	// Update the date & time
	//
	TuiUpdateDateTime();

	VideoCopyOffScreenBufferToVRAM();
}

/*
 * FillArea()
 * This function assumes coordinates are zero-based
 */
VOID TuiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, CHAR FillChar, UCHAR Attr /* Color Attributes */)
{
	PUCHAR	ScreenMemory = (PUCHAR)TextVideoBuffer;
	ULONG		i, j;

	// Clip the area to the screen
	if ((Left >= UiScreenWidth) || (Top >= UiScreenHeight))
	{
		return;
	}
	if (Right >= UiScreenWidth)
	{
		Right = UiScreenWidth - 1;
	}
	if (Bottom >= UiScreenHeight)
	{
		Bottom = UiScreenHeight - 1;
	}

	// Loop through each line and fill it in
	for (i=Top; i<=Bottom; i++)
	{
		// Loop through each character (column) in the line and fill it in
		for (j=Left; j<=Right; j++)
		{
			ScreenMemory[((i*2)*UiScreenWidth)+(j*2)] = (UCHAR)FillChar;
			ScreenMemory[((i*2)*UiScreenWidth)+(j*2)+1] = Attr;
		}
	}
}

/*
 * DrawShadow()
 * This function assumes coordinates are zero-based
 */
VOID TuiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom)
{
	PUCHAR	ScreenMemory = (PUCHAR)TextVideoBuffer;
	ULONG		Idx;

	// Shade the bottom of the area
	if (Bottom < (UiScreenHeight - 1))
	{
		if (UiScreenHeight < 34)
		{
			Idx=Left + 2;
		}
		else
		{
			Idx=Left + 1;
		}

		for (; Idx<=Right; Idx++)
		{
			ScreenMemory[(((Bottom+1)*2)*UiScreenWidth)+(Idx*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
		}
	}

	// Shade the right of the area
	if (Right < (UiScreenWidth - 1))
	{
		for (Idx=Top+1; Idx<=Bottom; Idx++)
		{
			ScreenMemory[((Idx*2)*UiScreenWidth)+((Right+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
		}
	}
	if (UiScreenHeight < 34)
	{
		if ((Right + 1) < (UiScreenWidth - 1))
		{
			for (Idx=Top+1; Idx<=Bottom; Idx++)
			{
				ScreenMemory[((Idx*2)*UiScreenWidth)+((Right+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
			}
		}
	}

	// Shade the bottom right corner
	if ((Right < (UiScreenWidth - 1)) && (Bottom < (UiScreenHeight - 1)))
	{
		ScreenMemory[(((Bottom+1)*2)*UiScreenWidth)+((Right+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
	}
	if (UiScreenHeight < 34)
	{
		if (((Right + 1) < (UiScreenWidth - 1)) && (Bottom < (UiScreenHeight - 1)))
		{
			ScreenMemory[(((Bottom+1)*2)*UiScreenWidth)+((Right+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
		}
	}
}

/*
 * DrawBox()
 * This function assumes coordinates are zero-based
 */
VOID TuiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOLEAN Fill, BOOLEAN Shadow, UCHAR Attr)
{
	UCHAR	ULCorner, URCorner, LLCorner, LRCorner;

	// Calculate the corner values
	if (HorzStyle == HORZ)
	{
		if (VertStyle == VERT)
		{
			ULCorner = UL;
			URCorner = UR;
			LLCorner = LL;
			LRCorner = LR;
		}
		else // VertStyle == D_VERT
		{
			ULCorner = VD_UL;
			URCorner = VD_UR;
			LLCorner = VD_LL;
			LRCorner = VD_LR;
		}
	}
	else // HorzStyle == D_HORZ
	{
		if (VertStyle == VERT)
		{
			ULCorner = HD_UL;
			URCorner = HD_UR;
			LLCorner = HD_LL;
			LRCorner = HD_LR;
		}
		else // VertStyle == D_VERT
		{
			ULCorner = D_UL;
			URCorner = D_UR;
			LLCorner = D_LL;
			LRCorner = D_LR;
		}
	}

	// Fill in box background
	if (Fill)
	{
		TuiFillArea(Left, Top, Right, Bottom, ' ', Attr);
	}

	// Fill in corners
	TuiFillArea(Left, Top, Left, Top, ULCorner, Attr);
	TuiFillArea(Right, Top, Right, Top, URCorner, Attr);
	TuiFillArea(Left, Bottom, Left, Bottom, LLCorner, Attr);
	TuiFillArea(Right, Bottom, Right, Bottom, LRCorner, Attr);

	// Fill in left line
	TuiFillArea(Left, Top+1, Left, Bottom-1, VertStyle, Attr);
	// Fill in top line
	TuiFillArea(Left+1, Top, Right-1, Top, HorzStyle, Attr);
	// Fill in right line
	TuiFillArea(Right, Top+1, Right, Bottom-1, VertStyle, Attr);
	// Fill in bottom line
	TuiFillArea(Left+1, Bottom, Right-1, Bottom, HorzStyle, Attr);

	// Draw the shadow
	if (Shadow)
	{
		TuiDrawShadow(Left, Top, Right, Bottom);
	}
}

/*
 * DrawText()
 * This function assumes coordinates are zero-based
 */
VOID TuiDrawText(ULONG X, ULONG Y, PCSTR Text, UCHAR Attr)
{
	PUCHAR	ScreenMemory = (PUCHAR)TextVideoBuffer;
	ULONG		i, j;

	// Draw the text
	for (i=X, j=0; Text[j]  && i<UiScreenWidth; i++,j++)
	{
		ScreenMemory[((Y*2)*UiScreenWidth)+(i*2)] = (UCHAR)Text[j];
		ScreenMemory[((Y*2)*UiScreenWidth)+(i*2)+1] = Attr;
	}
}

VOID TuiDrawCenteredText(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PCSTR TextString, UCHAR Attr)
{
	ULONG		TextLength;
	ULONG		BoxWidth;
	ULONG		BoxHeight;
	ULONG		LineBreakCount;
	ULONG		Index;
	ULONG		LastIndex;
	ULONG		RealLeft;
	ULONG		RealTop;
	ULONG		X;
	ULONG		Y;
	CHAR	Temp[2];

	TextLength = strlen(TextString);

	// Count the new lines and the box width
	LineBreakCount = 0;
	BoxWidth = 0;
	LastIndex = 0;
	for (Index=0; Index<TextLength; Index++)
	{
		if (TextString[Index] == '\n')
		{
			LastIndex = Index;
			LineBreakCount++;
		}
		else
		{
			if ((Index - LastIndex) > BoxWidth)
			{
				BoxWidth = (Index - LastIndex);
			}
		}
	}

	BoxHeight = LineBreakCount + 1;

	RealLeft = (((Right - Left) - BoxWidth) / 2) + Left;
	RealTop = (((Bottom - Top) - BoxHeight) / 2) + Top;

	LastIndex = 0;
	for (Index=0; Index<TextLength; Index++)
	{
		if (TextString[Index] == '\n')
		{
			RealTop++;
			LastIndex = 0;
		}
		else
		{
			X = RealLeft + LastIndex;
			Y = RealTop;
			LastIndex++;
			Temp[0] = TextString[Index];
			Temp[1] = 0;
			TuiDrawText(X, Y, Temp, Attr);
		}
	}
}

VOID TuiDrawStatusText(PCSTR StatusText)
{
	ULONG		i;

    //
    // Minimal UI doesn't have a status bar
    //
    if (UiMinimal) return;

	TuiDrawText(0, UiScreenHeight-1, " ", ATTR(UiStatusBarFgColor, UiStatusBarBgColor));
	TuiDrawText(1, UiScreenHeight-1, StatusText, ATTR(UiStatusBarFgColor, UiStatusBarBgColor));

	for (i=strlen(StatusText)+1; i<UiScreenWidth; i++)
	{
		TuiDrawText(i, UiScreenHeight-1, " ", ATTR(UiStatusBarFgColor, UiStatusBarBgColor));
	}

	VideoCopyOffScreenBufferToVRAM();
}

VOID TuiUpdateDateTime(VOID)
{
	ULONG	Year, Month, Day;
	ULONG	Hour, Minute, Second;
	CHAR	DateString[40];
	CHAR	TimeString[40];
	CHAR	TempString[20];
	BOOLEAN	PMHour = FALSE;

    /* Don't draw the time if this has been disabled */
    if (!UiDrawTime) return;

	MachRTCGetCurrentDateTime(&Year, &Month, &Day, &Hour, &Minute, &Second);
	if (Year < 1 || 9999 < Year || Month < 1 || 12 < Month || Day < 1 ||
            31 < Day || 23 < Hour || 59 < Minute || 59 < Second)
	{
		/* This happens on QEmu sometimes. We just skip updating */
		return;
	}
	// Get the month name
	strcpy(DateString, UiMonthNames[Month - 1]);
	// Get the day
	_itoa(Day, TempString, 10);
	// Get the day postfix
	if (1 == Day || 21 == Day || 31 == Day)
	{
		strcat(TempString, "st");
	}
	else if (2 == Day || 22 == Day)
	{
		strcat(TempString, "nd");
	}
	else if (3 == Day || 23 == Day)
	{
		strcat(TempString, "rd");
	}
	else
	{
		strcat(TempString, "th");
	}

	// Add the day to the date
	strcat(DateString, TempString);
	strcat(DateString, " ");

	// Get the year and add it to the date
	_itoa(Year, TempString, 10);
	strcat(DateString, TempString);

	// Draw the date
	TuiDrawText(UiScreenWidth-strlen(DateString)-2, 1, DateString, ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));

	// Get the hour and change from 24-hour mode to 12-hour
	if (Hour > 12)
	{
		Hour -= 12;
		PMHour = TRUE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -