Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions src/arena.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include "arena.h"
#include <stdlib.h>
#include <string.h>

arena_t *arena_create(size_t block_size)
{
if (block_size == 0)
block_size = ARENA_DEFAULT_SIZE;

arena_t *arena = malloc(sizeof(arena_t));
if (!arena)
return NULL;

arena->head = NULL;
arena->current = NULL;
arena->block_size = block_size;
return arena;
}

static arena_block_t *arena_new_block(arena_t *arena, size_t min_size)
{
size_t capacity = arena->block_size;
if (min_size > capacity)
capacity = min_size;

arena_block_t *block = malloc(sizeof(arena_block_t) + capacity);
if (!block)
return NULL;

block->next = NULL;
block->used = 0;
block->capacity = capacity;
return block;
}

void *arena_alloc(arena_t *arena, size_t size)
{
if (!arena || size == 0)
return NULL;

/* Align size */
size = (size + ARENA_ALIGNMENT - 1) & ~(ARENA_ALIGNMENT - 1);

arena_block_t *block = arena->current;
if (!block || block->used + size > block->capacity)
{
block = arena_new_block(arena, size);
if (!block)
return NULL;

block->next = arena->current;
arena->current = block;
if (!arena->head)
arena->head = block;
}

void *ptr = block->data + block->used;
block->used += size;
return ptr;
}

void *arena_alloc_zeroed(arena_t *arena, size_t size)
{
void *ptr = arena_alloc(arena, size);
if (ptr)
memset(ptr, 0, size);
return ptr;
}

char *arena_strdup(arena_t *arena, const char *str)
{
if (!str)
return NULL;
size_t len = strlen(str) + 1;
char *copy = arena_alloc(arena, len);
if (copy)
memcpy(copy, str, len);
return copy;
}

void arena_reset(arena_t *arena)
{
if (!arena)
return;

arena_block_t *block = arena->head;
while (block)
{
block->used = 0;
block = block->next;
}
arena->current = arena->head;
}

void arena_destroy(arena_t *arena)
{
if (!arena)
return;

arena_block_t *block = arena->head;
while (block)
{
arena_block_t *next = block->next;
free(block);
block = next;
}
free(arena);
}

size_t arena_used(arena_t *arena)
{
if (!arena)
return 0;

size_t total = 0;
arena_block_t *block = arena->head;
while (block)
{
total += block->used;
block = block->next;
}
return total;
}
39 changes: 39 additions & 0 deletions src/arena.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef ARENA_H
#define ARENA_H

#include <stddef.h>
#include <stdint.h>

#define ARENA_DEFAULT_SIZE (1024 * 1024) /* 1MB */
#define ARENA_ALIGNMENT 16

typedef struct arena_block
{
struct arena_block *next;
size_t used;
size_t capacity;
char data[];
} arena_block_t;

typedef struct
{
arena_block_t *head;
arena_block_t *current;
size_t block_size;
} arena_t;

/* Arena lifecycle */
arena_t *arena_create(size_t block_size);
void arena_destroy(arena_t *arena);
void arena_reset(arena_t *arena); /* Reset without freeing */

/* Memory allocation */
void *arena_alloc(arena_t *arena, size_t size);
void *arena_alloc_zeroed(arena_t *arena, size_t size);
char *arena_strdup(arena_t *arena, const char *str);

/* Utilities */
size_t arena_used(arena_t *arena);
void arena_print_stats(arena_t *arena);

#endif /* ARENA_H */
67 changes: 67 additions & 0 deletions src/editor_context.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include "editor_context.h"
#include "terminal.h"
#include <stdlib.h>
#include <string.h>

editor_context_t *editor_context_create(void)
{
editor_context_t *ctx = malloc(sizeof(editor_context_t));
if (!ctx)
return NULL;

memset(ctx, 0, sizeof(editor_context_t));

ctx->persistent_arena = arena_create(ARENA_DEFAULT_SIZE);
if (!ctx->persistent_arena)
goto error;

ctx->scratch_arena = arena_create(ARENA_DEFAULT_SIZE);
if (!ctx->scratch_arena)
goto error;

ctx->piece_table = piece_table_create(ctx->persistent_arena);
if (!ctx->piece_table)
goto error;

piece_table_init_empty(ctx->piece_table);

ctx->config.tab_stop = EDITOR_TAB_STOP;
ctx->config.status_msg_timeout = STATUS_MSG_TIMEOUT;
ctx->raw_mode_enabled = 0;
ctx->dirty = 0;
ctx->undo_stack = NULL;
ctx->redo_stack = NULL;

return ctx;

error:
if (ctx->persistent_arena)
arena_destroy(ctx->persistent_arena);
if (ctx->scratch_arena)
arena_destroy(ctx->scratch_arena);
free(ctx);
return NULL;
}

