Fix texture packs without content length header not decoding, on windows.

This commit is contained in:
UnknownShadow200 2018-11-21 23:05:57 +11:00
parent 10e0a4ea2e
commit 348ca90306
17 changed files with 159 additions and 140 deletions

View File

@ -21,6 +21,7 @@ struct AsyncRequest {
TimeMS TimeAdded, TimeDownloaded; TimeMS TimeAdded, TimeDownloaded;
int StatusCode; int StatusCode;
uint32_t ContentLength;
ReturnCode Result; ReturnCode Result;
void* ResultData; void* ResultData;

View File

@ -6,6 +6,7 @@
#include "ErrorHandler.h" #include "ErrorHandler.h"
#include "Stream.h" #include "Stream.h"
#include "Errors.h" #include "Errors.h"
#include "Utils.h"
BitmapCol BitmapCol_Scale(BitmapCol value, float t) { BitmapCol BitmapCol_Scale(BitmapCol value, float t) {
value.R = (uint8_t)(value.R * t); value.R = (uint8_t)(value.R * t);

View File

@ -307,8 +307,7 @@ STRING_REF String Block_UNSAFE_GetName(BlockID block) {
} }
void Block_SetName(BlockID block, const String* name) { void Block_SetName(BlockID block, const String* name) {
String dst = { Block_NamePtr(block), 0, STRING_SIZE }; String dst = String_InitAndClear(Block_NamePtr(block), STRING_SIZE);
Mem_Set(dst.buffer, 0, STRING_SIZE);
String_AppendString(&dst, name); String_AppendString(&dst, name);
} }

View File

@ -45,7 +45,7 @@ static char Chat_LogPathBuffer[FILENAME_SIZE];
static String Chat_LogPath = String_FromArray(Chat_LogPathBuffer); static String Chat_LogPath = String_FromArray(Chat_LogPathBuffer);
static struct Stream Chat_LogStream; static struct Stream Chat_LogStream;
static DateTime ChatLog_LastLogDate; static struct DateTime ChatLog_LastLogDate;
static void Chat_CloseLog(void) { static void Chat_CloseLog(void) {
ReturnCode res; ReturnCode res;
@ -82,7 +82,7 @@ static void Chat_DisableLogging(void) {
Chat_AddRaw("&cDisabling chat logging"); Chat_AddRaw("&cDisabling chat logging");
} }
static void Chat_OpenLog(DateTime* now) { static void Chat_OpenLog(struct DateTime* now) {
void* file; void* file;
int i; int i;
ReturnCode res; ReturnCode res;
@ -119,7 +119,7 @@ static void Chat_OpenLog(DateTime* now) {
static void Chat_AppendLog(const String* text) { static void Chat_AppendLog(const String* text) {
String str; char strBuffer[STRING_SIZE * 2]; String str; char strBuffer[STRING_SIZE * 2];
DateTime now; struct DateTime now;
ReturnCode res; ReturnCode res;
if (!Chat_LogName.length || !Game_ChatLogging) return; if (!Chat_LogName.length || !Game_ChatLogging) return;

View File

@ -4,6 +4,7 @@
#include "Platform.h" #include "Platform.h"
#include "Stream.h" #include "Stream.h"
#include "Errors.h" #include "Errors.h"
#include "Utils.h"
#define Header_ReadU8(value) if ((res = s->ReadU8(s, &value))) return res; #define Header_ReadU8(value) if ((res = s->ReadU8(s, &value))) return res;
/*########################################################################################################################* /*########################################################################################################################*

View File

@ -645,7 +645,7 @@ static void Game_DoScheduledTasks(double time) {
void Game_TakeScreenshot(void) { void Game_TakeScreenshot(void) {
String filename; char fileBuffer[STRING_SIZE]; String filename; char fileBuffer[STRING_SIZE];
String path; char pathBuffer[FILENAME_SIZE]; String path; char pathBuffer[FILENAME_SIZE];
DateTime now; struct DateTime now;
struct Stream stream; struct Stream stream;
ReturnCode res; ReturnCode res;

View File

@ -3259,7 +3259,7 @@ static void TexPackOverlay_Render(void* screen, double delta) {
MenuScreen_Render(s, delta); MenuScreen_Render(s, delta);
if (!AsyncDownloader_Get(&s->Identifier, &item)) return; if (!AsyncDownloader_Get(&s->Identifier, &item)) return;
s->ContentLength = item.ResultSize; s->ContentLength = item.ContentLength;
if (!s->ContentLength) return; if (!s->ContentLength) return;
Elem_Recreate(s); Elem_Recreate(s);
} }

View File

@ -258,7 +258,7 @@ TimeMS DateTime_CurrentUTC_MS(void) {
return FileTime_TotalMS(raw); return FileTime_TotalMS(raw);
} }
static void Platform_FromSysTime(DateTime* time, SYSTEMTIME* sysTime) { static void Platform_FromSysTime(struct DateTime* time, SYSTEMTIME* sysTime) {
time->Year = sysTime->wYear; time->Year = sysTime->wYear;
time->Month = sysTime->wMonth; time->Month = sysTime->wMonth;
time->Day = sysTime->wDay; time->Day = sysTime->wDay;
@ -268,13 +268,13 @@ static void Platform_FromSysTime(DateTime* time, SYSTEMTIME* sysTime) {
time->Milli = sysTime->wMilliseconds; time->Milli = sysTime->wMilliseconds;
} }
void DateTime_CurrentUTC(DateTime* time) { void DateTime_CurrentUTC(struct DateTime* time) {
SYSTEMTIME utcTime; SYSTEMTIME utcTime;
GetSystemTime(&utcTime); GetSystemTime(&utcTime);
Platform_FromSysTime(time, &utcTime); Platform_FromSysTime(time, &utcTime);
} }
void DateTime_CurrentLocal(DateTime* time) { void DateTime_CurrentLocal(struct DateTime* time) {
SYSTEMTIME localTime; SYSTEMTIME localTime;
GetLocalTime(&localTime); GetLocalTime(&localTime);
Platform_FromSysTime(time, &localTime); Platform_FromSysTime(time, &localTime);
@ -308,7 +308,7 @@ TimeMS DateTime_CurrentUTC_MS(void) {
return UnixTime_TotalMS(cur); return UnixTime_TotalMS(cur);
} }
static void Platform_FromSysTime(DateTime* time, struct tm* sysTime) { static void Platform_FromSysTime(struct DateTime* time, struct tm* sysTime) {
time->Year = sysTime->tm_year + 1900; time->Year = sysTime->tm_year + 1900;
time->Month = sysTime->tm_mon + 1; time->Month = sysTime->tm_mon + 1;
time->Day = sysTime->tm_mday; time->Day = sysTime->tm_mday;
@ -317,7 +317,7 @@ static void Platform_FromSysTime(DateTime* time, struct tm* sysTime) {
time->Second = sysTime->tm_sec; time->Second = sysTime->tm_sec;
} }
void DateTime_CurrentUTC(DateTime* time_) { void DateTime_CurrentUTC(struct DateTime* time_) {
struct timeval cur; struct timeval cur;
struct tm utc_time; struct tm utc_time;
@ -328,7 +328,7 @@ void DateTime_CurrentUTC(DateTime* time_) {
time_->Milli = cur.tv_usec / 1000; time_->Milli = cur.tv_usec / 1000;
} }
void DateTime_CurrentLocal(DateTime* time_) { void DateTime_CurrentLocal(struct DateTime* time_) {
struct timeval cur; struct timeval cur;
struct tm loc_time; struct tm loc_time;
@ -451,51 +451,51 @@ ReturnCode File_GetModifiedTime_MS(const String* path, TimeMS* time) {
return res; return res;
} }
ReturnCode File_Do(void** file, const String* path, DWORD access, DWORD createMode) { static ReturnCode File_Do(FileHandle* file, const String* path, DWORD access, DWORD createMode) {
TCHAR str[300]; TCHAR str[300];
Platform_ConvertString(str, path); Platform_ConvertString(str, path);
*file = CreateFile(str, access, FILE_SHARE_READ, NULL, createMode, 0, NULL); *file = CreateFile(str, access, FILE_SHARE_READ, NULL, createMode, 0, NULL);
return Win_Return(*file != INVALID_HANDLE_VALUE); return Win_Return(*file != INVALID_HANDLE_VALUE);
} }
ReturnCode File_Open(void** file, const String* path) { ReturnCode File_Open(FileHandle* file, const String* path) {
return File_Do(file, path, GENERIC_READ, OPEN_EXISTING); return File_Do(file, path, GENERIC_READ, OPEN_EXISTING);
} }
ReturnCode File_Create(void** file, const String* path) { ReturnCode File_Create(FileHandle* file, const String* path) {
return File_Do(file, path, GENERIC_WRITE, CREATE_ALWAYS); return File_Do(file, path, GENERIC_WRITE, CREATE_ALWAYS);
} }
ReturnCode File_Append(void** file, const String* path) { ReturnCode File_Append(FileHandle* file, const String* path) {
ReturnCode res = File_Do(file, path, GENERIC_WRITE, OPEN_ALWAYS); ReturnCode res = File_Do(file, path, GENERIC_WRITE, OPEN_ALWAYS);
if (res) return res; if (res) return res;
return File_Seek(*file, 0, FILE_SEEKFROM_END); return File_Seek(*file, 0, FILE_SEEKFROM_END);
} }
ReturnCode File_Read(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead) { ReturnCode File_Read(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead) {
BOOL success = ReadFile((HANDLE)file, buffer, count, bytesRead, NULL); BOOL success = ReadFile(file, buffer, count, bytesRead, NULL);
return Win_Return(success); return Win_Return(success);
} }
ReturnCode File_Write(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote) { ReturnCode File_Write(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote) {
BOOL success = WriteFile((HANDLE)file, buffer, count, bytesWrote, NULL); BOOL success = WriteFile(file, buffer, count, bytesWrote, NULL);
return Win_Return(success); return Win_Return(success);
} }
ReturnCode File_Close(void* file) { ReturnCode File_Close(FileHandle file) {
return Win_Return(CloseHandle((HANDLE)file)); return Win_Return(CloseHandle(file));
} }
ReturnCode File_Seek(void* file, int offset, int seekType) { ReturnCode File_Seek(FileHandle file, int offset, int seekType) {
static uint8_t modes[3] = { FILE_BEGIN, FILE_CURRENT, FILE_END }; static uint8_t modes[3] = { FILE_BEGIN, FILE_CURRENT, FILE_END };
DWORD pos = SetFilePointer(file, offset, NULL, modes[seekType]); DWORD pos = SetFilePointer(file, offset, NULL, modes[seekType]);
return Win_Return(pos != INVALID_SET_FILE_POINTER); return Win_Return(pos != INVALID_SET_FILE_POINTER);
} }
ReturnCode File_Position(void* file, uint32_t* position) { ReturnCode File_Position(FileHandle file, uint32_t* position) {
*position = SetFilePointer(file, 0, NULL, 1); /* SEEK_CUR */ *position = SetFilePointer(file, 0, NULL, FILE_CURRENT);
return Win_Return(*position != INVALID_SET_FILE_POINTER); return Win_Return(*position != INVALID_SET_FILE_POINTER);
} }
ReturnCode File_Length(void* file, uint32_t* length) { ReturnCode File_Length(FileHandle file, uint32_t* length) {
*length = GetFileSize(file, NULL); *length = GetFileSize(file, NULL);
return Win_Return(*length != INVALID_FILE_SIZE); return Win_Return(*length != INVALID_FILE_SIZE);
} }
@ -577,52 +577,52 @@ ReturnCode File_GetModifiedTime_MS(const String* path, TimeMS* time) {
return 0; return 0;
} }
ReturnCode File_Do(void** file, const String* path, int mode) { static ReturnCode File_Do(FileHandle* file, const String* path, int mode) {
char str[600]; char str[600];
Platform_ConvertString(str, path); Platform_ConvertString(str, path);
*file = open(str, mode, (6 << 6) | (4 << 3) | 4); /* rw|r|r */ *file = open(str, mode, (6 << 6) | (4 << 3) | 4); /* rw|r|r */
return Nix_Return(*file != -1); return Nix_Return(*file != -1);
} }
ReturnCode File_Open(void** file, const String* path) { ReturnCode File_Open(FileHandle* file, const String* path) {
return File_Do(file, path, O_RDONLY); return File_Do(file, path, O_RDONLY);
} }
ReturnCode File_Create(void** file, const String* path) { ReturnCode File_Create(FileHandle* file, const String* path) {
return File_Do(file, path, O_WRONLY | O_CREAT | O_TRUNC); return File_Do(file, path, O_WRONLY | O_CREAT | O_TRUNC);
} }
ReturnCode File_Append(void** file, const String* path) { ReturnCode File_Append(FileHandle* file, const String* path) {
ReturnCode res = File_Do(file, path, O_WRONLY | O_CREAT); ReturnCode res = File_Do(file, path, O_WRONLY | O_CREAT);
if (res) return res; if (res) return res;
return File_Seek(*file, 0, FILE_SEEKFROM_END); return File_Seek(*file, 0, FILE_SEEKFROM_END);
} }
ReturnCode File_Read(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead) { ReturnCode File_Read(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead) {
*bytesRead = read((int)file, buffer, count); *bytesRead = read(file, buffer, count);
return Nix_Return(*bytesRead != -1); return Nix_Return(*bytesRead != -1);
} }
ReturnCode File_Write(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote) { ReturnCode File_Write(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote) {
*bytesWrote = write((int)file, buffer, count); *bytesWrote = write(file, buffer, count);
return Nix_Return(*bytesWrote != -1); return Nix_Return(*bytesWrote != -1);
} }
ReturnCode File_Close(void* file) { ReturnCode File_Close(FileHandle file) {
return Nix_Return(close((int)file) != -1); return Nix_Return(close(file) != -1);
} }
ReturnCode File_Seek(void* file, int offset, int seekType) { ReturnCode File_Seek(FileHandle file, int offset, int seekType) {
static uint8_t modes[3] = { SEEK_SET, SEEK_CUR, SEEK_END }; static uint8_t modes[3] = { SEEK_SET, SEEK_CUR, SEEK_END };
return Nix_Return(lseek((int)file, offset, modes[seekType]) != -1); return Nix_Return(lseek(file, offset, modes[seekType]) != -1);
} }
ReturnCode File_Position(void* file, uint32_t* position) { ReturnCode File_Position(FileHandle file, uint32_t* position) {
*position = lseek((int)file, 0, SEEK_CUR); *position = lseek(file, 0, SEEK_CUR);
return Nix_Return(*position != -1); return Nix_Return(*position != -1);
} }
ReturnCode File_Length(void* file, uint32_t* length) { ReturnCode File_Length(FileHandle file, uint32_t* length) {
struct stat st; struct stat st;
if (fstat((int)file, &st) == -1) { *length = -1; return errno; } if (fstat(file, &st) == -1) { *length = -1; return errno; }
*length = st.st_size; return 0; *length = st.st_size; return 0;
} }
#endif #endif
@ -1113,14 +1113,14 @@ static void Font_Init(void) {
/*########################################################################################################################* /*########################################################################################################################*
*---------------------------------------------------------Socket----------------------------------------------------------* *---------------------------------------------------------Socket----------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
void Socket_Create(SocketPtr* socketResult) { void Socket_Create(SocketHandle* socketResult) {
*socketResult = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); *socketResult = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (*socketResult == -1) { if (*socketResult == -1) {
ErrorHandler_Fail2(Socket__Error(), "Failed to create socket"); ErrorHandler_Fail2(Socket__Error(), "Failed to create socket");
} }
} }
static ReturnCode Socket_ioctl(SocketPtr socket, uint32_t cmd, int* data) { static ReturnCode Socket_ioctl(SocketHandle socket, uint32_t cmd, int* data) {
#ifdef CC_BUILD_WIN #ifdef CC_BUILD_WIN
return ioctlsocket(socket, cmd, data); return ioctlsocket(socket, cmd, data);
#else #else
@ -1128,20 +1128,20 @@ static ReturnCode Socket_ioctl(SocketPtr socket, uint32_t cmd, int* data) {
#endif #endif
} }
ReturnCode Socket_Available(SocketPtr socket, uint32_t* available) { ReturnCode Socket_Available(SocketHandle socket, uint32_t* available) {
return Socket_ioctl(socket, FIONREAD, available); return Socket_ioctl(socket, FIONREAD, available);
} }
ReturnCode Socket_SetBlocking(SocketPtr socket, bool blocking) { ReturnCode Socket_SetBlocking(SocketHandle socket, bool blocking) {
int blocking_raw = blocking ? 0 : -1; int blocking_raw = blocking ? 0 : -1;
return Socket_ioctl(socket, FIONBIO, &blocking_raw); return Socket_ioctl(socket, FIONBIO, &blocking_raw);
} }
ReturnCode Socket_GetError(SocketPtr socket, ReturnCode* result) { ReturnCode Socket_GetError(SocketHandle socket, ReturnCode* result) {
int resultSize = sizeof(ReturnCode); int resultSize = sizeof(ReturnCode);
return getsockopt(socket, SOL_SOCKET, SO_ERROR, result, &resultSize); return getsockopt(socket, SOL_SOCKET, SO_ERROR, result, &resultSize);
} }
ReturnCode Socket_Connect(SocketPtr socket, const String* ip, int port) { ReturnCode Socket_Connect(SocketHandle socket, const String* ip, int port) {
struct { int16_t Family; uint8_t Port[2], IP[4], Pad[8]; } addr; struct { int16_t Family; uint8_t Port[2], IP[4], Pad[8]; } addr;
ReturnCode res; ReturnCode res;
@ -1153,19 +1153,19 @@ ReturnCode Socket_Connect(SocketPtr socket, const String* ip, int port) {
return res == -1 ? Socket__Error() : 0; return res == -1 ? Socket__Error() : 0;
} }
ReturnCode Socket_Read(SocketPtr socket, uint8_t* buffer, uint32_t count, uint32_t* modified) { ReturnCode Socket_Read(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified) {
int recvCount = recv(socket, buffer, count, 0); int recvCount = recv(socket, buffer, count, 0);
if (recvCount != -1) { *modified = recvCount; return 0; } if (recvCount != -1) { *modified = recvCount; return 0; }
*modified = 0; return Socket__Error(); *modified = 0; return Socket__Error();
} }
ReturnCode Socket_Write(SocketPtr socket, uint8_t* buffer, uint32_t count, uint32_t* modified) { ReturnCode Socket_Write(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified) {
int sentCount = send(socket, buffer, count, 0); int sentCount = send(socket, buffer, count, 0);
if (sentCount != -1) { *modified = sentCount; return 0; } if (sentCount != -1) { *modified = sentCount; return 0; }
*modified = 0; return Socket__Error(); *modified = 0; return Socket__Error();
} }
ReturnCode Socket_Close(SocketPtr socket) { ReturnCode Socket_Close(SocketHandle socket) {
ReturnCode res = 0; ReturnCode res = 0;
ReturnCode res1, res2; ReturnCode res1, res2;
@ -1185,7 +1185,7 @@ ReturnCode Socket_Close(SocketPtr socket) {
return res; return res;
} }
ReturnCode Socket_Select(SocketPtr socket, int selectMode, bool* success) { ReturnCode Socket_Select(SocketHandle socket, int selectMode, bool* success) {
fd_set set; fd_set set;
struct timeval time = { 0 }; struct timeval time = { 0 };
int selectCount, nfds; int selectCount, nfds;
@ -1270,12 +1270,12 @@ static ReturnCode Http_GetHeaders(struct AsyncRequest* req, HINTERNET handle) {
if (!HttpQueryInfoA(handle, FLAG_STATUS, &req->StatusCode, &len, NULL)) return GetLastError(); if (!HttpQueryInfoA(handle, FLAG_STATUS, &req->StatusCode, &len, NULL)) return GetLastError();
len = sizeof(DWORD); len = sizeof(DWORD);
HttpQueryInfoA(handle, FLAG_LENGTH, &req->ResultSize, &len, NULL); HttpQueryInfoA(handle, FLAG_LENGTH, &req->ContentLength, &len, NULL);
SYSTEMTIME sysTime; SYSTEMTIME sysTime;
len = sizeof(SYSTEMTIME); len = sizeof(SYSTEMTIME);
if (HttpQueryInfoA(handle, FLAG_LASTMOD, &sysTime, &len, NULL)) { if (HttpQueryInfoA(handle, FLAG_LASTMOD, &sysTime, &len, NULL)) {
DateTime time; struct DateTime time;
Platform_FromSysTime(&time, &sysTime); Platform_FromSysTime(&time, &sysTime);
req->LastModified = DateTime_TotalMs(&time); req->LastModified = DateTime_TotalMs(&time);
} }
@ -1288,27 +1288,37 @@ static ReturnCode Http_GetHeaders(struct AsyncRequest* req, HINTERNET handle) {
} }
static ReturnCode Http_GetData(struct AsyncRequest* req, HINTERNET handle, volatile int* progress) { static ReturnCode Http_GetData(struct AsyncRequest* req, HINTERNET handle, volatile int* progress) {
uint32_t size = req->ResultSize; uint8_t* buffer;
if (!size) return ERROR_NOT_SUPPORTED; uint32_t size, totalRead;
uint32_t read, avail;
bool success;
*progress = 0; *progress = 0;
size = req->ContentLength ? req->ContentLength : 1;
buffer = Mem_Alloc(size, 1, "http get data");
totalRead = 0;
uint8_t* buffer = Mem_Alloc(size, 1, "http get data");
uint32_t left = size, read, totalRead = 0;
req->ResultData = buffer; req->ResultData = buffer;
req->ResultSize = 0;
while (left) { for (;;) {
uint32_t toRead = left, avail = 0; if (!InternetQueryDataAvailable(handle, &avail, 0, 0)) break;
/* only read as much data that is pending */ if (!avail) break;
if (InternetQueryDataAvailable(handle, &avail, 0, 0)) {
toRead = min(toRead, avail); /* expand if buffer is too small (some servers don't give content length) */
if (totalRead + avail > size) {
size = totalRead + avail;
buffer = Mem_Realloc(buffer, size, 1, "http inc data");
req->ResultData = buffer;
} }
bool success = InternetReadFile(handle, buffer, toRead, &read); success = InternetReadFile(handle, &buffer[totalRead], avail, &read);
if (!success) { Mem_Free(buffer); return GetLastError(); } if (!success) { Mem_Free(buffer); return GetLastError(); }
if (!read) break; if (!read) break;
buffer += read; totalRead += read; left -= read;
*progress = (int)(100.0f * totalRead / size); totalRead += read;
if (req->ContentLength) *progress = (int)(100.0f * totalRead / size);
req->ResultSize += read;
} }
*progress = 100; *progress = 100;
@ -1393,7 +1403,9 @@ static size_t Http_GetHeaders(char *buffer, size_t size, size_t nitems, struct A
tmp = String_ClearedArray(req->Etag); tmp = String_ClearedArray(req->Etag);
String_AppendString(&tmp, &value); String_AppendString(&tmp, &value);
} else if (String_CaselessEqualsConst(&name, "Content-Length")) { } else if (String_CaselessEqualsConst(&name, "Content-Length")) {
Convert_TryParseInt(&value, &req->ResultSize); Convert_TryParseInt(&value, &req->ContentLength);
/* TODO: Fix when ContentLength isn't RequestSize */
req->RequestSize = req->ContentLength;
} else if (String_CaselessEqualsConst(&name, "Last-Modified")) { } else if (String_CaselessEqualsConst(&name, "Last-Modified")) {
String_InitArray_NT(tmp, tmpBuffer); String_InitArray_NT(tmp, tmpBuffer);
String_AppendString(&tmp, &value); String_AppendString(&tmp, &value);

View File

@ -1,6 +1,5 @@
#ifndef CC_PLATFORM_H #ifndef CC_PLATFORM_H
#define CC_PLATFORM_H #define CC_PLATFORM_H
#include "Utils.h"
#include "PackedCol.h" #include "PackedCol.h"
#include "Bitmap.h" #include "Bitmap.h"
/* Abstracts platform specific memory management, I/O, etc. /* Abstracts platform specific memory management, I/O, etc.
@ -8,16 +7,19 @@
*/ */
struct DrawTextArgs; struct DrawTextArgs;
struct AsyncRequest; struct AsyncRequest;
struct DateTime;
enum SOCKET_SELECT { SOCKET_SELECT_READ, SOCKET_SELECT_WRITE }; enum Socket_Select { SOCKET_SELECT_READ, SOCKET_SELECT_WRITE };
#ifdef CC_BUILD_WIN #ifdef CC_BUILD_WIN
typedef uintptr_t SocketPtr; typedef uintptr_t SocketHandle;
typedef void* FileHandle;
#else #else
typedef int SocketPtr; typedef int SocketHandle;
typedef int FileHandle;
#endif #endif
/* Origin points for when seeking in a file. */ /* Origin points for when seeking in a file. */
enum FILE_SEEKFROM { FILE_SEEKFROM_BEGIN, FILE_SEEKFROM_CURRENT, FILE_SEEKFROM_END }; enum File_SeekFrom { FILE_SEEKFROM_BEGIN, FILE_SEEKFROM_CURRENT, FILE_SEEKFROM_END };
/* Newline for console and text files. */ /* Newline for console and text files. */
extern char* Platform_NewLine; extern char* Platform_NewLine;
@ -95,9 +97,9 @@ void Platform_Log4(const char* format, const void* a1, const void* a2, const voi
TimeMS DateTime_CurrentUTC_MS(void); TimeMS DateTime_CurrentUTC_MS(void);
/* Returns the current UTC Time. */ /* Returns the current UTC Time. */
/* NOTE: Generally DateTime_CurrentUTC_MS should be used instead. */ /* NOTE: Generally DateTime_CurrentUTC_MS should be used instead. */
void DateTime_CurrentUTC(DateTime* time); void DateTime_CurrentUTC(struct DateTime* time);
/* Returns the current local Time. */ /* Returns the current local Time. */
void DateTime_CurrentLocal(DateTime* time); void DateTime_CurrentLocal(struct DateTime* time);
/* Takes a platform-specific stopwatch measurement. */ /* Takes a platform-specific stopwatch measurement. */
/* NOTE: The value returned is platform-specific - do NOT try to interpret the value. */ /* NOTE: The value returned is platform-specific - do NOT try to interpret the value. */
uint64_t Stopwatch_Measure(void); uint64_t Stopwatch_Measure(void);
@ -118,23 +120,23 @@ bool File_Exists(const String* path);
ReturnCode File_GetModifiedTime_MS(const String* path, TimeMS* ms); ReturnCode File_GetModifiedTime_MS(const String* path, TimeMS* ms);
/* Attempts to create a new (or overwrite) file for writing. */ /* Attempts to create a new (or overwrite) file for writing. */
ReturnCode File_Create(void** file, const String* path); ReturnCode File_Create(FileHandle* file, const String* path);
/* Attempts to open an existing file for reading. */ /* Attempts to open an existing file for reading. */
ReturnCode File_Open(void** file, const String* path); ReturnCode File_Open(FileHandle* file, const String* path);
/* Attempts to open (or create) a file, for appending data to the end of the file. */ /* Attempts to open (or create) a file, for appending data to the end of the file. */
ReturnCode File_Append(void** file, const String* path); ReturnCode File_Append(FileHandle* file, const String* path);
/* Attempts to read data from the file. */ /* Attempts to read data from the file. */
ReturnCode File_Read(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead); ReturnCode File_Read(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead);
/* Attempts to write data to the file. */ /* Attempts to write data to the file. */
ReturnCode File_Write(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote); ReturnCode File_Write(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote);
/* Attempts to close the given file. */ /* Attempts to close the given file. */
ReturnCode File_Close(void* file); ReturnCode File_Close(FileHandle file);
/* Attempts to seek to a position in the given file. */ /* Attempts to seek to a position in the given file. */
ReturnCode File_Seek(void* file, int offset, int seekType); ReturnCode File_Seek(FileHandle file, int offset, int seekType);
/* Attempts to get the current position in the given file. */ /* Attempts to get the current position in the given file. */
ReturnCode File_Position(void* file, uint32_t* position); ReturnCode File_Position(FileHandle file, uint32_t* position);
/* Attempts to retrieve the length of the given file. */ /* Attempts to retrieve the length of the given file. */
ReturnCode File_Length(void* file, uint32_t* length); ReturnCode File_Length(FileHandle file, uint32_t* length);
/* Blocks the current thread for the given number of milliseconds. */ /* Blocks the current thread for the given number of milliseconds. */
CC_EXPORT void Thread_Sleep(uint32_t milliseconds); CC_EXPORT void Thread_Sleep(uint32_t milliseconds);
@ -180,25 +182,25 @@ CC_EXPORT Size2D Platform_TextMeasure(struct DrawTextArgs* args);
CC_EXPORT Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, BitmapCol col); CC_EXPORT Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, BitmapCol col);
/* Allocates a new socket. */ /* Allocates a new socket. */
void Socket_Create(SocketPtr* socket); void Socket_Create(SocketHandle* socket);
/* Returns how much data is available to be read from the given socket. */ /* Returns how much data is available to be read from the given socket. */
ReturnCode Socket_Available(SocketPtr socket, uint32_t* available); ReturnCode Socket_Available(SocketHandle socket, uint32_t* available);
/* Sets whether operations on this socket block the calling thread. */ /* Sets whether operations on this socket block the calling thread. */
/* e.g. if blocking is on, calling Connect() blocks until a response is received. */ /* e.g. if blocking is on, calling Connect() blocks until a response is received. */
ReturnCode Socket_SetBlocking(SocketPtr socket, bool blocking); ReturnCode Socket_SetBlocking(SocketHandle socket, bool blocking);
/* Returns (and resets) the last error generated by this socket. */ /* Returns (and resets) the last error generated by this socket. */
ReturnCode Socket_GetError(SocketPtr socket, ReturnCode* result); ReturnCode Socket_GetError(SocketHandle socket, ReturnCode* result);
/* Attempts to initalise a TCP connection to the given IP address:port. */ /* Attempts to initalise a TCP connection to the given IP address:port. */
ReturnCode Socket_Connect(SocketPtr socket, const String* ip, int port); ReturnCode Socket_Connect(SocketHandle socket, const String* ip, int port);
/* Attempts to read data from the given socket. */ /* Attempts to read data from the given socket. */
ReturnCode Socket_Read(SocketPtr socket, uint8_t* buffer, uint32_t count, uint32_t* modified); ReturnCode Socket_Read(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified);
/* Attempts to write data to the given socket. */ /* Attempts to write data to the given socket. */
ReturnCode Socket_Write(SocketPtr socket, uint8_t* buffer, uint32_t count, uint32_t* modified); ReturnCode Socket_Write(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified);
/* Attempts to close the given socket. */ /* Attempts to close the given socket. */
ReturnCode Socket_Close(SocketPtr socket); ReturnCode Socket_Close(SocketHandle socket);
/* Attempts to poll the socket for reading or writing. */ /* Attempts to poll the socket for reading or writing. */
ReturnCode Socket_Select(SocketPtr socket, int selectMode, bool* success); ReturnCode Socket_Select(SocketHandle socket, int selectMode, bool* success);
/* Initalises the platform specific http library state. */ /* Initalises the platform specific http library state. */
void Http_Init(void); void Http_Init(void);

View File

@ -240,7 +240,7 @@ void ServerConnection_InitSingleplayer(void) {
/*########################################################################################################################* /*########################################################################################################################*
*--------------------------------------------------Multiplayer connection-------------------------------------------------* *--------------------------------------------------Multiplayer connection-------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
static SocketPtr net_socket; static SocketHandle net_socket;
static uint8_t net_readBuffer[4096 * 5]; static uint8_t net_readBuffer[4096 * 5];
static uint8_t net_writeBuffer[131]; static uint8_t net_writeBuffer[131];
static uint8_t* net_readCurrent; static uint8_t* net_readCurrent;

View File

@ -108,19 +108,19 @@ static ReturnCode Stream_FileLength(struct Stream* s, uint32_t* length) {
} }
ReturnCode Stream_OpenFile(struct Stream* s, const String* path) { ReturnCode Stream_OpenFile(struct Stream* s, const String* path) {
void* file; FileHandle file;
ReturnCode res = File_Open(&file, path); ReturnCode res = File_Open(&file, path);
Stream_FromFile(s, file); Stream_FromFile(s, file);
return res; return res;
} }
ReturnCode Stream_CreateFile(struct Stream* s, const String* path) { ReturnCode Stream_CreateFile(struct Stream* s, const String* path) {
void* file; FileHandle file;
ReturnCode res = File_Create(&file, path); ReturnCode res = File_Create(&file, path);
Stream_FromFile(s, file); Stream_FromFile(s, file);
return res; return res;
} }
void Stream_FromFile(struct Stream* s, void* file) { void Stream_FromFile(struct Stream* s, FileHandle file) {
Stream_Init(s); Stream_Init(s);
s->Meta.File = file; s->Meta.File = file;

View File

@ -1,7 +1,7 @@
#ifndef CC_STREAM_H #ifndef CC_STREAM_H
#define CC_STREAM_H #define CC_STREAM_H
#include "String.h"
#include "Constants.h" #include "Constants.h"
#include "Platform.h"
/* Defines an abstract way of reading and writing data in a streaming manner. /* Defines an abstract way of reading and writing data in a streaming manner.
Also provides common helper methods for reading/writing data to/from streams. Also provides common helper methods for reading/writing data to/from streams.
Copyright 2017 ClassicalSharp | Licensed under BSD-3 Copyright 2017 ClassicalSharp | Licensed under BSD-3
@ -29,7 +29,7 @@ struct Stream {
ReturnCode (*Close)(struct Stream* s); ReturnCode (*Close)(struct Stream* s);
union { union {
void* File; FileHandle File;
void* Inflate; void* Inflate;
/* NOTE: These structs rely on overlapping Meta_Mem fields being the same! Don't change them */ /* NOTE: These structs rely on overlapping Meta_Mem fields being the same! Don't change them */
struct { uint8_t* Cur; uint32_t Left, Length; uint8_t* Base; } Mem; struct { uint8_t* Cur; uint32_t Left, Length; uint8_t* Base; } Mem;
@ -54,7 +54,7 @@ CC_EXPORT ReturnCode Stream_OpenFile(struct Stream* s, const String* path);
/* Wrapper for File_Create() then Stream_FromFile() */ /* Wrapper for File_Create() then Stream_FromFile() */
CC_EXPORT ReturnCode Stream_CreateFile(struct Stream* s, const String* path); CC_EXPORT ReturnCode Stream_CreateFile(struct Stream* s, const String* path);
/* Wraps a file, allowing reading from/writing to/seeking in the file. */ /* Wraps a file, allowing reading from/writing to/seeking in the file. */
CC_EXPORT void Stream_FromFile(struct Stream* s, void* file); CC_EXPORT void Stream_FromFile(struct Stream* s, FileHandle file);
/* Wraps another Stream, only allows reading up to 'len' bytes from the wrapped stream. */ /* Wraps another Stream, only allows reading up to 'len' bytes from the wrapped stream. */
CC_EXPORT void Stream_ReadonlyPortion(struct Stream* s, struct Stream* source, uint32_t len); CC_EXPORT void Stream_ReadonlyPortion(struct Stream* s, struct Stream* source, uint32_t len);

View File

@ -3,6 +3,7 @@
#include "ErrorHandler.h" #include "ErrorHandler.h"
#include "Platform.h" #include "Platform.h"
#include "Stream.h" #include "Stream.h"
#include "Utils.h"
String String_Init(STRING_REF char* buffer, int length, int capacity) { String String_Init(STRING_REF char* buffer, int length, int capacity) {
String s; String s;

View File

@ -21,7 +21,7 @@ static bool DateTime_IsLeapYear(int year) {
return (year % 400) == 0; return (year % 400) == 0;
} }
int DateTime_TotalDays(const DateTime* time) { int DateTime_TotalDays(const struct DateTime* time) {
/* Days from before this year */ /* Days from before this year */
int y = time->Year - 1, days = 365 * y; int y = time->Year - 1, days = 365 * y;
/* A year is a leap year when the year is: */ /* A year is a leap year when the year is: */
@ -38,7 +38,7 @@ int DateTime_TotalDays(const DateTime* time) {
return days; return days;
} }
TimeMS DateTime_TotalMs(const DateTime* time) { TimeMS DateTime_TotalMs(const struct DateTime* time) {
int days = DateTime_TotalDays(time); int days = DateTime_TotalDays(time);
uint64_t seconds = uint64_t seconds =
(uint64_t)days * DATETIME_SECONDS_PER_DAY + (uint64_t)days * DATETIME_SECONDS_PER_DAY +
@ -48,7 +48,7 @@ TimeMS DateTime_TotalMs(const DateTime* time) {
return seconds * DATETIME_MILLIS_PER_SEC + time->Milli; return seconds * DATETIME_MILLIS_PER_SEC + time->Milli;
} }
void DateTime_FromTotalMs(DateTime* time, TimeMS ms) { void DateTime_FromTotalMs(struct DateTime* time, TimeMS ms) {
int dayMS, days, year; int dayMS, days, year;
int daysInYear, month; int daysInYear, month;
uint16_t* totalDays; uint16_t* totalDays;
@ -90,7 +90,7 @@ void DateTime_FromTotalMs(DateTime* time, TimeMS ms) {
void DateTime_HttpDate(TimeMS ms, String* str) { void DateTime_HttpDate(TimeMS ms, String* str) {
static char* days_of_week[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; static char* days_of_week[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
static char* month_names[13] = { NULL, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static char* month_names[13] = { NULL, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
DateTime t; struct DateTime t;
int days; int days;
DateTime_FromTotalMs(&t, ms); DateTime_FromTotalMs(&t, ms);

View File

@ -8,7 +8,7 @@
/* Represents a particular instance in time in some timezone. Not necessarily UTC time. */ /* Represents a particular instance in time in some timezone. Not necessarily UTC time. */
/* NOTE: This is not an efficiently sized struct. Store DateTime_TotalMs instead for that. */ /* NOTE: This is not an efficiently sized struct. Store DateTime_TotalMs instead for that. */
typedef struct DateTime_ { struct DateTime {
int Year; /* Year, ranges from 0 to 65535 */ int Year; /* Year, ranges from 0 to 65535 */
int Month; /* Month, ranges from 1 to 12 */ int Month; /* Month, ranges from 1 to 12 */
int Day; /* Day, ranges from 1 to 31 */ int Day; /* Day, ranges from 1 to 31 */
@ -16,12 +16,12 @@ typedef struct DateTime_ {
int Minute; /* Minute, ranges from 0 to 59 */ int Minute; /* Minute, ranges from 0 to 59 */
int Second; /* Second, ranges from 0 to 59 */ int Second; /* Second, ranges from 0 to 59 */
int Milli; /* Milliseconds, ranges from 0 to 999 */ int Milli; /* Milliseconds, ranges from 0 to 999 */
} DateTime; };
#define DATETIME_MILLIS_PER_SEC 1000 #define DATETIME_MILLIS_PER_SEC 1000
int DateTime_TotalDays(const DateTime* time); int DateTime_TotalDays(const struct DateTime* time);
TimeMS DateTime_TotalMs(const DateTime* time); TimeMS DateTime_TotalMs(const struct DateTime* time);
void DateTime_FromTotalMs(DateTime* time, TimeMS ms); void DateTime_FromTotalMs(struct DateTime* time, TimeMS ms);
void DateTime_HttpDate(TimeMS ms, String* str); void DateTime_HttpDate(TimeMS ms, String* str);
CC_NOINLINE int Utils_ParseEnum(const String* text, int defValue, const char** names, int namesCount); CC_NOINLINE int Utils_ParseEnum(const String* text, int defValue, const char** names, int namesCount);

View File

@ -1916,21 +1916,25 @@ static void PlayerListWidget_SetColumnPos(struct PlayerListWidget* w, int column
} }
static void PlayerListWidget_RepositionColumns(struct PlayerListWidget* w) { static void PlayerListWidget_RepositionColumns(struct PlayerListWidget* w) {
int width = 0, centreX = Game_Width / 2; int x, y, width = 0, height;
w->YHeight = 0; int col, columns;
w->YHeight = 0;
columns = Math_CeilDiv(w->NamesCount, LIST_NAMES_PER_COLUMN);
int col, columns = Math_CeilDiv(w->NamesCount, LIST_NAMES_PER_COLUMN);
for (col = 0; col < columns; col++) { for (col = 0; col < columns; col++) {
width += PlayerListWidget_GetColumnWidth(w, col); width += PlayerListWidget_GetColumnWidth(w, col);
int colHeight = PlayerListWidget_GetColumnHeight(w, col); height = PlayerListWidget_GetColumnHeight(w, col);
w->YHeight = max(colHeight, w->YHeight); w->YHeight = max(height, w->YHeight);
} }
if (width < 480) width = 480; if (width < 480) width = 480;
w->XMin = centreX - width / 2; w->XMin = Game_Width / 2 - width / 2;
w->XMax = centreX + width / 2; w->XMax = Game_Width / 2 + width / 2;
x = w->XMin;
y = Game_Height / 2 - w->YHeight / 2;
int x = w->XMin, y = Game_Height / 2 - w->YHeight / 2;
for (col = 0; col < columns; col++) { for (col = 0; col < columns; col++) {
PlayerListWidget_SetColumnPos(w, col, x, y); PlayerListWidget_SetColumnPos(w, col, x, y);
x += PlayerListWidget_GetColumnWidth(w, col); x += PlayerListWidget_GetColumnWidth(w, col);

View File

@ -115,12 +115,14 @@ static void Window_ResetWindowState(void) {
static bool win_hiddenBorder; static bool win_hiddenBorder;
static void Window_DoSetHiddenBorder(bool value) { static void Window_DoSetHiddenBorder(bool value) {
bool wasVisible;
RECT rect;
if (win_hiddenBorder == value) return; if (win_hiddenBorder == value) return;
/* We wish to avoid making an invisible window visible just to change the border. /* We wish to avoid making an invisible window visible just to change the border.
However, it's a good idea to make a visible window invisible temporarily, to However, it's a good idea to make a visible window invisible temporarily, to
avoid garbage caused by the border change. */ avoid garbage caused by the border change. */
bool was_visible = Window_GetVisible(); wasVisible = Window_GetVisible();
/* To ensure maximized/minimized windows work correctly, reset state to normal, /* To ensure maximized/minimized windows work correctly, reset state to normal,
change the border, then go back to maximized/minimized. */ change the border, then go back to maximized/minimized. */
@ -130,14 +132,13 @@ static void Window_DoSetHiddenBorder(bool value) {
style |= (value ? WS_POPUP : WS_OVERLAPPEDWINDOW); style |= (value ? WS_POPUP : WS_OVERLAPPEDWINDOW);
/* Make sure client size doesn't change when changing the border style.*/ /* Make sure client size doesn't change when changing the border style.*/
RECT rect;
rect.left = Window_Bounds.X; rect.top = Window_Bounds.Y; rect.left = Window_Bounds.X; rect.top = Window_Bounds.Y;
rect.right = rect.left + Window_Bounds.Width; rect.right = rect.left + Window_Bounds.Width;
rect.bottom = rect.top + Window_Bounds.Height; rect.bottom = rect.top + Window_Bounds.Height;
AdjustWindowRect(&rect, style, false); AdjustWindowRect(&rect, style, false);
/* This avoids leaving garbage on the background window. */ /* This avoids leaving garbage on the background window. */
if (was_visible) Window_SetVisible(false); if (wasVisible) Window_SetVisible(false);
SetWindowLong(win_handle, GWL_STYLE, style); SetWindowLong(win_handle, GWL_STYLE, style);
SetWindowPos(win_handle, NULL, 0, 0, Rect_Width(rect), Rect_Height(rect), SetWindowPos(win_handle, NULL, 0, 0, Rect_Width(rect), Rect_Height(rect),
@ -146,7 +147,7 @@ static void Window_DoSetHiddenBorder(bool value) {
/* Force window to redraw update its borders, but only if it's /* Force window to redraw update its borders, but only if it's
already visible (invisible windows will change borders when already visible (invisible windows will change borders when
they become visible, so no need to make them visiable prematurely).*/ they become visible, so no need to make them visiable prematurely).*/
if (was_visible) Window_SetVisible(true); if (wasVisible) Window_SetVisible(true);
Window_SetWindowState(state); Window_SetWindowState(state);
} }
@ -166,15 +167,19 @@ static void Window_UpdateClientSize(HWND handle) {
} }
static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) { static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {
char keyChar;
bool wasFocused;
float wheelDelta;
switch (message) { switch (message) {
case WM_ACTIVATE: case WM_ACTIVATE:
{ wasFocused = Window_Focused;
bool wasFocused = Window_Focused;
Window_Focused = LOWORD(wParam) != 0; Window_Focused = LOWORD(wParam) != 0;
if (Window_Focused != wasFocused) { if (Window_Focused != wasFocused) {
Event_RaiseVoid(&WindowEvents_FocusChanged); Event_RaiseVoid(&WindowEvents_FocusChanged);
} }
} break; break;
case WM_ENTERMENULOOP: case WM_ENTERMENULOOP:
case WM_ENTERSIZEMOVE: case WM_ENTERSIZEMOVE:
@ -238,31 +243,24 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara
case WM_CHAR: case WM_CHAR:
{
char keyChar;
if (Convert_TryUnicodeToCP437((Codepoint)wParam, &keyChar)) { if (Convert_TryUnicodeToCP437((Codepoint)wParam, &keyChar)) {
Event_RaiseInt(&KeyEvents_Press, keyChar); Event_RaiseInt(&KeyEvents_Press, keyChar);
} }
} break; break;
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
{
/* set before position change, in case mouse buttons changed when outside window */ /* set before position change, in case mouse buttons changed when outside window */
Mouse_SetPressed(MouseButton_Left, (wParam & 0x01) != 0); Mouse_SetPressed(MouseButton_Left, (wParam & 0x01) != 0);
Mouse_SetPressed(MouseButton_Right, (wParam & 0x02) != 0); Mouse_SetPressed(MouseButton_Right, (wParam & 0x02) != 0);
Mouse_SetPressed(MouseButton_Middle, (wParam & 0x10) != 0); Mouse_SetPressed(MouseButton_Middle, (wParam & 0x10) != 0);
/* TODO: do we need to set XBUTTON1 / XBUTTON 2 here */ /* TODO: do we need to set XBUTTON1/XBUTTON2 here */
Mouse_SetPosition(LOWORD(lParam), HIWORD(lParam));
WORD mouse_x = LOWORD(lParam); break;
WORD mouse_y = HIWORD(lParam);
Mouse_SetPosition(mouse_x, mouse_y);
} break;
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
{ wheelDelta = ((short)HIWORD(wParam)) / (float)WHEEL_DELTA;
float wheel_delta = ((short)HIWORD(wParam)) / (float)WHEEL_DELTA; Mouse_SetWheel(Mouse_Wheel + wheelDelta);
Mouse_SetWheel(Mouse_Wheel + wheel_delta); return 0;
} return 0;
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
Mouse_SetPressed(MouseButton_Left, true); Mouse_SetPressed(MouseButton_Left, true);