yet more c90 rewrite

This commit is contained in:
UnknownShadow200 2018-11-04 13:23:40 +11:00
parent 514174f2bf
commit feaf213fa2
15 changed files with 273 additions and 215 deletions

View File

@ -23,7 +23,8 @@ void GZipHeader_Init(struct GZipHeader* header) {
}
ReturnCode GZipHeader_Read(struct Stream* s, struct GZipHeader* header) {
ReturnCode res; uint8_t tmp;
uint8_t tmp;
ReturnCode res;
switch (header->State) {
case GZIP_STATE_HEADER1:
@ -104,7 +105,8 @@ void ZLibHeader_Init(struct ZLibHeader* header) {
}
ReturnCode ZLibHeader_Read(struct Stream* s, struct ZLibHeader* header) {
ReturnCode res; uint8_t tmp;
uint8_t tmp;
ReturnCode res;
switch (header->State) {
case ZLIB_STATE_COMPRESSIONMETHOD:
@ -196,7 +198,8 @@ static void Huffman_Build(struct HuffmanTable* table, uint8_t* bitLens, int coun
offset += bl_count[i];
/* Last codeword is actually: code + (bl_count[i] - 1) */
/* When decoding we peform < against this value though, so we need to add 1 here */
/* When decoding we peform < against this value though, so need to add 1 here */
/* This way, don't need to special case bit lengths with 0 codewords when decoding */
if (bl_count[i]) {
table->EndCodewords[i] = code + bl_count[i];
} else {
@ -306,7 +309,7 @@ void Inflate_Init(struct InflateState* state, struct Stream* source) {
state->LastBlock = false;
state->Bits = 0;
state->NumBits = 0;
state->NextIn = state->Input;
state->NextIn = state->Input;
state->AvailIn = 0;
state->Output = NULL;
state->AvailOut = 0;
@ -420,7 +423,7 @@ void Inflate_Process(struct InflateState* state) {
} break;
case 1: { /* Fixed/static huffman compressed */
Huffman_Build(&state->Table.Lits, fixed_lits, INFLATE_MAX_LITS);
Huffman_Build(&state->Table.Lits, fixed_lits, INFLATE_MAX_LITS);
Huffman_Build(&state->TableDists, fixed_dists, INFLATE_MAX_DISTS);
state->State = Inflate_NextCompressState(state);
} break;

View File

@ -75,8 +75,8 @@ NOINLINE_ void Inflate_MakeStream(struct Stream* stream, struct InflateState* st
#define DEFLATE_HASH_SIZE 0x1000UL
#define DEFLATE_HASH_MASK 0x0FFFUL
struct DeflateState {
uint32_t Bits; /* Holds bits across byte boundaries*/
uint32_t NumBits; /* Number of bits in Bits buffer*/
uint32_t Bits; /* Holds bits across byte boundaries */
uint32_t NumBits; /* Number of bits in Bits buffer */
uint32_t InputPosition;
uint8_t* NextOut; /* Pointer within Output buffer to next byte that can be written */

View File

@ -40,8 +40,9 @@ void Drawer2D_Make2DTexture(struct Texture* tex, Bitmap* bmp, Size2D used, int X
bool Drawer2D_ValidColCodeAt(const String* text, int i);
bool Drawer2D_ValidColCode(char c);
/* Whether text is empty or consists purely of valid colour codes. */
bool Drawer2D_IsEmptyText(const String* text);
/* Returns the last valid colour code in the given input, or \0 if no valid colour code was found. */
/* Returns the last valid colour code in the given input, or \0 if not found. */
char Drawer2D_LastCol(const String* text, int start);
bool Drawer2D_IsWhiteCol(char c);

View File

@ -528,6 +528,7 @@ static void Player_DrawName(struct Player* player) {
struct Model* model = e->Model;
Vector3 pos;
float scale;
VertexP3fT2fC4b vertices[4];
if (player->NameTex.X == PLAYER_NAME_EMPTY_TEX) return;
if (!player->NameTex.ID) Player_MakeNameTexture(player);
@ -548,7 +549,6 @@ static void Player_DrawName(struct Player* player) {
size.X *= tempW * 0.2f; size.Y *= tempW * 0.2f;
}
VertexP3fT2fC4b vertices[4];
TextureRec rec = { 0.0f, 0.0f, player->NameTex.U2, player->NameTex.V2 };
PackedCol col = PACKEDCOL_WHITE;
Particle_DoRender(&size, &pos, &rec, col, vertices);
@ -664,26 +664,27 @@ static void Player_ClearHat(Bitmap* bmp, uint8_t skinType) {
}
}
static void Player_EnsurePow2(struct Player* player, Bitmap* bmp) {
int width = Math_NextPowOf2(bmp->Width);
int height = Math_NextPowOf2(bmp->Height);
static void Player_EnsurePow2(struct Player* p, Bitmap* bmp) {
uint32_t stride;
int width, height;
Bitmap scaled;
int y;
width = Math_NextPowOf2(bmp->Width);
height = Math_NextPowOf2(bmp->Height);
if (width == bmp->Width && height == bmp->Height) return;
Bitmap_Allocate(&scaled, width, height);
int y;
uint32_t stride = (uint32_t)(bmp->Width) * BITMAP_SIZEOF_PIXEL;
p->Base.uScale = (float)bmp->Width / width;
p->Base.vScale = (float)bmp->Height / height;
stride = bmp->Width * BITMAP_SIZEOF_PIXEL;
for (y = 0; y < bmp->Height; y++) {
uint32_t* src = Bitmap_GetRow(bmp, y);
uint32_t* dst = Bitmap_GetRow(&scaled, y);
Mem_Copy(dst, src, stride);
}
struct Entity* entity = &player->Base;
entity->uScale = (float)bmp->Width / width;
entity->vScale = (float)bmp->Height / height;
Mem_Free(bmp->Scan0);
*bmp = scaled;
}
@ -831,16 +832,18 @@ static void LocalPlayer_SetLocation(struct Entity* e, struct LocationUpdate* upd
}
void LocalPlayer_Tick(struct Entity* e, double delta) {
if (!World_Blocks) return;
struct LocalPlayer* p = (struct LocalPlayer*)e;
struct HacksComp* hacks = &p->Hacks;
e->StepSize = hacks->FullBlockStep && hacks->Enabled && hacks->CanAnyHacks && hacks->CanSpeed ? 1.0f : 0.5f;
p->OldVelocity = e->Velocity;
float xMoving = 0, zMoving = 0;
LocalInterpComp_AdvanceState(&p->Interp);
bool wasOnGround = e->OnGround;
bool wasOnGround;
Vector3 headingVelocity;
if (!World_Blocks) return;
e->StepSize = hacks->FullBlockStep && hacks->Enabled && hacks->CanAnyHacks && hacks->CanSpeed ? 1.0f : 0.5f;
p->OldVelocity = e->Velocity;
wasOnGround = e->OnGround;
LocalInterpComp_AdvanceState(&p->Interp);
LocalPlayer_HandleInput(&xMoving, &zMoving);
hacks->Floating = hacks->Noclip || hacks->Flying;
if (!hacks->Floating && hacks->CanBePushed) PhysicsComp_DoEntityPush(e);
@ -851,7 +854,7 @@ void LocalPlayer_Tick(struct Entity* e, double delta) {
}
PhysicsComp_UpdateVelocityState(&p->Physics);
Vector3 headingVelocity = Vector3_RotateY3(xMoving, 0, zMoving, e->HeadY * MATH_DEG2RAD);
headingVelocity = Vector3_RotateY3(xMoving, 0, zMoving, e->HeadY * MATH_DEG2RAD);
PhysicsComp_PhysicsTick(&p->Physics, headingVelocity);
/* Fixes high jump, when holding down a movement key, jump, fly, then let go of fly key */
@ -861,7 +864,7 @@ void LocalPlayer_Tick(struct Entity* e, double delta) {
AnimatedComp_Update(e, p->Interp.Prev.Pos, p->Interp.Next.Pos, delta);
TiltComp_Update(&p->Tilt, delta);
Player_CheckSkin((struct Player*)p);
Player_CheckSkin(&p->Base);
SoundComp_Tick(wasOnGround);
}
@ -928,7 +931,7 @@ struct EntityVTABLE localPlayer_VTABLE = {
void LocalPlayer_Init(void) {
struct LocalPlayer* p = &LocalPlayer_Instance;
Player_Init(&p->Base);
Player_SetName((struct Player*)p, &Game_Username, &Game_Username);
Player_SetName(&p->Base, &Game_Username, &Game_Username);
p->Collisions.Entity = &p->Base;
HacksComp_Init(&p->Hacks);
@ -944,22 +947,26 @@ void LocalPlayer_Init(void) {
static bool LocalPlayer_IsSolidCollide(BlockID b) { return Block_Collide[b] == COLLIDE_SOLID; }
static void LocalPlayer_DoRespawn(void) {
struct LocalPlayer* p = &LocalPlayer_Instance;
Vector3 spawn = p->Spawn;
Vector3I P;
struct LocationUpdate update;
struct AABB bb;
Vector3 spawn = p->Spawn;
Vector3I pos;
BlockID block;
float height, spawnY;
int y;
if (!World_Blocks) return;
Vector3I_Floor(&P, &spawn);
Vector3I_Floor(&pos, &spawn);
/* Spawn player at highest valid position */
if (World_IsValidPos_3I(P)) {
if (World_IsValidPos_3I(pos)) {
AABB_Make(&bb, &spawn, &p->Base.Size);
int y;
for (y = P.Y; y <= World_Height; y++) {
float spawnY = Respawn_HighestFreeY(&bb);
for (y = pos.Y; y <= World_Height; y++) {
spawnY = Respawn_HighestFreeY(&bb);
if (spawnY == RESPAWN_NOT_FOUND) {
BlockID block = World_GetPhysicsBlock(P.X, y, P.Z);
float height = Block_Collide[block] == COLLIDE_SOLID ? Block_MaxBB[block].Y : 0.0f;
block = World_GetPhysicsBlock(pos.X, y, pos.Z);
height = Block_Collide[block] == COLLIDE_SOLID ? Block_MaxBB[block].Y : 0.0f;
spawn.Y = y + height + ENTITY_ADJUSTMENT;
break;
}
@ -967,8 +974,8 @@ static void LocalPlayer_DoRespawn(void) {
}
}
spawn.Y += 2.0f / 16.0f;
struct LocationUpdate update; LocationUpdate_MakePosAndOri(&update, spawn, p->SpawnRotY, p->SpawnHeadX, false);
spawn.Y += 2.0f/16.0f;
LocationUpdate_MakePosAndOri(&update, spawn, p->SpawnRotY, p->SpawnHeadX, false);
p->Base.VTABLE->SetLocation(&p->Base, &update, false);
p->Base.Velocity = Vector3_Zero;
@ -1063,7 +1070,7 @@ static void NetPlayer_SetLocation(struct Entity* e, struct LocationUpdate* updat
static void NetPlayer_Tick(struct Entity* e, double delta) {
struct NetPlayer* p = (struct NetPlayer*)e;
Player_CheckSkin((struct Player*)p);
Player_CheckSkin(&p->Base);
NetInterpComp_AdvanceState(&p->Interp);
AnimatedComp_Update(e, p->Interp.Prev.Pos, p->Interp.Next.Pos, delta);
}
@ -1086,16 +1093,16 @@ static void NetPlayer_RenderName(struct Entity* e) {
distance = Model_RenderDistance(e);
threshold = Entities_NameMode == NAME_MODE_ALL_UNSCALED ? 8192 * 8192 : 32 * 32;
if (distance <= (float)threshold) Player_DrawName((struct Player*)p);
if (distance <= (float)threshold) Player_DrawName(&p->Base);
}
struct EntityVTABLE netPlayer_VTABLE = {
NetPlayer_Tick, Player_Despawn, NetPlayer_SetLocation, Entity_GetCol,
NetPlayer_RenderModel, NetPlayer_RenderName, Player_ContextLost, Player_ContextRecreated,
};
void NetPlayer_Init(struct NetPlayer* player, const String* displayName, const String* skinName) {
Mem_Set(player, 0, sizeof(struct NetPlayer));
Player_Init(&player->Base);
Player_SetName((struct Player*)player, displayName, skinName);
player->Base.VTABLE = &netPlayer_VTABLE;
void NetPlayer_Init(struct NetPlayer* p, const String* displayName, const String* skinName) {
Mem_Set(p, 0, sizeof(struct NetPlayer));
Player_Init(&p->Base);
Player_SetName(&p->Base, displayName, skinName);
p->Base.VTABLE = &netPlayer_VTABLE;
}

View File

@ -166,8 +166,7 @@ void HacksComp_Init(struct HacksComp* hacks) {
hacks->NoclipSlide = true;
hacks->CanBePushed = true;
String str = String_FromArray(hacks->__HacksFlagsBuffer);
hacks->HacksFlags = str;
String_InitArray(hacks->HacksFlags, hacks->__HacksFlagsBuffer);
}
bool HacksComp_CanJumpHigher(struct HacksComp* hacks) {

View File

@ -485,14 +485,21 @@ static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
X11Button ok = { 0 };
X11Textbox body = { 0 };
XFontStruct* font;
Atom wmDelete;
int x, y, width, height;
XSizeHints hints = { 0 };
int mouseX = -1, mouseY = -1, over;
XEvent e;
X11Window_Init(w);
XMapWindow(dpy, w->win);
XStoreName(dpy, w->win, title);
Atom wmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
wmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
XSetWMProtocols(dpy, w->win, &wmDelete, 1);
XFontStruct* font = XQueryFont(dpy, XGContextFromGC(w->gc));
font = XQueryFont(dpy, XGContextFromGC(w->gc));
if (!font) return;
/* Compute size of widgets */
@ -504,10 +511,10 @@ static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
ok.Height = ok.Text.Height + 10;
/* Compute size and position of window */
int width = body.Width + 20;
int height = body.Height + 20 + ok.Height + 20;
int x = DisplayWidth (dpy, DefaultScreen(dpy))/2 - width/2;
int y = DisplayHeight(dpy, DefaultScreen(dpy))/2 - height/2;
width = body.Width + 20;
height = body.Height + 20 + ok.Height + 20;
x = DisplayWidth (dpy, DefaultScreen(dpy))/2 - width/2;
y = DisplayHeight(dpy, DefaultScreen(dpy))/2 - height/2;
XMoveResizeWindow(dpy, w->win, x, y, width, height);
/* Adjust bounds of widgets */
@ -518,7 +525,6 @@ static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
XFreeFontInfo(NULL, font, 1);
XUnmapWindow(dpy, w->win); /* Make window non resizeable */
XSizeHints hints = { 0 };
hints.flags = PSize | PMinSize | PMaxSize;
hints.min_width = hints.max_width = hints.base_width = width;
hints.min_height = hints.max_height = hints.base_height = height;
@ -527,9 +533,6 @@ static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
XMapRaised(dpy, w->win);
XFlush(dpy);
XEvent e;
int mouseX = -1, mouseY = -1;
for (;;) {
XNextEvent(dpy, &e);
@ -538,7 +541,7 @@ static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
case ButtonPress:
case ButtonRelease:
if (e.xbutton.button != Button1) break;
int over = X11Button_Contains(&ok, mouseX, mouseY);
over = X11Button_Contains(&ok, mouseX, mouseY);
if (ok.Clicked && e.type == ButtonRelease) {
if (over) return;

View File

@ -305,9 +305,10 @@ static ReturnCode Nbt_ReadTag(uint8_t typeId, bool readTagName, struct Stream* s
uint32_t i, count;
if (typeId == NBT_END) return 0;
tag.TagID = typeId; tag.Parent = parent;
tag.Name = String_Init(tag.NameBuffer, 0, NBT_STRING_SIZE);
tag.TagID = typeId;
tag.Parent = parent;
tag.DataSize = 0;
String_InitArray(tag.Name, tag.NameBuffer);
if (readTagName) {
res = Nbt_ReadString(stream, &tag.Name);
@ -343,7 +344,7 @@ static ReturnCode Nbt_ReadTag(uint8_t typeId, bool readTagName, struct Stream* s
}
break;
case NBT_STR:
tag.Value.Str.Text = String_Init(tag.Value.Str.Buffer, 0, NBT_STRING_SIZE);
String_InitArray(tag.Value.Str.Text, tag.Value.Str.Buffer);
res = Nbt_ReadString(stream, &tag.Value.Str.Text);
break;

View File

@ -1267,9 +1267,7 @@ static void SaveLevelScreen_Schematic(void* a, void* b) { SaveLevelScreen_Save(a
static void SaveLevelScreen_Init(void* screen) {
struct SaveLevelScreen* s = screen;
String str = String_FromArray(s->__TextPathBuffer);
s->TextPath = str;
String_InitArray(s->TextPath, s->__TextPathBuffer);
Key_KeyRepeat = true;
MenuScreen_Init(s);
}
@ -3158,9 +3156,8 @@ struct Screen* UrlWarningOverlay_MakeInstance(const String* url) {
s->Widgets = widgets;
s->WidgetsCount = Array_Elems(widgets);
String dstUrl = String_FromArray(s->__UrlBuffer);
String_Copy(&dstUrl, url);
s->Url = dstUrl;
String_InitArray(s->Url, s->__UrlBuffer);
String_Copy(&s->Url, url);
s->VTABLE = &UrlWarningOverlay_VTABLE;
return (struct Screen*)s;
@ -3225,9 +3222,8 @@ struct Screen* ConfirmDenyOverlay_MakeInstance(const String* url, bool alwaysDen
s->Widgets = widgets;
s->WidgetsCount = Array_Elems(widgets);
String dstUrl = String_FromArray(s->__UrlBuffer);
String_Copy(&dstUrl, url);
s->Url = dstUrl;
String_InitArray(s->Url, s->__UrlBuffer);
String_Copy(&s->Url, url);
s->AlwaysDeny = alwaysDeny;
s->VTABLE = &ConfirmDenyOverlay_VTABLE;
@ -3337,12 +3333,11 @@ struct Screen* TexPackOverlay_MakeInstance(const String* url) {
s->Widgets = widgets;
s->WidgetsCount = Array_Elems(widgets);
String identifier = String_FromArray(s->__IdentifierBuffer);
String_Format1(&identifier, "CL_%s", url);
s->Identifier = identifier;
String_InitArray(s->Identifier, s->__IdentifierBuffer);
String_Format1(&s->Identifier, "CL_%s", url);
s->ContentLength = 0;
AsyncDownloader_GetContentLength(url, true, &identifier);
AsyncDownloader_GetContentLength(url, true, &s->Identifier);
s->VTABLE = &TexPackOverlay_VTABLE;
return (struct Screen*)s;
}

View File

@ -113,10 +113,14 @@ void Model_Render(struct Model* model, struct Entity* entity) {
}
void Model_SetupState(struct Model* model, struct Entity* entity) {
model->index = 0;
PackedCol col = entity->VTABLE->GetCol(entity);
PackedCol col;
bool _64x64;
float yawDelta;
bool _64x64 = entity->SkinType != SKIN_64x32;
model->index = 0;
col = entity->VTABLE->GetCol(entity);
_64x64 = entity->SkinType != SKIN_64x32;
/* only apply when using humanoid skins */
_64x64 &= model->UsesHumanSkin || entity->MobTextureId;
@ -131,10 +135,11 @@ void Model_SetupState(struct Model* model, struct Entity* entity) {
} else {
Model_Cols[1] = col; Model_Cols[2] = col; Model_Cols[4] = col;
}
Model_Cols[3] = Model_Cols[2];
Model_Cols[5] = Model_Cols[4];
yawDelta = entity->HeadY - entity->RotY;
float yawDelta = entity->HeadY - entity->RotY;
Model_cosHead = (float)Math_Cos(yawDelta * MATH_DEG2RAD);
Model_sinHead = (float)Math_Sin(yawDelta * MATH_DEG2RAD);
Model_ActiveModel = model;
@ -148,9 +153,11 @@ void Model_UpdateVB(void) {
void Model_ApplyTexture(struct Entity* entity) {
struct Model* model = Model_ActiveModel;
GfxResourceID tex = model->UsesHumanSkin ? entity->TextureId : entity->MobTextureId;
struct CachedTexture* data;
GfxResourceID tex;
bool _64x64;
tex = model->UsesHumanSkin ? entity->TextureId : entity->MobTextureId;
if (tex) {
Model_skinType = entity->SkinType;
} else {
@ -160,7 +167,8 @@ void Model_ApplyTexture(struct Entity* entity) {
}
Gfx_BindTexture(tex);
bool _64x64 = Model_skinType != SKIN_64x32;
_64x64 = Model_skinType != SKIN_64x32;
Model_uScale = entity->uScale * 0.015625f;
Model_vScale = entity->vScale * (_64x64 ? 0.015625f : 0.03125f);
}

View File

@ -597,13 +597,10 @@ struct Screen* LoadingScreen_MakeInstance(const String* title, const String* mes
s->VTABLE = &LoadingScreen_VTABLE;
s->Progress = 0.0f;
String title_copy = String_FromArray(s->__TitleBuffer);
String_AppendString(&title_copy, title);
s->TitleStr = title_copy;
String message_copy = String_FromArray(s->__MessageBuffer);
String_AppendString(&message_copy, message);
s->MessageStr = message_copy;
String_InitArray(s->TitleStr, s->__TitleBuffer);
String_AppendString(&s->TitleStr, title);
String_InitArray(s->MessageStr, s->__MessageBuffer);
String_AppendString(&s->MessageStr, message);
s->HandlesAllInput = true;
s->BlocksWorld = true;
@ -1540,13 +1537,10 @@ struct Screen* DisconnectScreen_MakeInstance(const String* title, const String*
s->BlocksWorld = true;
s->HidesHUD = true;
String title_copy = String_FromArray(s->__TitleBuffer);
String_AppendString(&title_copy, title);
s->TitleStr = title_copy;
String message_copy = String_FromArray(s->__MessageBuffer);
String_AppendString(&message_copy, message);
s->MessageStr = message_copy;
String_InitArray(s->TitleStr, s->__TitleBuffer);
String_AppendString(&s->TitleStr, title);
String_InitArray(s->MessageStr, s->__MessageBuffer);
String_AppendString(&s->MessageStr, message);
char whyBuffer[STRING_SIZE];
String why = String_FromArray(whyBuffer);

View File

@ -45,6 +45,8 @@ NOINLINE_ String String_FromReadonly(STRING_REF const char* buffer);
#define String_FromRawArray(buffer) String_FromRaw(buffer, sizeof(buffer))
/* Constructs a string from a compile time array (leaving 1 byte of room for null terminator) */
#define String_NT_Array(buffer) { buffer, 0, (sizeof(buffer) - 1)}
/* Initialises a string from a compile time array. */
#define String_InitArray(str, buffr) str.buffer = buffr; str.length = 0; str.capacity = sizeof(buffr);
/* Removes all colour codes from the given string. */
NOINLINE_ void String_StripCols(String* str);

View File

@ -204,7 +204,8 @@ static void EntryList_Load(struct EntryList* list) {
char lineBuffer[FILENAME_SIZE];
String line = String_FromArray(lineBuffer);
struct Stream stream;
uint8_t buffer[2048];
struct Stream stream, buffered;
ReturnCode res;
String_Format3(&path, "%c%r%c", list->Folder, &Directory_Separator, list->Filename);
@ -213,7 +214,6 @@ static void EntryList_Load(struct EntryList* list) {
if (res) { Chat_LogError2(res, "opening", &path); return; }
/* ReadLine reads single byte at a time */
uint8_t buffer[2048]; struct Stream buffered;
Stream_ReadonlyBuffered(&buffered, &stream, buffer, sizeof(buffer));
for (;;) {

View File

@ -52,7 +52,7 @@ bool TextureCache_Has(const String* url);
/* Attempts to get the cached data stream for the given url. */
bool TextureCache_Get(const String* url, struct Stream* stream);
/* Attempts to get the Last-Modified header cached for the given URL. */
/* If header is not found, returns last time the cached datastream was modified. */
/* If header is not found, returns last time the cached data was modified. */
void TextureCache_GetLastModified(const String* url, TimeMS* time);
/* Attempts to get the ETag header cached for the given URL. */
void TextureCache_GetETag(const String* url, String* etag);

View File

@ -117,7 +117,10 @@ static void ButtonWidget_Reposition(void* widget) {
static void ButtonWidget_Render(void* widget, double delta) {
struct ButtonWidget* w = widget;
struct Texture back = w->Active ? Button_SelectedTex : Button_ShadowTex;
struct Texture back;
PackedCol col;
back = w->Active ? Button_SelectedTex : Button_ShadowTex;
if (w->Disabled) back = Button_DisabledTex;
back.ID = Game_UseClassicGui ? Gui_GuiClassicTex : Gui_GuiTex;
@ -147,7 +150,7 @@ static void ButtonWidget_Render(void* widget, double delta) {
PackedCol disabledCol = PACKEDCOL_CONST(160, 160, 160, 255);
if (!w->Texture.ID) return;
PackedCol col = w->Disabled ? disabledCol : (w->Active ? activeCol : normCol);
col = w->Disabled ? disabledCol : (w->Active ? activeCol : normCol);
Texture_RenderShaded(&w->Texture, col);
}
@ -503,13 +506,13 @@ static int Table_Height(struct TableWidget* w) {
#define TABLE_MAX_VERTICES (8 * 10 * ISOMETRICDRAWER_MAXVERTICES)
static bool TableWidget_GetCoords(struct TableWidget* w, int i, int* winX, int* winY) {
int x = i % w->ElementsPerRow, y = i / w->ElementsPerRow;
*winX = w->X + w->BlockSize * x;
*winY = w->Y + w->BlockSize * y + 3;
static bool TableWidget_GetCoords(struct TableWidget* w, int i, int* cellX, int* cellY) {
int x, y;
x = i % w->ElementsPerRow;
y = i / w->ElementsPerRow - w->Scroll.ScrollY;
*winY -= w->Scroll.ScrollY * w->BlockSize;
y -= w->Scroll.ScrollY;
*cellX = w->X + w->BlockSize * x;
*cellY = w->Y + w->BlockSize * y + 3;
return y >= 0 && y < TABLE_MAX_ROWS_DISPLAYED;
}
@ -536,8 +539,10 @@ static void TableWidget_MoveCursorToSelected(struct TableWidget* w) {
}
static void TableWidget_MakeBlockDesc(String* desc, BlockID block) {
String name;
if (Game_PureClassic) { String_AppendConst(desc, "Select block"); return; }
String name = Block_UNSAFE_GetName(block);
name = Block_UNSAFE_GetName(block);
String_AppendString(desc, &name);
if (Game_ClassicMode) return;
@ -574,9 +579,9 @@ static void TableWidget_RecreateDescTex(struct TableWidget* w) {
}
void TableWidget_MakeDescTex(struct TableWidget* w, BlockID block) {
struct DrawTextArgs args;
char descBuffer[STRING_SIZE * 2];
String desc = String_FromArray(descBuffer);
struct DrawTextArgs args;
Gfx_DeleteTexture(&w->DescTex.ID);
if (block == BLOCK_AIR) return;
@ -627,6 +632,9 @@ static void TableWidget_Init(void* widget) {
static void TableWidget_Render(void* widget, double delta) {
struct TableWidget* w = widget;
VertexP3fT2fC4b vertices[TABLE_MAX_VERTICES];
int i, x, y;
/* These were sourced by taking a screenshot of vanilla
Then using paint to extract the colour components
Then using wolfram alpha to solve the glblendfunc equation */
@ -644,8 +652,8 @@ static void TableWidget_Render(void* widget, double delta) {
int blockSize = w->BlockSize;
if (w->SelectedIndex != -1 && Game_ClassicMode) {
int x, y;
TableWidget_GetCoords(w, w->SelectedIndex, &x, &y);
float off = blockSize * 0.1f;
int size = (int)(blockSize + off * 2);
GfxCommon_Draw2DGradient((int)(x - off), (int)(y - off),
@ -654,11 +662,8 @@ static void TableWidget_Render(void* widget, double delta) {
Gfx_SetTexturing(true);
Gfx_SetBatchFormat(VERTEX_FORMAT_P3FT2FC4B);
VertexP3fT2fC4b vertices[TABLE_MAX_VERTICES];
IsometricDrawer_BeginBatch(vertices, w->VB);
int i;
for (i = 0; i < w->ElementsCount; i++) {
int x, y;
if (!TableWidget_GetCoords(w, i, &x, &y)) continue;
/* We want to always draw the selected block on top of others */
@ -669,8 +674,8 @@ static void TableWidget_Render(void* widget, double delta) {
i = w->SelectedIndex;
if (i != -1) {
int x, y;
TableWidget_GetCoords(w, i, &x, &y);
IsometricDrawer_DrawBatch(w->Elements[i],
(blockSize + w->SelBlockExpand) * 0.7f / 2.0f,
x + blockSize / 2, y + blockSize / 2);
@ -872,13 +877,13 @@ static void InputWidget_FormatLine(struct InputWidget* w, int i, String* line) {
}
static void InputWidget_CalculateLineSizes(struct InputWidget* w) {
char lineBuffer[STRING_SIZE];
String line = String_FromArray(lineBuffer);
struct DrawTextArgs args;
Size2D size;
int y;
char lineBuffer[STRING_SIZE];
String line = String_FromArray(lineBuffer);
for (y = 0; y < INPUTWIDGET_MAX_LINES; y++) {
w->LineSizes[y] = Size2D_Empty;
}
@ -1042,14 +1047,16 @@ static bool InputWidget_CheckCol(struct InputWidget* w, int index) {
}
static void InputWidget_BackspaceKey(struct InputWidget* w) {
int i, len;
if (InputWidget_ControlDown()) {
if (w->CaretPos == -1) { w->CaretPos = w->Text.length - 1; }
int len = WordWrap_GetBackLength(&w->Text, w->CaretPos);
len = WordWrap_GetBackLength(&w->Text, w->CaretPos);
if (!len) return;
w->CaretPos -= len;
if (w->CaretPos < 0) { w->CaretPos = 0; }
int i;
for (i = 0; i <= len; i++) {
String_DeleteAt(&w->Text, w->CaretPos);
}
@ -1214,10 +1221,12 @@ static bool InputWidget_KeyPress(void* widget, char keyChar) {
static bool InputWidget_MouseDown(void* widget, int x, int y, MouseButton button) {
struct InputWidget* w = widget;
struct DrawTextArgs args;
if (button != MouseButton_Left) return true;
x -= w->InputTex.X; y -= w->InputTex.Y;
struct DrawTextArgs args; DrawTextArgs_MakeEmpty(&args, &w->Font, true);
DrawTextArgs_MakeEmpty(&args, &w->Font, true);
int offset = 0, charHeight = w->CaretTex.Height;
char lineBuffer[STRING_SIZE];
@ -1399,7 +1408,7 @@ struct MenuInputValidator MenuInputValidator_Path(void) {
struct MenuInputValidator MenuInputValidator_Enum(const char** names, int namesCount) {
struct MenuInputValidator v;
v.VTABLE = NULL;
v.VTABLE = NULL;
v.Meta._Enum.Names = names;
v.Meta._Enum.Count = namesCount;
return v;
@ -1444,14 +1453,18 @@ static void MenuInputWidget_Render(void* widget, double delta) {
static void MenuInputWidget_RemakeTexture(void* widget) {
struct MenuInputWidget* w = widget;
struct MenuInputValidator* v;
struct DrawTextArgs args;
Size2D size;
Bitmap bmp;
DrawTextArgs_Make(&args, &w->Base.Lines[0], &w->Base.Font, false);
Size2D size = Drawer2D_MeasureText(&args);
size = Drawer2D_MeasureText(&args);
w->Base.CaretAccumulator = 0.0;
char rangeBuffer[STRING_SIZE];
String range = String_FromArray(rangeBuffer);
struct MenuInputValidator* v = &w->Validator;
v = &w->Validator;
v->VTABLE->GetRange(v, &range);
/* Ensure we don't have 0 text height */
@ -1465,7 +1478,7 @@ static void MenuInputWidget_RemakeTexture(void* widget) {
w->Base.Height = max(size.Height, w->MinHeight);
Size2D adjSize = size; adjSize.Width = w->Base.Width;
Bitmap bmp; Bitmap_AllocateClearedPow2(&bmp, adjSize.Width, adjSize.Height);
Bitmap_AllocateClearedPow2(&bmp, adjSize.Width, adjSize.Height);
{
Drawer2D_DrawText(&bmp, &args, w->Base.Padding, 0);
@ -1491,13 +1504,14 @@ static void MenuInputWidget_RemakeTexture(void* widget) {
static bool MenuInputWidget_AllowedChar(void* widget, char c) {
struct InputWidget* w = widget;
struct MenuInputValidator* v;
int maxChars;
bool valid;
if (c == '&') return false;
v = &((struct MenuInputWidget*)w)->Validator;
if (!v->VTABLE->IsValidChar(v, c)) return false;
int maxChars = w->GetMaxLines() * INPUTWIDGET_LEN;
maxChars = w->GetMaxLines() * INPUTWIDGET_LEN;
if (w->Text.length == maxChars) return false;
/* See if the new string is in valid format */
@ -1524,8 +1538,7 @@ void MenuInputWidget_Create(struct MenuInputWidget* w, int width, int height, co
w->Base.ConvertPercents = false;
w->Base.Padding = 3;
String inputStr = String_FromArray(w->__TextBuffer);
w->Base.Text = inputStr;
String_InitArray(w->Base.Text, w->__TextBuffer);
w->Base.GetMaxLines = MenuInputWidget_GetMaxLines;
w->Base.RemakeTexture = MenuInputWidget_RemakeTexture;
@ -1541,19 +1554,21 @@ void MenuInputWidget_Create(struct MenuInputWidget* w, int width, int height, co
*#########################################################################################################################*/
static void ChatInputWidget_RemakeTexture(void* widget) {
struct InputWidget* w = widget;
int totalHeight = 0, maxWidth = 0, i;
struct DrawTextArgs args;
Size2D size = { 0, 0 };
Bitmap bmp;
int i;
w->CaretAccumulator = 0;
for (i = 0; i < w->GetMaxLines(); i++) {
totalHeight += w->LineSizes[i].Height;
maxWidth = max(maxWidth, w->LineSizes[i].Width);
size.Height += w->LineSizes[i].Height;
size.Width = max(size.Width, w->LineSizes[i].Width);
}
Size2D size = { maxWidth, totalHeight };
int realHeight = 0;
Bitmap bmp; Bitmap_AllocateClearedPow2(&bmp, size.Width, size.Height);
Bitmap_AllocateClearedPow2(&bmp, size.Width, size.Height);
struct DrawTextArgs args; DrawTextArgs_MakeEmpty(&args, &w->Font, true);
DrawTextArgs_MakeEmpty(&args, &w->Font, true);
if (w->Prefix.length) {
args.Text = w->Prefix;
Drawer2D_DrawText(&bmp, &args, 0, 0);
@ -1566,7 +1581,7 @@ static void ChatInputWidget_RemakeTexture(void* widget) {
if (!w->Lines[i].length) break;
line.length = 0;
/* Colour code goes to next line */
/* Colour code continues in next line */
char lastCol = InputWidget_GetLastCol(w, 0, i);
if (!Drawer2D_IsWhiteCol(lastCol)) {
String_Append(&line, '&'); String_Append(&line, lastCol);
@ -1632,8 +1647,11 @@ static void ChatInputWidget_OnPressedEnter(void* widget) {
static void ChatInputWidget_UpKey(struct InputWidget* w) {
struct ChatInputWidget* W = (struct ChatInputWidget*)w;
String prevInput;
int pos;
if (InputWidget_ControlDown()) {
int pos = w->CaretPos == -1 ? w->Text.length : w->CaretPos;
pos = w->CaretPos == -1 ? w->Text.length : w->CaretPos;
if (pos < INPUTWIDGET_LEN) return;
w->CaretPos = pos - INPUTWIDGET_LEN;
@ -1650,7 +1668,7 @@ static void ChatInputWidget_UpKey(struct InputWidget* w) {
w->Text.length = 0;
if (W->TypingLogPos < 0) W->TypingLogPos = 0;
String prevInput = StringsBuffer_UNSAFE_Get(&Chat_InputLog, W->TypingLogPos);
prevInput = StringsBuffer_UNSAFE_Get(&Chat_InputLog, W->TypingLogPos);
String_AppendString(&w->Text, &prevInput);
w->CaretPos = -1;
@ -1659,8 +1677,11 @@ static void ChatInputWidget_UpKey(struct InputWidget* w) {
static void ChatInputWidget_DownKey(struct InputWidget* w) {
struct ChatInputWidget* W = (struct ChatInputWidget*)w;
String prevInput;
int lines;
if (InputWidget_ControlDown()) {
int lines = w->GetMaxLines();
lines = w->GetMaxLines();
if (w->CaretPos == -1 || w->CaretPos >= (lines - 1) * INPUTWIDGET_LEN) return;
w->CaretPos += INPUTWIDGET_LEN;
@ -1676,7 +1697,7 @@ static void ChatInputWidget_DownKey(struct InputWidget* w) {
W->TypingLogPos = Chat_InputLog.Count;
String_AppendString(&w->Text, &W->OrigStr);
} else {
String prevInput = StringsBuffer_UNSAFE_Get(&Chat_InputLog, W->TypingLogPos);
prevInput = StringsBuffer_UNSAFE_Get(&Chat_InputLog, W->TypingLogPos);
String_AppendString(&w->Text, &prevInput);
}
@ -1690,18 +1711,18 @@ static bool ChatInputWidget_IsNameChar(char c) {
}
static void ChatInputWidget_TabKey(struct InputWidget* w) {
EntityID matches[TABLIST_MAX_NAMES];
String part, match;
int end = w->CaretPos == -1 ? w->Text.length - 1 : w->CaretPos;
int start = end;
int beg = end;
char* buffer = w->Text.buffer;
while (start >= 0 && ChatInputWidget_IsNameChar(buffer[start])) { start--; }
start++;
if (end < 0 || start > end) return;
while (beg >= 0 && ChatInputWidget_IsNameChar(buffer[beg])) { beg--; }
beg++;
if (end < 0 || beg > end) return;
String part = String_UNSAFE_Substring(&w->Text, start, (end + 1) - start);
part = String_UNSAFE_Substring(&w->Text, beg, (end + 1) - beg);
Chat_AddOf(&String_Empty, MSG_TYPE_CLIENTSTATUS_3);
EntityID matches[TABLIST_MAX_NAMES];
int i, matchesCount = 0;
for (i = 0; i < TABLIST_MAX_NAMES; i++) {
@ -1715,13 +1736,13 @@ static void ChatInputWidget_TabKey(struct InputWidget* w) {
if (matchesCount == 1) {
if (w->CaretPos == -1) end++;
int len = end - start, j;
int len = end - beg, j;
for (j = 0; j < len; j++) {
String_DeleteAt(&w->Text, start);
String_DeleteAt(&w->Text, beg);
}
if (w->CaretPos != -1) w->CaretPos -= len;
String match = TabList_UNSAFE_GetPlayer(matches[0]);
match = TabList_UNSAFE_GetPlayer(matches[0]);
InputWidget_AppendString(w, &match);
} else if (matchesCount > 1) {
char strBuffer[STRING_SIZE];
@ -1729,7 +1750,7 @@ static void ChatInputWidget_TabKey(struct InputWidget* w) {
String_Format1(&str, "&e%i matching names: ", &matchesCount);
for (i = 0; i < matchesCount; i++) {
String match = TabList_UNSAFE_GetPlayer(matches[i]);
match = TabList_UNSAFE_GetPlayer(matches[i]);
if ((str.length + match.length + 1) > STRING_SIZE) break;
String_AppendString(&str, &match);
@ -1771,10 +1792,8 @@ void ChatInputWidget_Create(struct ChatInputWidget* w, const FontDesc* font) {
w->Base.RemakeTexture = ChatInputWidget_RemakeTexture;
w->Base.OnPressedEnter = ChatInputWidget_OnPressedEnter;
String inputStr = String_FromArray(w->__TextBuffer);
w->Base.Text = inputStr;
String origStr = String_FromArray(w->__OrigBuffer);
w->OrigStr = origStr;
String_InitArray(w->Base.Text, w->__TextBuffer);
String_InitArray(w->OrigStr, w->__OrigBuffer);
}
@ -1827,40 +1846,41 @@ void PlayerListWidget_GetNameUnder(struct PlayerListWidget* w, int x, int y, Str
static void PlayerListWidget_UpdateTableDimensions(struct PlayerListWidget* w) {
int width = w->XMax - w->XMin, height = w->YHeight;
w->X = (w->XMin ) - LIST_BOUNDS_SIZE;
w->X = (w->XMin ) - LIST_BOUNDS_SIZE;
w->Y = (Game_Height / 2 - height / 2) - LIST_BOUNDS_SIZE;
w->Width = width + LIST_BOUNDS_SIZE * 2;
w->Height = height + LIST_BOUNDS_SIZE * 2;
}
static int PlayerListWidget_GetColumnWidth(struct PlayerListWidget* w, int column) {
int i = column * LIST_NAMES_PER_COLUMN;
int i = column * LIST_NAMES_PER_COLUMN;
int end = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
int maxWidth = 0;
int maxIndex = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
for (; i < maxIndex; i++) {
for (; i < end; i++) {
maxWidth = max(maxWidth, w->Textures[i].Width);
}
return maxWidth + LIST_COLUMN_PADDING + w->ElementOffset;
}
static int PlayerListWidget_GetColumnHeight(struct PlayerListWidget* w, int column) {
int i = column * LIST_NAMES_PER_COLUMN;
int total = 0;
int maxIndex = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
int i = column * LIST_NAMES_PER_COLUMN;
int end = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
int height = 0;
for (; i < maxIndex; i++) {
total += w->Textures[i].Height + 1;
for (; i < end; i++) {
height += w->Textures[i].Height + 1;
}
return total;
return height;
}
static void PlayerListWidget_SetColumnPos(struct PlayerListWidget* w, int column, int x, int y) {
int i = column * LIST_NAMES_PER_COLUMN;
int maxIndex = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
struct Texture tex;
int i = column * LIST_NAMES_PER_COLUMN;
int end = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
for (; i < maxIndex; i++) {
struct Texture tex = w->Textures[i];
for (; i < end; i++) {
tex = w->Textures[i];
tex.X = x; tex.Y = y - 10;
y += tex.Height + 1;
@ -1909,11 +1929,12 @@ static void PlayerListWidget_Reposition(void* widget) {
}
static void PlayerListWidget_AddName(struct PlayerListWidget* w, EntityID id, int index) {
String name;
/* insert at end of list */
if (index == -1) { index = w->NamesCount; w->NamesCount++; }
String name = TabList_UNSAFE_GetList(id);
w->IDs[index] = id;
name = TabList_UNSAFE_GetList(id);
w->IDs[index] = id;
PlayerListWidget_DrawName(&w->Textures[index], w, &name);
}
@ -1950,11 +1971,12 @@ static void PlayerListWidget_AddGroup(struct PlayerListWidget* w, int id, int* i
static int PlayerListWidget_GetGroupCount(struct PlayerListWidget* w, int id, int i) {
String group = TabList_UNSAFE_GetGroup(id);
String curGroup;
int count = 0;
for (; i < w->NamesCount; i++, count++) {
String curGroup = TabList_UNSAFE_GetGroup(w->IDs[i]);
if (!String_CaselessEquals(&group, &curGroup)) return count;
curGroup = TabList_UNSAFE_GetGroup(w->IDs[i]);
if (!String_CaselessEquals(&group, &curGroup)) break;
}
return count;
}
@ -2089,8 +2111,8 @@ static void PlayerListWidget_Init(void* widget) {
}
PlayerListWidget_SortAndReposition(w);
TextWidget_Create(&w->Overview, &title, &w->Font);
Widget_SetLocation(&w->Overview, ANCHOR_CENTRE, ANCHOR_MIN, 0, 0);
TextWidget_Create(&w->Title, &title, &w->Font);
Widget_SetLocation(&w->Title, ANCHOR_CENTRE, ANCHOR_MIN, 0, 0);
Event_RegisterInt(&TabListEvents_Added, w, PlayerListWidget_TabEntryAdded);
Event_RegisterInt(&TabListEvents_Changed, w, PlayerListWidget_TabEntryChanged);
@ -2099,26 +2121,29 @@ static void PlayerListWidget_Init(void* widget) {
static void PlayerListWidget_Render(void* widget, double delta) {
struct PlayerListWidget* w = widget;
struct TextWidget* overview = &w->Overview;
PackedCol topCol = PACKEDCOL_CONST(0, 0, 0, 180);
struct TextWidget* title = &w->Title;
struct Texture tex;
int offset, height;
int i, selectedI;
PackedCol topCol = PACKEDCOL_CONST( 0, 0, 0, 180);
PackedCol bottomCol = PACKEDCOL_CONST(50, 50, 50, 205);
Gfx_SetTexturing(false);
int offset = overview->Height + 10;
int height = max(300, w->Height + overview->Height);
offset = title->Height + 10;
height = max(300, w->Height + title->Height);
GfxCommon_Draw2DGradient(w->X, w->Y - offset, w->Width, height, topCol, bottomCol);
Gfx_SetTexturing(true);
overview->YOffset = w->Y - offset + 5;
Widget_Reposition(overview);
Elem_Render(overview, delta);
title->YOffset = w->Y - offset + 5;
Widget_Reposition(title);
Elem_Render(title, delta);
int i, highlightedI = PlayerListWidget_HighlightedName(w, Mouse_X, Mouse_Y);
selectedI = PlayerListWidget_HighlightedName(w, Mouse_X, Mouse_Y);
for (i = 0; i < w->NamesCount; i++) {
if (!w->Textures[i].ID) continue;
struct Texture tex = w->Textures[i];
if (i == highlightedI) tex.X += 4;
tex = w->Textures[i];
if (i == selectedI) tex.X += 4;
Texture_Render(&tex);
}
}
@ -2130,7 +2155,7 @@ static void PlayerListWidget_Free(void* widget) {
Gfx_DeleteTexture(&w->Textures[i].ID);
}
Elem_TryFree(&w->Overview);
Elem_TryFree(&w->Title);
Event_UnregisterInt(&TabListEvents_Added, w, PlayerListWidget_TabEntryAdded);
Event_UnregisterInt(&TabListEvents_Changed, w, PlayerListWidget_TabEntryChanged);
Event_UnregisterInt(&TabListEvents_Removed, w, PlayerListWidget_TabEntryRemoved);
@ -2160,8 +2185,8 @@ void PlayerListWidget_Create(struct PlayerListWidget* w, const FontDesc* font, b
*#########################################################################################################################*/
#define TextGroupWidget_LineBuffer(w, i) ((w)->Buffer + (i) * TEXTGROUPWIDGET_LEN)
String TextGroupWidget_UNSAFE_Get(struct TextGroupWidget* w, int i) {
int length = w->LineLengths[i];
return String_Init(TextGroupWidget_LineBuffer(w, i), length, length);
int len = w->LineLengths[i];
return String_Init(TextGroupWidget_LineBuffer(w, i), len, len);
}
void TextGroupWidget_GetText(struct TextGroupWidget* w, int index, String* text) {
@ -2170,9 +2195,11 @@ void TextGroupWidget_GetText(struct TextGroupWidget* w, int index, String* text)
}
void TextGroupWidget_PushUpAndReplaceLast(struct TextGroupWidget* w, const String* text) {
int y = w->Y;
int max_index;
int i, y = w->Y;
Gfx_DeleteTexture(&w->Textures[0].ID);
int i, max_index = w->LinesCount - 1;
max_index = w->LinesCount - 1;
/* Move contents of X line to X - 1 line */
for (i = 0; i < max_index; i++) {
@ -2276,13 +2303,15 @@ struct Portion { int16_t Beg, Len, LineBeg, LineLen; };
#define TEXTGROUPWIDGET_PACKED_LEN 0x7FFF
static int TextGroupWidget_NextUrl(char* chars, int charsLen, int i) {
int start, left;
for (; i < charsLen; i++) {
if (!(chars[i] == 'h' || chars[i] == '&')) continue;
int left = charsLen - i;
left = charsLen - i;
if (left < TEXTGROUPWIDGET_HTTP_LEN) return charsLen;
/* colour codes at start of URL */
int start = i;
start = i;
while (left >= 2 && chars[i] == '&') { left -= 2; i += 2; }
if (left < TEXTGROUPWIDGET_HTTP_LEN) continue;
@ -2299,9 +2328,12 @@ static int TextGroupWidget_NextUrl(char* chars, int charsLen, int i) {
static int TextGroupWidget_UrlEnd(char* chars, int charsLen, int32_t* begs, int begsLen, int i) {
int start = i, j;
int next, left;
bool isBeg;
for (; i < charsLen && chars[i] != ' '; i++) {
/* Is this character the start of a line */
bool isBeg = false;
isBeg = false;
for (j = 0; j < begsLen; j++) {
if (i == begs[j]) { isBeg = true; break; }
}
@ -2311,7 +2343,7 @@ static int TextGroupWidget_UrlEnd(char* chars, int charsLen, int32_t* begs, int
if (chars[i] != '>') break;
/* Does this line start with "> ", making it a multiline */
int next = i + 1, left = charsLen - next;
next = i + 1; left = charsLen - next;
while (left >= 2 && chars[next] == '&') { left -= 2; next += 2; }
if (left == 0 || chars[next] != ' ') break;
@ -2321,7 +2353,10 @@ static int TextGroupWidget_UrlEnd(char* chars, int charsLen, int32_t* begs, int
}
static void TextGroupWidget_Output(struct Portion bit, int lineBeg, int lineEnd, struct Portion** portions) {
struct Portion* cur;
int overBy, underBy;
if (bit.Beg >= lineEnd || !bit.Len) return;
bit.LineBeg = bit.Beg;
bit.LineLen = bit.Len & TEXTGROUPWIDGET_PACKED_LEN;
@ -2329,18 +2364,18 @@ static void TextGroupWidget_Output(struct Portion bit, int lineBeg, int lineEnd,
if (bit.Beg >= lineBeg) {
} else if (bit.Beg + bit.LineLen > lineBeg) {
/* Adjust start of portion to be within this line */
int underBy = lineBeg - bit.Beg;
underBy = lineBeg - bit.Beg;
bit.LineBeg += underBy; bit.LineLen -= underBy;
} else { return; }
/* Limit length of portion to be within this line */
int overBy = (bit.LineBeg + bit.LineLen) - lineEnd;
overBy = (bit.LineBeg + bit.LineLen) - lineEnd;
if (overBy > 0) bit.LineLen -= overBy;
bit.LineBeg -= lineBeg;
if (!bit.LineLen) return;
struct Portion* cur = *portions; *cur++ = bit; *portions = cur;
cur = *portions; *cur++ = bit; *portions = cur;
}
static int TextGroupWidget_Reduce(struct TextGroupWidget* w, char* chars, int target, struct Portion* portions) {
@ -2348,20 +2383,22 @@ static int TextGroupWidget_Reduce(struct TextGroupWidget* w, char* chars, int ta
int32_t begs[TEXTGROUPWIDGET_MAX_LINES];
int32_t ends[TEXTGROUPWIDGET_MAX_LINES];
struct Portion bit;
int i, total = 0, end = 0;
int len, nextStart;
int i, total = 0, end;
for (i = 0; i < w->LinesCount; i++) {
int lineLen = w->LineLengths[i];
len = w->LineLengths[i];
begs[i] = -1; ends[i] = -1;
if (!lineLen) continue;
if (!len) continue;
begs[i] = total;
Mem_Copy(&chars[total], TextGroupWidget_LineBuffer(w, i), lineLen);
total += lineLen; ends[i] = total;
Mem_Copy(&chars[total], TextGroupWidget_LineBuffer(w, i), len);
total += len; ends[i] = total;
}
end = 0;
for (;;) {
int nextStart = TextGroupWidget_NextUrl(chars, total, end);
nextStart = TextGroupWidget_NextUrl(chars, total, end);
/* add normal portion between urls */
bit.Beg = end;
@ -2397,25 +2434,28 @@ static void TextGroupWidget_FormatUrl(String* text, const String* url) {
static bool TextGroupWidget_GetUrl(struct TextGroupWidget* w, String* text, int index, int mouseX) {
char chars[TEXTGROUPWIDGET_MAX_LINES * TEXTGROUPWIDGET_LEN];
struct Portion portions[2 * (TEXTGROUPWIDGET_LEN / TEXTGROUPWIDGET_HTTP_LEN)];
struct Portion bit;
struct DrawTextArgs args = { 0 };
String line;
String line, url;
int portionsCount;
int i, x, width;
mouseX -= w->Textures[index].X;
args.UseShadow = true;
line = TextGroupWidget_UNSAFE_Get(w, index);
if (Game_ClassicMode) return false;
int i, x, portionsCount = TextGroupWidget_Reduce(w, chars, index, portions);
portionsCount = TextGroupWidget_Reduce(w, chars, index, portions);
for (i = 0, x = 0; i < portionsCount; i++) {
struct Portion bit = portions[i];
bit = portions[i];
args.Text = String_UNSAFE_Substring(&line, bit.LineBeg, bit.LineLen);
args.Font = (bit.Len & TEXTGROUPWIDGET_URL) ? w->UnderlineFont : w->Font;
int width = Drawer2D_MeasureText(&args).Width;
width = Drawer2D_MeasureText(&args).Width;
if ((bit.Len & TEXTGROUPWIDGET_URL) && mouseX >= x && mouseX < x + width) {
bit.Len &= TEXTGROUPWIDGET_PACKED_LEN;
String url = String_Init(&chars[bit.Beg], bit.Len, bit.Len);
url = String_Init(&chars[bit.Beg], bit.Len, bit.Len);
TextGroupWidget_FormatUrl(text, &url);
return true;
@ -2460,33 +2500,38 @@ static bool TextGroupWidget_MightHaveUrls(struct TextGroupWidget* w) {
static void TextGroupWidget_DrawAdvanced(struct TextGroupWidget* w, struct Texture* tex, struct DrawTextArgs* args, int index, const String* text) {
char chars[TEXTGROUPWIDGET_MAX_LINES * TEXTGROUPWIDGET_LEN];
struct Portion portions[2 * (TEXTGROUPWIDGET_LEN / TEXTGROUPWIDGET_HTTP_LEN)];
int i, x, portionsCount = TextGroupWidget_Reduce(w, chars, index, portions);
Size2D total = { 0, 0 };
struct Portion bit;
Size2D size = { 0, 0 };
Size2D partSizes[Array_Elems(portions)];
Bitmap bmp;
int portionsCount;
int i, x;
portionsCount = TextGroupWidget_Reduce(w, chars, index, portions);
for (i = 0; i < portionsCount; i++) {
struct Portion bit = portions[i];
bit = portions[i];
args->Text = String_UNSAFE_Substring(text, bit.LineBeg, bit.LineLen);
args->Font = (bit.Len & TEXTGROUPWIDGET_URL) ? w->UnderlineFont : w->Font;
partSizes[i] = Drawer2D_MeasureText(args);
total.Height = max(partSizes[i].Height, total.Height);
total.Width += partSizes[i].Width;
size.Height = max(partSizes[i].Height, size.Height);
size.Width += partSizes[i].Width;
}
Bitmap_AllocateClearedPow2(&bmp, total.Width, total.Height);
Bitmap_AllocateClearedPow2(&bmp, size.Width, size.Height);
{
for (i = 0, x = 0; i < portionsCount; i++) {
struct Portion bit = portions[i];
x = 0;
for (i = 0; i < portionsCount; i++) {
bit = portions[i];
args->Text = String_UNSAFE_Substring(text, bit.LineBeg, bit.LineLen);
args->Font = (bit.Len & TEXTGROUPWIDGET_URL) ? w->UnderlineFont : w->Font;
Drawer2D_DrawText(&bmp, args, x, 0);
x += partSizes[i].Width;
}
Drawer2D_Make2DTexture(tex, &bmp, total, 0, 0);
Drawer2D_Make2DTexture(tex, &bmp, size, 0, 0);
}
Mem_Free(bmp.Scan0);
}

View File

@ -183,7 +183,7 @@ struct PlayerListWidget {
int NamesCount, ElementOffset;
int XMin, XMax, YHeight;
bool Classic;
struct TextWidget Overview;
struct TextWidget Title;
uint16_t IDs[TABLIST_MAX_NAMES * 2];
struct Texture Textures[TABLIST_MAX_NAMES * 2];
};