logging works ( but it's buggy 😭 )
This commit is contained in:
+270
@@ -0,0 +1,270 @@
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
ADDED
|
||||
ADDED
|
||||
ADDED
|
||||
ADDED
|
||||
ADDED
|
||||
ADDED
|
||||
ADDED
|
||||
ADDED
|
||||
ADDED
|
||||
ADDED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
REMOVED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
UNMODIFIED
|
||||
+11
-4
@@ -96,7 +96,6 @@ String_t str_from_file(FILE* file) {
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
int str_to_file(String_t* self, FILE* file) {
|
||||
char* data = to_chars(self);
|
||||
|
||||
@@ -108,16 +107,24 @@ int str_to_file(String_t* self, FILE* file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
String_t str_clone(String_t* self) {
|
||||
String_t clone;
|
||||
clone.size = self->size;
|
||||
clone.capacity = self->capacity;
|
||||
clone.data = (char*)malloc(clone.capacity);
|
||||
clone.data = (char*)calloc(clone.capacity, sizeof(char));
|
||||
memcpy(clone.data, self->data, clone.capacity);
|
||||
return clone;
|
||||
}
|
||||
|
||||
String_t* str_clone_all(String_t* strings, int len) {
|
||||
String_t* clones = (String_t*)calloc(len, sizeof(String_t));
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
clones[i] = str_clone(&strings[i]);
|
||||
}
|
||||
return clones;
|
||||
}
|
||||
|
||||
char str_pop(String_t* self) {
|
||||
if (self->size == 0) {
|
||||
return '\0';
|
||||
@@ -244,4 +251,4 @@ String_t str_slice(String_t* s, int start, int end) {
|
||||
s2.data[i] = s->data[start + i];
|
||||
}
|
||||
return s2;
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -70,7 +70,9 @@ String_t str_new();
|
||||
* This allocates new memory that must be freed
|
||||
* @param self Pointer to the String_t to clone
|
||||
*/
|
||||
String_t str_clone();
|
||||
String_t str_clone(String_t* self);
|
||||
|
||||
String_t* str_clone_all(String_t* strings, int len);
|
||||
|
||||
/**
|
||||
* Creates a new string containing a slice of an existing string.
|
||||
|
||||
+191
-30
@@ -1,6 +1,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "dynstr.h"
|
||||
#include "log.h"
|
||||
#include "state.h"
|
||||
#include <ncurses.h>
|
||||
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
@@ -15,9 +17,13 @@ typedef struct {
|
||||
uint32_t x_offset;
|
||||
bool unsaved_changes;
|
||||
bool editmode;
|
||||
String_t* buffer;
|
||||
String_t* original;
|
||||
String_t filename;
|
||||
String_t* buffer;
|
||||
|
||||
// variables needed for the changelog functionality
|
||||
int original_len; // length of the original buffer
|
||||
String_t* original; // original buffer
|
||||
StateArray diff; // changelog
|
||||
} Editor;
|
||||
|
||||
void add_toolbar(Editor* self) {
|
||||
@@ -46,6 +52,23 @@ void add_toolbar(Editor* self) {
|
||||
attroff(COLOR_PAIR(1));
|
||||
}
|
||||
|
||||
void refresh_cursor(Editor* self) {
|
||||
|
||||
int max_x,max_y;
|
||||
getmaxyx(stdscr, max_y, max_x);
|
||||
|
||||
// Clamp cursor position to screen bounds
|
||||
int cursor_y = min(
|
||||
max(self->buffer_line - self->y_offset, 0),
|
||||
max_y - 1
|
||||
);
|
||||
int cursor_x = min(
|
||||
max(self->buffer_col - self->x_offset + 5, 5),
|
||||
max_x - 1
|
||||
);
|
||||
|
||||
move(cursor_y, cursor_x);
|
||||
}
|
||||
|
||||
void refresh_buffer(Editor* self) {
|
||||
move(0, 0);
|
||||
@@ -99,41 +122,42 @@ void refresh_buffer(Editor* self) {
|
||||
}
|
||||
|
||||
add_toolbar(self);
|
||||
refresh_cursor(self);
|
||||
}
|
||||
|
||||
// Ensure cursor position is valid
|
||||
int cursor_y = self->buffer_line - self->y_offset;
|
||||
int cursor_x = self->buffer_col - self->x_offset + 5;
|
||||
|
||||
// Clamp cursor position to screen bounds
|
||||
cursor_y = min(max(cursor_y, 0), max_y - 1);
|
||||
cursor_x = min(max(cursor_x, 5), max_x - 1);
|
||||
|
||||
move(cursor_y, cursor_x);
|
||||
}
|
||||
|
||||
void move_cursor_on_screen(Editor* editor, int x, int y) {
|
||||
void move_cursor_on_screen(Editor* self, int x, int y) {
|
||||
bool offset_changed = false;
|
||||
int max_x, max_y;
|
||||
|
||||
getmaxyx(stdscr, max_y, max_x);
|
||||
max_y--; // Reserve bottom line for toolbar
|
||||
max_x -= 5; // Account for line number margin
|
||||
|
||||
// Adjust x_offset if cursor would be off screen
|
||||
if (x + 5 >= max_x + editor->x_offset) {
|
||||
editor->x_offset = x - max_x + 6;
|
||||
// Adjust x_offset if cursor would be off screen
|
||||
if (x + 5 >= max_x + self->x_offset) {
|
||||
self->x_offset = x - max_x + 6;
|
||||
offset_changed = true;
|
||||
}
|
||||
if (x < editor->x_offset) {
|
||||
editor->x_offset = x;
|
||||
if (x < self->x_offset) {
|
||||
self->x_offset = x;
|
||||
offset_changed = true;
|
||||
}
|
||||
|
||||
// Adjust y_offset if cursor would be off screen
|
||||
if (y >= max_y + editor->y_offset) {
|
||||
editor->y_offset = y - max_y + 1;
|
||||
if (y >= max_y + self->y_offset) {
|
||||
self->y_offset = y - max_y + 1;
|
||||
offset_changed = true;
|
||||
}
|
||||
if (y < editor->y_offset) {
|
||||
editor->y_offset = y;
|
||||
if (y < self->y_offset) {
|
||||
self->y_offset = y;
|
||||
offset_changed = true;
|
||||
}
|
||||
if (offset_changed) {
|
||||
refresh_buffer(self);
|
||||
} else {
|
||||
refresh_cursor(self);
|
||||
}
|
||||
|
||||
refresh_buffer(editor);
|
||||
}
|
||||
|
||||
void switch_mode(Editor* self) {
|
||||
@@ -144,7 +168,7 @@ void switch_mode(Editor* self) {
|
||||
void newline(Editor* self) {
|
||||
move(self->buffer_line, 0);
|
||||
char line_no[6];
|
||||
snprintf(line_no, 6, "%-6d", self->buffer_line + 1);
|
||||
snprintf(line_no, 6, "%-5d", self->buffer_line + 1);
|
||||
|
||||
// add the line number
|
||||
attron(COLOR_PAIR(1));
|
||||
@@ -166,9 +190,13 @@ Editor editor_from(String_t input_string, String_t filename) {
|
||||
|
||||
int linenum = 0;
|
||||
e.buffer = str_lines(&input_string, &linenum);
|
||||
e.original = str_clone_all(e.buffer, linenum);
|
||||
e.lines = (uint32_t)linenum;
|
||||
e.original_len = linenum;
|
||||
e.capacity = e.lines;
|
||||
|
||||
e.diff = arr_init(e.lines);
|
||||
|
||||
str_dealloc(&input_string);
|
||||
|
||||
refresh_buffer(&e);
|
||||
@@ -179,22 +207,129 @@ Editor new_editor(String_t filename) {
|
||||
return editor_from(str_new(), filename);
|
||||
}
|
||||
|
||||
int print_diff(Editor* self) {
|
||||
|
||||
char buffer[512];
|
||||
String_t log_string = str_new();
|
||||
int original_offset;
|
||||
int modified_offset;
|
||||
|
||||
for (size_t i = 0; i < self->diff.size; i++) {
|
||||
LineState state = self->diff.data[i];
|
||||
switch (state) {
|
||||
// case UNMODIFIED:
|
||||
// original_offset = arr_original_offset(&self->diff, i);
|
||||
// snprintf(
|
||||
// buffer,
|
||||
// 512,
|
||||
// "UNMODIFIED %s \n",
|
||||
// to_chars(&self->buffer[original_offset + i])
|
||||
// );
|
||||
// str_push_str(&log_string, buffer);
|
||||
// break;
|
||||
|
||||
case MODIFIED:
|
||||
original_offset = arr_original_offset(&self->diff, i);
|
||||
modified_offset = arr_modified_offset(&self->diff, i);
|
||||
snprintf(
|
||||
buffer,
|
||||
512,
|
||||
"MODIFIED %-6d | %s\n -> %-6d | %s \n",
|
||||
original_offset + i + 1,
|
||||
to_chars(&self->original[original_offset + i]),
|
||||
modified_offset + i + 1,
|
||||
to_chars(&self->buffer[modified_offset + i])
|
||||
);
|
||||
str_push_str(&log_string, buffer);
|
||||
break;
|
||||
|
||||
case REMOVED:
|
||||
original_offset = arr_original_offset(&self->diff, i);
|
||||
snprintf(
|
||||
buffer,
|
||||
512,
|
||||
"REMOVED %-6d | %s \n",
|
||||
original_offset + i + 1,
|
||||
to_chars(&self->original[original_offset + i])
|
||||
);
|
||||
str_push_str(&log_string, buffer);
|
||||
break;
|
||||
|
||||
case ADDED:
|
||||
modified_offset = arr_modified_offset(&self->diff, i);
|
||||
snprintf(
|
||||
buffer,
|
||||
512,
|
||||
"ADDED %-6d | %s \n",
|
||||
modified_offset + i + 1,
|
||||
to_chars(&self->buffer[modified_offset + i])
|
||||
);
|
||||
str_push_str(&log_string, buffer);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (write_log(&log_string) == -1) {
|
||||
fprintf(stderr, "Error writing log\n");
|
||||
return -1;
|
||||
}
|
||||
str_dealloc(&log_string);
|
||||
}
|
||||
|
||||
int save_file(Editor* self) {
|
||||
String_t log_string = str_new();
|
||||
char log_message[64];
|
||||
char* name = to_chars(&self->filename);
|
||||
FILE* file = fopen(name, "w");
|
||||
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Error: Could not open file %s\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// writes the content line by line to the file
|
||||
FILE* file = fopen(name, "w");
|
||||
for (size_t i = 0; i < self->lines; i++) {
|
||||
if (str_to_file(&self->buffer[i], file) == -1) {
|
||||
|
||||
free(name);
|
||||
fprintf(stderr, "Error writing to file\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
arr_print(&self->diff);
|
||||
print_diff(self);
|
||||
|
||||
free(name);
|
||||
fclose(file);
|
||||
|
||||
for (size_t i = 0; i < self->original_len; i++) {
|
||||
str_dealloc(&self->original[i]);
|
||||
}
|
||||
free(self->original);
|
||||
self->original = str_clone_all(self->buffer, self->lines);
|
||||
|
||||
snprintf(log_message, 64, "Edited file [%s]\n", to_chars(&self->filename));
|
||||
str_push_str(&log_string, log_message);
|
||||
|
||||
self->original_len = self->lines;
|
||||
|
||||
snprintf(log_message, 64, "Old Length: [%d] New Length: [%d]\n", self->original_len, self->lines);
|
||||
str_push_str(&log_string, log_message);
|
||||
|
||||
// log messages
|
||||
if (write_log(&log_string) == -1) {
|
||||
fprintf(stderr, "Error writing log\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("wrote log");
|
||||
str_dealloc(&log_string);
|
||||
|
||||
arr_dealloc(&self->diff);
|
||||
self->diff = arr_init(self->lines);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -235,7 +370,6 @@ void delchar(Editor* self) {
|
||||
self->unsaved_changes = true;
|
||||
|
||||
if (self->buffer_col == str_len(&self->buffer[self->buffer_line])) {
|
||||
|
||||
if (self->buffer_line +1 == self->lines) {
|
||||
return;
|
||||
}
|
||||
@@ -245,7 +379,13 @@ void delchar(Editor* self) {
|
||||
String_t old_next_line = self->buffer[self->buffer_line + 1];
|
||||
|
||||
// assign the new line
|
||||
self->buffer[self->buffer_line] = str_merge(&self->buffer[self->buffer_line], &self->buffer[self->buffer_line + 1]);
|
||||
self->buffer[self->buffer_line] = str_merge(&old_curr_line, &old_next_line);
|
||||
|
||||
if (arr_get(&self->diff, self->buffer_line + 1) == ADDED) {
|
||||
arr_remove(&self->diff, self->buffer_line + 1);
|
||||
} else {
|
||||
arr_set(&self->diff, self->buffer_line + 1, REMOVED);
|
||||
}
|
||||
|
||||
// deallocate the memory for the old lines
|
||||
str_dealloc(&old_curr_line);
|
||||
@@ -261,6 +401,8 @@ void delchar(Editor* self) {
|
||||
refresh_buffer(self);
|
||||
} else {
|
||||
// removes the character from the current line
|
||||
arr_set(&self->diff, self->buffer_line, MODIFIED);
|
||||
|
||||
str_remove(&self->buffer[self->buffer_line], self->buffer_col);
|
||||
delch();
|
||||
}
|
||||
@@ -278,6 +420,9 @@ void pressed_enter(Editor* self) {
|
||||
}
|
||||
self->buffer = (String_t*)realloc(self->buffer, sizeof(String_t) * (self->capacity));
|
||||
|
||||
// logs the change of adding a new line
|
||||
arr_insert(&self->diff, self->buffer_line + 1, ADDED);
|
||||
|
||||
if (self->buffer_line == self->lines -1) {
|
||||
// if at end of file add an empty line
|
||||
self->buffer[self->lines - 1] = str_new();
|
||||
@@ -314,6 +459,12 @@ void addchar(Editor* self, char c) {
|
||||
|
||||
if (self->buffer_line == self->lines) {
|
||||
// if we are at the end of the file then we need to add a new line
|
||||
if (arr_get(&self->diff, self->buffer_line) == REMOVED) {
|
||||
arr_set(&self->diff, self->buffer_line, MODIFIED);
|
||||
} else {
|
||||
arr_insert(&self->diff, self->buffer_line, ADDED);
|
||||
}
|
||||
|
||||
newline(self);
|
||||
|
||||
// reallocate self->buffer to be 1 larger
|
||||
@@ -327,6 +478,10 @@ void addchar(Editor* self, char c) {
|
||||
|
||||
// allocate the memory space for the new line and add it to the buffer
|
||||
self->buffer[self->buffer_line] = str_new();
|
||||
} else {
|
||||
if (arr_get(&self->diff, self->buffer_line) == UNMODIFIED) {
|
||||
arr_set(&self->diff, self->buffer_line, MODIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
insch(c);
|
||||
@@ -339,6 +494,12 @@ void shutdown_editor(Editor* self) {
|
||||
for (size_t i = 0; i < self->capacity; i++) {
|
||||
str_dealloc(&self->buffer[i]);
|
||||
}
|
||||
str_dealloc(&self->filename);
|
||||
free(self->buffer);
|
||||
|
||||
for (size_t i = 0; i < self->original_len; i++) {
|
||||
str_dealloc(&self->original[i]);
|
||||
}
|
||||
free(self->original);
|
||||
|
||||
str_dealloc(&self->filename);
|
||||
}
|
||||
|
||||
+8
-3
@@ -1,4 +1,5 @@
|
||||
#include "dynstr.h"
|
||||
#include "state.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
@@ -6,7 +7,7 @@
|
||||
* cursor position, and various editor settings.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t lines;
|
||||
uint32_t lines;
|
||||
uint32_t capacity;
|
||||
uint32_t buffer_line;
|
||||
uint32_t buffer_col;
|
||||
@@ -14,9 +15,13 @@ typedef struct {
|
||||
uint32_t x_offset;
|
||||
bool unsaved_changes;
|
||||
bool editmode;
|
||||
String_t* buffer;
|
||||
String_t* original;
|
||||
String_t filename;
|
||||
String_t* buffer;
|
||||
|
||||
// variables needed for the changelog functionality
|
||||
int original_len; // length of the original buffer
|
||||
String_t* original; // original buffer
|
||||
StateArray diff; // changelog
|
||||
} Editor;
|
||||
|
||||
/**
|
||||
|
||||
+7
-3
@@ -1,14 +1,18 @@
|
||||
#include "dynstr.h"
|
||||
|
||||
|
||||
int write_log(String_t* string, int lines) {
|
||||
int write_log(String_t* string) {
|
||||
|
||||
FILE* file = fopen("log.txt", "a");
|
||||
int numlines;
|
||||
String_t* lines = str_lines(string, &numlines);
|
||||
|
||||
for (int i = 0; i < lines; i++) {
|
||||
str_to_file(&string[i], file);
|
||||
for (int i = 0; i < numlines; i++) {
|
||||
str_to_file(&lines[i], file);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -8,5 +8,5 @@
|
||||
* @return 0 on success, -1 on error
|
||||
* @note This function frees the string passed to it!
|
||||
*/
|
||||
int write_log(String_t* string, int lines);
|
||||
int write_log(String_t* string);
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
REMOVED 16 |
|
||||
REMOVED 17 |
|
||||
REMOVED 18 | modifie
|
||||
REMOVED 19 |
|
||||
REMOVED 20 |
|
||||
ADDED 35 | } AND modified a line.
|
||||
ADDED 36 |
|
||||
ADDED 37 |
|
||||
ADDED 38 | added some lines
|
||||
ADDED 39 |
|
||||
ADDED 40 |
|
||||
ADDED 41 |
|
||||
ADDED 42 |
|
||||
ADDED 43 |
|
||||
ADDED 44 |
|
||||
REMOVED 40 | } AND modified a line.
|
||||
REMOVED 41 |
|
||||
REMOVED 42 |
|
||||
REMOVED 43 | added some lines
|
||||
REMOVED 44 |
|
||||
REMOVED 45 |
|
||||
REMOVED 46 |
|
||||
REMOVED 47 |
|
||||
REMOVED 48 |
|
||||
REMOVED 49 |
|
||||
REMOVED 50 |
|
||||
REMOVED 51 |
|
||||
+3
-2
@@ -211,7 +211,7 @@ int main(int argc, char* argv[]) {
|
||||
if (argc == 3) {
|
||||
switch (cmd) {
|
||||
case CMD_OPEN:
|
||||
sprintf(log_fmt_string, "Edited File [%s]", argv[2]);
|
||||
sprintf(log_fmt_string, "Opened File [%s]", argv[2]);
|
||||
open_editor(argv[2]);
|
||||
break;
|
||||
case CMD_RM:
|
||||
@@ -263,7 +263,8 @@ int main(int argc, char* argv[]) {
|
||||
// log output of command
|
||||
if (log_fmt_string[0] != '\0') {
|
||||
String_t str = str_from_chars(log_fmt_string);
|
||||
write_log(&str, 1);
|
||||
write_log(&str);
|
||||
str_dealloc(&str);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
/// dynamic array class
|
||||
/// written by: Harry Irving
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum LineState {
|
||||
UNMODIFIED,
|
||||
MODIFIED,
|
||||
ADDED,
|
||||
REMOVED,
|
||||
} LineState;
|
||||
|
||||
typedef struct {
|
||||
uint32_t size; // Current number of elements
|
||||
uint32_t capacity; // Total capacity allocated
|
||||
LineState* data; // Array of LineState values
|
||||
} StateArray;
|
||||
|
||||
StateArray arr_init(int capacity) {
|
||||
StateArray arr;
|
||||
arr.size = capacity;
|
||||
arr.capacity = capacity;
|
||||
arr.data = (LineState*)calloc(capacity, sizeof(LineState));
|
||||
// Initialize all elements to UNMODIFIED
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
arr.data[i] = UNMODIFIED;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
void arr_print(StateArray* self) {
|
||||
FILE* log_file = fopen("diff.txt", "w");
|
||||
if (log_file == NULL) {
|
||||
fprintf(stderr, "Error: Could not open log file\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < self->size; i++) {
|
||||
switch (self->data[i]) {
|
||||
case UNMODIFIED:
|
||||
fwrite("UNMODIFIED\n", sizeof(char), strlen("UNMODIFIED\n"), log_file);
|
||||
break;
|
||||
case MODIFIED:
|
||||
fwrite("MODIFIED\n", sizeof(char), strlen("MODIFIED\n"), log_file);
|
||||
break;
|
||||
case ADDED:
|
||||
fwrite("ADDED\n", sizeof(char), strlen("ADDED\n"), log_file);
|
||||
break;
|
||||
case REMOVED:
|
||||
fwrite("REMOVED\n", sizeof(char), strlen("REMOVED\n"), log_file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(log_file);
|
||||
}
|
||||
|
||||
int arr_added_or_removed_before(StateArray* self, int index) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < index; i++) {
|
||||
if (self->data[i] == ADDED || self->data[i] == REMOVED) {
|
||||
if (self->data[i] == REMOVED) {
|
||||
index++;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void arr_set(StateArray* self, int index, LineState state) {
|
||||
int offset = arr_added_or_removed_before(self, index);
|
||||
self->data[index] = state;
|
||||
}
|
||||
|
||||
LineState arr_remove(StateArray* self, int index) {
|
||||
int offset = arr_added_or_removed_before(self, index);
|
||||
|
||||
if (index >= self->size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
LineState removed = self->data[index];
|
||||
|
||||
// Shift remaining elements left
|
||||
for (int i = index; i < self->size - 1; i++) {
|
||||
self->data[i] = self->data[i + 1];
|
||||
}
|
||||
self->size--;
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
int arr_insert(StateArray* self, int index, LineState state) {
|
||||
int offset = arr_added_or_removed_before(self, index);
|
||||
|
||||
if (index > self->size) {
|
||||
return -1;
|
||||
}
|
||||
self->size++;
|
||||
|
||||
// Grow array if needed
|
||||
if (self->size > self->capacity) {
|
||||
self->capacity = (self->size) * sizeof(LineState);
|
||||
self->data = (LineState*)realloc(self->data, self->capacity * sizeof(LineState));
|
||||
}
|
||||
|
||||
// Shift elements right to make room
|
||||
for (int i = self->size - 1; i > index; i--) {
|
||||
self->data[i] = self->data[i - 1];
|
||||
}
|
||||
self->data[index] = state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LineState arr_get(StateArray* self, int index) {
|
||||
int offset = arr_added_or_removed_before(self, index);
|
||||
return self->data[index];
|
||||
}
|
||||
|
||||
int arr_original_offset(StateArray* self, int index) {
|
||||
int offset = 0;
|
||||
for (int i = 0; i < index; i++) {
|
||||
if (self->data[i] == ADDED) {
|
||||
offset--;
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
int arr_modified_offset(StateArray* self, int index) {
|
||||
int offset = 0;
|
||||
for (int i = 0; i < index; i++) {
|
||||
if (self->data[i] == REMOVED) {
|
||||
offset--;
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
int arr_dealloc(StateArray* self) {
|
||||
free(self->data);
|
||||
self->data = NULL;
|
||||
self->size = 0;
|
||||
self->capacity = 0;
|
||||
return 0;
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
#ifndef STATEARR_H
|
||||
#define STATEARR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum LineState {
|
||||
UNMODIFIED,
|
||||
MODIFIED,
|
||||
ADDED,
|
||||
REMOVED,
|
||||
} LineState;
|
||||
|
||||
/**
|
||||
* Dynamic array structure for storing LineState values
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t size; // Current number of elements
|
||||
uint32_t capacity; // Total capacity allocated
|
||||
LineState* data; // Array of LineState values
|
||||
} StateArray;
|
||||
|
||||
void arr_print(StateArray* self);
|
||||
|
||||
/**
|
||||
* Creates a new StateArray with the specified initial capacity
|
||||
*
|
||||
* All elements will have a default value of UNMODIFIED
|
||||
*
|
||||
* @param capacity Initial capacity in number of elements
|
||||
* @return A new StateArray structure with allocated memory
|
||||
*/
|
||||
StateArray arr_init(int capacity);
|
||||
|
||||
/**
|
||||
* Sets a LineState value at the specified index
|
||||
* Does not perform bounds checking
|
||||
*
|
||||
* @param self Pointer to the StateArray to modify
|
||||
* @param index Position to set the value
|
||||
* @param state The LineState value to set
|
||||
*/
|
||||
void arr_set(StateArray* self, int index, LineState state);
|
||||
|
||||
/**
|
||||
* Removes a LineState value at the specified index
|
||||
* Shifts remaining elements left to fill the gap
|
||||
*
|
||||
* @param self Pointer to the StateArray to modify
|
||||
* @param index Position of value to remove
|
||||
* @return The LineState value that was removed
|
||||
*/
|
||||
LineState arr_remove(StateArray* self, int index);
|
||||
|
||||
/**
|
||||
* Inserts a LineState value at the specified index
|
||||
* Shifts existing elements right to make room
|
||||
* Automatically reallocates if more capacity is needed
|
||||
*
|
||||
* @param self Pointer to the StateArray to modify
|
||||
* @param index Position to insert the value
|
||||
* @param state The LineState value to insert
|
||||
* @return 0 on success, -1 if index is out of bounds
|
||||
*/
|
||||
int arr_insert(StateArray* self, int index, LineState state);
|
||||
|
||||
/**
|
||||
* Gets the LineState value at the specified index
|
||||
* Does not perform bounds checking
|
||||
*
|
||||
* @param self Pointer to the StateArray to read from
|
||||
* @param index Position to get the value from
|
||||
* @return The LineState value at the specified index
|
||||
*/
|
||||
LineState arr_get(StateArray* self, int index);
|
||||
|
||||
/**
|
||||
* Deallocates memory used by the StateArray
|
||||
* Must be called when the array is no longer needed
|
||||
*
|
||||
* @param self Pointer to the StateArray to deallocate
|
||||
* @return 0 on success
|
||||
*/
|
||||
int arr_dealloc(StateArray* self);
|
||||
|
||||
/**
|
||||
* Calculates the offset needed to map from state array index to original buffer index
|
||||
* by counting ADDED lines before the given index
|
||||
*
|
||||
* @param self Pointer to the StateArray
|
||||
* @param index The index in the state array
|
||||
* @return The negative offset (number of ADDED lines before index)
|
||||
*/
|
||||
int arr_original_offset(StateArray* self, int index);
|
||||
|
||||
/**
|
||||
* Calculates the offset needed to map from state array index to modified buffer index
|
||||
* by counting REMOVED lines before the given index
|
||||
*
|
||||
* @param self Pointer to the StateArray
|
||||
* @param index The index in the state array
|
||||
* @return The negative offset (number of REMOVED lines before index)
|
||||
*/
|
||||
int arr_modified_offset(StateArray* self, int index);
|
||||
|
||||
/**
|
||||
* Counts the number of lines that have been either added or removed
|
||||
* Does not count lines that have been modified
|
||||
*
|
||||
* @param self Pointer to the StateArray to analyze
|
||||
* @param index The index to count up to.
|
||||
* @return The count of lines marked as either ADDED or REMOVED
|
||||
*/
|
||||
int arr_added_or_removed_before(StateArray* self, int index);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user