1.44 Beta

[BUG FIX UPDATE]
Updates until 1.50 will be bug fix updates as 1.50 will be a full release.
Bug fixes for 1.44:
-Stopped the crashing when moving stuff onto the desktop
-Fixed codeblock formatting in the markdown viewer.
This commit is contained in:
Chris
2026-02-09 21:00:32 +01:00
parent 9a4b7b05ff
commit e939d50be6
34 changed files with 247 additions and 103 deletions

View File

@@ -32,7 +32,7 @@ static void about_paint(Window *win) {
// Version info
draw_string(offset_x, offset_y + 105, "BrewOS", COLOR_BLACK);
draw_string(offset_x, offset_y + 120, "BrewOS Version 1.43", COLOR_BLACK);
draw_string(offset_x, offset_y + 120, "BrewOS Version 1.44", COLOR_BLACK);
draw_string(offset_x, offset_y + 135, "Kernel Version 2.3.1", COLOR_BLACK);
// Copyright

View File

@@ -11,7 +11,6 @@ _start:
; Ensure interrupts are disabled
cli
; Setup stack is handled by Limine, but we can re-align if paranoid
; (Limine guarantees 16-byte alignment)
; Call the C kernel entry point

View File

@@ -60,7 +60,6 @@ static void fixed_to_str(long long n, char *buf) {
}
frac_buf[f_idx] = 0;
// If we have a fraction, add it to buffer (reversed first)
if (f_idx > 0) {
for (int i = f_idx - 1; i >= 0; i--) {
temp[pos++] = frac_buf[i];

View File

@@ -2,6 +2,6 @@
void cli_cmd_brewver(char *args) {
(void)args;
cli_write("BrewOS v1.43 Beta\n");
cli_write("BrewOS v1.44 Beta\n");
cli_write("BrewOS Kernel V2.3.1 Beta\n");
}

View File

@@ -140,7 +140,6 @@ void cli_cmd_udptest(char *args){
void cli_cmd_msgrc(char *args) {
(void)args;
// Reset message count since we are viewing them
cmd_reset_msg_count();
FAT32_FileHandle *fh = fat32_open("messages", "r");

View File

@@ -957,7 +957,7 @@ static void create_test_files(void) {
fh = fat32_open("README.md", "w");
if (fh) {
const char *content =
"# Brew OS 1.40 Beta\n\n"
"# Brew OS 1.44 Beta\n\n"
"BrewOS is now in a Beta stage as i have brought over all apps from brewkernel and have made the DE a lot more usable and stable.\n"
"## Brewkernel is now BrewOS!\n"
"Brewkernel will from now on be deprecated as it's core became too messy. I have built a less bloated kernel and wrote a DE above it, which is why it is now an OS instead of a kernel (in my opinion).\n\n"

View File

@@ -75,7 +75,7 @@ static void explorer_handle_right_click(Window *win, int x, int y);
static void explorer_handle_file_context_menu_click(Window *win, int x, int y);
static void explorer_perform_paste(Window *win, const char *dest_dir);
static void explorer_perform_move_internal(Window *win, const char *source_path, const char *dest_dir);
static void explorer_copy_recursive(const char *src_path, const char *dest_path);
static bool explorer_copy_recursive(const char *src_path, const char *dest_path);
Window* explorer_create_window(const char *path);
extern bool is_dragging_file;
@@ -433,11 +433,11 @@ bool explorer_clipboard_has_content(void) {
return clipboard_action != 0 && clipboard_path[0] != 0;
}
static void explorer_copy_recursive(const char *src_path, const char *dest_path) {
static bool explorer_copy_recursive(const char *src_path, const char *dest_path) {
if (fat32_is_directory(src_path)) {
fat32_mkdir(dest_path);
if (!fat32_mkdir(dest_path)) return false;
FAT32_FileInfo *files = (FAT32_FileInfo*)kmalloc(64 * sizeof(FAT32_FileInfo));
if (!files) return;
if (!files) return false;
int count = fat32_list_directory(src_path, files, 64);
for (int i = 0; i < count; i++) {
@@ -452,23 +452,29 @@ static void explorer_copy_recursive(const char *src_path, const char *dest_path)
if (d_sub[explorer_strlen(d_sub)-1] != '/') explorer_strcat(d_sub, "/");
explorer_strcat(d_sub, files[i].name);
explorer_copy_recursive(s_sub, d_sub);
if (!explorer_copy_recursive(s_sub, d_sub)) { kfree(files); return false; }
}
kfree(files);
return true;
} else {
// Copy file
FAT32_FileHandle *src = fat32_open(src_path, "r");
FAT32_FileHandle *dst = fat32_open(dest_path, "w");
bool success = false;
if (src && dst) {
uint8_t *buf = (uint8_t*)kmalloc(4096);
if (buf) {
int bytes;
while ((bytes = fat32_read(src, buf, 4096)) > 0) fat32_write(dst, buf, bytes);
success = true;
while ((bytes = fat32_read(src, buf, 4096)) > 0) {
if (fat32_write(dst, buf, bytes) != bytes) { success = false; break; }
}
kfree(buf);
}
}
if (src) fat32_close(src);
if (dst) fat32_close(dst);
return success;
}
}
@@ -513,8 +519,16 @@ void explorer_clipboard_paste(Window *win, const char *dest_dir) {
ExplorerState *state = (ExplorerState*)win->data;
if (!explorer_clipboard_has_content()) return;
// Prevent pasting a directory into itself or its subdirectories
if (explorer_str_starts_with(dest_dir, clipboard_path)) {
int src_len = explorer_strlen(clipboard_path);
if (dest_dir[src_len] == '\0' || dest_dir[src_len] == '/') {
return;
}
}
// Check for collision
char filename[256];
char filename[FAT32_MAX_FILENAME];
int len = explorer_strlen(clipboard_path);
int i = len - 1;
while (i >= 0 && clipboard_path[i] != '/') i--;
@@ -522,7 +536,7 @@ void explorer_clipboard_paste(Window *win, const char *dest_dir) {
for (int k = i + 1; k < len; k++) filename[j++] = clipboard_path[k];
filename[j] = 0;
char dest_path[256];
char dest_path[FAT32_MAX_PATH];
explorer_strcpy(dest_path, dest_dir);
if (dest_path[explorer_strlen(dest_path) - 1] != '/') {
explorer_strcat(dest_path, "/");
@@ -1760,7 +1774,7 @@ void explorer_refresh_all(void) {
static void explorer_perform_move_internal(Window *win, const char *source_path, const char *dest_dir) {
(void)win;
// 1. Extract filename
char filename[256];
char filename[FAT32_MAX_FILENAME];
int len = explorer_strlen(source_path);
int i = len - 1;
while (i >= 0 && source_path[i] != '/') i--;
@@ -1769,7 +1783,7 @@ static void explorer_perform_move_internal(Window *win, const char *source_path,
filename[j] = 0;
// 2. Build dest path
char dest_path[256];
char dest_path[FAT32_MAX_PATH];
explorer_strcpy(dest_path, dest_dir);
if (dest_path[explorer_strlen(dest_path) - 1] != '/') {
explorer_strcat(dest_path, "/");
@@ -1782,7 +1796,7 @@ static void explorer_perform_move_internal(Window *win, const char *source_path,
}
if (explorer_str_starts_with(dest_path, "/RecycleBin") && !explorer_str_starts_with(source_path, "/RecycleBin")) {
char origin_path[256];
char origin_path[FAT32_MAX_PATH];
explorer_strcpy(origin_path, dest_path);
explorer_strcat(origin_path, ".origin");
FAT32_FileHandle *fh = fat32_open(origin_path, "w");
@@ -1793,16 +1807,16 @@ static void explorer_perform_move_internal(Window *win, const char *source_path,
}
if (!explorer_str_starts_with(dest_path, "/RecycleBin") && explorer_str_starts_with(source_path, "/RecycleBin")) {
char origin_path[256];
char origin_path[FAT32_MAX_PATH];
explorer_strcpy(origin_path, source_path);
explorer_strcat(origin_path, ".origin");
fat32_delete(origin_path);
}
explorer_copy_recursive(source_path, dest_path);
// 4. Delete source (Move operation)
explorer_delete_permanently(source_path);
if (explorer_copy_recursive(source_path, dest_path)) {
// 4. Delete source (Move operation)
explorer_delete_permanently(source_path);
}
// Refresh
explorer_refresh_all();
@@ -1810,8 +1824,17 @@ static void explorer_perform_move_internal(Window *win, const char *source_path,
void explorer_import_file_to(Window *win, const char *source_path, const char *dest_dir) {
ExplorerState *state = (ExplorerState*)win->data;
// Prevent moving a directory into itself or its subdirectories
if (explorer_str_starts_with(dest_dir, source_path)) {
int src_len = explorer_strlen(source_path);
if (dest_dir[src_len] == '\0' || dest_dir[src_len] == '/') {
return;
}
}
// Check for collision
char filename[256];
char filename[FAT32_MAX_FILENAME];
int len = explorer_strlen(source_path);
int i = len - 1;
while (i >= 0 && source_path[i] != '/') i--;
@@ -1819,7 +1842,7 @@ void explorer_import_file_to(Window *win, const char *source_path, const char *d
for (int k = i + 1; k < len; k++) filename[j++] = source_path[k];
filename[j] = 0;
char dest_path[256];
char dest_path[FAT32_MAX_PATH];
explorer_strcpy(dest_path, dest_dir);
if (dest_path[explorer_strlen(dest_path) - 1] != '/') explorer_strcat(dest_path, "/");
explorer_strcat(dest_path, filename);

View File

@@ -1,4 +1,6 @@
#include "fat32.h"
#include "memory_manager.h"
#include "io.h"
#include <stdbool.h>
#include <stddef.h>
@@ -116,6 +118,9 @@ static void extract_parent_path(const char *path, char *parent) {
// Normalize path (remove .., ., etc)
void fat32_normalize_path(const char *path, char *normalized) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
char temp[FAT32_MAX_PATH];
int temp_len = 0;
@@ -173,6 +178,7 @@ void fat32_normalize_path(const char *path, char *normalized) {
}
fs_strcpy(normalized, temp);
asm volatile("push %0; popfq" : : "r"(rflags));
}
// Find file entry by path
@@ -237,8 +243,10 @@ static bool check_desktop_limit(const char *normalized_path) {
}
// Count files in /Desktop
FAT32_FileInfo info[256]; // Temp buffer
FAT32_FileInfo *info = (FAT32_FileInfo*)kmalloc(256 * sizeof(FAT32_FileInfo));
if (!info) return true;
int count = fat32_list_directory("/Desktop", info, 256);
kfree(info);
if (count >= desktop_file_limit) return false;
}
return true;
@@ -276,6 +284,9 @@ void fat32_set_desktop_limit(int limit) {
}
FAT32_FileHandle* fat32_open(const char *path, const char *mode) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
char normalized[FAT32_MAX_PATH];
fat32_normalize_path(path, normalized);
@@ -284,24 +295,32 @@ FAT32_FileHandle* fat32_open(const char *path, const char *mode) {
if (mode[0] == 'r') {
// Read mode
if (!entry || (entry->attributes & ATTR_DIRECTORY)) {
asm volatile("push %0; popfq" : : "r"(rflags));
return NULL; // File not found or is directory
}
} else if (mode[0] == 'w' || (mode[0] == 'a')) {
// Write/append mode - create if not exists
if (!entry) {
if (!check_desktop_limit(normalized)) {
asm volatile("push %0; popfq" : : "r"(rflags));
return NULL;
}
entry = find_free_entry();
if (!entry) return NULL;
if (!entry) {
asm volatile("push %0; popfq" : : "r"(rflags));
return NULL;
}
entry->used = true;
fs_strcpy(entry->full_path, normalized);
extract_filename(normalized, entry->filename);
extract_parent_path(normalized, entry->parent_path);
entry->start_cluster = allocate_cluster();
if (!entry->start_cluster) return NULL;
if (!entry->start_cluster) {
asm volatile("push %0; popfq" : : "r"(rflags));
return NULL;
}
entry->size = 0;
entry->attributes = 0; // Regular file
}
@@ -313,7 +332,10 @@ FAT32_FileHandle* fat32_open(const char *path, const char *mode) {
// Find free handle
FAT32_FileHandle *handle = find_free_handle();
if (!handle) return NULL;
if (!handle) {
asm volatile("push %0; popfq" : : "r"(rflags));
return NULL;
}
handle->valid = true;
handle->cluster = entry->start_cluster;
@@ -341,17 +363,24 @@ FAT32_FileHandle* fat32_open(const char *path, const char *mode) {
handle->cluster = current_cluster;
}
asm volatile("push %0; popfq" : : "r"(rflags));
return handle;
}
void fat32_close(FAT32_FileHandle *handle) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
if (handle) {
handle->valid = false;
}
asm volatile("push %0; popfq" : : "r"(rflags));
}
int fat32_read(FAT32_FileHandle *handle, void *buffer, int size) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
if (!handle || !handle->valid || handle->mode != 0) {
asm volatile("push %0; popfq" : : "r"(rflags));
return -1;
}
@@ -388,11 +417,15 @@ int fat32_read(FAT32_FileHandle *handle, void *buffer, int size) {
}
}
asm volatile("push %0; popfq" : : "r"(rflags));
return bytes_read;
}
int fat32_write(FAT32_FileHandle *handle, const void *buffer, int size) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
if (!handle || !handle->valid || (handle->mode != 1 && handle->mode != 2)) {
asm volatile("push %0; popfq" : : "r"(rflags));
return -1;
}
@@ -404,7 +437,10 @@ int fat32_write(FAT32_FileHandle *handle, const void *buffer, int size) {
uint32_t next = fat_table[handle->cluster];
if (next >= 0xFFFFFFF8) {
next = allocate_cluster();
if (!next) return 0;
if (!next) {
asm volatile("push %0; popfq" : : "r"(rflags));
return 0;
}
fat_table[handle->cluster] = next;
}
handle->cluster = next;
@@ -451,11 +487,15 @@ int fat32_write(FAT32_FileHandle *handle, const void *buffer, int size) {
}
}
asm volatile("push %0; popfq" : : "r"(rflags));
return bytes_written;
}
int fat32_seek(FAT32_FileHandle *handle, int offset, int whence) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
if (!handle || !handle->valid) {
asm volatile("push %0; popfq" : : "r"(rflags));
return -1;
}
@@ -474,23 +514,31 @@ int fat32_seek(FAT32_FileHandle *handle, int offset, int whence) {
}
handle->position = new_position;
asm volatile("push %0; popfq" : : "r"(rflags));
return new_position;
}
bool fat32_mkdir(const char *path) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
char normalized[FAT32_MAX_PATH];
fat32_normalize_path(path, normalized);
if (find_file(normalized)) {
asm volatile("push %0; popfq" : : "r"(rflags));
return false; // Already exists
}
if (!check_desktop_limit(normalized)) {
asm volatile("push %0; popfq" : : "r"(rflags));
return false;
}
FileEntry *entry = find_free_entry();
if (!entry) return false;
if (!entry) {
asm volatile("push %0; popfq" : : "r"(rflags));
return false;
}
entry->used = true;
fs_strcpy(entry->full_path, normalized);
@@ -500,43 +548,58 @@ bool fat32_mkdir(const char *path) {
entry->size = 0;
entry->attributes = ATTR_DIRECTORY;
asm volatile("push %0; popfq" : : "r"(rflags));
return true;
}
bool fat32_rmdir(const char *path) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
char normalized[FAT32_MAX_PATH];
fat32_normalize_path(path, normalized);
FileEntry *entry = find_file(normalized);
if (!entry || !(entry->attributes & ATTR_DIRECTORY)) {
asm volatile("push %0; popfq" : : "r"(rflags));
return false;
}
entry->used = false;
asm volatile("push %0; popfq" : : "r"(rflags));
return true;
}
bool fat32_delete(const char *path) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
char normalized[FAT32_MAX_PATH];
fat32_normalize_path(path, normalized);
FileEntry *entry = find_file(normalized);
if (!entry || (entry->attributes & ATTR_DIRECTORY)) {
asm volatile("push %0; popfq" : : "r"(rflags));
return false;
}
entry->used = false;
asm volatile("push %0; popfq" : : "r"(rflags));
return true;
}
bool fat32_exists(const char *path) {
return find_file(path) != NULL;
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
bool res = find_file(path) != NULL;
asm volatile("push %0; popfq" : : "r"(rflags));
return res;
}
bool fat32_rename(const char *old_path, const char *new_path) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
FileEntry *entry = find_file(old_path);
if (!entry) return false;
if (find_file(new_path)) return false; // Destination exists
if (!entry) { asm volatile("push %0; popfq" : : "r"(rflags)); return false; }
if (find_file(new_path)) { asm volatile("push %0; popfq" : : "r"(rflags)); return false; } // Destination exists
int old_len = fs_strlen(old_path);
@@ -572,20 +635,28 @@ bool fat32_rename(const char *old_path, const char *new_path) {
fs_strcat(files[i].parent_path, suffix);
}
}
asm volatile("push %0; popfq" : : "r"(rflags));
return true;
}
bool fat32_is_directory(const char *path) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
FileEntry *entry = find_file(path);
return entry && (entry->attributes & ATTR_DIRECTORY);
bool res = entry && (entry->attributes & ATTR_DIRECTORY);
asm volatile("push %0; popfq" : : "r"(rflags));
return res;
}
int fat32_list_directory(const char *path, FAT32_FileInfo *entries, int max_entries) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
char normalized[FAT32_MAX_PATH];
fat32_normalize_path(path, normalized);
FileEntry *dir = find_file(normalized);
if (!dir || !(dir->attributes & ATTR_DIRECTORY)) {
asm volatile("push %0; popfq" : : "r"(rflags));
return 0; // Not a directory
}
@@ -600,23 +671,30 @@ int fat32_list_directory(const char *path, FAT32_FileInfo *entries, int max_entr
}
}
asm volatile("push %0; popfq" : : "r"(rflags));
return count;
}
bool fat32_chdir(const char *path) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
char normalized[FAT32_MAX_PATH];
fat32_normalize_path(path, normalized);
FileEntry *entry = find_file(normalized);
if (!entry || !(entry->attributes & ATTR_DIRECTORY)) {
asm volatile("push %0; popfq" : : "r"(rflags));
return false;
}
fs_strcpy(current_dir, normalized);
asm volatile("push %0; popfq" : : "r"(rflags));
return true;
}
void fat32_get_current_dir(char *buffer, int size) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
int len = fs_strlen(current_dir);
if (len >= size) len = size - 1;
@@ -624,4 +702,5 @@ void fat32_get_current_dir(char *buffer, int size) {
buffer[i] = current_dir[i];
}
buffer[len] = 0;
asm volatile("push %0; popfq" : : "r"(rflags));
}

View File

@@ -1,6 +1,7 @@
#include <stddef.h>
#include "graphics.h"
#include "font.h"
#include "io.h"
static struct limine_framebuffer *g_fb = NULL;
static uint32_t g_bg_color = 0xFF696969; // Dark gray background
@@ -69,6 +70,9 @@ static void merge_dirty_rect(int x, int y, int w, int h) {
}
void graphics_mark_dirty(int x, int y, int w, int h) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
// Clamp to screen bounds
if (x < 0) {
w += x;
@@ -85,9 +89,13 @@ void graphics_mark_dirty(int x, int y, int w, int h) {
h = get_screen_height() - y;
}
if (w <= 0 || h <= 0) return;
if (w <= 0 || h <= 0) {
asm volatile("push %0; popfq" : : "r"(rflags));
return;
}
merge_dirty_rect(x, y, w, h);
asm volatile("push %0; popfq" : : "r"(rflags));
}
void graphics_mark_screen_dirty(void) {
@@ -103,7 +111,10 @@ DirtyRect graphics_get_dirty_rect(void) {
}
void graphics_clear_dirty(void) {
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
g_dirty.active = false;
asm volatile("push %0; popfq" : : "r"(rflags));
}
void put_pixel(int x, int y, uint32_t color) {

View File

@@ -11,10 +11,7 @@ send_eoi:
push rax
mov al, 0x20
out 0x20, al ; Master PIC
; If IRQ > 7, send to Slave too (Mouse is IRQ 12)
; We'll handle this in the specific wrappers or C code.
; Actually, simpler to do EOI in C or here.
; Let's just do it in C.
pop rax
ret

View File

@@ -116,10 +116,6 @@ static void md_parse_line(const char *raw_line, char *output, MDLineType *type,
*type = MD_LINE_BLOCKQUOTE;
i++;
if (raw_line[i] == ' ') i++;
} else if (raw_line[i] == '`') {
// Code block
*type = MD_LINE_CODE;
i++;
}
// Parse inline formatting and copy content
@@ -215,26 +211,36 @@ void markdown_open_file(const char *filename) {
int line = 0;
int col = 0;
char raw_line[256] = "";
bool in_code_block = false;
for (int i = 0; i < bytes_read && line < MD_MAX_LINES; i++) {
char ch = buffer[i];
if (ch == '\n') {
raw_line[col] = 0;
// Parse the raw line
char parsed_content[256];
MDLineType type;
int indent;
md_parse_line(raw_line, parsed_content, &type, &indent);
// Store parsed line
md_strcpy(lines[line].content, parsed_content);
lines[line].length = md_strlen(parsed_content);
lines[line].type = type;
lines[line].indent_level = indent;
line++;
if (raw_line[0] == '`' && raw_line[1] == '`' && raw_line[2] == '`') {
in_code_block = !in_code_block;
} else {
if (in_code_block) {
md_strcpy(lines[line].content, raw_line);
lines[line].length = md_strlen(raw_line);
lines[line].type = MD_LINE_CODE;
lines[line].indent_level = 0;
line++;
} else {
char parsed_content[256];
MDLineType type;
int indent;
md_parse_line(raw_line, parsed_content, &type, &indent);
md_strcpy(lines[line].content, parsed_content);
lines[line].length = md_strlen(parsed_content);
lines[line].type = type;
lines[line].indent_level = indent;
line++;
}
}
col = 0;
raw_line[0] = 0;
} else if (col < 255) {
@@ -245,16 +251,24 @@ void markdown_open_file(const char *filename) {
// Handle last line if no trailing newline
if (col > 0 && line < MD_MAX_LINES) {
raw_line[col] = 0;
char parsed_content[256];
MDLineType type;
int indent;
md_parse_line(raw_line, parsed_content, &type, &indent);
md_strcpy(lines[line].content, parsed_content);
lines[line].length = md_strlen(parsed_content);
lines[line].type = type;
lines[line].indent_level = indent;
line++;
if (raw_line[0] == '`' && raw_line[1] == '`' && raw_line[2] == '`') {
} else if (in_code_block) {
md_strcpy(lines[line].content, raw_line);
lines[line].length = md_strlen(raw_line);
lines[line].type = MD_LINE_CODE;
lines[line].indent_level = 0;
line++;
} else {
char parsed_content[256];
MDLineType type;
int indent;
md_parse_line(raw_line, parsed_content, &type, &indent);
md_strcpy(lines[line].content, parsed_content);
lines[line].length = md_strlen(parsed_content);
lines[line].type = type;
lines[line].indent_level = indent;
line++;
}
}
line_count = line;
@@ -331,7 +345,7 @@ static void md_paint(Window *win) {
text_color = 0xFF808080; // Gray
break;
case MD_LINE_CODE:
text_color = 0xFF800000; // Dark red
text_color = COLOR_WHITE;
break;
default:
text_color = COLOR_BLACK;
@@ -371,7 +385,6 @@ static void md_paint(Window *win) {
}
line_segment[segment_len] = 0;
// Word-based wrapping: if we didn't reach end of string, find last space
if (char_idx < text_len && segment_len > 0) {
// Look for the last space in the segment
int last_space = -1;
@@ -382,7 +395,6 @@ static void md_paint(Window *win) {
}
}
// If we found a space, break there
if (last_space > 0) {
segment_len = last_space;
line_segment[segment_len] = 0;
@@ -395,6 +407,10 @@ static void md_paint(Window *win) {
}
}
if (line->type == MD_LINE_CODE && segment_len > 0) {
draw_rect(x_offset - 2, line_y - 2, (segment_len * MD_CHAR_WIDTH) + 4, 12, COLOR_BLACK);
}
// Draw special elements for first wrapped line of this markdown line
if (local_display_line == 0) {
switch (line->type) {
@@ -414,10 +430,6 @@ static void md_paint(Window *win) {
// Draw left border
draw_rect(x_offset - 4, line_y, 2, line_height, 0xFF404080);
break;
case MD_LINE_CODE:
// Draw background for code
draw_rect(x_offset - 2, line_y, (max_chars_per_line * MD_CHAR_WIDTH) + 4, line_height, 0xFFF0F0F0);
break;
default:
break;
}
@@ -438,8 +450,7 @@ static void md_paint(Window *win) {
if (char_idx >= text_len) break;
}
// Move display line forward by the actual number of wrapped lines created
// Each wrapped line uses one MD_LINE_HEIGHT worth of space
display_line += wrapped_line_count;
i++;
@@ -451,8 +462,7 @@ static void md_paint(Window *win) {
static void md_handle_key(Window *win, char c) {
(void)win; // Suppress unused warning
// Handle scrolling with arrow keys and W/S
// 17 = UP arrow, 18 = DOWN arrow (from ps2 keyboard mapping)
if (c == 'w' || c == 'W' || c == 17) { // Page up or UP arrow
scroll_top -= 3;
if (scroll_top < 0) scroll_top = 0;

View File

@@ -148,23 +148,30 @@ void* kmalloc(size_t size) {
memory_manager_init();
}
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
if (size == 0 || size > memory_pool_size) {
asm volatile("push %0; popfq" : : "r"(rflags));
return NULL;
}
// Check if we can allocate
if (total_allocated + size > memory_pool_size) {
asm volatile("push %0; popfq" : : "r"(rflags));
return NULL;
}
// Find free space
void *ptr = find_free_space(size);
if (ptr == NULL) {
asm volatile("push %0; popfq" : : "r"(rflags));
return NULL;
}
// Add block entry
if (block_count >= MAX_ALLOCATIONS) {
asm volatile("push %0; popfq" : : "r"(rflags));
return NULL;
}
@@ -185,6 +192,7 @@ void* kmalloc(size_t size) {
// Clear memory
mem_memset(ptr, 0, size);
asm volatile("push %0; popfq" : : "r"(rflags));
return ptr;
}
@@ -193,6 +201,9 @@ void kfree(void *ptr) {
return;
}
uint64_t rflags;
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
// Find and free the block
for (int i = 0; i < block_count; i++) {
if (block_list[i].allocated && block_list[i].address == ptr) {
@@ -204,9 +215,11 @@ void kfree(void *ptr) {
block_list[j] = block_list[j + 1];
}
block_count--;
asm volatile("push %0; popfq" : : "r"(rflags));
return;
}
}
asm volatile("push %0; popfq" : : "r"(rflags));
}
void* krealloc(void *ptr, size_t new_size) {

View File

@@ -195,7 +195,6 @@ void tcp_close(tcp_socket_t *sock) {
int tcp_read(tcp_socket_t *sock, char *buffer, int max_len) {
if (!sock) return 0;
// Simple copy of what we have
int count = 0;
for (int i = 0; i < sock->rx_pos && i < max_len; i++) {
buffer[i] = sock->rx_buffer[i];

View File

@@ -976,6 +976,7 @@ void wm_handle_click(int x, int y) {
}
if (can_paste) {
int old_count = desktop_icon_count;
if (desktop_menu_target_icon != -1 && desktop_icons[desktop_menu_target_icon].type == 1) {
// Paste into folder
char path[128] = "/Desktop/";
@@ -987,6 +988,20 @@ void wm_handle_click(int x, int y) {
explorer_clipboard_paste(&win_explorer, "/Desktop");
}
refresh_desktop_icons();
// If auto-align is OFF and we pasted to the background, place at click location
if (!desktop_auto_align && desktop_icon_count > old_count && desktop_menu_target_icon == -1) {
int new_idx = desktop_icon_count - 1;
desktop_icons[new_idx].x = desktop_menu_x - 20;
desktop_icons[new_idx].y = desktop_menu_y - 20;
if (desktop_snap_to_grid) {
int col = (desktop_icons[new_idx].x - 20 + 40) / 80;
int row = (desktop_icons[new_idx].y - 20 + 40) / 80;
if (col < 0) col = 0; if (row < 0) row = 0;
desktop_icons[new_idx].x = 20 + col * 80;
desktop_icons[new_idx].y = 20 + row * 80;
}
}
}
}
else if (item == 3 && desktop_menu_target_icon != -1) { // Delete
@@ -1496,20 +1511,17 @@ void wm_handle_right_click(int x, int y) {
wm_show_message("Error", "Desktop is full!");
} else {
explorer_import_file_to(&win_explorer, drag_file_path, "/Desktop");
refresh_desktop_icons();
}
// Handle insertion at specific position
char filename[64];
int len = 0; while(drag_file_path[len]) len++;
int s = len - 1; while(s >= 0 && drag_file_path[s] != '/') s--;
s++;
int d = 0; while(drag_file_path[s] && d < 63) filename[d++] = drag_file_path[s++];
filename[d] = 0;
if (desktop_auto_align && !msg_box_visible) {
// Find the newly added icon (it will be at the end)
// Extract filename from drag_file_path
char filename[64];
int len = 0; while(drag_file_path[len]) len++;
int s = len - 1; while(s >= 0 && drag_file_path[s] != '/') s--;
s++;
int d = 0; while(drag_file_path[s] && d < 63) filename[d++] = drag_file_path[s++];
filename[d] = 0;
int new_idx = -1;
for(int i=0; i<desktop_icon_count; i++) {
if (str_eq(desktop_icons[i].name, filename) == 0) {
@@ -1534,6 +1546,21 @@ void wm_handle_right_click(int x, int y) {
refresh_desktop_icons(); // Re-apply layout
}
} else if (!desktop_auto_align && !msg_box_visible) {
for(int i=0; i<desktop_icon_count; i++) {
if (str_eq(desktop_icons[i].name, filename) == 0) {
desktop_icons[i].x = mx - 20;
desktop_icons[i].y = my - 20;
if (desktop_snap_to_grid) {
int col = (desktop_icons[i].x - 20 + 40) / 80;
int row = (desktop_icons[i].y - 20 + 40) / 80;
if (col < 0) col = 0; if (row < 0) row = 0;
desktop_icons[i].x = 20 + col * 80;
desktop_icons[i].y = 20 + row * 80;
}
break;
}
}
}
} else if (!dropped_on_target) {
// Moved within desktop