# HG changeset patch # User June Park # Date 1766196030 28800 # Node ID d4cdb87212fbf5ab24f01172de59821ecb37b9dd # Parent 0dcfbf5ba9972b6496a7f332a1fefa36e0e850a9 [PostDog] Working version. diff -r 0dcfbf5ba997 -r d4cdb87212fb postdog/main.c --- a/postdog/main.c Fri Dec 19 13:59:11 2025 -0800 +++ b/postdog/main.c Fri Dec 19 18:00:30 2025 -0800 @@ -16,13 +16,21 @@ #define SCREEN_WIDTH 1280 #define SCREEN_HEIGHT 780 -#define SIDEBAR_WIDTH 200 -#define URL_INPUT_HEIGHT 40 -#define PADDING 15 - #define TEXT_SIZE 10 #define LINE_HEIGHT 15 +#define GENERIC_PADDING 15 +#define SIDEBAR_WIDTH 200 +#define SIDEBAR_PADDING_GENERAL 5 +#define SIDEBAR_AREA_PADDING_X 10 +#define SIDEBAR_AREA_PADDING_Y 10 +#define SIDEBAR_REFERSH_BUTTON_WIDTH 90 +#define SIDEBAR_REFERSH_BUTTON_HEIGHT 20 +#define SIDEBAR_HISTORY_ITEM_HEIGHT 45 + +#define URL_INPUT_HEIGHT 40 + +#define TAB_LEN 3 #define METHOD_BUTTON_WIDTH 100 #define METHOD_BUTTON_HEIGHT 40 #define SEND_BUTTON_WIDTH 100 @@ -48,10 +56,10 @@ } HistoryItem; typedef enum { - ActiveTab_JSON = 0 + ActiveTab_JSON = 0, ActiveTab_Headers, ActiveTab_Params, -} ActiveTab +} ActiveTab; // Callback function for curl to write response data static size_t Postdog_Curl_Callback(void *contents, size_t size, size_t nmemb, void *userp) @@ -449,21 +457,21 @@ // Layout calculations Rectangle sidebar = { 0, 10, SIDEBAR_WIDTH, screenHeight }; - float mainX = SIDEBAR_WIDTH + PADDING; - float mainWidth = screenWidth - SIDEBAR_WIDTH - PADDING * 2; + float mainX = SIDEBAR_WIDTH + GENERIC_PADDING; + float mainWidth = screenWidth - SIDEBAR_WIDTH - GENERIC_PADDING * 2; // URL input box - leave space for SEND button on the right Rectangle urlBox = { mainX, - PADDING, - mainWidth - SEND_BUTTON_WIDTH - PADDING, + GENERIC_PADDING, + mainWidth - SEND_BUTTON_WIDTH - GENERIC_PADDING, URL_INPUT_HEIGHT }; // SEND button positioned beside URL input Rectangle sendButton = { - urlBox.x + urlBox.width + PADDING, - PADDING, + urlBox.x + urlBox.width + GENERIC_PADDING, + GENERIC_PADDING, SEND_BUTTON_WIDTH, SEND_BUTTON_HEIGHT }; @@ -471,20 +479,20 @@ // Method dropdown below URL Rectangle methodButton = { mainX, - urlBox.y + urlBox.height + PADDING, + urlBox.y + urlBox.height + GENERIC_PADDING, METHOD_BUTTON_WIDTH, METHOD_BUTTON_HEIGHT }; float tabHeight = 30; - float contentY = methodButton.y + methodButton.height + PADDING + tabHeight; - float contentHeight = screenHeight - contentY - PADDING; + float contentY = methodButton.y + methodButton.height + GENERIC_PADDING + tabHeight; + float contentHeight = screenHeight - contentY - GENERIC_PADDING; - float panelWidth = (mainWidth - PADDING) / 2; + float panelWidth = (mainWidth - GENERIC_PADDING) / 2; Rectangle tabBar = { mainX, - methodButton.y + methodButton.height + PADDING, + methodButton.y + methodButton.height + GENERIC_PADDING, panelWidth, tabHeight }; @@ -497,7 +505,7 @@ }; Rectangle responsePanel = { - mainX + panelWidth + PADDING, + mainX + panelWidth + GENERIC_PADDING, contentY, panelWidth, contentHeight @@ -506,21 +514,29 @@ BeginDrawing(); ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); - // Sidebar with history + // --- Sidebar Component--- DrawRectangleRec(sidebar, Fade(GRAY, 0.1f)); GuiGroupBox(sidebar, "HISTORY"); - // Refresh history button - Rectangle refreshBtn = { sidebar.x + 5, sidebar.y + 5, 90, 20 }; - if (GuiButton(refreshBtn, "Refresh")) { + Rectangle refreshBtn = { + sidebar.x + SIDEBAR_PADDING_GENERAL, + sidebar.y + SIDEBAR_PADDING_GENERAL, + SIDEBAR_REFERSH_BUTTON_WIDTH, + SIDEBAR_REFERSH_BUTTON_HEIGHT + }; + if (GuiButton(refreshBtn, "Refresh")) + { historyCount = PostDog_HistoryDistory_ItemsLoad(historyItems, MAX_HISTORY_ITEMS); } - // Scroll area for history - Rectangle historyArea = { sidebar.x + 5, sidebar.y + 30, sidebar.width - 10, sidebar.height - 40 }; - - // Handle scroll - if (CheckCollisionPointRec(GetMousePosition(), historyArea)) { + Rectangle historyArea = { + sidebar.x + SIDEBAR_PADDING_GENERAL, + sidebar.y + SIDEBAR_AREA_PADDING_Y, + sidebar.width - SIDEBAR_AREA_PADDING_X, + sidebar.height - SIDEBAR_AREA_PADDING_Y + }; + if (CheckCollisionPointRec(GetMousePosition(), historyArea)) + { float wheel = GetMouseWheelMove(); historyScroll.y += wheel * 20; if (historyScroll.y < 0) historyScroll.y = 0; @@ -528,39 +544,48 @@ BeginScissorMode(historyArea.x, historyArea.y, historyArea.width, historyArea.height); - if (historyCount == 0) { - DrawText("No requests yet", historyArea.x + 5, historyArea.y + 5, 10, DARKGRAY); - } else { - int yPos = historyArea.y + 5 - (int)historyScroll.y; - int itemHeight = 45; - - for (int i = 0; i < historyCount; i++) { - if (yPos > historyArea.y - itemHeight && yPos < historyArea.y + historyArea.height) { - Rectangle itemRect = { historyArea.x, yPos, historyArea.width, itemHeight - 2 }; + if (historyCount == 0) + { + DrawText("No requests yet", historyArea.x + 5, historyArea.y + 25, 10, DARKGRAY); + } + else + { + int item_y_position = historyArea.y + 5 - (int)historyScroll.y; + for ( + int current_history_item_number = 0; + current_history_item_number < historyCount; + current_history_item_number++ + ) + { + if (item_y_position > historyArea.y - SIDEBAR_HISTORY_ITEM_HEIGHT && item_y_position < historyArea.y + historyArea.height) + { + Rectangle itemRect = { historyArea.x, item_y_position, historyArea.width, SIDEBAR_HISTORY_ITEM_HEIGHT - 2 }; // Draw button for history item - Color bgColor = (selectedHistoryIndex == i) ? Fade(BLUE, 0.3f) : Fade(LIGHTGRAY, 0.5f); - - if (CheckCollisionPointRec(GetMousePosition(), itemRect) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { - // Load this request + Color bgColor = (selectedHistoryIndex == current_history_item_number) ? Fade(BLUE, 0.3f) : Fade(LIGHTGRAY, 0.5f); + if (CheckCollisionPointRec(GetMousePosition(), itemRect) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + // TODO: This is cringe as fuck probably should just have a strucut that we assign and then zero out lol char tempUrl[1024], tempMethod[16], tempHeaders[HEADER_INPUT_BUFFER_LEN], tempBody[JSON_INPUT_BUFFER_LEN]; if (PostDog_HistoryDirectory_LoadRequest( - historyItems[i].filename, tempUrl, tempMethod, tempHeaders, tempBody) == 0) + historyItems[current_history_item_number].filename, tempUrl, tempMethod, tempHeaders, tempBody) == 0) { strncpy(urlInput, tempUrl, sizeof(urlInput) - 1); strncpy(headersInput, tempHeaders, sizeof(headersInput) - 1); strncpy(jsonInput, tempBody, sizeof(jsonInput) - 1); // Set method - for (int m = 0; m < 4; m++) { - if (strcmp(methods[m], tempMethod) == 0) { + for (int m = 0; m < 4; m++) + { + if (strcmp(methods[m], tempMethod) == 0) + { methodActive = m; break; } } - selectedHistoryIndex = i; + selectedHistoryIndex = current_history_item_number; strcpy(responseText, "Request loaded from history. Click SEND to execute."); } } @@ -569,44 +594,45 @@ DrawRectangleLinesEx(itemRect, 1, GRAY); // Draw method badge - DrawText(historyItems[i].method, itemRect.x + 5, yPos + 5, 10, BLACK); + DrawText(historyItems[current_history_item_number].method, itemRect.x + 5, item_y_position + 5, 10, BLACK); // Draw timestamp (date only) char dateStr[16] = ""; - if (strlen(historyItems[i].filename) >= 8) { + if (strlen(historyItems[current_history_item_number].filename) >= 8) + { snprintf(dateStr, sizeof(dateStr), "%.4s-%.2s-%.2s", - historyItems[i].filename, historyItems[i].filename + 4, historyItems[i].filename + 6); + historyItems[current_history_item_number].filename, historyItems[current_history_item_number].filename + 4, historyItems[current_history_item_number].filename + 6); } - DrawText(dateStr, itemRect.x + 5, yPos + 18, 8, DARKGRAY); + DrawText(dateStr, itemRect.x + 5, item_y_position + 18, 8, DARKGRAY); // Draw time char timeStr[16] = ""; - if (strlen(historyItems[i].filename) >= 15) { + if (strlen(historyItems[current_history_item_number].filename) >= 15) { snprintf(timeStr, sizeof(timeStr), "%.2s:%.2s:%.2s", - historyItems[i].filename + 9, historyItems[i].filename + 11, historyItems[i].filename + 13); + historyItems[current_history_item_number].filename + 9, historyItems[current_history_item_number].filename + 11, historyItems[current_history_item_number].filename + 13); } - DrawText(timeStr, itemRect.x + 5, yPos + 28, 8, DARKGRAY); + DrawText(timeStr, itemRect.x + 5, item_y_position + 28, 8, DARKGRAY); } - yPos += itemHeight; + item_y_position += SIDEBAR_HISTORY_ITEM_HEIGHT; } } EndScissorMode(); - // URL Input - GuiLabel((Rectangle){ mainX, PADDING - 15, 100, 20 }, "URL:"); + // --- URL Input Component --- + GuiLabel((Rectangle){ mainX, GENERIC_PADDING - 15, 100, 20 }, "URL:"); if (GuiTextBox(urlBox, urlInput, 1024, urlEditMode)) { urlEditMode = !urlEditMode; } - // Copy support for URL - if (urlEditMode && (IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) { + if (urlEditMode && (IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) + { SetClipboardText(urlInput); } // Send button (beside URL) - if (GuiButton(sendButton, "SEND")) + if (GuiButton(sendButton, "SEND") || (urlEditMode && IsKeyDown(KEY_ENTER))) { strcpy(responseText, "Sending request...\n"); @@ -624,9 +650,9 @@ // Reload history to show the new request historyCount = PostDog_HistoryDistory_ItemsLoad(historyItems, MAX_HISTORY_ITEMS); + // Making the requests. PostDog_Make_HttpRequest(urlInput, selectedMethod, requestHeaders, requestBody, tempResponse, sizeof(tempResponse)); - strncpy(responseText, tempResponse, sizeof(responseText) - 1); responseText[sizeof(responseText) - 1] = '\0'; } @@ -649,22 +675,25 @@ if (GuiButton(paramsTab, activeTab == ActiveTab_Params ? "#191#Params" : "Params")) { - activeTab = ActiveTab_Headers; + activeTab = ActiveTab_Params; } const char *panelTitle; switch(activeTab) { case ActiveTab_JSON: { - panelTitle = "Request Body (JSON)" + panelTitle = "Request Body (JSON)"; + break; } case ActiveTab_Headers: { - panelTitle = "Request Headers" + panelTitle = "Request Headers"; + break; } case ActiveTab_Params: { - panelTitle = "Query Parameters" + panelTitle = "Query Parameters"; + break; } } @@ -695,7 +724,8 @@ if (CheckCollisionPointRec(GetMousePosition(), textArea)) { float wheel = GetMouseWheelMove(); - switch(activeTab) { + switch(activeTab) + { case ActiveTab_JSON: { jsonScroll.y += wheel * 20; @@ -713,105 +743,57 @@ } } } - if (activeTab == 0) + + char *copyFromInput; + bool *currentMode; + switch(activeTab) { - BeginScissorMode(textArea.x, textArea.y, textArea.width, textArea.height); - - int yPos = textArea.y + 5 - (int)jsonScroll.y; - char *textCopy = strdup(jsonInput); - char *line = strtok(textCopy, "\n"); - - while (line != NULL && yPos < textArea.y + textArea.height) + case ActiveTab_JSON: { - if (yPos + LINE_HEIGHT > textArea.y) { - DrawText(line, textArea.x + 5, yPos, TEXT_SIZE, DARKGRAY); - } - yPos += LINE_HEIGHT; - line = strtok(NULL, "\n"); - } - free(textCopy); - - EndScissorMode(); - - if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) { - SetClipboardText(jsonInput); + PostDog_Render_TextWithScroll(textArea, jsonScroll, jsonInput); + copyFromInput = jsonInput; + currentMode = &jsonEditMode; + break; } - - // Edit button - Rectangle editBtn = { textArea.x + textArea.width - 60, textArea.y + textArea.height - 10, 50, 20 }; - if (GuiButton(editBtn, "Edit")) { - jsonEditMode = !jsonEditMode; - } - } else if (activeTab == 1) { - BeginScissorMode(textArea.x, textArea.y, textArea.width, textArea.height); - - int yPos = textArea.y + 5 - (int)headersScroll.y; - char *textCopy = strdup(headersInput); - char *line = strtok(textCopy, "\n"); - - while (line != NULL && yPos < textArea.y + textArea.height) + case ActiveTab_Headers: { - if (yPos + LINE_HEIGHT > textArea.y) - { - DrawText(line, textArea.x + 5, yPos, TEXT_SIZE, DARKGRAY); - } - yPos += LINE_HEIGHT; - line = strtok(NULL, "\n"); - } - free(textCopy); - - EndScissorMode(); + PostDog_Render_TextWithScroll(textArea, headersScroll, headersInput); + copyFromInput = headersInput; + currentMode = &headersEditMode; + break; + } + case ActiveTab_Params: + { + PostDog_Render_TextWithScroll(textArea, paramsScroll, paramsInput); + copyFromInput = paramsInput; + currentMode = ¶msEditMode; - if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) { - SetClipboardText(headersInput); - } + Rectangle updateUrlBtn = { textArea.x + 30, textArea.y + textArea.height - 10, 120, 20 }; + // TODO: Automatic update + if (GuiButton(updateUrlBtn, "Update URL")) + { + char tempUrl[1024]; + strncpy(tempUrl, urlInput, sizeof(tempUrl) - 1); - // Edit button - Rectangle editBtn = { textArea.x + textArea.width - 60, textArea.y + textArea.height + 5, 50, 20 }; - if (GuiButton(editBtn, "Edit")) { - headersEditMode = !headersEditMode; - } - } else { - // Params input with manual scroll - BeginScissorMode(textArea.x, textArea.y, textArea.width, textArea.height); + // Remove existing params if any + char *questionMark = strchr(tempUrl, '?'); + if (questionMark) *questionMark = '\0'; - int yPos = textArea.y + 5 - (int)paramsScroll.y; - char *textCopy = strdup(paramsInput); - char *line = strtok(textCopy, "\n"); - - while (line != NULL && yPos < textArea.y + textArea.height) { - if (yPos + LINE_HEIGHT > textArea.y) { - DrawText(line, textArea.x + 5, yPos, TEXT_SIZE, DARKGRAY); + updateUrlWithParams(urlInput, sizeof(urlInput), tempUrl, paramsInput); } - yPos += LINE_HEIGHT; - line = strtok(NULL, "\n"); + break; } - free(textCopy); - - EndScissorMode(); - - if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) { - SetClipboardText(paramsInput); - } + } - // Buttons - Rectangle editBtn = { textArea.x + textArea.width - 60, textArea.y + textArea.height + 5, 50, 20 }; - if (GuiButton(editBtn, "Edit")) - { - paramsEditMode = !paramsEditMode; - } + if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) + { + SetClipboardText(copyFromInput); + } - Rectangle updateUrlBtn = { textArea.x, textArea.y + textArea.height + 5, 120, 20 }; - if (GuiButton(updateUrlBtn, "Update URL")) - { - char tempUrl[1024]; - strncpy(tempUrl, urlInput, sizeof(tempUrl) - 1); - // Remove existing params if any - char *questionMark = strchr(tempUrl, '?'); - if (questionMark) *questionMark = '\0'; - - updateUrlWithParams(urlInput, sizeof(urlInput), tempUrl, paramsInput); - } + Rectangle editBtn = { textArea.x + textArea.width - 60, textArea.y + textArea.height - 10, 50, 20 }; + if (GuiButton(editBtn, "Edit")) + { + *currentMode = !(*currentMode); } // Response Panel with scroll