Mercurial
comparison postdog/main.c @ 114:e2a73e64e8e6
[Postdog] Got history working.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Tue, 06 Jan 2026 08:15:37 -0800 |
| parents | d6d578b49a19 |
| children | 96db6c3f38d6 |
comparison
equal
deleted
inserted
replaced
| 113:7a4e942814bc | 114:e2a73e64e8e6 |
|---|---|
| 1 #include <stdio.h> | 1 #include <stdio.h> |
| 2 #include <stdlib.h> | 2 #include <stdlib.h> |
| 3 #include <string.h> | 3 #include <string.h> |
| 4 #include <time.h> | 4 #include <time.h> |
| 5 #include <sys/stat.h> | 5 #include <sys/stat.h> |
| 6 #include <dirent.h> | |
| 7 #include "dowa/dowa.h" | 6 #include "dowa/dowa.h" |
| 8 | 7 |
| 9 #include <curl/curl.h> | 8 #include <curl/curl.h> |
| 10 #include "third_party/raylib/include/raylib.h" | 9 #include "third_party/raylib/include/raylib.h" |
| 11 #define RAYGUI_IMPLEMENTATION | 10 #define RAYGUI_IMPLEMENTATION |
| 12 #include "third_party/raylib/include/raygui.h" | 11 #include "third_party/raylib/include/raygui.h" |
| 12 | |
| 13 #ifndef POSTDOG_PATHS | |
| 14 #define POSTDOG_PATHS "/Users/mrjunejune/zenbu/postdog/history" | |
| 15 #endif | |
| 13 | 16 |
| 14 #define SCREEN_WIDTH 1280 | 17 #define SCREEN_WIDTH 1280 |
| 15 #define SCREEN_HEIGHT 780 | 18 #define SCREEN_HEIGHT 780 |
| 16 #define TEXT_SIZE 10 | 19 #define TEXT_SIZE 10 |
| 17 | 20 |
| 25 #define URL_TEXT_BUFFER 1024 * 10 | 28 #define URL_TEXT_BUFFER 1024 * 10 |
| 26 #define BODY_BUFFER_LENGTH 1024 * 1025 * 5 | 29 #define BODY_BUFFER_LENGTH 1024 * 1025 * 5 |
| 27 #define RESULT_BUFFER_LENGTH 1024 * 1025 * 5 | 30 #define RESULT_BUFFER_LENGTH 1024 * 1025 * 5 |
| 28 #define AREANA_BUFFER_LENGTH 1024 * 1025 * 15 | 31 #define AREANA_BUFFER_LENGTH 1024 * 1025 * 15 |
| 29 | 32 |
| 33 | |
| 34 #ifdef _WIN32 | |
| 35 #include <direct.h> | |
| 36 #include <io.h> | |
| 37 #define mkdir(path, mode) _mkdir(path) | |
| 38 #define access _access | |
| 39 #define F_OK 0 | |
| 40 #else | |
| 41 #include <sys/stat.h> | |
| 42 #include <dirent.h> | |
| 43 #include <unistd.h> | |
| 44 #endif | |
| 45 | |
| 30 typedef Dowa_KV(char*, char*) INPUT_HASHMAP; | 46 typedef Dowa_KV(char*, char*) INPUT_HASHMAP; |
| 31 | 47 |
| 32 typedef struct { | 48 typedef struct { |
| 33 char *data; | 49 char *data; |
| 34 size_t size; | 50 size_t size; |
| 35 } ResponseBuffer; | 51 } ResponseBuffer; |
| 36 | 52 |
| 37 typedef struct { | 53 typedef struct { |
| 38 char filename[256]; | 54 char *filename; |
| 39 char displayName[128]; | 55 Rectangle rect; |
| 40 char method[16]; | 56 long time_modified; |
| 41 time_t timestamp; | |
| 42 } HistoryItem; | 57 } HistoryItem; |
| 58 | |
| 59 typedef struct { | |
| 60 Rectangle rectangle; | |
| 61 char *label; | |
| 62 bool active; | |
| 63 } TabItem; | |
| 64 | |
| 65 typedef enum { | |
| 66 TAB_HEADER = 0, | |
| 67 TAB_BODY, | |
| 68 TAB_GET_PARAMS, | |
| 69 TAB_BAR, | |
| 70 TAB_LENGTH | |
| 71 } PostDog_Tab_Enum; | |
| 72 | |
| 73 static uint32 counter = 0; | |
| 74 HistoryItem *history_items = NULL; | |
| 75 HistoryItem *new_history_items = NULL; | |
| 76 | |
| 77 int CompareHistoryItemsByDate(const void *a, const void *b) { | |
| 78 HistoryItem *itemA = (HistoryItem *)a; | |
| 79 HistoryItem *itemB = (HistoryItem *)b; | |
| 80 return (itemB->time_modified - itemA->time_modified); | |
| 81 } | |
| 82 | |
| 83 // TODO: Make this into generic fucntion so I can use it across different thing. | |
| 84 void PostDog_List_Directory(const char *path, HistoryItem **p_file_arr) | |
| 85 { | |
| 86 HistoryItem *file_arr = *p_file_arr; | |
| 87 #ifdef _WIN32 | |
| 88 struct _finddata_t fileinfo; | |
| 89 intptr_t handle; | |
| 90 char search_path[256]; | |
| 91 sprintf(search_path, "%s\\*", path); | |
| 92 | |
| 93 if ((handle = _findfirst(search_path, &fileinfo)) == -1L) { | |
| 94 printf("Directory is empty or cannot be read.\n"); | |
| 95 } else { | |
| 96 do { | |
| 97 HistoryItem item = {0}; | |
| 98 item.filename = strdup(fileinfo.name); | |
| 99 item.rect = (Rectangle){0}; | |
| 100 item.time_modified = fileinfo.time_write; | |
| 101 Dowa_Array_Push(file_arr, item); | |
| 102 } while (_findnext(handle, &fileinfo) == 0); | |
| 103 _findclose(handle); | |
| 104 } | |
| 105 #else | |
| 106 struct dirent *entry; | |
| 107 struct stat file_stat; | |
| 108 DIR *dp = opendir(path); | |
| 109 if (dp == NULL) return; | |
| 110 | |
| 111 char full_path[256]; | |
| 112 while ((entry = readdir(dp))) | |
| 113 { | |
| 114 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) | |
| 115 continue; | |
| 116 snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name); | |
| 117 if (stat(full_path, &file_stat) == 0) | |
| 118 { | |
| 119 HistoryItem item = {0}; | |
| 120 item.filename = strdup(entry->d_name); | |
| 121 item.time_modified = file_stat.st_mtime; | |
| 122 Dowa_Array_Push(file_arr, item); | |
| 123 } | |
| 124 } | |
| 125 closedir(dp); | |
| 126 #endif | |
| 127 int count = Dowa_Array_Length(file_arr); | |
| 128 if (count > 1) { | |
| 129 qsort(file_arr, count, sizeof(HistoryItem), CompareHistoryItemsByDate); | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 int PostDog_History_Load(HistoryItem **p_history_files) | |
| 134 { | |
| 135 if (access(POSTDOG_PATHS, F_OK) == -1) | |
| 136 { | |
| 137 printf("Directory '%s' not found. Creating it...\n", POSTDOG_PATHS); | |
| 138 if (mkdir(POSTDOG_PATHS, 0777) != 0) | |
| 139 return -1; | |
| 140 return 0; | |
| 141 } | |
| 142 printf("Directory '%s' already exists.\n", POSTDOG_PATHS); | |
| 143 PostDog_List_Directory(POSTDOG_PATHS, p_history_files); | |
| 144 return 0; | |
| 145 } | |
| 146 | |
| 147 bool InArea(Vector2 mouse_position, Rectangle area) | |
| 148 { | |
| 149 return ( | |
| 150 mouse_position.x >= area.x && | |
| 151 mouse_position.x < area.x + area.width && | |
| 152 mouse_position.y >= area.y && | |
| 153 mouse_position.y < area.y + area.height | |
| 154 ); | |
| 155 } | |
| 156 | |
| 157 bool Clicked(Vector2 mouse_position, Rectangle area) | |
| 158 { | |
| 159 return (InArea(mouse_position, area) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)); | |
| 160 } | |
| 43 | 161 |
| 44 char *PostDog_Enum_To_String(int active_enum) | 162 char *PostDog_Enum_To_String(int active_enum) |
| 45 { | 163 { |
| 46 switch(active_enum) | 164 switch(active_enum) |
| 47 { | 165 { |
| 48 case 0: return "GET"; | 166 case 0: return "GET"; |
| 49 case 1: return "POST"; | 167 case 1: return "POST"; |
| 50 case 2: return "PUT"; | 168 case 2: return "PUT"; |
| 51 case 3: return "DELETE"; | 169 case 3: return "DELETE"; |
| 52 } | 170 } |
| 171 return 0; | |
| 172 } | |
| 173 | |
| 174 void PostDog_History_CreateFile(char *filename, char* values) | |
| 175 { | |
| 176 char full_file_path[512] = {0}; | |
| 177 snprintf(full_file_path, 512, "%s/%s", POSTDOG_PATHS, filename); | |
| 178 FILE *file = fopen(full_file_path, "w"); | |
| 179 if (!file) | |
| 180 { | |
| 181 printf("Failed to create a file: %s\n", full_file_path); | |
| 182 return; | |
| 183 } | |
| 184 fwrite(values, 1, strlen(values), file); | |
| 185 fclose(file); | |
| 186 } | |
| 187 | |
| 188 void PostDog_Request_SaveFile( | |
| 189 const char *url, | |
| 190 const char *method, | |
| 191 const char *headers, | |
| 192 const char *body, | |
| 193 const char *response) | |
| 194 { | |
| 195 size_t new_file_size = 1024 * 1024; | |
| 196 Dowa_Arena *arena = Dowa_Arena_Create(1024 * 1024 * 2); | |
| 197 char *new_file = Dowa_Arena_Allocate(arena, 1024 * 1024); | |
| 198 snprintf( | |
| 199 new_file, | |
| 200 new_file_size, | |
| 201 "%s\n" | |
| 202 "---\n" | |
| 203 "%s\n" | |
| 204 "---\n" | |
| 205 "%s\n" | |
| 206 "---\n" | |
| 207 "%s\n" | |
| 208 "---\n" | |
| 209 "%s\n", | |
| 210 url, | |
| 211 method, | |
| 212 headers, | |
| 213 body, | |
| 214 response | |
| 215 ); | |
| 216 char *filename = Dowa_Arena_Allocate(arena, 1024); | |
| 217 if (!filename) | |
| 218 { | |
| 219 perror("Error opening file"); | |
| 220 exit(EXIT_FAILURE); | |
| 221 } | |
| 222 char *uuid4 = (char *)Dowa_Arena_Allocate(arena, 37); | |
| 223 if (!uuid4) | |
| 224 { | |
| 225 perror("Error uuid"); | |
| 226 exit(EXIT_FAILURE); | |
| 227 } | |
| 228 | |
| 229 int32 seed = (uint32)time(NULL) ^ counter++; | |
| 230 Dowa_String_UUID(seed, uuid4); | |
| 231 snprintf(filename, 1024, "%s.txt", uuid4); | |
| 232 PostDog_History_CreateFile(filename, new_file); | |
| 233 | |
| 234 HistoryItem item = (HistoryItem){ .filename = malloc(sizeof(char) * strlen(filename) + 1), .rect = (Rectangle){0} }; | |
| 235 memcpy(item.filename, filename, strlen(filename) + 1); | |
| 236 Dowa_Array_Push(new_history_items, item); | |
| 237 | |
| 238 Dowa_Arena_Free(arena); | |
| 53 } | 239 } |
| 54 | 240 |
| 55 static size_t Postdog_Curl_Callback(void *contents, size_t size, size_t nmemb, void *userp) | 241 static size_t Postdog_Curl_Callback(void *contents, size_t size, size_t nmemb, void *userp) |
| 56 { | 242 { |
| 57 size_t real_size = size * nmemb; | 243 size_t real_size = size * nmemb; |
| 70 buf->data[buf->size] = 0; | 256 buf->data[buf->size] = 0; |
| 71 | 257 |
| 72 return real_size; | 258 return real_size; |
| 73 } | 259 } |
| 74 | 260 |
| 75 int PostDog_Make_HttpRequest( | 261 int PostDog_Http_Request( |
| 76 const char *url, | 262 const char *url, |
| 77 const char *method, | 263 const char *method, |
| 78 const char *headers, | 264 const char *headers, |
| 79 const char *body, | 265 const char *body, |
| 80 char *response, size_t responseSize) | 266 char *response, size_t responseSize) |
| 104 | 290 |
| 105 // Set HTTP method | 291 // Set HTTP method |
| 106 if (strcmp(method, "POST") == 0) | 292 if (strcmp(method, "POST") == 0) |
| 107 { | 293 { |
| 108 curl_easy_setopt(curl, CURLOPT_POST, 1L); | 294 curl_easy_setopt(curl, CURLOPT_POST, 1L); |
| 109 if (body && strlen(body) > 0) { | 295 if (body && strlen(body) > 0) |
| 110 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); | 296 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); |
| 111 } | |
| 112 } | 297 } |
| 113 else if (strcmp(method, "PUT") == 0) | 298 else if (strcmp(method, "PUT") == 0) |
| 114 { | 299 { |
| 115 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); | 300 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); |
| 116 if (body && strlen(body) > 0) { | 301 if (body && strlen(body) > 0) |
| 117 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); | 302 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); |
| 118 } | |
| 119 } | 303 } |
| 120 else if (strcmp(method, "DELETE") == 0) | 304 else if (strcmp(method, "DELETE") == 0) |
| 121 { | 305 { |
| 122 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); | 306 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); |
| 123 } | 307 } |
| 129 char *headersCopy = strdup(headers); | 313 char *headersCopy = strdup(headers); |
| 130 char *line = strtok(headersCopy, "\n"); | 314 char *line = strtok(headersCopy, "\n"); |
| 131 while (line != NULL) { | 315 while (line != NULL) { |
| 132 // Trim whitespace | 316 // Trim whitespace |
| 133 while (*line == ' ' || *line == '\t') line++; | 317 while (*line == ' ' || *line == '\t') line++; |
| 134 if (strlen(line) > 0) { | 318 if (strlen(line) > 0) |
| 135 headerList = curl_slist_append(headerList, line); | 319 headerList = curl_slist_append(headerList, line); |
| 136 } | |
| 137 line = strtok(NULL, "\n"); | 320 line = strtok(NULL, "\n"); |
| 138 } | 321 } |
| 139 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerList); | 322 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerList); |
| 140 free(headersCopy); | 323 free(headersCopy); |
| 141 } | 324 } |
| 144 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Postdog_Curl_Callback); | 327 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Postdog_Curl_Callback); |
| 145 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&buffer); | 328 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&buffer); |
| 146 | 329 |
| 147 // Follow redirects | 330 // Follow redirects |
| 148 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); | 331 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); |
| 149 | |
| 150 // Set timeout | 332 // Set timeout |
| 151 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); | 333 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); |
| 152 | |
| 153 // Perform request | 334 // Perform request |
| 154 res = curl_easy_perform(curl); | 335 res = curl_easy_perform(curl); |
| 155 | 336 |
| 156 if (res != CURLE_OK) | 337 if (res != CURLE_OK) |
| 157 snprintf(response, responseSize, "Error: %s\n", curl_easy_strerror(res)); | 338 snprintf(response, responseSize, "Error: %s\n", curl_easy_strerror(res)); |
| 172 } | 353 } |
| 173 | 354 |
| 174 free(buffer.data); | 355 free(buffer.data); |
| 175 curl_global_cleanup(); | 356 curl_global_cleanup(); |
| 176 | 357 |
| 358 PostDog_Request_SaveFile( | |
| 359 url, | |
| 360 method, | |
| 361 headers, | |
| 362 body, | |
| 363 response); | |
| 177 return 0; | 364 return 0; |
| 178 } | 365 } |
| 179 | 366 |
| 180 typedef struct { | |
| 181 Rectangle rectangle; | |
| 182 char *label; | |
| 183 bool active; | |
| 184 } TabItem; | |
| 185 | |
| 186 typedef enum { | |
| 187 TAB_HEADER = 0, | |
| 188 TAB_BODY, | |
| 189 TAB_GET_PARAMS, | |
| 190 TAB_BAR, | |
| 191 } PostDog_Tab_Enum; | |
| 192 | |
| 193 void PostDog_Update_URL(char **p_url_input_text, char* get_params) | 367 void PostDog_Update_URL(char **p_url_input_text, char* get_params) |
| 194 { | 368 { |
| 195 char *url_input_text = *p_url_input_text; | 369 char *url_input_text = *p_url_input_text; |
| 196 | 370 |
| 197 // Reset | 371 // Reset |
| 198 char *question_mark = strchr(url_input_text, '?'); | 372 char *question_mark = strchr(url_input_text, '?'); |
| 199 if (question_mark) | 373 if (question_mark) |
| 200 *question_mark = '\0'; | 374 *question_mark = '\0'; |
| 201 | 375 |
| 202 int get_params_length = (int)strlen(get_params) ; | 376 int get_params_length = (int)strlen(get_params) ; |
| 205 | 379 |
| 206 char *separator = "?"; | 380 char *separator = "?"; |
| 207 | 381 |
| 208 Dowa_Arena *arena = Dowa_Arena_Create(1024*1024); | 382 Dowa_Arena *arena = Dowa_Arena_Create(1024*1024); |
| 209 char **lines = Dowa_String_Split(get_params, "\n", get_params_length, 1, arena); | 383 char **lines = Dowa_String_Split(get_params, "\n", get_params_length, 1, arena); |
| 210 | |
| 211 size_t url_len = strlen(url_input_text); | |
| 212 size_t url_capacity = URL_TEXT_BUFFER; | |
| 213 | |
| 214 for (int i = 0; i < Dowa_Array_Length(lines); i++) | 384 for (int i = 0; i < Dowa_Array_Length(lines); i++) |
| 215 { | 385 { |
| 216 char *line = lines[i]; | 386 char *line = lines[i]; |
| 217 char **key_value = Dowa_String_Split(line, " ", (int)strlen(line), 1, arena); | 387 char **key_value = Dowa_String_Split(line, " ", (int)strlen(line), 1, arena); |
| 218 | 388 |
| 219 if (Dowa_Array_Length(key_value) < 2) | 389 if (Dowa_Array_Length(key_value) < 2) |
| 220 continue; // Skip this line, not break entire loop | 390 break; |
| 221 | |
| 222 // Check buffer capacity before each append | |
| 223 size_t needed = url_len + strlen(separator) + strlen(key_value[0]) + 1 + 10; // +10 for "=" and safety | |
| 224 if (needed >= url_capacity) break; | |
| 225 | 391 |
| 226 strcat(url_input_text, separator); | 392 strcat(url_input_text, separator); |
| 227 strcat(url_input_text, key_value[0]); | 393 strcat(url_input_text, key_value[0]); |
| 228 strcat(url_input_text, "="); | 394 strcat(url_input_text, "="); |
| 229 url_len = strlen(url_input_text); | |
| 230 | |
| 231 for (int i = 1; i < Dowa_Array_Length(key_value); i++) | 395 for (int i = 1; i < Dowa_Array_Length(key_value); i++) |
| 232 { | 396 { |
| 233 if (!key_value[i] || key_value[i][0] == '\0') | 397 if (!key_value[i] || key_value[i][0] == '\0') |
| 234 break; | 398 break; |
| 235 | |
| 236 size_t value_len = strlen(key_value[i]); | |
| 237 needed = url_len + value_len + 4; // +4 for "%20" if needed | |
| 238 if (needed >= url_capacity) break; | |
| 239 | |
| 240 printf("\n\n------\n\n"); | |
| 241 printf("key_value[%i]: %s, p = %p\n", i, key_value[i], key_value[i]); | |
| 242 printf("\n\n------\n\n"); | |
| 243 | |
| 244 if (i > 1) strcat(url_input_text, "%20"); | 399 if (i > 1) strcat(url_input_text, "%20"); |
| 245 strcat(url_input_text, key_value[i]); | 400 strcat(url_input_text, key_value[i]); |
| 246 url_len = strlen(url_input_text); | |
| 247 } | 401 } |
| 248 separator = "&"; | 402 separator = "&"; |
| 249 } | 403 } |
| 250 | 404 |
| 251 Dowa_Arena_Free(arena); | 405 Dowa_Arena_Free(arena); |
| 406 } | |
| 407 | |
| 408 int PostDog_String_To_MethodEnum(char *value) | |
| 409 { | |
| 410 if (strstr(value, "GET")) | |
| 411 return 0; | |
| 412 if (strstr(value, "POST")) | |
| 413 return 1; | |
| 414 if (strstr(value, "PUT")) | |
| 415 return 2; | |
| 416 if (strstr(value, "DELETE")) | |
| 417 return 3; | |
| 418 return 0; | |
| 419 } | |
| 420 | |
| 421 void PostDog_Params_Reset( | |
| 422 char **p_url_input_text, | |
| 423 int *p_active_method_dropdown, | |
| 424 char **url_body_map, | |
| 425 char **p_url_result_text | |
| 426 ) | |
| 427 { | |
| 428 char *url_input_text = *p_url_input_text; | |
| 429 char *url_result_text = *p_url_result_text; | |
| 430 int active_method_dropdown = *p_active_method_dropdown; | |
| 431 | |
| 432 url_input_text = ""; | |
| 433 url_result_text = ""; | |
| 434 active_method_dropdown = 0; | |
| 435 for (int i = 0; i < Dowa_Array_Length(url_body_map); i++) | |
| 436 url_body_map[i] = ""; | |
| 437 } | |
| 438 | |
| 439 void PostDog_Load_File( | |
| 440 const char *filename, | |
| 441 char **p_url_input_text, | |
| 442 int *p_active_method_dropdown, | |
| 443 char **url_body_map, | |
| 444 char **p_url_result_text | |
| 445 ) { | |
| 446 char *url_input_text = *p_url_input_text; | |
| 447 char *url_result_text = *p_url_result_text; | |
| 448 int active_method_dropdown = *p_active_method_dropdown; | |
| 449 | |
| 450 char full_file_path[512] = {0}; | |
| 451 snprintf(full_file_path, 512, "%s/%s", POSTDOG_PATHS, filename); | |
| 452 FILE *file = fopen(full_file_path, "r"); | |
| 453 if (!file) | |
| 454 return; | |
| 455 | |
| 456 fseek(file, 0, SEEK_END); | |
| 457 size_t file_size = ftell(file); | |
| 458 fseek(file, 0, SEEK_SET); | |
| 459 | |
| 460 Dowa_Arena *init_arena = Dowa_Arena_Create(file_size + 2); | |
| 461 Dowa_Arena *split_arena = Dowa_Arena_Create(file_size * 2); | |
| 462 char *file_buffer = Dowa_Arena_Allocate(init_arena, file_size+1); | |
| 463 fread(file_buffer, 1, file_size, file); | |
| 464 char **values = Dowa_String_Split(file_buffer, "---\n", file_size, 4, split_arena); | |
| 465 Dowa_Arena_Free(init_arena); | |
| 466 for (int i = 0; i < Dowa_Array_Length(values); i++) | |
| 467 { | |
| 468 if (i == 0) | |
| 469 { | |
| 470 snprintf(url_input_text, strlen(values[i]) + 1, "%s", values[i]); | |
| 471 url_input_text[strcspn(url_input_text, "\n")] = '\0'; | |
| 472 } | |
| 473 else if (i == 1) | |
| 474 active_method_dropdown = PostDog_String_To_MethodEnum(values[i]); | |
| 475 else if (i <= 3) | |
| 476 { | |
| 477 snprintf(url_body_map[i-2], strlen(values[i]) + 1, "%s", values[i]); | |
| 478 for (int j = strlen(values[i]); j > 0; j--) | |
| 479 { | |
| 480 if (url_body_map[i-2][j] == '\n') | |
| 481 { | |
| 482 url_body_map[i-2][j] = '\0'; | |
| 483 break; | |
| 484 } | |
| 485 } | |
| 486 } | |
| 487 else | |
| 488 snprintf(url_result_text, strlen(values[i]) + 1, "%s", values[i]); | |
| 489 } | |
| 490 } | |
| 491 | |
| 492 Rectangle AddPadding(Rectangle rect, float padding) | |
| 493 { | |
| 494 return (Rectangle){ | |
| 495 rect.x + padding, | |
| 496 rect.y + padding, | |
| 497 rect.width - (2 * padding), | |
| 498 rect.height - (2 * padding) | |
| 499 }; | |
| 252 } | 500 } |
| 253 | 501 |
| 254 int main() | 502 int main() |
| 255 { | 503 { |
| 256 // -- initizlied --// | 504 // -- initizlied --// |
| 258 SetWindowState(FLAG_WINDOW_RESIZABLE); | 506 SetWindowState(FLAG_WINDOW_RESIZABLE); |
| 259 SetTargetFPS(60); | 507 SetTargetFPS(60); |
| 260 | 508 |
| 261 Dowa_Arena *arena = Dowa_Arena_Create(AREANA_BUFFER_LENGTH); | 509 Dowa_Arena *arena = Dowa_Arena_Create(AREANA_BUFFER_LENGTH); |
| 262 | 510 |
| 511 Font customFont = LoadFontEx("postdog/Roboto-Regular.ttf", 20, 0, 0); | |
| 512 GuiSetFont(customFont); | |
| 513 GuiSetStyle(DEFAULT, TEXT_SIZE, 20); | |
| 514 | |
| 263 // -- Starting pos ---// | 515 // -- Starting pos ---// |
| 516 // Everyhting is relative to sidebar at this point lol | |
| 264 float side_bar_x = 10; | 517 float side_bar_x = 10; |
| 265 float side_bar_y = 10; | 518 float side_bar_y = 10; |
| 266 | |
| 267 Rectangle history_sidebar = { .x = side_bar_x, .y = side_bar_y, .width = 0, .height = 0 }; | 519 Rectangle history_sidebar = { .x = side_bar_x, .y = side_bar_y, .width = 0, .height = 0 }; |
| 520 Dowa_Array_Reserve(history_items, 10); | |
| 521 Dowa_Array_Reserve(new_history_items, 10); | |
| 522 PostDog_History_Load(&history_items); | |
| 268 | 523 |
| 269 Rectangle url_area = { 0 }; | 524 Rectangle url_area = { 0 }; |
| 270 Rectangle textBounds = { 0 }; | 525 Rectangle textBounds = { 0 }; |
| 271 Rectangle url_input_bounds = { 0 }; | 526 Rectangle url_input_bounds = { 0 }; |
| 272 bool url_input_bool = false; | 527 bool url_input_edit = false; |
| 273 Rectangle url_text_bounds = { 0 }; | 528 Rectangle url_text_bounds = { 0 }; |
| 274 Rectangle url_enter_button = { 0 }; | 529 Rectangle url_enter_button = { 0 }; |
| 275 Rectangle method_dropdown = { 0 }; | 530 Rectangle method_dropdown = { 0 }; |
| 276 | 531 |
| 532 | |
| 277 char *url_input_text = (char *)Dowa_Arena_Allocate(arena, URL_TEXT_BUFFER); | 533 char *url_input_text = (char *)Dowa_Arena_Allocate(arena, URL_TEXT_BUFFER); |
| 278 snprintf(url_input_text, URL_TEXT_BUFFER, "https://httpbin.org/get"); | 534 snprintf(url_input_text, URL_TEXT_BUFFER, "https://httpbin.org/get"); |
| 279 | 535 |
| 280 INPUT_HASHMAP *url_body_map = NULL; | 536 char **url_body_map = NULL; |
| 281 Dowa_HashMap_Push_Arena(url_body_map, "Header", (char *)Dowa_Arena_Allocate(arena, HEADER_BUFFER_LENGTH), arena); | 537 Dowa_Array_Push_Arena(url_body_map, (char *)Dowa_Arena_Allocate(arena, HEADER_BUFFER_LENGTH), arena); |
| 282 Dowa_HashMap_Push_Arena(url_body_map, "Body", (char *)Dowa_Arena_Allocate(arena, BODY_BUFFER_LENGTH), arena); | 538 Dowa_Array_Push_Arena(url_body_map, (char *)Dowa_Arena_Allocate(arena, BODY_BUFFER_LENGTH), arena); |
| 283 Dowa_HashMap_Push_Arena(url_body_map, "Get Param", (char *)Dowa_Arena_Allocate(arena, DEFAULT_TEXT_BUFFER_LENGTH), arena); | 539 Dowa_Array_Push_Arena(url_body_map, (char *)Dowa_Arena_Allocate(arena, DEFAULT_TEXT_BUFFER_LENGTH), arena); |
| 284 Dowa_HashMap_Push_Arena(url_body_map, "Bar", (char *)Dowa_Arena_Allocate(arena, DEFAULT_TEXT_BUFFER_LENGTH), arena); | 540 Dowa_Array_Push_Arena(url_body_map, (char *)Dowa_Arena_Allocate(arena, DEFAULT_TEXT_BUFFER_LENGTH), arena); |
| 285 | 541 |
| 286 snprintf(url_body_map[0].value, HEADER_BUFFER_LENGTH, "Content-Type: application/json"); | 542 snprintf(url_body_map[TAB_HEADER], HEADER_BUFFER_LENGTH, "Content-Type: application/json"); |
| 287 snprintf(url_body_map[1].value, HEADER_BUFFER_LENGTH, ""); | 543 snprintf(url_body_map[TAB_BODY], HEADER_BUFFER_LENGTH, ""); |
| 288 | 544 |
| 289 char *url_result_text = (char *)Dowa_Arena_Allocate(arena, RESULT_BUFFER_LENGTH); | 545 char *url_result_text = (char *)Dowa_Arena_Allocate(arena, RESULT_BUFFER_LENGTH); |
| 290 | 546 |
| 291 int active_method_dropdown = 0; | 547 int active_method_dropdown = 0; |
| 292 bool method_edit = false; | 548 bool method_edit = false; |
| 303 // -- result --// | 559 // -- result --// |
| 304 Rectangle result_area = { 0 }; | 560 Rectangle result_area = { 0 }; |
| 305 Rectangle result_body = { 0 }; | 561 Rectangle result_body = { 0 }; |
| 306 | 562 |
| 307 // General styling. | 563 // General styling. |
| 308 int padding = 10; // TODO make it % based? | 564 float padding = 10; // TODO make it % based? |
| 309 int active_input_tab = 0; | 565 int active_input_tab = 0; |
| 310 | 566 |
| 311 while (!WindowShouldClose()) | 567 while (!WindowShouldClose()) |
| 312 { | 568 { |
| 313 int screen_width = GetScreenWidth(); | 569 int screen_width = GetScreenWidth(); |
| 314 int screen_height = GetScreenHeight(); | 570 int screen_height = GetScreenHeight(); |
| 315 | 571 |
| 316 history_sidebar.width = screen_width * 0.15; | 572 history_sidebar.width = screen_width * 0.15; |
| 317 history_sidebar.height = screen_width - 10; | 573 history_sidebar.height = screen_width - 10; |
| 574 | |
| 575 int32 new_history_items_length = Dowa_Array_Length(new_history_items); | |
| 576 int32 history_item_length = Dowa_Array_Length(history_items); | |
| 577 int32 total = new_history_items_length + history_item_length; | |
| 578 for (int i = 0; i < total; i++) | |
| 579 { | |
| 580 HistoryItem *curr_history_items = i < new_history_items_length ? &new_history_items[i] : &history_items[i - new_history_items_length]; | |
| 581 curr_history_items->rect.x = history_sidebar.x + padding; | |
| 582 curr_history_items->rect.y = history_sidebar.y + (padding * 2 * (i+1)) + (i * history_sidebar.height * 0.05); | |
| 583 curr_history_items->rect.width = history_sidebar.width - (padding * 2); | |
| 584 curr_history_items->rect.height = history_sidebar.height * 0.05; | |
| 585 } | |
| 318 | 586 |
| 319 // -- URL Area --// | 587 // -- URL Area --// |
| 320 url_area.x = (side_bar_x + history_sidebar.width); | 588 url_area.x = (side_bar_x + history_sidebar.width); |
| 321 url_area.y = (side_bar_y); | 589 url_area.y = (side_bar_y); |
| 322 url_area.width = (screen_width - history_sidebar.width) * 0.9; | 590 url_area.width = (screen_width - history_sidebar.width) * 0.9; |
| 369 result_body.x = result_area.x + padding; | 637 result_body.x = result_area.x + padding; |
| 370 result_body.y = result_area.y + input_tab.height + padding; | 638 result_body.y = result_area.y + input_tab.height + padding; |
| 371 result_body.width = url_area.width * 0.49 - padding; | 639 result_body.width = url_area.width * 0.49 - padding; |
| 372 result_body.height = result_area.height - input_tab.height - padding; | 640 result_body.height = result_area.height - input_tab.height - padding; |
| 373 | 641 |
| 642 Vector2 mouse_position = GetMousePosition(); | |
| 643 | |
| 374 BeginDrawing(); | 644 BeginDrawing(); |
| 375 ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); | 645 ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); |
| 376 | 646 |
| 377 // Sidebar Rect | |
| 378 DrawRectangleRec(history_sidebar, Fade(GRAY, 0.1f)); | 647 DrawRectangleRec(history_sidebar, Fade(GRAY, 0.1f)); |
| 648 for (int i = 0; i < total; i++) | |
| 649 { | |
| 650 HistoryItem *curr_history_items = i < new_history_items_length ? &new_history_items[i] : &history_items[i - new_history_items_length]; | |
| 651 DrawRectangleRec(curr_history_items->rect, Fade(RED, 0.1f)); | |
| 652 GuiDrawText(curr_history_items->filename, AddPadding(curr_history_items->rect, padding), TEXT_ALIGN_CENTER, RED); | |
| 653 } | |
| 379 | 654 |
| 380 // URL area Rect | 655 // URL area Rect |
| 381 GuiDrawText("URL: ", url_text_bounds, TEXT_ALIGN_CENTER, RED); | 656 GuiDrawText("URL: ", url_text_bounds, TEXT_ALIGN_CENTER, RED); |
| 382 DrawRectangleRec(url_area, Fade(RED, 0.1f)); | 657 DrawRectangleRec(url_area, Fade(RED, 0.1f)); |
| 383 if (GuiTextBox(url_input_bounds, url_input_text, DEFAULT_TEXT_BUFFER_LENGTH, url_input_bool)) | 658 if (GuiTextBox(url_input_bounds, url_input_text, DEFAULT_TEXT_BUFFER_LENGTH, url_input_edit)) |
| 384 url_input_bool = !url_input_bool; | 659 url_input_edit = !url_input_edit; |
| 660 | |
| 385 sendRequest = GuiButton(url_enter_button, "ENTER"); | 661 sendRequest = GuiButton(url_enter_button, "ENTER"); |
| 386 if (sendRequest) | 662 if (sendRequest) |
| 387 PostDog_Make_HttpRequest( | 663 PostDog_Http_Request( |
| 388 url_input_text, | 664 url_input_text, |
| 389 PostDog_Enum_To_String(active_method_dropdown), | 665 PostDog_Enum_To_String(active_method_dropdown), |
| 390 url_body_map[0].value, | 666 url_body_map[TAB_HEADER], |
| 391 url_body_map[1].value, | 667 url_body_map[TAB_BODY], |
| 392 url_result_text, | 668 url_result_text, |
| 393 RESULT_BUFFER_LENGTH | 669 RESULT_BUFFER_LENGTH |
| 394 ); | 670 ); |
| 395 if (GuiDropdownBox(method_dropdown, "GET;POST;PUT;DELETE", &active_method_dropdown, method_edit)) | 671 if (GuiDropdownBox(method_dropdown, "GET;POST;PUT;DELETE", &active_method_dropdown, method_edit)) |
| 396 method_edit = !method_edit; | 672 method_edit = !method_edit; |
| 397 | 673 |
| 398 // Input Tabs Rect | 674 // Input Tabs Rect |
| 399 DrawRectangleRec(input_area, Fade(BLUE, 0.1f)); | 675 DrawRectangleRec(input_area, Fade(BLUE, 0.1f)); |
| 400 DrawRectangleRec(input_tab, Fade(DARKBLUE, 0.1f)); | 676 DrawRectangleRec(input_tab, Fade(DARKBLUE, 0.1f)); |
| 401 GuiSetStyle(TOGGLE, GROUP_PADDING, 0); | 677 GuiSetStyle(TOGGLE, GROUP_PADDING, 0); |
| 402 if (JUNE_GuiTextBox(input_body, url_body_map[active_input_tab].value, DEFAULT_TEXT_BUFFER_LENGTH, input_body_bool)) | 678 if (JUNE_GuiTextBox(input_body, url_body_map[active_input_tab], DEFAULT_TEXT_BUFFER_LENGTH, input_body_bool)) |
| 403 input_body_bool = !input_body_bool; | 679 input_body_bool = !input_body_bool; |
| 404 GuiToggleGroup(input_tab_item, "Header;Body;Get Param;Bar", &active_input_tab); | 680 GuiToggleGroup(input_tab_item, "Header;Body;Get Param;Bar", &active_input_tab); |
| 405 PostDog_Update_URL(&url_input_text, url_body_map[TAB_GET_PARAMS].value); | 681 |
| 682 PostDog_Update_URL(&url_input_text, url_body_map[TAB_GET_PARAMS]); | |
| 406 | 683 |
| 407 // Result Rect | 684 // Result Rect |
| 408 DrawRectangleRec(result_area, Fade(GREEN, 0.1f)); | 685 DrawRectangleRec(result_area, Fade(GREEN, 0.1f)); |
| 409 DrawRectangleRec(result_body, Fade(DARKGREEN, 0.1f)); | 686 DrawRectangleRec(result_body, Fade(DARKGREEN, 0.1f)); |
| 410 GuiTextBoxMulti(result_body, url_result_text, RESULT_BUFFER_LENGTH, false); | 687 GuiTextBoxMulti(result_body, url_result_text, RESULT_BUFFER_LENGTH, false); |
| 688 | |
| 689 if (url_input_edit && (IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) | |
| 690 { | |
| 691 SetClipboardText(url_input_text); | |
| 692 } | |
| 693 else if (input_body_bool && (IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) | |
| 694 { | |
| 695 SetClipboardText(url_body_map[active_input_tab]); | |
| 696 } | |
| 697 else if (InArea(mouse_position, result_body)) | |
| 698 { | |
| 699 DrawRectangleRec(result_body, Fade(GREEN, 0.3f)); | |
| 700 if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) | |
| 701 SetClipboardText(url_result_text); | |
| 702 } | |
| 703 | |
| 704 for (int i = 0; i < Dowa_Array_Length(history_items); i++) | |
| 705 { | |
| 706 if (Clicked(mouse_position, history_items[i].rect)) | |
| 707 PostDog_Load_File( | |
| 708 history_items[i].filename, | |
| 709 &url_input_text, | |
| 710 &active_method_dropdown, | |
| 711 url_body_map, | |
| 712 &url_result_text | |
| 713 ); | |
| 714 } | |
| 411 EndDrawing(); | 715 EndDrawing(); |
| 412 } | 716 } |
| 413 CloseWindow(); | 717 CloseWindow(); |
| 414 return 0; | 718 return 0; |
| 415 } | 719 } |