diff --git a/ClassicalSharp/2D/Widgets/Chat/TextGroupWidget.cs b/ClassicalSharp/2D/Widgets/Chat/TextGroupWidget.cs index 78d1e11f0..21512aaf9 100644 --- a/ClassicalSharp/2D/Widgets/Chat/TextGroupWidget.cs +++ b/ClassicalSharp/2D/Widgets/Chat/TextGroupWidget.cs @@ -92,12 +92,14 @@ namespace ClassicalSharp.Gui.Widgets { } public int GetUsedHeight() { - int sum = 0; - for (int i = 0; i < Textures.Length; i++) { - if (!Textures[i].IsValid) continue; - sum += Textures[i].Height; + int height = 0, i = 0; + for (i = 0; i < Textures.Length; i++) { + if (Textures[i].IsValid) break; } - return sum; + for (; i < Textures.Length; i++) { + height += Textures[i].Height; + } + return height; } void UpdateDimensions() { diff --git a/src/Client/Client.vcxproj b/src/Client/Client.vcxproj index fd78e792a..c5dead715 100644 --- a/src/Client/Client.vcxproj +++ b/src/Client/Client.vcxproj @@ -194,7 +194,7 @@ - + @@ -262,7 +262,7 @@ - + diff --git a/src/Client/Client.vcxproj.filters b/src/Client/Client.vcxproj.filters index ee096e954..f58dff85f 100644 --- a/src/Client/Client.vcxproj.filters +++ b/src/Client/Client.vcxproj.filters @@ -273,9 +273,6 @@ Header Files\Defines - - Header Files\IO - Header Files\Math @@ -351,6 +348,9 @@ Header Files\Math + + Header Files\IO + @@ -437,9 +437,6 @@ Source Files\Entities - - Source Files\IO - Source Files\Math @@ -530,5 +527,8 @@ Source Files\Utils + + Source Files\IO + \ No newline at end of file diff --git a/src/Client/Deflate.c b/src/Client/Deflate.c new file mode 100644 index 000000000..a2c7ef221 --- /dev/null +++ b/src/Client/Deflate.c @@ -0,0 +1,142 @@ +#include "Deflate.h" +#include "ErrorHandler.h" + +#define GZipState_Header1 0 +#define GZipState_Header2 1 +#define GZipState_CompressionMethod 2 +#define GZipState_Flags 3 +#define GZipState_LastModifiedTime 4 +#define GZipState_CompressionFlags 5 +#define GZipState_OperatingSystem 6 +#define GZipState_HeaderChecksum 7 +#define GZipState_Filename 8 +#define GZipState_Comment 9 +#define GZipState_Done 10 + +#define ZLibState_CompressionMethod 0 +#define ZLibState_Flags 1 +#define ZLibState_Done 2 + +bool Header_ReadByte(Stream* s, UInt8* state, Int32* value) { + *value = s->TryReadByte(); + if (*value == -1) return false; + + (*state)++; + return true; +} + + +void GZipHeader_Init(GZipHeader* header) { + header->State = GZipState_Header1; + header->Done = false; + header->Flags = 0; + header->PartsRead = 0; +} + +void GZipHeader_Read(Stream* s, GZipHeader* header) { + Int32 temp; + switch (header->State) { + + case GZipState_Header1: + if (!Header_ReadByte(s, &header->State, &temp)) return; + if (temp != 0x1F) { + ErrorHandler_Fail("Byte 1 of GZIP header must be 1F"); + } + + case GZipState_Header2: + if (!Header_ReadByte(s, &header->State, &temp)) return; + if (temp != 0x8B) { + ErrorHandler_Fail("Byte 2 of GZIP header must be 8B"); + } + + case GZipState_CompressionMethod: + if (!Header_ReadByte(s, &header->State, &temp)) return; + if (temp != 0x08) { + ErrorHandler_Fail("Only DEFLATE compression supported"); + } + + case GZipState_Flags: + if (!Header_ReadByte(s, &header->State, &header->Flags)) return; + if ((header->Flags & 0x04) != 0) { + ErrorHandler_Fail("Unsupported GZIP header flags"); + } + + case GZipState_LastModifiedTime: + for (; header->PartsRead < 4; header->PartsRead++) { + temp = s->TryReadByte(); + if (temp == -1) return; + } + header->State++; + header->PartsRead = 0; + + case GZipState_CompressionFlags: + if (!Header_ReadByte(s, &header->State, &temp)) return; + + case GZipState_OperatingSystem: + if (!Header_ReadByte(s, &header->State, &temp)) return; + + case GZipState_Filename: + if ((header->Flags & 0x08) != 0) { + for (; ;) { + temp = s->TryReadByte(); + if (temp == -1) return; + if (temp == 0) break; + } + } + header->State++; + + case GZipState_Comment: + if ((header->Flags & 0x10) != 0) { + for (; ;) { + temp = s->TryReadByte(); + if (temp == -1) return; + if (temp == 0) break; + } + } + header->State++; + + case GZipState_HeaderChecksum: + if ((header->Flags & 0x02) != 0) { + for (; header->PartsRead < 2; header->PartsRead++) { + temp = s->TryReadByte(); + if (temp == -1) return; + } + } + + header->State++; + header->PartsRead = 0; + header->Done = true; + } +} + + +void ZLibHeader_Init(ZLibHeader* header) { + header->State = ZLibState_CompressionMethod; + header->Done = false; + header->LZ77WindowSize = 0; +} + +void ZLibHeader_Read(Stream* s, ZLibHeader* header) { + Int32 temp; + switch (header->State) { + + case ZLibState_CompressionMethod: + if (!Header_ReadByte(s, &header->State, &temp)) return; + if ((temp & 0x0F) != 0x08) { + ErrorHandler_Fail("Only DEFLATE compression supported"); + } + + Int32 log2Size = (temp >> 4) + 8; + header->LZ77WindowSize = 1L << log2Size; + if (header->LZ77WindowSize > 32768) { + ErrorHandler_Fail("LZ77 window size must be 32KB or less"); + } + + case ZLibState_Flags: + if (!Header_ReadByte(s, &header->State, &temp)) return; + if ((temp & 0x20) != 0) { + ErrorHandler_Fail("Unsupported ZLIB header flags"); + } + header->Done = true; + } +} \ No newline at end of file diff --git a/src/Client/Deflate.h b/src/Client/Deflate.h new file mode 100644 index 000000000..56585fd56 --- /dev/null +++ b/src/Client/Deflate.h @@ -0,0 +1,32 @@ +#ifndef CS_DEFLATE_H +#define CS_DEFLATE_H +#include "Typedefs.h" +#include "Stream.h" +/* Decodes data compressed using DEFLATE. + Copyright 2017 ClassicalSharp | Licensed under BSD-3 +*/ + +typedef struct GZipHeader_ { + UInt8 State; + bool Done; + UInt8 PartsRead; + Int32 Flags; +} GZipHeader; + +/* Initalises state of GZIP header. */ +void GZipHeader_Init(GZipHeader* header); +/* Reads part of the GZIP header. header.Done is set to true on completion of reading the header. */ +void GZipHeader_Read(Stream* s, GZipHeader* header); + + +typedef struct ZLibHeader_ { + UInt8 State; + bool Done; + Int32 LZ77WindowSize; +} ZLibHeader; + +/* Initalises state of ZLIB header. */ +void ZLibHeader_Init(ZLibHeader* header); +/* Reads part of the ZLIB header. header.Done is set to true on completion of reading the header. */ +void ZLibHeader_Read(Stream* s, ZLibHeader* header); +#endif \ No newline at end of file diff --git a/src/Client/GZipHeader.c b/src/Client/GZipHeader.c deleted file mode 100644 index d574b9728..000000000 --- a/src/Client/GZipHeader.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "GZipHeader.h" -#include "ErrorHandler.h" - -void GZipHeader_Init(GZipHeader* header) { - header->State = GZipState_Header1; - header->Done = false; - header->Flags = 0; - header->PartsRead = 0; -} - -bool GZipHeader_ReadByte(Stream* s, GZipHeader* header, Int32* value) { - *value = s->TryReadByte(); - if (*value == -1) return false; - - header->State++; - return true; -} - -bool GZipHeader_ReadAndCheckByte(Stream* s, GZipHeader* header, UInt8 expected) { - Int32 value; - if (!GZipHeader_ReadByte(s, header, &value)) return false; - - if (value != expected) { - ErrorHandler_Fail("Unexpected constant in GZIP header"); - } - return true; -} - -void GZipHeader_Read(Stream* s, GZipHeader* header) { - Int32 temp; - switch (header->State) { - - case GZipState_Header1: - if (!GZipHeader_ReadAndCheckByte(s, header, 0x1F)) return; - - case GZipState_Header2: - if (!GZipHeader_ReadAndCheckByte(s, header, 0x8B)) return; - - case GZipState_CompressionMethod: - if (!GZipHeader_ReadAndCheckByte(s, header, 0x08)) return; - - case GZipState_Flags: - if (!GZipHeader_ReadByte(s, header, &header->Flags)) return; - if ((header->Flags & 0x04) != 0) { - ErrorHandler_Fail("Unsupported GZIP header flags"); - } - - case GZipState_LastModifiedTime: - for (; header->PartsRead < 4; header->PartsRead++) { - temp = s->TryReadByte(); - if (temp == -1) return; - } - header->PartsRead = 0; - header->State++; - - case GZipState_CompressionFlags: - if (!GZipHeader_ReadByte(s, header, &temp)) return; - - case GZipState_OperatingSystem: - if (!GZipHeader_ReadByte(s, header, &temp)) return; - - case GZipState_Filename: - if ((header->Flags & 0x08) != 0) { - for (; ;) { - temp = s->TryReadByte(); - if (temp == -1) return; - if (temp == 0) break; - } - } - header->State++; - - case GZipState_Comment: - if ((header->Flags & 0x10) != 0) { - for (; ;) { - temp = s->TryReadByte(); - if (temp == -1) return; - if (temp == 0) break; - } - } - header->State++; - - case GZipState_HeaderChecksum: - if ((header->Flags & 0x02) != 0) { - for (; header->PartsRead < 2; header->PartsRead++) { - temp = s->TryReadByte(); - if (temp == -1) return; - } - } - header->PartsRead = 0; - header->State++; - - header->Done = true; - } -} \ No newline at end of file diff --git a/src/Client/GZipHeader.h b/src/Client/GZipHeader.h deleted file mode 100644 index 3eb739eb9..000000000 --- a/src/Client/GZipHeader.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef CS_GZIPHEADERREADER_H -#define CS_GZIPHEADERREADER_H -#include "Typedefs.h" -#include "Stream.h" -/* Skips the GZip header in a stream. - Copyright 2017 ClassicalSharp | Licensed under BSD-3 -*/ - -typedef Int32 GZipState; -#define GZipState_Header1 0 -#define GZipState_Header2 1 -#define GZipState_CompressionMethod 2 -#define GZipState_Flags 3 -#define GZipState_LastModifiedTime 4 -#define GZipState_CompressionFlags 5 -#define GZipState_OperatingSystem 6 -#define GZipState_HeaderChecksum 7 -#define GZipState_Filename 8 -#define GZipState_Comment 9 -#define GZipState_Done 10 - -typedef struct GZipHeader_ { - /* State header reader is up to.*/ - GZipState State; - /* Whether header has finished being read. */ - bool Done; - Int32 Flags; - Int32 PartsRead; -} GZipHeader; - -/* Initalises state of GZIP header. */ -void GZipHeader_Init(GZipHeader* header); -/* Reads part of the GZIP header. header.Done is set to true on completion. */ -void GZipHeader_Read(Stream* s, GZipHeader* header); -#endif \ No newline at end of file