diff --git a/ClassicalSharp/2D/Screens/InventoryScreen.cs b/ClassicalSharp/2D/Screens/InventoryScreen.cs index fb4b01a9d..3ffa8995a 100644 --- a/ClassicalSharp/2D/Screens/InventoryScreen.cs +++ b/ClassicalSharp/2D/Screens/InventoryScreen.cs @@ -26,7 +26,7 @@ namespace ClassicalSharp.Gui.Screens { void InitTableWidget() { table = new TableWidget(game); table.font = font; - table.ElementsPerRow = game.ClassicMode && !game.ClassicHacks ? 9 : 10; + table.ElementsPerRow = game.PureClassic ? 9 : 10; table.Init(); } diff --git a/ClassicalSharp/Network/Utils/AsyncDownloader.cs b/ClassicalSharp/Network/Utils/AsyncDownloader.cs index 5ab1ce436..eb9544e5c 100644 --- a/ClassicalSharp/Network/Utils/AsyncDownloader.cs +++ b/ClassicalSharp/Network/Utils/AsyncDownloader.cs @@ -341,7 +341,7 @@ namespace ClassicalSharp.Network { public object Data; /// Point in time the item most recently cached. (if at all) - public DateTime LastModified; + public DateTime LastModified; /// ETag of the item most recently cached. (if any) public string ETag; diff --git a/src/Client/Constants.h b/src/Client/Constants.h index 18dfd78dc..497466531 100644 --- a/src/Client/Constants.h +++ b/src/Client/Constants.h @@ -49,4 +49,9 @@ #define SkinType_64x64 1 #define SkinType_64x64Slim 2 #define SkinType_Invalid 3 + +#define FONT_STYLE_NORMAL 0 +#define FONT_STYLE_ITALIC 1 +#define FONT_STYLE_BOLD 2 +#define FONT_STYLE_UNDERLINE 3 #endif \ No newline at end of file diff --git a/src/Client/Drawer2D.c b/src/Client/Drawer2D.c index e556402ec..0e438c136 100644 --- a/src/Client/Drawer2D.c +++ b/src/Client/Drawer2D.c @@ -4,9 +4,9 @@ #include "Platform.h" #include "ExtMath.h" -void DrawTextArgs_Make(DrawTextArgs* args, STRING_REF String* text, void* font, bool useShadow) { +void DrawTextArgs_Make(DrawTextArgs* args, STRING_REF String* text, FontDesc* font, bool useShadow) { args->Text = *text; - args->Font = font; + args->Font = *font; args->UseShadow = useShadow; } @@ -113,7 +113,7 @@ void Drawer2D_Clear(PackedCol col, Int32 x, Int32 y, Int32 width, Int32 height) void Drawer2D_DrawText(DrawTextArgs* args, Int32 x, Int32 y); Size2D Drawer2D_MeasureText(DrawTextArgs* args); -Int32 Drawer2D_FontHeight(void* font, bool useShadow) { +Int32 Drawer2D_FontHeight(FontDesc* font, bool useShadow) { DrawTextArgs args; String text = String_FromConstant("I"); DrawTextArgs_Make(&args, &text, font, useShadow); diff --git a/src/Client/Drawer2D.h b/src/Client/Drawer2D.h index b85912bff..73d0bc200 100644 --- a/src/Client/Drawer2D.h +++ b/src/Client/Drawer2D.h @@ -10,13 +10,7 @@ Copyright 2017 ClassicalSharp | Licensed under BSD-3 #include "2DStructs.h" #include "Texture.h" -/* Contains arguments for measuring or drawing text. */ -typedef struct DrawTextArgs_ { - String Text; - void* Font; - bool UseShadow; -} DrawTextArgs; -void DrawTextArgs_Make(DrawTextArgs* args, STRING_REF String* text, void* font, bool useShadow); +void DrawTextArgs_Make(DrawTextArgs* args, STRING_REF String* text, FontDesc* font, bool useShadow); const float Offset = 1.3f; @@ -42,7 +36,7 @@ void Drawer2D_Clear(PackedCol col, Int32 x, Int32 y, Int32 width, Int32 height); void Drawer2D_DrawText(DrawTextArgs* args, Int32 x, Int32 y); Size2D Drawer2D_MeasureText(DrawTextArgs* args); -Int32 Drawer2D_FontHeight(void* font, bool useShadow); +Int32 Drawer2D_FontHeight(FontDesc* font, bool useShadow); Texture Drawer2D_MakeTextTexture(DrawTextArgs* args, Int32 windowX, Int32 windowY); Texture Drawer2D_Make2DTexture(Bitmap* bmp, Size2D used, Int32 windowX, Int32 windowY); diff --git a/src/Client/Platform.h b/src/Client/Platform.h index 33c394ece..e57c9ce75 100644 --- a/src/Client/Platform.h +++ b/src/Client/Platform.h @@ -56,4 +56,9 @@ UInt32 Platform_FileLength(void* file); /* Blocks the calling thread for given number of milliseconds. */ void Platform_ThreadSleep(UInt32 milliseconds); + +/* Allocates handle for the given font. */ +void Platform_MakeFont(FontDesc* desc); +/* Frees handle for the given font. */ +void Platform_FreeFont(FontDesc* desc); #endif \ No newline at end of file diff --git a/src/Client/Screens.c b/src/Client/Screens.c index 3cc8b8849..4d65ab17a 100644 --- a/src/Client/Screens.c +++ b/src/Client/Screens.c @@ -1,5 +1,7 @@ #include "Screens.h" #include "Widgets.h" +#include "Game.h" +#include "Events.h" void Screen_FreeWidgets(Widget** widgets, UInt32 widgetsCount) { if (widgets == NULL) return; @@ -80,4 +82,4 @@ void ClickableScreen_Create(ClickableScreen* screen) { screen->LastX = -1; screen->LastY = -1; screen->OnWidgetSelected = ClickableScreen_DefaultWidgetSelected; -} \ No newline at end of file +} diff --git a/src/Client/String.c b/src/Client/String.c index 3de70d232..d8eec0cb1 100644 --- a/src/Client/String.c +++ b/src/Client/String.c @@ -157,7 +157,7 @@ bool String_AppendConst(STRING_TRANSIENT String* str, const UInt8* buffer) { return true; } -bool String_AppendString(STRING_TRANSIENT String* str, String* buffer) { +bool String_AppendString(STRING_TRANSIENT String* str, STRING_TRANSIENT String* buffer) { Int32 i; for (i = 0; i < buffer->length; i++) { @@ -184,10 +184,39 @@ Int32 String_LastIndexOf(STRING_TRANSIENT String* str, UInt8 c) { } UInt8 String_CharAt(STRING_TRANSIENT String* str, Int32 offset) { - if (offset < 0 || offset >= str->length) return 0; + if (offset < 0 || offset >= str->length) return NULL; return str->buffer[offset]; } +void String_InsertAt(STRING_TRANSIENT String* str, UInt8 c, Int32 offset) { + if (offset < 0 || offset > str->length) { + ErrorHandler_Fail("Offset for InsertAt out of range"); + } + if (str->length == str->capacity) { + ErrorHandler_Fail("Cannot insert character into full string"); + } + + Int32 i; + for (i = str->length; i > offset; i--) { + str->buffer[i] = str->buffer[i - 1]; + } + str->buffer[offset] = c; + str->length++; +} + +void String_DeleteAt(STRING_TRANSIENT String* str, Int32 offset) { + if (offset < 0 || offset >= str->length) { + ErrorHandler_Fail("Offset for DeleteAt out of range"); + } + + Int32 i; + for (i = offset; i < str->length - 1; i++) { + str->buffer[i] = str->buffer[i + 1]; + } + str->buffer[str->length - 1] = NULL; + str->length--; +} + Int32 String_IndexOfString(STRING_TRANSIENT String* str, STRING_TRANSIENT String* sub) { Int32 i, j; /* Special case, sub is an empty string*/ diff --git a/src/Client/String.h b/src/Client/String.h index 3a8fe3f62..84334d4c2 100644 --- a/src/Client/String.h +++ b/src/Client/String.h @@ -63,6 +63,10 @@ Int32 String_IndexOf(STRING_TRANSIENT String* str, UInt8 c, Int32 offset); Int32 String_LastIndexOf(STRING_TRANSIENT String* str, UInt8 c); /* Gets the character at the given index in the string. */ UInt8 String_CharAt(STRING_TRANSIENT String* str, Int32 offset); +/* Inserts a character at the given index in the string. */ +void String_InsertAt(STRING_TRANSIENT String* str, UInt8 c, Int32 offset); +/* Deletes a character at the given index in the string. */ +void String_DeleteAt(STRING_TRANSIENT String* str, Int32 offset); /* Find the first index of sub in given string, -1 if not found. */ Int32 String_IndexOfString(STRING_TRANSIENT String* str, STRING_TRANSIENT String* sub); diff --git a/src/Client/Typedefs.h b/src/Client/Typedefs.h index 92a37631d..929f006e7 100644 --- a/src/Client/Typedefs.h +++ b/src/Client/Typedefs.h @@ -45,6 +45,9 @@ typedef UInt8 Face; /* Skin layout a humanoid skin texture can have. */ typedef UInt8 SkinType; +typedef struct FontDesc_ { void* Handle; UInt16 Size, Style; } FontDesc; +typedef struct DrawTextArgs_ { String Text; FontDesc Font; bool UseShadow; } DrawTextArgs; + #define UInt8_MaxValue ((UInt8)0xFF) #define Int16_MaxValue ((Int16)0x7FFF) #define UInt16_MaxValue ((UInt16)0xFFFF) diff --git a/src/Client/Widgets.c b/src/Client/Widgets.c index 60df5a093..021afb9f0 100644 --- a/src/Client/Widgets.c +++ b/src/Client/Widgets.c @@ -18,7 +18,7 @@ void Widget_SetLocation(Widget* widget, Anchor horAnchor, Anchor verAnchor, Int3 void TextWidget_SetHeight(TextWidget* widget, Int32 height) { if (widget->ReducePadding) { - Drawer2D_ReducePadding_Height(&height, font.Size, 4); + Drawer2D_ReducePadding_Height(&height, widget->Font.Size, 4); } widget->DefaultHeight = height; widget->Base.Height = height; @@ -26,7 +26,7 @@ void TextWidget_SetHeight(TextWidget* widget, Int32 height) { void TextWidget_Init(GuiElement* elem) { TextWidget* widget = (TextWidget*)elem; - Int32 height = Drawer2D_FontHeight(widget->Font, true); + Int32 height = Drawer2D_FontHeight(&widget->Font, true); TextWidget_SetHeight(widget, height); } @@ -50,11 +50,11 @@ void TextWidget_Reposition(Widget* elem) { widget->Texture.Y += elem->Y - oldY; } -void TextWidget_Create(TextWidget* widget, STRING_TRANSIENT String* text, void* font) { +void TextWidget_Create(TextWidget* widget, STRING_TRANSIENT String* text, FontDesc* font) { Widget_Init(&widget->Base); PackedCol col = PACKEDCOL_WHITE; widget->Col = col; - widget->Font = font; + widget->Font = *font; widget->Base.Reposition = TextWidget_Reposition; widget->Base.Base.Init = TextWidget_Init; widget->Base.Base.Render = TextWidget_Render; @@ -69,10 +69,10 @@ void TextWidget_SetText(TextWidget* widget, STRING_TRANSIENT String* text) { elem->Width = 0; elem->Height = widget->DefaultHeight; } else { DrawTextArgs args; - DrawTextArgs_Make(&args, text, widget->Font, true); + DrawTextArgs_Make(&args, text, &widget->Font, true); widget->Texture = Drawer2D_MakeTextTexture(&args, 0, 0); if (widget->ReducePadding) { - Drawer2D_ReducePadding_Tex(&widget->Texture, font.Size, 4); + Drawer2D_ReducePadding_Tex(&widget->Texture, widget->Font.Size, 4); } elem->Width = widget->Texture.Width; elem->Height = widget->Texture.Height; @@ -91,7 +91,7 @@ PackedCol Button_DisabledCol = PACKEDCOL_CONST(160, 160, 160, 255); void ButtonWidget_Init(GuiElement* elem) { ButtonWidget* widget = (ButtonWidget*)elem; - widget->DefaultHeight = Drawer2D_FontHeight(widget->Font, true); + widget->DefaultHeight = Drawer2D_FontHeight(&widget->Font, true); widget->Base.Height = widget->DefaultHeight; } @@ -143,14 +143,14 @@ void ButtonWidget_Render(GuiElement* elem, Real64 delta) { Texture_RenderShaded(&widget->Texture, col); } -void ButtonWidget_Create(ButtonWidget* widget, STRING_TRANSIENT String* text, Int32 minWidth, void* font, Gui_MouseHandler onClick) { +void ButtonWidget_Create(ButtonWidget* widget, STRING_TRANSIENT String* text, Int32 minWidth, FontDesc* font, Gui_MouseHandler onClick) { Widget_Init(&widget->Base); widget->Base.Base.Init = ButtonWidget_Init; widget->Base.Base.Render = ButtonWidget_Render; widget->Base.Base.Free = ButtonWidget_Free; widget->Base.Reposition = ButtonWidget_Reposition; - widget->Font = font; + widget->Font = *font; GuiElement* elem = &widget->Base.Base; elem->Init(elem); widget->MinWidth = minWidth; widget->MinHeight = 40; @@ -166,7 +166,7 @@ void ButtonWidget_SetText(ButtonWidget* widget, STRING_TRANSIENT String* text) { elem->Width = 0; elem->Height = widget->DefaultHeight; } else { DrawTextArgs args; - DrawTextArgs_Make(&args, text, widget->Font, true); + DrawTextArgs_Make(&args, text, &widget->Font, true); widget->Texture = Drawer2D_MakeTextTexture(&args, 0, 0); elem->Width = max(widget->Texture.Width, widget->MinWidth); elem->Height = max(widget->Texture.Height, widget->MinHeight); @@ -571,7 +571,7 @@ void TableWidget_RecreateDescTex(TableWidget* widget) { TableWidget_MakeBlockDesc(&desc, block); DrawTextArgs args; - DrawTextArgs_Make(&args, &desc, widget->Font, true); + DrawTextArgs_Make(&args, &desc, &widget->Font, true); widget->DescTex = Drawer2D_MakeTextTexture(&args, 0, 0); TableWidget_UpdateDescTexPos(widget); } diff --git a/src/Client/Widgets.h b/src/Client/Widgets.h index c625f207e..fff993339 100644 --- a/src/Client/Widgets.h +++ b/src/Client/Widgets.h @@ -16,13 +16,13 @@ typedef struct TextWidget_ { Widget Base; Texture Texture; Int32 DefaultHeight; - void* Font; + FontDesc Font; bool ReducePadding; PackedCol Col; } TextWidget; -void TextWidget_Create(TextWidget* widget, STRING_TRANSIENT String* text, void* font); +void TextWidget_Create(TextWidget* widget, STRING_TRANSIENT String* text, FontDesc* font); void TextWidget_SetText(TextWidget* widget, STRING_TRANSIENT String* text); @@ -33,7 +33,7 @@ typedef struct ButtonWidget_ { Widget Base; Texture Texture; Int32 DefaultHeight; - void* Font; + FontDesc Font; String OptName; ButtonWidget_GetValue GetValue; @@ -41,7 +41,7 @@ typedef struct ButtonWidget_ { Int32 MinWidth, MinHeight, Metadata; } ButtonWidget; -void ButtonWidget_Create(ButtonWidget* widget, STRING_TRANSIENT String* text, Int32 minWidth, void* font, Gui_MouseHandler onClick); +void ButtonWidget_Create(ButtonWidget* widget, STRING_TRANSIENT String* text, Int32 minWidth, FontDesc* font, Gui_MouseHandler onClick); void ButtonWidget_SetText(ButtonWidget* widget, STRING_TRANSIENT String* text); @@ -49,8 +49,8 @@ typedef struct ScrollbarWidget_ { Widget Base; Int32 TotalRows, ScrollY; Real32 ScrollingAcc; - bool DraggingMouse; Int32 MouseOffset; + bool DraggingMouse; } ScrollbarWidget; void ScrollbarWidget_Create(ScrollbarWidget* widget); @@ -62,8 +62,8 @@ typedef struct HotbarWidget_ { Texture SelTex, BackTex; Real32 BarHeight, SelBlockSize, ElemSize; Real32 BarXOffset, BorderSize; - bool AltHandled; Real32 ScrollAcc; + bool AltHandled; } HotbarWidget; void HotbarWidget_Create(HotbarWidget* widget); @@ -73,11 +73,11 @@ typedef struct TableWidget_ { Widget Base; Int32 ElementsCount, ElementsPerRow, RowsCount; Int32 LastCreatedIndex; - void* Font; - bool PendingClose; + FontDesc Font; Int32 SelectedIndex, BlockSize; Real32 SelBlockExpand; GfxResourceID VB; + bool PendingClose; BlockID Elements[BLOCK_COUNT]; ScrollbarWidget Scroll; @@ -103,13 +103,13 @@ void SpecialInputTab_Init(SpecialInputTab* tab, STRING_REF String* title, typedef struct SpecialInputWidget_ { Widget Base; Texture Tex; - void* Font; + FontDesc Font; SpecialInputAppendFunc AppendFunc; Size2D ElementSize; SpecialInputTab Tabs[5]; } SpecialInputWidget; -void SpecialInputWidget_Create(SpecialInputWidget* widget, void* font, SpecialInputAppendFunc appendFunc); +void SpecialInputWidget_Create(SpecialInputWidget* widget, FontDesc* font, SpecialInputAppendFunc appendFunc); void SpecialInputWidget_UpdateColours(SpecialInputWidget* widget); void SpecialInputWidget_SetActive(SpecialInputWidget* widget, bool active); void SpecialInputWidget_Redraw(SpecialInputWidget* widget); @@ -120,7 +120,7 @@ struct InputWidget_; /* Remakes the raw texture containing all the chat lines. Also updates the dimensions of the widget. */ typedef struct InputWidget_ { Widget Base; - void* Font; + FontDesc Font; Int32 MaxLines; Int32 MaxCharsPerLine; Int32 Padding; @@ -144,7 +144,7 @@ typedef struct InputWidget_ { Real64 CaretAccumulator; } InputWidget; -void InputWidget_Create(InputWidget* widget, void* font); +void InputWidget_Create(InputWidget* widget, FontDesc* font); /* Calculates the sizes of each line in the text buffer. */ void InputWidget_CalculateLineSizes(InputWidget* widget); /* Calculates the location and size of the caret character. */ @@ -176,15 +176,14 @@ typedef struct LinkData_ { typedef struct TextGroupWidget_ { Widget Base; Int32 LinesCount, DefaultHeight; - void* Font; - void* UnderlineFont; + FontDesc Font, UnderlineFont; bool PlaceholderHeight[TEXTGROUPWIDGET_MAX_LINES]; String Lines[TEXTGROUPWIDGET_MAX_LINES]; LinkData LinkDatas[TEXTGROUPWIDGET_MAX_LINES]; Texture Textures[TEXTGROUPWIDGET_MAX_LINES]; } TextGroupWidget; -void TextGroupWidget_Create(TextGroupWidget* widget, Int32 linesCount, void* font, void* underlineFont); +void TextGroupWidget_Create(TextGroupWidget* widget, Int32 linesCount, FontDesc* font, FontDesc* underlineFont); void TextGroupWidget_SetUsePlaceHolder(TextGroupWidget* widget, Int32 index, bool placeHolder); void TextGroupWidget_PushUpAndReplaceLast(TextGroupWidget* widget, STRING_TRANSIENT String* text); Int32 TextGroupWidget_GetUsedHeight(TextGroupWidget* widget); diff --git a/src/Client/WinPlatform.c b/src/Client/WinPlatform.c index 51fc69674..4c24a7bbc 100644 --- a/src/Client/WinPlatform.c +++ b/src/Client/WinPlatform.c @@ -1,6 +1,7 @@ #include "Platform.h" #include "Stream.h" #include "DisplayDevice.h" +#include "ExtMath.h" #define WIN32_LEAN_AND_MEAN #include @@ -61,7 +62,7 @@ void Platform_MemCpy(void* dst, void* src, UInt32 numBytes) { } -void Platform_Log(String message) { +void Platform_Log(STRING_TRANSIENT String* message) { /* TODO: log to console */ } @@ -172,4 +173,26 @@ UInt32 Platform_FileLength(void* file) { void Platform_ThreadSleep(UInt32 milliseconds) { Sleep(milliseconds); -} \ No newline at end of file +} + + +void Platform_MakeFont(FontDesc* desc) { + LOGFONTA font = { 0 }; + font.lfHeight = -Math_Ceil(desc->Size * GetDeviceCaps(hDC, LOGPIXELSY) / 72.0f); + font.lfItalic = desc->Style == FONT_STYLE_ITALIC; + font.lfUnderline = desc->Style == FONT_STYLE_UNDERLINE; + font.lfWeight = desc->Style == FONT_STYLE_BOLD ? FW_BOLD : FW_NORMAL; + font.lfQuality = ANTIALIASED_QUALITY; + + desc->Handle = CreateFontIndirectA(&font); + if (desc->Handle == NULL) { + ErrorHandler_Fail("Creating font handle failed"); + } +} + +void Platform_FreeFont(FontDesc* desc) { + if (!DeleteObject(desc->Handle)) { + ErrorHandler_Fail("Deleting font handle failed"); + } + desc->Handle = NULL; +} diff --git a/src/Client/WordWrap.c b/src/Client/WordWrap.c index 809463544..e961972eb 100644 --- a/src/Client/WordWrap.c +++ b/src/Client/WordWrap.c @@ -36,7 +36,8 @@ Int32 WordWrap_WrapLine(String* text, Int32 index, Int32 lineSize) { if (!WordWrap_IsWrapper(text->buffer[i])) continue; for (Int32 j = lineEnd; j >= i + 1; j--) { - InsertAt(index + lineSize, text->buffer[j]); + UInt8 c = text->buffer[j]; + String_InsertAt(text, index + lineSize, c); text->buffer[j] = ' '; } return (i + 1) - index;