Fix more crashes and start working on JSON port

This commit is contained in:
UnknownShadow200 2018-12-07 18:24:00 +11:00
parent eb1e69b86b
commit 35b6fadc95
8 changed files with 178 additions and 15 deletions

View File

@ -24,7 +24,7 @@ CC_NOINLINE static struct LWidget* LScreen_WidgetAt(struct LScreen* s, int x, in
w = s->Widgets[i];
if (w->Hidden) continue;
if (Gui_Contains(w->X, w->Y, w->Width, w->Height, w->X, w->Y)) return w;
if (Gui_Contains(w->X, w->Y, w->Width, w->Height, x, y)) return w;
}
return NULL;
}
@ -143,8 +143,10 @@ CC_NOINLINE static void LScreen_Reset(struct LScreen* s) {
s->MouseDown = LScreen_MouseDown;
s->MouseUp = LScreen_MouseUp;
s->MouseMove = LScreen_MouseMove;
s->HoverWidget = LScreen_HoverWidget;
s->UnhoverWidget = LScreen_UnhoverWidget;
s->HoverWidget = LScreen_HoverWidget;
s->UnhoverWidget = LScreen_UnhoverWidget;
s->SelectWidget = LScreen_SelectWidget;
s->UnselectWidget = LScreen_UnselectWidget;
/* reset all widgets mouse state */
for (i = 0; i < s->NumWidgets; i++) {

View File

@ -29,7 +29,7 @@ typedef void(*LWidget_Func)(struct LScreen* s, struct LWidget* w);
struct LWidget* OnEnterWidget; /* Default widget to auto-click when Enter is pressed. Can be NULL. */ \
struct LWidget* HoveredWidget; /* Widget the mouse is currently hovering over. */ \
struct LWidget* SelectedWidget; /* Widget mouse last clicked on. */ \
int NumWidgets; /* Number of widgets actually used. */ \
int NumWidgets; /* Number of widgets actually used. */ \
struct LWidget** Widgets; /* Array of pointers to all widgets in the screen. */
struct LScreen { LScreen_Layout };

View File

@ -1,6 +1,168 @@
#include "LWeb.h"
#include "Platform.h"
#define TOKEN_NONE 0
#define TOKEN_NUM 1
#define TOKEN_TRUE 2
#define TOKEN_FALSE 3
#define TOKEN_NULL 4
struct JsonContext {
/* Pointer to current character in JSON stream being inspected. */
char* Cur;
/* Number of characters left to be inspected. */
int Left;
/* Whether there was an error parsing the JSON. */
bool Failed;
/* Callback function invoked on each token read. */
void (*OnToken)(char token);
/* Callback function invoked on each member of an object or array. */
/* NOTE: This only works for 'simple' key-value pairs. */ newarray
void (*OnValue)(char token, String* value);
};
/* new array, new object functions?? */
/* need to push/pop 'CurrentKey' */
/* Consumes n characters from the JSON stream */
#define JsonContext_Consume(ctx, n) ctx->Cur += n; ctx->Left -= n;
static String strTrue = String_FromConst("true");
static String strFalse = String_FromConst("false");
static String strNull = String_FromConst("null");
static bool Json_IsWhitespace(char c) {
return c == '\r' || c == '\n' || c == '\t' || c == ' ';
}
static bool Json_IsNumber(char c) {
return c == '-' || c == '.' || (c >= '0' && c <= '9');
}
static bool Json_ConsumeConstant(struct JsonContext* ctx, String* value) {
int i;
if (value->length > ctx->Left) return false;
for (i = 0; i < value->length; i++) {
if (ctx->Cur[i] != value->buffer[i]) return false;
}
JsonContext_Consume(ctx, value->length);
return true;
}
static int Json_ConsumeToken(struct JsonContext* ctx) {
for (; ctx->Left && Json_IsWhitespace(*ctx->Cur); ) { JsonContext_Consume(ctx, 1); }
if (!ctx->Left) return TOKEN_NONE;
char c = *ctx->Cur;
if (c == '{' || c == '}' || c == '[' || c == ']' || c == ',' || c == '"' || c == ':') {
JsonContext_Consume(ctx, 1); return c;
}
/* number token forms part of value, don't consume it */
if (Json_IsNumber(c)) return TOKEN_NUM;
if (Json_ConsumeConstant(ctx, &strTrue)) return TOKEN_TRUE;
if (Json_ConsumeConstant(ctx, &strFalse)) return TOKEN_FALSE;
if (Json_ConsumeConstant(ctx, &strNull)) return TOKEN_NULL;
/* invalid token */
JsonContext_Consume(ctx, 1);
return TOKEN_NONE;
}
static String Json_ConsumeNumber(struct JsonContext* ctx) {
int len = 0;
for (; ctx->Left && Json_IsNumber(*ctx->Cur); len++) { JsonContext_Consume(ctx, 1); }
return String_Init(ctx->Cur - len, len, len);
}
static void Json_ConsumeObject(struct JsonContext* ctx) {
int token; /* push and pop cur key */
while (true) {
token = Json_ConsumeToken(ctx);
if (token == ',') continue;
if (token == '}') return;
if (token != '"') { ctx->Failed = true; return; }
string key = ParseString(ctx);
token = Json_ConsumeToken(ctx);
if (token != ':') { ctx->Failed = true; return; }
token = Json_ConsumeToken(ctx);
if (token == TOKEN_NONE) { ctx->Failed = true; return; }
members[key] = ParseValue(token, ctx);
}
}
static void Json_ConsumeArray(struct JsonContext* ctx) {
int token;
while (true) {
token = NextToken(ctx);
if (token == ',') continue;
if (token == ']') return;
if (token == TOKEN_NONE) { ctx->Failed = true; return; }
elements.Add(ParseValue(token, ctx));
}
}
static string ParseString(struct JsonContext* ctx) {
int codepoint, h[4];
char c;
StringBuilder s = ctx.strBuffer; s.Length = 0;
for (; ctx->Left;) {
c = *ctx->Cur; JsonContext_Consume(ctx, 1);
if (c == '"') return s.ToString();
if (c != '\\') { s.Append(c); continue; }
/* form of \X */
if (!ctx->Left) break;
c = *ctx->Cur; JsonContext_Consume(ctx, 1);
if (c == '/' || c == '\\' || c == '"') { s.Append(c); continue; }
/* form of \uYYYY */
if (c != 'u' || ctx->Left < 4) break;
if (!PackedCol_Unhex(ctx->Cur[0], &h[0])) break;
if (!PackedCol_Unhex(ctx->Cur[1], &h[1])) break;
if (!PackedCol_Unhex(ctx->Cur[2], &h[2])) break;
if (!PackedCol_Unhex(ctx->Cur[3], &h[3])) break;
codepoint = (h[0] << 12) | (h[1] << 8) | (h[2] << 4) | h[3];
/* don't want control characters in names/software */
if (codepoint >= 32) s.Append((char)codepoint);
JsonContext_Consume(ctx, 4);
}
ctx->Failed = true; return null;
}
static String Json_ConsumeValue(int token, struct JsonContext* ctx) {
switch (token) {
case '{': return ParseObject(ctx);
case '[': return ParseArray(ctx);
case '"': return ParseString(ctx);
case TOKEN_NUM: return Json_ConsumeNumber(ctx);
case TOKEN_TRUE: return strTrue;
case TOKEN_FALSE: return strFalse;
case TOKEN_NULL: break;
}
return String_Empty;
}
static object ParseStream(struct JsonContext* ctx) {
return ParseValue(NextToken(ctx), ctx);
}
static void LWebTask_Reset(struct LWebTask* task) {
task->Completed = false;
task->Working = true;

View File

@ -10,7 +10,7 @@
#define BORDER 1
void LWidget_SetLocation(void* widget, uint8_t horAnchor, uint8_t verAnchor, int xOffset, int yOffset) {
struct Widget* w = widget;
struct LWidget* w = widget;
w->HorAnchor = horAnchor; w->VerAnchor = verAnchor;
w->XOffset = xOffset; w->YOffset = yOffset;
LWidget_CalcPosition(widget);

View File

@ -335,7 +335,6 @@ static void Launcher_ProcessZipEntry(const String* path, struct Stream* data, st
if (res) {
Launcher_ShowError(res, "decoding terrain.png"); return;
} else {
Drawer2D_SetFontBitmap(&bmp);
Launcher_LoadTextures(&bmp);
}
}

View File

@ -206,7 +206,7 @@ ReturnCode Socket_Select(SocketHandle socket, int selectMode, bool* success);
/* Initalises the platform specific http library state. */
void Http_Init(void);
/* Performs a http request, setting progress as data is received. */
/* NOTE: NOT thread safe - you should always use AsyncDownloader for making requests. */
/* NOTE: NOT thread safe - you should ALWAYS use AsyncDownloader for making requests. */
ReturnCode Http_Do(struct AsyncRequest* req, volatile int* progress);
/* Frees the platform specific http library state. */
ReturnCode Http_Free(void);

View File

@ -88,7 +88,7 @@ void ServerConnection_CheckAsyncResources(void) {
Chat_Add1("&cError %i when trying to download texture pack", &item.Result);
} else {
int status = item.StatusCode;
if (status == 0 || status == 304) return;
if (status == 200 || status == 304) return;
Chat_Add1("&c%i error when trying to download texture pack", &status);
}
}

View File

@ -2,7 +2,7 @@
#define CC_WINDOW_H
#include "String.h"
#include "Bitmap.h"
/* Abstracts creating and managing a native window.
/* Abstracts creating and managing the native window.
Copyright 2017 ClassicalSharp | Licensed under BSD-3 | Based on OpenTK code
*/
@ -31,23 +31,23 @@
OTHER DEALINGS IN THE SOFTWARE.
*/
/* The states a window can be in. */
/* The states the window can be in. */
typedef enum WindowState_ {
WINDOW_STATE_NORMAL, WINDOW_STATE_MINIMISED, WINDOW_STATE_MAXIMISED, WINDOW_STATE_FULLSCREEN
} WindowState;
struct GraphicsMode;
/* Creates a new window of the given size at centre of the screen, with default graphics mode. */
/* Creates the window as the given size at centre of the screen, with default graphics mode. */
void Window_CreateSimple(int width, int height);
/* Creates a new window of the given size at the given position on screen. */
/* Creates the window as the given size at the given position on screen. */
void Window_Create(int x, int y, int width, int height, struct GraphicsMode* mode);
/* Sets the text of the titlebar above the window. */
void Window_SetTitle(const String* title);
/* Gets the text currently on the clipboard. */
/* NOTE: You must have created a window beforehand. (necessary for X11) */
/* NOTE: You MUST have created the window beforehand. (necessary for X11) */
void Window_GetClipboardText(String* value);
/* Sets the text currently on the clipboard. */
/* NOTE: You must have created a window beforehand. (necessary for X11) */
/* NOTE: You MUST have created the window beforehand. (necessary for X11) */
void Window_SetClipboardText(const String* value);
/* TODO: IMPLEMENT void Window_SetIcon(Bitmap* bmp); */
@ -100,7 +100,7 @@ void Window_SetScreenCursorPos(int x, int y);
/* Whether the cursor is visible when over this window. */
bool Window_GetCursorVisible(void);
/* Sets whether the cursor is visible when over this window. */
/* NOTE: You must be careful with this! OS typically uses a counter for visibility,
/* NOTE: You MUST BE VERY CAREFUL with this! OS typically uses a counter for visibility,
so setting invisible multiple times means you must then set visible multiple times. */
void Window_SetCursorVisible(bool visible);