void editor_context_destroy(editor_context_t *ctx)
{
if (!ctx)
return;

if (ctx->raw_mode_enabled)
{
terminal_disable_raw_mode(ctx);
}

if (ctx->persistent_arena)
arena_destroy(ctx->persistent_arena);
if (ctx->scratch_arena)
arena_destroy(ctx->scratch_arena);
free(ctx->filename);
free(ctx);
}

void editor_context_reset_scratch(editor_context_t *ctx)
{
arena_reset(ctx->scratch_arena);
}
64 changes: 64 additions & 0 deletions src/editor_context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#ifndef EDITOR_CONTEXT_H
#define EDITOR_CONTEXT_H

#include "arena.h"
#include "piece_table.h"
#include "syntax.h"
#include "config.h"
#include <termios.h>
#include <time.h>

typedef struct editor_config
{
int tab_stop;
int status_msg_timeout;
} editor_config_t;

typedef struct editor_context
{
/* Memory management */
arena_t *persistent_arena; /* Long-lived allocations */
arena_t *scratch_arena; /* Temporary operations */

/* Text storage */
piece_table_t *piece_table;

/* Editor state */
int cx, cy; /* Cursor position */
int rx; /* Render cursor position */
int rowoff; /* Row scroll offset */
int coloff; /* Column scroll offset */
int screenrows;
int screencols;

char *filename;
int dirty; /* Unsaved modifications */

char statusmsg[STATUS_MSG_SIZE];
time_t statusmsg_time;

/* Terminal */
struct termios orig_termios;
int raw_mode_enabled;

/* Syntax */
editor_syntax_t *syntax;

/* Configuration */
editor_config_t config;

/* Undo stack */
edit_log_t *undo_stack;
edit_log_t *redo_stack;
} editor_context_t;

/* Context lifecycle */
editor_context_t *editor_context_create(void);
void editor_context_destroy(editor_context_t *ctx);
void editor_context_reset_scratch(editor_context_t *ctx);

/* Error handling with context */
editor_error_t editor_context_set_error(editor_context_t *ctx, editor_error_t err);
const char *editor_context_error_string(editor_context_t *ctx, editor_error_t err);

#endif /* EDITOR_CONTEXT_H */
48 changes: 13 additions & 35 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,56 +17,34 @@

int main(int argc, char *argv[])
{
editor_error_t err;

/* Initialize terminal */
err = terminal_enable_raw_mode();
struct sigaction sa;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sa.sa_handler = terminal_handle_winch;

if (sigaction(SIGWINCH, &sa, NULL) == -1)
{
editor_set_status_message("Warning: Cannot handle window resize");
}

if (IS_ERR(err))
{
fprintf(stderr, "Fatal: %s\n", editor_error_string(err));
editor_context_t *ctx = editor_context_create();
if (!ctx)
return 1;
}

/* Initialize editor */
err = editor_init();
editor_error_t err = terminal_enable_raw_mode(ctx);
if (IS_ERR(err))
{
editor_set_status_error(err);
editor_safe_recovery();
fprintf(stderr, "Error: %s\n", editor_error_string(err));
editor_context_destroy(ctx);
return 1;
}

/* Open file if provided */
if (argc >= 2)
{
err = file_open(argv[1]);
err = piece_table_load(ctx->piece_table, argv[1]);
if (IS_ERR(err))
{
editor_set_status_error(err);
output_refresh_screen();
sleep(2);
editor_set_status_message(ctx, "Error loading file");
}
}

/* Show help message */
editor_set_status_message(
"HELP: Ctrl-S = save | Ctrl-Q = quit | Ctrl-F = find");

/* Main event loop */
/* Main loop */
while (1)
{
output_refresh_screen();
input_process_keypress();
output_refresh_screen(ctx);
input_process_keypress(ctx);
}

editor_context_destroy(ctx);
return 0;
}
}
Loading