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;