diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/src/net/network.c b/src/net/network.c index 61a46b2..4ae2702 100644 --- a/src/net/network.c +++ b/src/net/network.c @@ -224,7 +224,7 @@ int network_tcp_connect(const ipv4_address_t *ip, uint16_t port) { uint32_t start = sys_now(); asm volatile("sti"); - while (sys_now() - start < 5000) { // 5 second timeout + while (sys_now() - start < 15000) { // 15 second timeout network_poll_internal(); if (tcp_connect_done) { asm volatile("cli"); network_processing = 0; return 0; } if (tcp_connect_error) { asm volatile("cli"); network_processing = 0; return -1; } @@ -253,7 +253,7 @@ int network_tcp_recv(void *buf, size_t max_len) { if (tcp_closed) { network_processing = 0; return 0; } // End of stream uint32_t start = sys_now(); asm volatile("sti"); - while (sys_now() - start < 5000) { // 5 second timeout + while (sys_now() - start < 30000) { // 30 second timeout network_poll_internal(); if (tcp_recv_queue) break; if (tcp_closed) break; @@ -281,7 +281,10 @@ int network_tcp_recv_nb(void *buf, size_t max_len) { if (network_processing) return -1; network_processing = 1; + network_poll_internal(); + if (!tcp_recv_queue) { + if (tcp_closed) { network_processing = 0; return -2; } network_processing = 0; return 0; } diff --git a/src/sys/process.c b/src/sys/process.c index b3c47e9..7cad188 100644 --- a/src/sys/process.c +++ b/src/sys/process.c @@ -469,6 +469,9 @@ static void process_cleanup_inner(process_t *proc) { extern void cmd_process_finished(void); cmd_process_finished(); + extern void network_cleanup(void); + network_cleanup(); + extern void network_cleanup_pcb(void *pcb); // TODO: We need per-process PCB tracking to call this safely // For now, let's NOT call global network_cleanup diff --git a/src/userland/gui/browser.c b/src/userland/gui/browser.c index 709aa2d..8bde04b 100644 --- a/src/userland/gui/browser.c +++ b/src/userland/gui/browser.c @@ -280,18 +280,93 @@ static int fetch_content(const char *url, char *dest_buf, int max_len, bool prog int total = 0; int last_render = 0; if (progressive) inc_parse_offset = 0; + long long last_data_tick = sys_system(16, 0, 0, 0, 0); + while (1) { - int len = sys_tcp_recv(dest_buf + total, max_len - 1 - total); - if (len <= 0) break; + int len = sys_tcp_recv_nb(dest_buf + total, max_len - 1 - total); + if (len < 0 && len != -2) break; + if (len == -2) break; + + if (len == 0) { + long long now = sys_system(16, 0, 0, 0, 0); + if (now > last_data_tick + 1800) break; // 30 sec timeout + + gui_event_t ev; + bool scrolled = false; + while (ui_get_event(win_browser, &ev)) { + if (ev.type == 9) { // GUI_EVENT_MOUSE_WHEEL + scroll_y += ev.arg1 * 20; + int max_scroll = total_content_height - (win_h - URL_BAR_H); + if (max_scroll < 0) max_scroll = 0; + if (scroll_y > max_scroll) scroll_y = max_scroll; + if (scroll_y < 0) scroll_y = 0; + scrolled = true; + } else if (ev.type == 12) { // GUI_EVENT_CLOSE + sys_exit(0); + } + } + if (scrolled) { + browser_paint(); + ui_mark_dirty(win_browser, 0, 0, win_w, win_h); + } + sleep(10); + continue; + } + + last_data_tick = sys_system(16, 0, 0, 0, 0); total += len; if (total >= max_len - 1) break; + dest_buf[total] = 0; + char *body = strstr(dest_buf, "\r\n\r\n"); + if (body) { + char temp = body[0]; + body[0] = 0; // Null-terminate headers + + int expected = -1; + char *cl = str_istrstr(dest_buf, "Content-Length:"); + if (cl) { + cl += 15; + while (*cl == ' ') cl++; + expected = 0; + while (*cl >= '0' && *cl <= '9') { + expected = expected * 10 + (*cl - '0'); + cl++; + } + } + + int is_chunked = 0; + char *te = str_istrstr(dest_buf, "Transfer-Encoding:"); + if (te && str_istrstr(te, "chunked")) { + is_chunked = 1; + } + + body[0] = temp; // Restore body + + body += 4; + int body_len = total - (body - dest_buf); + + if (expected != -1) { + if (body_len >= expected) break; + } else if (is_chunked) { + if (total >= 5 && dest_buf[total-5] == '0' && dest_buf[total-4] == '\r' && + dest_buf[total-3] == '\n' && dest_buf[total-2] == '\r' && dest_buf[total-1] == '\n') { + break; + } + } + } + if (progressive && total - last_render > 32768) { dest_buf[total] = 0; char *body = strstr(dest_buf, "\r\n\r\n"); if (body) { + char temp = body[0]; + body[0] = 0; + int is_chunked = strstr(dest_buf, "Transfer-Encoding: chunked") != NULL; + body[0] = temp; + body += 4; - if (!strstr(dest_buf, "Transfer-Encoding: chunked")) { + if (!is_chunked) { int body_len = total - (body - dest_buf); int safe_len = body_len; while (safe_len > 0 && body[safe_len - 1] != '>') safe_len--; @@ -1436,7 +1511,9 @@ static void browser_paint(void) { for (int i = 0; i < element_count; i++) { RenderElement *el = &elements[i]; int draw_y = el->y - scroll_y + URL_BAR_H; - if (draw_y < URL_BAR_H - 400 || draw_y > win_h) continue; + int el_h = el->h; + if (el->tag == TAG_IMG && el->img_h > el_h) el_h = el->img_h; + if (draw_y + el_h < URL_BAR_H || draw_y > win_h) continue; if (el->tag == TAG_IMG) { uint32_t *pixels = el->img_pixels; if (el->img_frames) pixels = el->img_frames[el->img_current_frame]; @@ -1759,6 +1836,7 @@ int main(int argc, char **argv) { if (c == 13 || c == 10) { if (history_count < HISTORY_MAX) { int j=0; while(url_input_buffer[j]) { history_stack[history_count][j] = url_input_buffer[j]; j++; } history_stack[history_count][j] = 0; history_count++; } navigate(url_input_buffer); scroll_y = 0; + needs_repaint = true; } else if (c == 19) { if (url_cursor > 0) url_cursor--; } else if (c == 20) { int len = 0; while(url_input_buffer[len]) len++; if (url_cursor < len) url_cursor++; } diff --git a/src/wm/font_manager.c b/src/wm/font_manager.c index 0a2a5a4..60dc70f 100644 --- a/src/wm/font_manager.c +++ b/src/wm/font_manager.c @@ -71,12 +71,13 @@ static int loaded_font_count = 0; #define FONT_CACHE_SIZE 2048 typedef struct { - char c; - float pixel_height; + uint32_t codepoint; + float scale; + void *font; int w, h, xoff, yoff; unsigned char *bitmap; } font_cache_entry_t; - +static font_cache_entry_t font_cache[FONT_CACHE_SIZE] = {0}; bool font_manager_init(void) { return true; @@ -200,19 +201,33 @@ void font_manager_render_char_scaled(ttf_font_t *font, int x, int y, uint32_t co if (!font) font = default_font; if (!font) return; - stbtt_fontinfo *info = (stbtt_fontinfo *)font->info; + uint32_t hash = (codepoint * 31 + (uint32_t)scale * 73) % FONT_CACHE_SIZE; + font_cache_entry_t *entry = &font_cache[hash]; unsigned char *bitmap = NULL; int w, h, xoff, yoff; - float real_scale = stbtt_ScaleForPixelHeight(info, scale); - - if (stbtt_FindGlyphIndex(info, codepoint) == 0 && fallback_font) { - info = (stbtt_fontinfo *)fallback_font->info; - real_scale = stbtt_ScaleForPixelHeight(info, scale); - } + if (entry->bitmap && entry->codepoint == codepoint && entry->scale == scale && entry->font == font) { + bitmap = entry->bitmap; + w = entry->w; h = entry->h; xoff = entry->xoff; yoff = entry->yoff; + } else { + stbtt_fontinfo *info = (stbtt_fontinfo *)font->info; + float real_scale = stbtt_ScaleForPixelHeight(info, scale); + + if (stbtt_FindGlyphIndex(info, codepoint) == 0 && fallback_font) { + info = (stbtt_fontinfo *)fallback_font->info; + real_scale = stbtt_ScaleForPixelHeight(info, scale); + } - bitmap = stbtt_GetCodepointBitmap(info, 0, real_scale, codepoint, &w, &h, &xoff, &yoff); + bitmap = stbtt_GetCodepointBitmap(info, 0, real_scale, codepoint, &w, &h, &xoff, &yoff); + + if (entry->bitmap) stbtt_FreeBitmap(entry->bitmap, NULL); + entry->codepoint = codepoint; + entry->scale = scale; + entry->font = font; + entry->w = w; entry->h = h; entry->xoff = xoff; entry->yoff = yoff; + entry->bitmap = bitmap; + } if (bitmap) { for (int row = 0; row < h; row++) { @@ -226,7 +241,6 @@ void font_manager_render_char_scaled(ttf_font_t *font, int x, int y, uint32_t co } } } - stbtt_FreeBitmap(bitmap, NULL); } } @@ -234,19 +248,33 @@ void font_manager_render_char_sloped(ttf_font_t *font, int x, int y, uint32_t co if (!font) font = default_font; if (!font) return; - stbtt_fontinfo *info = (stbtt_fontinfo *)font->info; + uint32_t hash = (codepoint * 31 + (uint32_t)scale * 73) % FONT_CACHE_SIZE; + font_cache_entry_t *entry = &font_cache[hash]; unsigned char *bitmap = NULL; int w, h, xoff, yoff; - float real_scale = stbtt_ScaleForPixelHeight(info, scale); - - if (stbtt_FindGlyphIndex(info, codepoint) == 0 && fallback_font) { - info = (stbtt_fontinfo *)fallback_font->info; - real_scale = stbtt_ScaleForPixelHeight(info, scale); - } + if (entry->bitmap && entry->codepoint == codepoint && entry->scale == scale && entry->font == font) { + bitmap = entry->bitmap; + w = entry->w; h = entry->h; xoff = entry->xoff; yoff = entry->yoff; + } else { + stbtt_fontinfo *info = (stbtt_fontinfo *)font->info; + float real_scale = stbtt_ScaleForPixelHeight(info, scale); + + if (stbtt_FindGlyphIndex(info, codepoint) == 0 && fallback_font) { + info = (stbtt_fontinfo *)fallback_font->info; + real_scale = stbtt_ScaleForPixelHeight(info, scale); + } - bitmap = stbtt_GetCodepointBitmap(info, 0, real_scale, codepoint, &w, &h, &xoff, &yoff); + bitmap = stbtt_GetCodepointBitmap(info, 0, real_scale, codepoint, &w, &h, &xoff, &yoff); + + if (entry->bitmap) stbtt_FreeBitmap(entry->bitmap, NULL); + entry->codepoint = codepoint; + entry->scale = scale; + entry->font = font; + entry->w = w; entry->h = h; entry->xoff = xoff; entry->yoff = yoff; + entry->bitmap = bitmap; + } if (bitmap) { for (int row = 0; row < h; row++) { @@ -262,7 +290,6 @@ void font_manager_render_char_sloped(ttf_font_t *font, int x, int y, uint32_t co } } } - stbtt_FreeBitmap(bitmap, NULL); } }