Mercurial
changeset 63:fff1b048dda6
[Postdog] Fixed a problem where string did not wrap.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Tue, 23 Dec 2025 14:00:37 -0800 |
| parents | ea9ef388ab97 |
| children | a30944e5719e |
| files | MODULE.bazel.lock color_game/main.c dowa/d_string.c dowa/dowa.h postdog/main.c |
| diffstat | 5 files changed, 271 insertions(+), 79 deletions(-) [+] |
line wrap: on
line diff
--- a/MODULE.bazel.lock Tue Dec 23 11:48:11 2025 -0800 +++ b/MODULE.bazel.lock Tue Dec 23 14:00:37 2025 -0800 @@ -1,5 +1,5 @@ { - "lockFileVersion": 24, + "lockFileVersion": 18, "registryFileHashes": { "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", @@ -16,8 +16,7 @@ "https://bcr.bazel.build/modules/abseil-py/2.1.0/source.json": "0e8fc4f088ce07099c1cd6594c20c7ddbb48b4b3c0849b7d94ba94be88ff042b", "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", - "https://bcr.bazel.build/modules/apple_support/1.23.1/MODULE.bazel": "53763fed456a968cf919b3240427cf3a9d5481ec5466abc9d5dc51bc70087442", - "https://bcr.bazel.build/modules/apple_support/1.23.1/source.json": "d888b44312eb0ad2c21a91d026753f330caa48a25c9b2102fae75eb2b0dcfdd2", + "https://bcr.bazel.build/modules/apple_support/1.15.1/source.json": "517f2b77430084c541bc9be2db63fdcbb7102938c5f64c17ee60ffda2e5cf07b", "https://bcr.bazel.build/modules/bazel_features/1.1.0/MODULE.bazel": "cfd42ff3b815a5f39554d97182657f8c4b9719568eb7fded2b9135f084bf760b", "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", @@ -28,7 +27,6 @@ "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a", - "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65", "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d", "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9", "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", @@ -228,6 +226,37 @@ }, "selectedYankedVersions": {}, "moduleExtensions": { + "@@apple_support+//crosstool:setup.bzl%apple_cc_configure_extension": { + "general": { + "bzlTransitiveDigest": "p7Ghcq3+nnQxCrf+U3xnhdn7yOSTDbcFyGHK7Ja+rU4=", + "usagesDigest": "EJfdUgbJdIRboG70S9dz8HhGVkL2/s3qFQ9xht8y2Rs=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "local_config_apple_cc_toolchains": { + "repoRuleId": "@@apple_support+//crosstool:setup.bzl%_apple_cc_autoconf_toolchains", + "attributes": {} + }, + "local_config_apple_cc": { + "repoRuleId": "@@apple_support+//crosstool:setup.bzl%_apple_cc_autoconf", + "attributes": {} + } + }, + "recordedRepoMappingEntries": [ + [ + "apple_support+", + "bazel_tools", + "bazel_tools" + ], + [ + "bazel_tools", + "rules_cc", + "rules_cc+" + ] + ] + } + }, "@@rules_android+//rules/android_sdk_repository:rule.bzl%android_sdk_repository_extension": { "general": { "bzlTransitiveDigest": "NAy+0M15JNVEBb8Tny6t7j3lKqTnsAMjoBB6LJ+C370=", @@ -246,7 +275,7 @@ }, "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { "general": { - "bzlTransitiveDigest": "rL/34P1aFDq2GqVC2zCFgQ8nTuOC6ziogocpvG50Qz8=", + "bzlTransitiveDigest": "OlvsB0HsvxbR8ZN+J9Vf00X/+WVz/Y/5Xrq2LgcVfdo=", "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, @@ -310,7 +339,7 @@ }, "@@rules_python+//python/extensions:config.bzl%config": { "general": { - "bzlTransitiveDigest": "W97kKxM+lW7l/kO0rQa7Jm31CA1j+W1bNHGKjwX5xMg=", + "bzlTransitiveDigest": "xaCns8Qt+8bJqVLy8r6nc/eL2AjEIX/vOdjqoh5xYac=", "usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, @@ -545,7 +574,7 @@ }, "@@rules_python+//python/uv:uv.bzl%uv": { "general": { - "bzlTransitiveDigest": "zyNsrbgVKwpA0B3zI84imAfuC424VSzYNPgjr/HJy5M=", + "bzlTransitiveDigest": "N8SCcKcL6KnzBLApxvY2jR9vhXjA2VCBZMLZfY3sDRA=", "usagesDigest": "H8dQoNZcoqP+Mu0tHZTi4KHATzvNkM5ePuEqoQdklIU=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, @@ -584,6 +613,5 @@ ] } } - }, - "facts": {} + } }
--- a/color_game/main.c Tue Dec 23 11:48:11 2025 -0800 +++ b/color_game/main.c Tue Dec 23 14:00:37 2025 -0800 @@ -9,34 +9,58 @@ #define INIT_SCREEN_HEIGHT 700 #define PLAYER_SPEED 200.0f #define PLAYER_RADIUS 20.0f +#define PLAYER_MAX_HEALTH 100.0f + #define MONSTER_SPEED 100.0f #define MONSTER_RADIUS 15.0f + #define BULLET_SPEED 300.0f #define BULLET_RADIUS 5.0f #define BULLET_LIFETIME 3.0f #define SHOOT_INTERVAL 0.5f #define HIT_PROBABILITY 0.7f // 70% aim accuracy (0.0 = random, 1.0 = perfect) + #define MAX_PASSIVE_NODES 12 #define PASSIVE_TREE_RADIUS 250.0f #define PASSIVE_NODE_RADIUS 20.0f -#define BASE_DAMAGE 10.0f -#define PLAYER_MAX_HEALTH 100.0f + +#define MONSTER_WEIGHT 10.0f #define MONSTER_CONTACT_DAMAGE 5.0f + +#define BASE_DAMAGE 10.0f #define BOSS_HEALTH_MULTIPLIER 5.0f -#define COLOR_UNLOCK_TIME 30.0f -#define BOSS_SPAWN_TIME 60.0f +#define BOSS_MONSTER_WEIGHT 10.0f +#define BOSS_SPAWN_TIME 10.0f + +#define COLOR_UNLOCK_TIME 5.0f +#define MAX_DAMAGE_NUMBERS 100 +#define DAMAGE_NUMBER_LIFETIME 1.0f +#define EXP_PER_MONSTER 10.0f +#define EXP_PER_BOSS 50.0f +#define EXP_TO_LEVEL 100.0f typedef struct Player { Vector2 position; - Color color; float health; float maxHealth; + float invulnerabilityTimer; int unlockedBulletTypes[MAX_PASSIVE_NODES]; int unlockedCount; int passivePoints; - float invulnerabilityTimer; + int level; + float experience; + float expToNextLevel; + Color color; } Player; +typedef struct DamageNumber { + Vector2 position; + float damage; + float lifetime; + bool active; + Color color; +} DamageNumber; + typedef struct Map { float width; float height; @@ -48,6 +72,7 @@ float saturation; float health; float maxHealth; + float weight; bool alive; bool hasCollision; bool isBoss; @@ -89,6 +114,53 @@ return baseDamage * damageMultiplier; } +void SpawnDamageNumber(DamageNumber* damageNumbers, int maxCount, Vector2 position, float damage, Color color) +{ + for (int i = 0; i < maxCount; i++) + { + if (!damageNumbers[i].active) + { + damageNumbers[i].position = position; + damageNumbers[i].damage = damage; + damageNumbers[i].lifetime = DAMAGE_NUMBER_LIFETIME; + damageNumbers[i].active = true; + damageNumbers[i].color = color; + break; + } + } +} + +void UpdateDamageNumbers(DamageNumber* damageNumbers, int count, float deltaTime) +{ + for (int i = 0; i < count; i++) + { + if (!damageNumbers[i].active) continue; + + damageNumbers[i].lifetime -= deltaTime; + damageNumbers[i].position.y -= 30.0f * deltaTime; // Float upward + + if (damageNumbers[i].lifetime <= 0) + { + damageNumbers[i].active = false; + } + } +} + +void AddExperience(Player* player, float exp) +{ + player->experience += exp; + + // Check for level up + while (player->experience >= player->expToNextLevel) + { + player->experience -= player->expToNextLevel; + player->level++; + player->passivePoints++; + // Increase exp requirement for next level + player->expToNextLevel = EXP_TO_LEVEL * player->level; + } +} + void InitializePassiveTree(PassiveNode* nodes) { const char* nodeDescriptions[MAX_PASSIVE_NODES] = { @@ -175,7 +247,7 @@ // Check collision with other monsters if this monster has collision enabled if (monsters[i].hasCollision) { - bool collision = false; + bool canMove = true; for (int j = 0; j < monsterCount; j++) { if (i == j || !monsters[j].alive || !monsters[j].hasCollision) continue; @@ -186,12 +258,33 @@ if (distance < MONSTER_RADIUS * 2) { - collision = true; - break; + // If this monster is heavier, push the other monster away + if (monsters[i].weight > monsters[j].weight) + { + // Calculate push direction (away from current monster) + Vector2 pushDir = {dx, dy}; + float pushLength = sqrtf(pushDir.x * pushDir.x + pushDir.y * pushDir.y); + if (pushLength > 0) + { + pushDir.x /= pushLength; + pushDir.y /= pushLength; + } + + // Push the lighter monster away + float pushForce = (monsters[i].weight - monsters[j].weight) * MONSTER_SPEED * deltaTime * 0.5f; + monsters[j].position.x += pushDir.x * pushForce; + monsters[j].position.y += pushDir.y * pushForce; + } + else + { + // This monster is lighter or equal weight, can't move through + canMove = false; + break; + } } } - if (!collision) + if (canMove) { monsters[i].position = newPos; } @@ -248,7 +341,7 @@ } } -int CheckCollisions(Bullet* bullets, int bulletCount, Monster* monsters, int monsterCount, Player* player) +int CheckCollisions(Bullet* bullets, int bulletCount, Monster* monsters, int monsterCount, Player* player, DamageNumber* damageNumbers) { int bossesKilled = 0; @@ -271,11 +364,19 @@ float damage = CalculateColorDamage(bullets[i].hue, monsters[j].hue, bullets[i].damage); monsters[j].health -= damage; + // Spawn damage number + Color damageColor = damage > bullets[i].damage * 1.5f ? ORANGE : WHITE; + SpawnDamageNumber(damageNumbers, MAX_DAMAGE_NUMBERS, monsters[j].position, damage, damageColor); + // Check if monster died if (monsters[j].health <= 0) { monsters[j].alive = false; + // Award experience + float expGain = monsters[j].isBoss ? EXP_PER_BOSS : EXP_PER_MONSTER; + AddExperience(player, expGain); + // Award passive point if boss was killed if (monsters[j].isBoss) { @@ -313,6 +414,9 @@ nearestPos = monsters[i].position; found = true; } + + if (found) + break; } if (!found) @@ -340,26 +444,31 @@ .height = INIT_SCREEN_HEIGHT * 3 }; - // Initialize player at map center Player player = { .position = {map.width / 2, map.height / 2}, .color = BLUE, .health = PLAYER_MAX_HEALTH, .maxHealth = PLAYER_MAX_HEALTH, .unlockedCount = 0, - .passivePoints = 0, - .invulnerabilityTimer = 0.0f + .passivePoints = 3, + .invulnerabilityTimer = 0.0f, + .level = 1, + .experience = 0.0f, + .expToNextLevel = EXP_TO_LEVEL }; - // Initialize passive tree PassiveNode passiveTree[MAX_PASSIVE_NODES]; InitializePassiveTree(passiveTree); - - // Unlock first node only (grayscale bullet to start) passiveTree[0].unlocked = true; player.unlockedBulletTypes[player.unlockedCount++] = 0; - // Initialize camera + // Initialize damage numbers array + DamageNumber damageNumbers[MAX_DAMAGE_NUMBERS]; + for (int i = 0; i < MAX_DAMAGE_NUMBERS; i++) + { + damageNumbers[i].active = false; + } + Camera2D camera = {0}; camera.target = player.position; camera.offset = (Vector2){INIT_SCREEN_WIDTH / 2.0f, INIT_SCREEN_HEIGHT / 2.0f}; @@ -374,7 +483,6 @@ .y = INIT_SCREEN_HEIGHT / 2 }; - // Game progression variables float gameTime = 0.0f; float currentMonsterHue = 0.0f; float currentMonsterSaturation = 0.0f; // Start grayscale @@ -383,17 +491,18 @@ bool colorUnlocked = false; // Initialize monsters array - #define MAX_MONSTERS 100 + #define MAX_MONSTERS 1000 Monster live_monsters[MAX_MONSTERS]; int monsterCount = 0; // Spawn initial monsters (grayscale) - for (int i = 0; i < 10; i++) + for (int i = 0; i < 30; i++) { live_monsters[monsterCount++] = (Monster){ .position = {RandomFloat(0, map.width), RandomFloat(0, map.height)}, .hue = currentMonsterHue, .saturation = currentMonsterSaturation, + .weight = MONSTER_WEIGHT, .health = 50.0f, .maxHealth = 50.0f, .alive = true, @@ -488,6 +597,7 @@ .saturation = currentMonsterSaturation, .health = 50.0f * BOSS_HEALTH_MULTIPLIER, .maxHealth = 50.0f * BOSS_HEALTH_MULTIPLIER, + .weight = BOSS_MONSTER_WEIGHT, .alive = true, .hasCollision = true, .isBoss = true @@ -580,8 +690,11 @@ // Update bullets UpdateBullets(bullets, MAX_BULLETS, deltaTime); + // Update damage numbers + UpdateDamageNumbers(damageNumbers, MAX_DAMAGE_NUMBERS, deltaTime); + // Check collisions - int bossKills = CheckCollisions(bullets, MAX_BULLETS, live_monsters, monsterCount, &player); + int bossKills = CheckCollisions(bullets, MAX_BULLETS, live_monsters, monsterCount, &player, damageNumbers); bossesDefeated += bossKills; // Update camera to follow player @@ -728,6 +841,23 @@ } } + // Draw damage numbers + for (int i = 0; i < MAX_DAMAGE_NUMBERS; i++) + { + if (damageNumbers[i].active) + { + printf("True\n"); + float alpha = damageNumbers[i].lifetime / DAMAGE_NUMBER_LIFETIME; + Color color = damageNumbers[i].color; + color.a = (unsigned char)(255 * alpha); + DrawText(TextFormat("%.0f", damageNumbers[i].damage), + damageNumbers[i].position.x - 10, + damageNumbers[i].position.y, + 20, + color); + } + } + // Draw player (flash when invulnerable) if (player.invulnerabilityTimer <= 0 || ((int)(player.invulnerabilityTimer * 10) % 2 == 0)) { @@ -748,11 +878,18 @@ DrawRectangle(10, 10, 200 * healthPercent, 20, RED); DrawText(TextFormat("HP: %.0f/%.0f", player.health, player.maxHealth), 15, 12, 16, WHITE); + // Experience bar + float expPercent = player.experience / player.expToNextLevel; + DrawRectangle(10, 35, 200, 15, DARKGRAY); + DrawRectangle(10, 35, 200 * expPercent, 15, SKYBLUE); + DrawText(TextFormat("Lvl %d", player.level), 15, 36, 12, WHITE); + DrawText(TextFormat("%.0f/%.0f XP", player.experience, player.expToNextLevel), 70, 36, 12, WHITE); + // Passive points - DrawText(TextFormat("Passive Points: %d", player.passivePoints), 10, 40, 20, PURPLE); + DrawText(TextFormat("Passive Points: %d", player.passivePoints), 10, 55, 18, PURPLE); // Controls - DrawText("WASD: Move | P: Menu | R: Toggle Colors", 10, 70, 16, DARKGRAY); + DrawText("WASD: Move | P: Menu | R: Toggle Colors", 10, 80, 16, DARKGRAY); // Count alive monsters and bosses int aliveCount = 0; @@ -765,9 +902,9 @@ if (live_monsters[i].isBoss) bossCount++; } } - DrawText(TextFormat("Monsters: %d | Bosses: %d", aliveCount, bossCount), 10, 95, 18, DARKGRAY); - DrawText(TextFormat("Unlocked bullets: %d/%d", player.unlockedCount, MAX_PASSIVE_NODES), 10, 120, 16, DARKGRAY); - DrawText(TextFormat("Bosses defeated: %d", bossesDefeated), 10, 145, 16, DARKGRAY); + DrawText(TextFormat("Monsters: %d | Bosses: %d", aliveCount, bossCount), 10, 105, 18, DARKGRAY); + DrawText(TextFormat("Unlocked bullets: %d/%d", player.unlockedCount, MAX_PASSIVE_NODES), 10, 130, 16, DARKGRAY); + DrawText(TextFormat("Bosses defeated: %d", bossesDefeated), 10, 155, 16, DARKGRAY); } EndDrawing();
--- a/dowa/d_string.c Tue Dec 23 11:48:11 2025 -0800 +++ b/dowa/d_string.c Tue Dec 23 14:00:37 2025 -0800 @@ -6,3 +6,16 @@ return buffer; } +const char *Dowa_String_Slice(const char *from, size_t start, size_t end) +{ + static char buffer[1024] = {0}; + size_t buffer_pos = 0; + for (int i = start; start < strlen(from) || start < end; i++) + { + buffer[buffer_pos++] = from[i]; + } + return buffer; +} + + +
--- a/dowa/dowa.h Tue Dec 23 11:48:11 2025 -0800 +++ b/dowa/dowa.h Tue Dec 23 14:00:37 2025 -0800 @@ -5,7 +5,12 @@ #include <string.h> // stdup #include <stdlib.h> // only for malloc, free, stuff #include <assert.h> // mostly for TODO + +#ifdef DIRECTORY +// Only for linux and mac since window do not support. +// Maybe move this into seobeo file directly? #include <dirent.h> // some functions loop through files +#endif #include <math.h> // I am not re-writing stuff I guess... #include <sys/stat.h> @@ -34,12 +39,6 @@ typedef char int8; // 8-bit signed integer typedef char boolean; // Boolean type (0 = false, nonzero = true) - -// --- Miscellaneous --- // -/* Just use atoid lmao*/ -char *Dowa_Int32ToString(uint32 value, char *buffer); - - // --- Arena Allocator --- // typedef struct { char *buffer; @@ -111,6 +110,12 @@ /* Returns the number of entries currently in the hashmap. */ extern uint32 Dowa_HashMap_Get_Count(Dowa_PHashMap p_hash_map); +// --- String manipuliation -- // +// Splice string from start to end +const char *Dowa_String_Slice(const char *from, size_t start, size_t end); +// --- Miscellaneous --- // +char *Dowa_Int32ToString(uint32 value, char *buffer); /* Just use atoid lmao*/ + // --- Utility Functions --- // /* Prints all entries in the hashmap to stdout for debugging purposes. */ extern void Dowa_HashMap_Print(Dowa_PHashMap map);
--- a/postdog/main.c Tue Dec 23 11:48:11 2025 -0800 +++ b/postdog/main.c Tue Dec 23 14:00:37 2025 -0800 @@ -300,7 +300,7 @@ return 0; } -void updateUrlWithParams(char *url, size_t urlSize, const char *baseUrl, const char *params) +void Postdog_UpdateUrlWithParams(char *url, size_t urlSize, const char *baseUrl, const char *params) { // Find if there's already a ? in the URL char *questionMark = strchr(baseUrl, '?'); @@ -338,7 +338,7 @@ } // Save request to history file -void saveRequestToHistory(const char *url, const char *method, const char *headers, const char *body) +void Postdog_SaveRequestToHistory(const char *url, const char *method, const char *headers, const char *body) { PostDog_HistoryDirectory_Exists(); @@ -364,9 +364,12 @@ // Write headers fprintf(f, "Headers:\n"); - if (headers && strlen(headers) > 0) { + if (headers && strlen(headers) > 0) + { fprintf(f, "%s\n", headers); - } else { + } + else + { fprintf(f, "None\n"); } @@ -374,9 +377,12 @@ // Write body fprintf(f, "Body:\n"); - if (body && strlen(body) > 0) { + if (body && strlen(body) > 0) + { fprintf(f, "%s\n", body); - } else { + } + else + { fprintf(f, "None\n"); } @@ -384,23 +390,43 @@ printf("Request saved to %s\n", filename); } -void PostDog_Render_TextWithScroll(Rectangle textArea, Vector2 scroll, char * input) { +void PostDog_Render_TextWithScroll(Rectangle textArea, Vector2 scroll, char *input) +{ BeginScissorMode(textArea.x, textArea.y, textArea.width, textArea.height); - + int yPos = textArea.y + 5 - (int)scroll.y; - char *textCopy = strdup(input); - char *line = strtok(textCopy, "\n"); - - while (line != NULL && yPos < textArea.y + textArea.height) + int charactersPerLine = (int)(textArea.width / (TEXT_SIZE/1.5)); // Account for padding + int totalPos = 0; + int inputLen = strlen(input); + + while (totalPos < inputLen) { - if (yPos + LINE_HEIGHT > textArea.y) { - DrawText(line, textArea.x + 5, yPos, TEXT_SIZE, DARKGRAY); + int lineEnd = totalPos; + int lineLength = 0; + + while (lineEnd < inputLen && lineLength < charactersPerLine && input[lineEnd] != '\n') + { + lineEnd++; + lineLength++; } + + if (yPos + LINE_HEIGHT > textArea.y && yPos < textArea.y + textArea.height) + { + char savedChar = input[lineEnd]; + input[lineEnd] = '\0'; + DrawText(&input[totalPos], textArea.x + 5, yPos, TEXT_SIZE, DARKGRAY); + input[lineEnd] = savedChar; + } + yPos += LINE_HEIGHT; - line = strtok(NULL, "\n"); + + totalPos = lineEnd; + if (totalPos < inputLen && input[totalPos] == '\n') + { + totalPos++; + } } - free(textCopy); - + EndScissorMode(); } @@ -646,7 +672,7 @@ const char *requestHeaders = headersInput; // Save request to history - saveRequestToHistory(urlInput, selectedMethod, requestHeaders, requestBody); + Postdog_SaveRequestToHistory(urlInput, selectedMethod, requestHeaders, requestBody); // Reload history to show the new request historyCount = PostDog_HistoryDistory_ItemsLoad(historyItems, MAX_HISTORY_ITEMS); @@ -780,7 +806,7 @@ char *questionMark = strchr(tempUrl, '?'); if (questionMark) *questionMark = '\0'; - updateUrlWithParams(urlInput, sizeof(urlInput), tempUrl, paramsInput); + Postdog_UpdateUrlWithParams(urlInput, sizeof(urlInput), tempUrl, paramsInput); } break; } @@ -819,24 +845,7 @@ DrawRectangleLinesEx(responseArea, 1, GRAY); // Draw response text with scroll - BeginScissorMode(responseArea.x, responseArea.y, responseArea.width, responseArea.height); - - int yPos = responseArea.y + 5 - (int)responseScroll.y; - char *textCopy = strdup(responseText); - char *line = strtok(textCopy, "\n"); - - while (line != NULL && yPos < responseArea.y + responseArea.height) - { - if (yPos + LINE_HEIGHT > responseArea.y) - { - DrawText(line, responseArea.x + 5, yPos, TEXT_SIZE, DARKGRAY); - } - yPos += LINE_HEIGHT; - line = strtok(NULL, "\n"); - } - free(textCopy); - - EndScissorMode(); + PostDog_Render_TextWithScroll(responseArea, responseScroll, responseText); if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) {