added documentation, almost done with code
This commit is contained in:
+78
-77
@@ -7,36 +7,35 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
typedef struct String {
|
||||
uint32_t size, capacity;
|
||||
char* data;
|
||||
} String_t;
|
||||
|
||||
String_t str_with_capacity(int capacity) {
|
||||
String_t s;
|
||||
|
||||
/// allocate memory for 'capacity' chars
|
||||
s.data = (char*)calloc(capacity, sizeof(char));
|
||||
|
||||
s.size = 0;
|
||||
s.capacity = capacity;
|
||||
|
||||
return s;
|
||||
int str_len(String_t* s) {
|
||||
return (int)s->size;
|
||||
}
|
||||
|
||||
String_t str_from_chars(const char* string) {
|
||||
String_t s;
|
||||
char* to_chars(String_t* s) {
|
||||
// allocate buffer with null terminator
|
||||
char* buffer = (char*)calloc(s->size + 1, sizeof(char));
|
||||
for (int i = 0; i < s->size; i++) {
|
||||
buffer[i] = s->data[i];
|
||||
}
|
||||
buffer[s->size] = '\0';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
s.data = (char*)calloc(strlen(string), sizeof(char));
|
||||
strcpy(s.data, string);
|
||||
s.size = strlen(string);
|
||||
s.capacity = strlen(string);
|
||||
String_t str_with_capacity(int capacity) {
|
||||
String_t s;
|
||||
s.data = (char*)calloc(capacity, sizeof(char));
|
||||
s.size = 0;
|
||||
s.capacity = capacity;
|
||||
return s;
|
||||
}
|
||||
|
||||
String_t str_from_slice(const char* string, int len) {
|
||||
String_t s;
|
||||
|
||||
s.data = (char*)calloc(len, sizeof(char));
|
||||
strncpy(s.data, string, len);
|
||||
s.size = len;
|
||||
@@ -44,27 +43,26 @@ String_t str_from_slice(const char* string, int len) {
|
||||
return s;
|
||||
}
|
||||
|
||||
String_t str_from_chars(const char* string) {
|
||||
return str_from_slice(string, strlen(string));
|
||||
}
|
||||
|
||||
String_t str_new() {
|
||||
return str_with_capacity(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int str_dealloc(String_t* self) {
|
||||
free(self->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int str_push(String_t* self, char c) {
|
||||
// check size < capacity
|
||||
if (self->size < self->capacity) {
|
||||
self->data[self->size] = c;
|
||||
self->size++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// reallocate to add capacity for an extra char
|
||||
int newcap = self->capacity + sizeof(char);
|
||||
self->data = (char*)realloc(self->data, newcap);
|
||||
self->data[self->size] = c;
|
||||
@@ -77,39 +75,55 @@ int str_push_str(String_t* self, char* c) {
|
||||
if (self->size + strlen(c) >= self->capacity) {
|
||||
self->capacity = (self->size + strlen(c)) * sizeof(char);
|
||||
self->data = (char*)realloc(self->data, self->capacity);
|
||||
|
||||
}
|
||||
for (int i = 0; i < strlen(c); i++) {
|
||||
self->data[self->size + i] = c[i];
|
||||
}
|
||||
self->size = self->capacity;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
String_t str_from_file(FILE* file) {
|
||||
if (file == NULL) {
|
||||
return str_new();
|
||||
}
|
||||
|
||||
char buffer[64];
|
||||
|
||||
String_t string = str_new();
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), file) != NULL) {
|
||||
str_push_str(&string, buffer);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
int str_to_file(String_t* self, FILE* file) {
|
||||
char* data = to_chars(self);
|
||||
|
||||
if (fprintf(file, "%s\n", data) == -1) {
|
||||
free(data);
|
||||
return -1;
|
||||
}
|
||||
free(data);
|
||||
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);
|
||||
memcpy(clone.data, self->data, clone.capacity);
|
||||
return clone;
|
||||
}
|
||||
|
||||
char str_pop(String_t* self) {
|
||||
if (self->size == 0) {
|
||||
return '\0';
|
||||
}
|
||||
self->size--;
|
||||
char c = self->data[self->size];
|
||||
return c;
|
||||
return self->data[self->size];
|
||||
}
|
||||
|
||||
int str_insert(String_t* self, int index, char c) {
|
||||
@@ -117,6 +131,10 @@ int str_insert(String_t* self, int index, char c) {
|
||||
return -1;
|
||||
}
|
||||
self->size++;
|
||||
if (self->size > self->capacity) {
|
||||
self->capacity = (self->size) * sizeof(char);
|
||||
self->data = (char*)realloc(self->data, self->capacity);
|
||||
}
|
||||
for (int i = self->size - 1; i > index; i--) {
|
||||
self->data[i] = self->data[i - 1];
|
||||
}
|
||||
@@ -135,22 +153,16 @@ int str_remove(String_t* self, int index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// splits a string into an array of strings based on a delimiter
|
||||
String_t* str_split(String_t* self, int* res_len, char c) {
|
||||
|
||||
char* string = self->data;
|
||||
String_t* elements = NULL;
|
||||
|
||||
// find the number of lines in the file
|
||||
|
||||
bool flag = false;
|
||||
*res_len = 0;
|
||||
for (int i = 0; i < strlen(string); i++) {
|
||||
|
||||
// Count number of splits
|
||||
for (int i = 0; i < self->size; i++) {
|
||||
if (string[i] == c) {
|
||||
// if (flag) { // this condition was here so that empty strings would be ignore
|
||||
(*res_len)++;
|
||||
flag = false;
|
||||
// }
|
||||
} else {
|
||||
flag = true;
|
||||
}
|
||||
@@ -159,20 +171,17 @@ String_t* str_split(String_t* self, int* res_len, char c) {
|
||||
(*res_len)++;
|
||||
}
|
||||
|
||||
// allocate memory for an array of pointers to each line
|
||||
elements = (String_t*)malloc((*res_len) * sizeof(String_t));
|
||||
|
||||
String_t* elements = (String_t*)malloc((*res_len) * sizeof(String_t));
|
||||
int i = 0;
|
||||
flag = false;
|
||||
char* start = string;
|
||||
char* end = string;
|
||||
char* string_end = string + self->size;
|
||||
|
||||
while (*end != '\0') {
|
||||
while (end < string_end) {
|
||||
if (*end == c) {
|
||||
// if (flag) {
|
||||
elements[i] = str_from_slice(start, end - start);
|
||||
i++;
|
||||
// }
|
||||
end++;
|
||||
start = end;
|
||||
flag = false;
|
||||
@@ -180,12 +189,10 @@ String_t* str_split(String_t* self, int* res_len, char c) {
|
||||
end++;
|
||||
flag = true;
|
||||
}
|
||||
} if (flag) {
|
||||
}
|
||||
if (flag) {
|
||||
elements[i] = str_from_slice(start, end - start);
|
||||
}
|
||||
|
||||
|
||||
// returns an array of String_t
|
||||
return elements;
|
||||
}
|
||||
|
||||
@@ -209,38 +216,32 @@ String_t* str_lines(String_t* self, int* numlines) {
|
||||
|
||||
String_t str_slice(String_t* s, int start, int end) {
|
||||
String_t s2;
|
||||
|
||||
if (start < 0) start = 0;
|
||||
if (end > s->size) end = s->size;
|
||||
|
||||
// if the range is invalid, we return an empty string
|
||||
if (start >= end || start >= s->size) {
|
||||
s2.size = 0;
|
||||
s2.capacity = 1;
|
||||
s2.data = (char*)calloc(1, sizeof(char));
|
||||
return s2;
|
||||
}
|
||||
|
||||
s2.size = end - start;
|
||||
s2.capacity = s2.size;
|
||||
|
||||
s2.data = (char*)calloc(s2.size, sizeof(char));
|
||||
|
||||
// if the allocation fails we return a zero sized string
|
||||
if (s2.data == NULL) {
|
||||
s2.size = 0;
|
||||
s2.capacity = 0;
|
||||
return s2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < s2.size; i++) {
|
||||
s2.data[i] = s->data[start + i];
|
||||
}
|
||||
return s2;
|
||||
}
|
||||
|
||||
int str_len(String_t* s) {
|
||||
return s->size;
|
||||
}
|
||||
|
||||
char* to_chars(String_t* s) {
|
||||
return s->data;
|
||||
}
|
||||
|
||||
// int main() {
|
||||
// String_t s = str_from_chars("hello\nworld\neeeee\notherline\n");
|
||||
|
||||
// str_remove(&s, 10);
|
||||
// str_insert(&s, 10, 'h');
|
||||
|
||||
// printf("%s\n", to_chars(&s));
|
||||
|
||||
// int linen = 0;
|
||||
// String_t* lines = str_lines(&s, &linen);
|
||||
// for (int i=0; i < linen; i++) {
|
||||
// printf("%s", to_chars(&lines[i]));
|
||||
// }
|
||||
|
||||
// str_dealloc(&s);
|
||||
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
+161
-14
@@ -2,44 +2,191 @@
|
||||
#define DYNSTR_H
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
int capacity;
|
||||
/**
|
||||
* Custom String type that stores an array of characters
|
||||
*/
|
||||
typedef struct String {
|
||||
uint32_t size, capacity;
|
||||
char* data;
|
||||
} String_t;
|
||||
|
||||
/**
|
||||
* Creates a new string with the specified initial capacity.
|
||||
* The string will be empty but can hold up to capacity characters
|
||||
* without requiring reallocation.
|
||||
*
|
||||
* @param capacity Initial capacity in bytes
|
||||
* @return A new String_t structure with allocated memory
|
||||
*/
|
||||
String_t str_with_capacity(int capacity);
|
||||
|
||||
/**
|
||||
* Creates a new string from a null-terminated character array.
|
||||
*
|
||||
* @param string Null-terminated source string
|
||||
* @return A new String_t containing a copy of the input string
|
||||
*/
|
||||
String_t str_from_chars(char* string);
|
||||
|
||||
/**
|
||||
* Creates a new string from a character array slice.
|
||||
* Allocates new memory and copies the specified number of characters.
|
||||
*
|
||||
* @param string Source character array
|
||||
* @param len Number of characters to copy
|
||||
* @return A new String_t containing the copied characters
|
||||
*/
|
||||
String_t str_from_slice(char* string, int len);
|
||||
|
||||
/**
|
||||
* Merges two strings into a new string.
|
||||
* The resulting string contains s1's contents followed by s2's contents.
|
||||
*
|
||||
* @param s1 Pointer to the first String_t
|
||||
* @param s2 Pointer to the second String_t
|
||||
* @return A new String_t containing the merged contents
|
||||
*/
|
||||
String_t str_merge(String_t* s1, String_t* s2);
|
||||
|
||||
/**
|
||||
* Creates a new string by reading from a file.
|
||||
* Reads the file line by line and concatenates all lines.
|
||||
*
|
||||
* @param file Pointer to an open FILE
|
||||
* @return A new String_t containing the file's contents
|
||||
*/
|
||||
String_t str_from_file(FILE* file);
|
||||
|
||||
int str_push_str(String_t* string, char* other);
|
||||
|
||||
/**
|
||||
* Creates a new empty string with minimal capacity.
|
||||
*
|
||||
* @return A new empty String_t with capacity of 1 byte
|
||||
*/
|
||||
String_t str_new();
|
||||
|
||||
String_t* str_lines(String_t* self, int* numlines);
|
||||
/**
|
||||
* Returns a clone of the string.
|
||||
* This allocates new memory that must be freed
|
||||
* @param self Pointer to the String_t to clone
|
||||
*/
|
||||
String_t str_clone();
|
||||
|
||||
/**
|
||||
* Creates a new string containing a slice of an existing string.
|
||||
* The slice includes characters from start index up to (but not including) end index.
|
||||
*
|
||||
* @param s Pointer to the source String_t
|
||||
* @param start Starting index (inclusive)
|
||||
* @param end Ending index (exclusive)
|
||||
* @return A new String_t containing the specified slice
|
||||
*/
|
||||
String_t str_slice(String_t* s, int start, int end);
|
||||
|
||||
// String_t* str_split(String_t* self, int* res_len, char c);
|
||||
/**
|
||||
* Splits a string into lines based on newline characters.
|
||||
* Convenience wrapper around str_split that uses '\n' as delimiter.
|
||||
*
|
||||
* @param self Pointer to the String_t to split
|
||||
* @param numlines Pointer to store the number of resulting lines
|
||||
* @return Array of String_t structures, one per line
|
||||
*/
|
||||
String_t* str_lines(String_t* self, int* numlines);
|
||||
|
||||
void str_push(String_t* s, char c);
|
||||
/**
|
||||
* Splits a string into an array of strings based on a delimiter.
|
||||
* Each occurrence of the delimiter creates a new string.
|
||||
*
|
||||
* @param self Pointer to the String_t to split
|
||||
* @param res_len Pointer to store the number of resulting strings
|
||||
* @param c Delimiter character
|
||||
* @return Array of String_t structures, must be freed by caller
|
||||
*/
|
||||
String_t* str_split(String_t* self, int* res_len, char c);
|
||||
|
||||
/**
|
||||
* Removes and returns the last character in the string.
|
||||
*
|
||||
* @param self Pointer to the String_t to modify
|
||||
* @return The removed character, or '\0' if string is empty
|
||||
*/
|
||||
char str_pop(String_t* s);
|
||||
|
||||
void str_insert(String_t* s, int index, char c);
|
||||
|
||||
void str_remove(String_t* s, int index);
|
||||
|
||||
int str_dealloc(String_t* s);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the underlying character array.
|
||||
* Note: The returned pointer is still owned by the String_t structure.
|
||||
*
|
||||
* @param s Pointer to the String_t structure
|
||||
* @return Pointer to the null-terminated character array
|
||||
*/
|
||||
char* to_chars(String_t* s);
|
||||
|
||||
/**
|
||||
* Writes the string's contents to a file.
|
||||
* Appends a newline character after writing the string.
|
||||
*
|
||||
* @param self Pointer to the String_t to write
|
||||
* @param file Pointer to an open FILE
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int str_to_file(String_t* self, FILE* file);
|
||||
|
||||
/**
|
||||
* Appends a null-terminated string to the end of the string.
|
||||
* Automatically reallocates if more capacity is needed.
|
||||
*
|
||||
* @param self Pointer to the String_t to modify
|
||||
* @param c Null-terminated string to append
|
||||
* @return 0 on success
|
||||
*/
|
||||
int str_push_str(String_t* string, char* other);
|
||||
|
||||
/**
|
||||
* Deallocates the memory used by a string.
|
||||
* Must be called when the string is no longer needed to prevent memory leaks.
|
||||
*
|
||||
* @param self Pointer to the String_t to deallocate
|
||||
* @return 0 on success
|
||||
*/
|
||||
int str_dealloc(String_t* s);
|
||||
|
||||
/**
|
||||
* Returns the current length of the string.
|
||||
*
|
||||
* @param s Pointer to the String_t structure
|
||||
* @return The number of characters in the string
|
||||
*/
|
||||
int str_len(String_t* s);
|
||||
|
||||
/**
|
||||
* Inserts a character at the specified index.
|
||||
* Shifts existing characters right to make room.
|
||||
* Automatically reallocates if more capacity is needed.
|
||||
*
|
||||
* @param self Pointer to the String_t to modify
|
||||
* @param index Position to insert the character
|
||||
* @param c Character to insert
|
||||
* @return 0 on success, -1 if index is out of bounds
|
||||
*/
|
||||
void str_insert(String_t* s, int index, char c);
|
||||
|
||||
/**
|
||||
* Removes the character at the specified index.
|
||||
* Shifts remaining characters left to fill the gap.
|
||||
*
|
||||
* @param self Pointer to the String_t to modify
|
||||
* @param index Position of character to remove
|
||||
* @return 0 on success, -1 if index is out of bounds
|
||||
*/
|
||||
void str_remove(String_t* s, int index);
|
||||
|
||||
/**
|
||||
* Appends a single character to the end of the string.
|
||||
* Automatically reallocates if more capacity is needed.
|
||||
*
|
||||
* @param self Pointer to the String_t to modify
|
||||
* @param c Character to append
|
||||
* @return 0 on success
|
||||
*/
|
||||
void str_push(String_t* s, char c);
|
||||
|
||||
#endif
|
||||
|
||||
+125
-52
@@ -3,8 +3,12 @@
|
||||
#include "dynstr.h"
|
||||
#include <ncurses.h>
|
||||
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
typedef struct {
|
||||
uint32_t lines;
|
||||
uint32_t capacity;
|
||||
uint32_t buffer_line;
|
||||
uint32_t buffer_col;
|
||||
uint32_t y_offset;
|
||||
@@ -12,6 +16,8 @@ typedef struct {
|
||||
bool unsaved_changes;
|
||||
bool editmode;
|
||||
String_t* buffer;
|
||||
String_t* original;
|
||||
String_t filename;
|
||||
} Editor;
|
||||
|
||||
void add_toolbar(Editor* self) {
|
||||
@@ -22,7 +28,7 @@ void add_toolbar(Editor* self) {
|
||||
|
||||
// add an entry for the current mode
|
||||
move(max_y - 1, 0);
|
||||
char mode[8];
|
||||
char mode[9];
|
||||
snprintf(mode, 9, "[%6s]", self->editmode ? "Insert" : "Normal");
|
||||
addstr(mode);
|
||||
|
||||
@@ -40,82 +46,96 @@ void add_toolbar(Editor* self) {
|
||||
attroff(COLOR_PAIR(1));
|
||||
}
|
||||
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
void refresh_buffer(Editor* self) {
|
||||
|
||||
move(0, 0);
|
||||
|
||||
clear();
|
||||
|
||||
// get the screen size so we can figure out where to place characters
|
||||
int max_x, max_y;
|
||||
getmaxyx(stdscr, max_y, max_x);
|
||||
max_y--; // Reserve bottom line for toolbar
|
||||
|
||||
// Ensure y_offset is valid
|
||||
if (self->buffer_line >= self->y_offset + max_y) {
|
||||
self->y_offset = self->buffer_line - max_y + 1;
|
||||
}
|
||||
if (self->buffer_line < self->y_offset) {
|
||||
self->y_offset = self->buffer_line;
|
||||
}
|
||||
|
||||
// Display visible lines
|
||||
for (size_t i = self->y_offset; i < self->lines && i < self->y_offset + max_y; i++) {
|
||||
// adding the line number
|
||||
move(i - self->y_offset, 0);
|
||||
|
||||
// adding the line number
|
||||
attron(COLOR_PAIR(1));
|
||||
char line_no[6];
|
||||
snprintf(line_no, 6, "%-6d", i + 1);
|
||||
snprintf(line_no, 6, "%-4d]", i + 1);
|
||||
addstr(line_no);
|
||||
attroff(COLOR_PAIR(1));
|
||||
|
||||
// refreshing the text for the line
|
||||
// Only try to display the line if it's within bounds
|
||||
if (i < self->lines) {
|
||||
// Calculate visible portion of line
|
||||
int visible_start = self->x_offset;
|
||||
int line_len = str_len(&self->buffer[i]);
|
||||
int visible_end = min(line_len, self->x_offset + max_x - 5);
|
||||
|
||||
if (visible_start < line_len) {
|
||||
String_t line_segment = str_slice(
|
||||
&self->buffer[i],
|
||||
self->x_offset,
|
||||
min(str_len(&self->buffer[i]), self->x_offset + max_x - 5)
|
||||
visible_start,
|
||||
visible_end
|
||||
);
|
||||
|
||||
addstr(to_chars(&line_segment));
|
||||
str_dealloc(&line_segment);
|
||||
char* data = to_chars(&line_segment);
|
||||
|
||||
addstr("\n");
|
||||
addstr(data);
|
||||
str_dealloc(&line_segment);
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add_toolbar(self);
|
||||
|
||||
move(self->buffer_line - self->y_offset, self->buffer_col + 5 - self->x_offset);
|
||||
// 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) {
|
||||
add_toolbar(editor);
|
||||
|
||||
int newx = x + 5; // account for the line number
|
||||
|
||||
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
|
||||
|
||||
bool flag = false;
|
||||
|
||||
while (newx + 3 > max_x + editor->x_offset) {
|
||||
editor->x_offset += 1;
|
||||
flag = true;
|
||||
// Adjust x_offset if cursor would be off screen
|
||||
if (x + 5 >= max_x + editor->x_offset) {
|
||||
editor->x_offset = x - max_x + 6;
|
||||
}
|
||||
if (x < editor->x_offset) {
|
||||
editor->x_offset = x;
|
||||
}
|
||||
|
||||
while (newx - 3 < editor->x_offset) {
|
||||
editor->x_offset -= 1;
|
||||
flag = 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 < editor->y_offset) {
|
||||
editor->y_offset = y;
|
||||
}
|
||||
|
||||
while (y + 3 > max_y + editor->y_offset) {
|
||||
editor->y_offset += 1;
|
||||
flag = true;
|
||||
}
|
||||
|
||||
while (y - 3 < editor->y_offset) {
|
||||
editor->y_offset -= 1;
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
refresh_buffer(editor);
|
||||
}
|
||||
|
||||
move(y - editor->y_offset, newx - editor->x_offset);
|
||||
}
|
||||
|
||||
void switch_mode(Editor* self) {
|
||||
self->editmode = !self->editmode;
|
||||
refresh_buffer(self);
|
||||
@@ -125,7 +145,6 @@ void newline(Editor* self) {
|
||||
move(self->buffer_line, 0);
|
||||
char line_no[6];
|
||||
snprintf(line_no, 6, "%-6d", self->buffer_line + 1);
|
||||
fprintf(stderr, "ln: %d, col: %d", self->buffer_line, self->buffer_col);
|
||||
|
||||
// add the line number
|
||||
attron(COLOR_PAIR(1));
|
||||
@@ -134,7 +153,7 @@ void newline(Editor* self) {
|
||||
move_cursor_on_screen(self, self->buffer_col, self->buffer_line);
|
||||
}
|
||||
|
||||
Editor editor_from(String_t input_string) {
|
||||
Editor editor_from(String_t input_string, String_t filename) {
|
||||
Editor e;
|
||||
e.lines = 0;
|
||||
e.buffer_line = 0;
|
||||
@@ -143,24 +162,46 @@ Editor editor_from(String_t input_string) {
|
||||
e.x_offset = 0;
|
||||
e.editmode = false;
|
||||
e.unsaved_changes = false;
|
||||
e.filename = filename;
|
||||
|
||||
int linenum = 0;
|
||||
e.buffer = str_lines(&input_string, &linenum);
|
||||
e.lines = (size_t)linenum;
|
||||
e.lines = (uint32_t)linenum;
|
||||
e.capacity = e.lines;
|
||||
|
||||
str_dealloc(&input_string);
|
||||
|
||||
refresh_buffer(&e);
|
||||
return e;
|
||||
}
|
||||
|
||||
Editor new_editor() {
|
||||
return editor_from(str_new());
|
||||
Editor new_editor(String_t filename) {
|
||||
return editor_from(str_new(), filename);
|
||||
}
|
||||
|
||||
int save_file(Editor* self) {
|
||||
char* name = to_chars(&self->filename);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
free(name);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void move_cursor(Editor* self, int x, int y) {
|
||||
if (y != 0
|
||||
&& (int)(self->buffer_line) + y >= 0
|
||||
&& self->buffer_line + y <= self->lines)
|
||||
&& self->buffer_line + y < self->lines)
|
||||
{
|
||||
// move the cursor up or down
|
||||
self->buffer_line += y;
|
||||
@@ -174,17 +215,19 @@ void move_cursor(Editor* self, int x, int y) {
|
||||
self->buffer_line -= 1;
|
||||
self->buffer_col = str_len(&self->buffer[self->buffer_line]);
|
||||
}
|
||||
} else if (self->buffer_col + x > str_len(&self->buffer[self->buffer_line])) {
|
||||
} else if (x != 0 && self->buffer_line < self->lines) {
|
||||
int line_width = str_len(&self->buffer[self->buffer_line]);
|
||||
if (self->buffer_col + x > line_width) {
|
||||
// moving the cursor off the right hand side of the line
|
||||
if (self->buffer_line < self->lines) {
|
||||
if (self->buffer_line + 1 < self->lines) {
|
||||
self->buffer_col = 0;
|
||||
self->buffer_line += 1;
|
||||
}
|
||||
} else if (x != 0) {
|
||||
} else {
|
||||
// moving the cursor left or right in any other case
|
||||
self->buffer_col += x;
|
||||
}
|
||||
fprintf(stderr, "ln: %d, col: %d xoff: %d yoff: %d\n", self->buffer_line, self->buffer_col, self->x_offset, self->y_offset);
|
||||
}
|
||||
move_cursor_on_screen(self, self->buffer_col, self->buffer_line);
|
||||
}
|
||||
|
||||
@@ -197,12 +240,22 @@ void delchar(Editor* self) {
|
||||
return;
|
||||
}
|
||||
|
||||
// obtain string objects that reference the old lines.
|
||||
String_t old_curr_line = self->buffer[self->buffer_line];
|
||||
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]);
|
||||
|
||||
// deallocate the memory for the old lines
|
||||
str_dealloc(&old_curr_line);
|
||||
str_dealloc(&old_next_line);
|
||||
|
||||
for (size_t i = self->buffer_line + 2; i < self->lines; i++) {
|
||||
self->buffer[i - 1] = self->buffer[i];
|
||||
}
|
||||
|
||||
// replace the last line
|
||||
self->buffer[self->lines - 1] = str_new();
|
||||
self->lines--;
|
||||
refresh_buffer(self);
|
||||
@@ -219,7 +272,11 @@ void pressed_enter(Editor* self) {
|
||||
|
||||
// allocate memory immediately since we know a new line is being added
|
||||
self->lines++;
|
||||
self->buffer = realloc(self->buffer, sizeof(String_t) * (self->lines));
|
||||
|
||||
while (self->lines > self->capacity) {
|
||||
self->capacity++;
|
||||
}
|
||||
self->buffer = (String_t*)realloc(self->buffer, sizeof(String_t) * (self->capacity));
|
||||
|
||||
if (self->buffer_line == self->lines -1) {
|
||||
// if at end of file add an empty line
|
||||
@@ -230,6 +287,8 @@ void pressed_enter(Editor* self) {
|
||||
self->buffer[i] = self->buffer[i - 1];
|
||||
}
|
||||
|
||||
String_t old_line = self->buffer[self->buffer_line];
|
||||
|
||||
self->buffer[self->buffer_line + 1] = str_slice(
|
||||
&self->buffer[self->buffer_line],
|
||||
self->buffer_col,
|
||||
@@ -241,6 +300,8 @@ void pressed_enter(Editor* self) {
|
||||
0,
|
||||
self->buffer_col
|
||||
);
|
||||
|
||||
str_dealloc(&old_line);
|
||||
}
|
||||
// refresh the screen with the new data
|
||||
refresh_buffer(self);
|
||||
@@ -257,7 +318,12 @@ void addchar(Editor* self, char c) {
|
||||
|
||||
// reallocate self->buffer to be 1 larger
|
||||
self->lines++;
|
||||
self->buffer = realloc(self->buffer, sizeof(String_t) * (self->lines));
|
||||
|
||||
while (self->lines > self->capacity) {
|
||||
self->capacity++;
|
||||
}
|
||||
|
||||
self->buffer = (String_t*)realloc(self->buffer, sizeof(String_t) * (self->capacity));
|
||||
|
||||
// allocate the memory space for the new line and add it to the buffer
|
||||
self->buffer[self->buffer_line] = str_new();
|
||||
@@ -269,7 +335,14 @@ void addchar(Editor* self, char c) {
|
||||
move_cursor(self, 1, 0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
String_t* to_string(Editor* self) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
+75
-2
@@ -1,8 +1,13 @@
|
||||
#include "dynstr.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* maintains the state of a text editor, including the text buffer,
|
||||
* cursor position, and various editor settings.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t lines;
|
||||
uint32_t capacity;
|
||||
uint32_t buffer_line;
|
||||
uint32_t buffer_col;
|
||||
uint32_t y_offset;
|
||||
@@ -10,16 +15,84 @@ typedef struct {
|
||||
bool unsaved_changes;
|
||||
bool editmode;
|
||||
String_t* buffer;
|
||||
String_t* original;
|
||||
String_t filename;
|
||||
} Editor;
|
||||
|
||||
Editor new_editor();
|
||||
/**
|
||||
* Creates a new editor instance from a filename
|
||||
*
|
||||
* @param filename The name of the file to open
|
||||
* @return Editor A new editor instance initialized with the file's content
|
||||
*/
|
||||
Editor new_editor(String_t filename);
|
||||
|
||||
Editor editor_from(String_t input_string);
|
||||
/**
|
||||
* Creates a new editor instance from an input string
|
||||
*
|
||||
* @param input_string initial editor content
|
||||
* @param filename name of the file being edited
|
||||
* @return an instance of the editor
|
||||
*/
|
||||
Editor editor_from(String_t input_string, String_t filename);
|
||||
|
||||
/**
|
||||
* Moves the cursor in the editor (relative to it's current position)
|
||||
*
|
||||
* @param self Pointer to the editor instance
|
||||
* @param x Horizontal movement (negative for left, positive for right)
|
||||
* @param y Vertical movement (negative for up, positive for down)
|
||||
*/
|
||||
void move_cursor(Editor* self, int x, int y);
|
||||
|
||||
/**
|
||||
* Deletes the character before the cursor
|
||||
*
|
||||
* @param self Pointer to the editor instance
|
||||
*/
|
||||
void delchar(Editor* self);
|
||||
|
||||
/**
|
||||
* Adds a character at the cursor position
|
||||
*
|
||||
* @param self Pointer to the editor instance
|
||||
* @param c The character to add
|
||||
*/
|
||||
void addchar(Editor* self, char c);
|
||||
|
||||
/**
|
||||
* Handles the enter key press, creating a new line
|
||||
*
|
||||
* @param self Pointer to the editor instance
|
||||
*/
|
||||
void pressed_enter(Editor* self);
|
||||
|
||||
/**
|
||||
* Toggles between edit and command mode
|
||||
*
|
||||
* @param self Pointer to the editor instance
|
||||
*/
|
||||
void switch_mode(Editor* self);
|
||||
|
||||
/**
|
||||
* Cleans up and frees resources used by the editor
|
||||
*
|
||||
* @param self Pointer to the editor instance
|
||||
*/
|
||||
void shutdown_editor(Editor* self);
|
||||
|
||||
/**
|
||||
* Saves the current buffer content to the file
|
||||
*
|
||||
* @param self Pointer to the editor instance
|
||||
* @return int Returns 0 on success, non-zero on failure
|
||||
*/
|
||||
int save_file(Editor* self);
|
||||
|
||||
/**
|
||||
* Converts the editor's buffer content to a String_t type
|
||||
*
|
||||
* @param self Pointer to the editor instance
|
||||
* @return String_t* Pointer to a string containing the buffer content
|
||||
*/
|
||||
String_t* to_string(Editor* self);
|
||||
|
||||
-630
@@ -1,630 +0,0 @@
|
||||
starting editor openiing file somecode.cln: 1, col: 0 xoff: 0 yoff: 0
|
||||
ln: 2, col: 0 xoff: 0 yoff: 0
|
||||
ln: 3, col: 0 xoff: 0 yoff: 0
|
||||
ln: 4, col: 0 xoff: 0 yoff: 0
|
||||
ln: 5, col: 0 xoff: 0 yoff: 0
|
||||
ln: 6, col: 0 xoff: 0 yoff: 0
|
||||
ln: 7, col: 0 xoff: 0 yoff: 0
|
||||
ln: 8, col: 0 xoff: 0 yoff: 0
|
||||
ln: 9, col: 0 xoff: 0 yoff: 0
|
||||
ln: 10, col: 0 xoff: 0 yoff: 0
|
||||
ln: 11, col: 0 xoff: 0 yoff: 0
|
||||
ln: 12, col: 0 xoff: 0 yoff: 0
|
||||
ln: 13, col: 0 xoff: 0 yoff: 0
|
||||
ln: 14, col: 0 xoff: 0 yoff: 0
|
||||
ln: 15, col: 0 xoff: 0 yoff: 0
|
||||
ln: 16, col: 0 xoff: 0 yoff: 0
|
||||
ln: 17, col: 0 xoff: 0 yoff: 0
|
||||
ln: 18, col: 0 xoff: 0 yoff: 0
|
||||
ln: 19, col: 0 xoff: 0 yoff: 0
|
||||
ln: 20, col: 0 xoff: 0 yoff: 0
|
||||
ln: 21, col: 0 xoff: 0 yoff: 0
|
||||
ln: 22, col: 0 xoff: 0 yoff: 0
|
||||
ln: 23, col: 0 xoff: 0 yoff: 0
|
||||
ln: 24, col: 0 xoff: 0 yoff: 0
|
||||
ln: 25, col: 0 xoff: 0 yoff: 0
|
||||
ln: 26, col: 0 xoff: 0 yoff: 0
|
||||
ln: 27, col: 0 xoff: 0 yoff: 0
|
||||
ln: 28, col: 0 xoff: 0 yoff: 0
|
||||
ln: 29, col: 0 xoff: 0 yoff: 0
|
||||
ln: 30, col: 0 xoff: 0 yoff: 0
|
||||
ln: 31, col: 0 xoff: 0 yoff: 0
|
||||
ln: 32, col: 0 xoff: 0 yoff: 0
|
||||
ln: 33, col: 0 xoff: 0 yoff: 0
|
||||
ln: 34, col: 0 xoff: 0 yoff: 0
|
||||
ln: 35, col: 0 xoff: 0 yoff: 0
|
||||
ln: 36, col: 0 xoff: 0 yoff: 0
|
||||
ln: 37, col: 0 xoff: 0 yoff: 0
|
||||
ln: 38, col: 0 xoff: 0 yoff: 0
|
||||
ln: 39, col: 0 xoff: 0 yoff: 0
|
||||
ln: 40, col: 0 xoff: 0 yoff: 0
|
||||
ln: 41, col: 0 xoff: 0 yoff: 0
|
||||
ln: 42, col: 0 xoff: 0 yoff: 0
|
||||
ln: 43, col: 0 xoff: 0 yoff: 0
|
||||
ln: 44, col: 0 xoff: 0 yoff: 0
|
||||
ln: 45, col: 0 xoff: 0 yoff: 0
|
||||
ln: 46, col: 0 xoff: 0 yoff: 0
|
||||
ln: 47, col: 0 xoff: 0 yoff: 0
|
||||
ln: 48, col: 0 xoff: 0 yoff: 0
|
||||
ln: 49, col: 0 xoff: 0 yoff: 0
|
||||
ln: 50, col: 0 xoff: 0 yoff: 0
|
||||
ln: 51, col: 0 xoff: 0 yoff: 0
|
||||
ln: 52, col: 0 xoff: 0 yoff: 0
|
||||
ln: 53, col: 0 xoff: 0 yoff: 0
|
||||
ln: 54, col: 0 xoff: 0 yoff: 0
|
||||
ln: 55, col: 0 xoff: 0 yoff: 0
|
||||
ln: 56, col: 0 xoff: 0 yoff: 0
|
||||
ln: 57, col: 0 xoff: 0 yoff: 0
|
||||
ln: 58, col: 0 xoff: 0 yoff: 0
|
||||
ln: 59, col: 0 xoff: 0 yoff: 0
|
||||
ln: 60, col: 0 xoff: 0 yoff: 0
|
||||
ln: 61, col: 0 xoff: 0 yoff: 0
|
||||
ln: 62, col: 0 xoff: 0 yoff: 0
|
||||
ln: 63, col: 0 xoff: 0 yoff: 1
|
||||
ln: 64, col: 0 xoff: 0 yoff: 2
|
||||
ln: 65, col: 0 xoff: 0 yoff: 3
|
||||
ln: 66, col: 0 xoff: 0 yoff: 4
|
||||
ln: 67, col: 0 xoff: 0 yoff: 5
|
||||
ln: 68, col: 0 xoff: 0 yoff: 6
|
||||
ln: 69, col: 0 xoff: 0 yoff: 7
|
||||
ln: 70, col: 0 xoff: 0 yoff: 8
|
||||
ln: 71, col: 0 xoff: 0 yoff: 9
|
||||
ln: 72, col: 0 xoff: 0 yoff: 10
|
||||
ln: 73, col: 0 xoff: 0 yoff: 11
|
||||
ln: 74, col: 0 xoff: 0 yoff: 12
|
||||
ln: 75, col: 0 xoff: 0 yoff: 13
|
||||
ln: 76, col: 0 xoff: 0 yoff: 14
|
||||
ln: 77, col: 0 xoff: 0 yoff: 15
|
||||
ln: 78, col: 0 xoff: 0 yoff: 16
|
||||
ln: 79, col: 0 xoff: 0 yoff: 17
|
||||
ln: 80, col: 0 xoff: 0 yoff: 18
|
||||
ln: 81, col: 0 xoff: 0 yoff: 19
|
||||
ln: 82, col: 0 xoff: 0 yoff: 20
|
||||
ln: 83, col: 0 xoff: 0 yoff: 21
|
||||
ln: 84, col: 0 xoff: 0 yoff: 22
|
||||
ln: 85, col: 0 xoff: 0 yoff: 23
|
||||
ln: 86, col: 0 xoff: 0 yoff: 24
|
||||
ln: 87, col: 0 xoff: 0 yoff: 25
|
||||
ln: 88, col: 0 xoff: 0 yoff: 26
|
||||
ln: 89, col: 0 xoff: 0 yoff: 27
|
||||
ln: 90, col: 0 xoff: 0 yoff: 28
|
||||
ln: 91, col: 0 xoff: 0 yoff: 29
|
||||
ln: 92, col: 0 xoff: 0 yoff: 30
|
||||
ln: 93, col: 0 xoff: 0 yoff: 31
|
||||
ln: 94, col: 0 xoff: 0 yoff: 32
|
||||
ln: 95, col: 0 xoff: 0 yoff: 33
|
||||
ln: 96, col: 0 xoff: 0 yoff: 34
|
||||
ln: 97, col: 0 xoff: 0 yoff: 35
|
||||
ln: 98, col: 0 xoff: 0 yoff: 36
|
||||
ln: 99, col: 0 xoff: 0 yoff: 37
|
||||
ln: 100, col: 0 xoff: 0 yoff: 38
|
||||
ln: 101, col: 0 xoff: 0 yoff: 39
|
||||
ln: 102, col: 0 xoff: 0 yoff: 40
|
||||
ln: 103, col: 0 xoff: 0 yoff: 41
|
||||
ln: 104, col: 0 xoff: 0 yoff: 42
|
||||
ln: 105, col: 0 xoff: 0 yoff: 43
|
||||
ln: 106, col: 0 xoff: 0 yoff: 44
|
||||
ln: 107, col: 0 xoff: 0 yoff: 45
|
||||
ln: 108, col: 0 xoff: 0 yoff: 46
|
||||
ln: 109, col: 0 xoff: 0 yoff: 47
|
||||
ln: 110, col: 0 xoff: 0 yoff: 48
|
||||
ln: 111, col: 0 xoff: 0 yoff: 49
|
||||
ln: 112, col: 0 xoff: 0 yoff: 50
|
||||
ln: 113, col: 0 xoff: 0 yoff: 51
|
||||
ln: 114, col: 0 xoff: 0 yoff: 52
|
||||
ln: 115, col: 0 xoff: 0 yoff: 53
|
||||
ln: 116, col: 0 xoff: 0 yoff: 54
|
||||
ln: 117, col: 0 xoff: 0 yoff: 55
|
||||
ln: 118, col: 0 xoff: 0 yoff: 56
|
||||
ln: 119, col: 0 xoff: 0 yoff: 57
|
||||
ln: 120, col: 0 xoff: 0 yoff: 58
|
||||
ln: 121, col: 0 xoff: 0 yoff: 59
|
||||
ln: 122, col: 0 xoff: 0 yoff: 60
|
||||
ln: 123, col: 0 xoff: 0 yoff: 61
|
||||
ln: 124, col: 0 xoff: 0 yoff: 62
|
||||
ln: 125, col: 0 xoff: 0 yoff: 63
|
||||
ln: 126, col: 0 xoff: 0 yoff: 64
|
||||
ln: 127, col: 0 xoff: 0 yoff: 65
|
||||
ln: 128, col: 0 xoff: 0 yoff: 66
|
||||
ln: 129, col: 0 xoff: 0 yoff: 67
|
||||
ln: 130, col: 0 xoff: 0 yoff: 68
|
||||
ln: 131, col: 0 xoff: 0 yoff: 69
|
||||
ln: 132, col: 0 xoff: 0 yoff: 70
|
||||
ln: 133, col: 0 xoff: 0 yoff: 71
|
||||
ln: 134, col: 0 xoff: 0 yoff: 72
|
||||
ln: 135, col: 0 xoff: 0 yoff: 73
|
||||
ln: 136, col: 0 xoff: 0 yoff: 74
|
||||
ln: 137, col: 0 xoff: 0 yoff: 75
|
||||
ln: 138, col: 0 xoff: 0 yoff: 76
|
||||
ln: 139, col: 0 xoff: 0 yoff: 77
|
||||
ln: 140, col: 0 xoff: 0 yoff: 78
|
||||
ln: 141, col: 0 xoff: 0 yoff: 79
|
||||
ln: 142, col: 0 xoff: 0 yoff: 80
|
||||
ln: 143, col: 0 xoff: 0 yoff: 81
|
||||
ln: 144, col: 0 xoff: 0 yoff: 82
|
||||
ln: 145, col: 0 xoff: 0 yoff: 83
|
||||
ln: 146, col: 0 xoff: 0 yoff: 84
|
||||
ln: 147, col: 0 xoff: 0 yoff: 85
|
||||
ln: 148, col: 0 xoff: 0 yoff: 86
|
||||
ln: 149, col: 0 xoff: 0 yoff: 87
|
||||
ln: 150, col: 0 xoff: 0 yoff: 88
|
||||
ln: 151, col: 0 xoff: 0 yoff: 89
|
||||
ln: 152, col: 0 xoff: 0 yoff: 90
|
||||
ln: 153, col: 0 xoff: 0 yoff: 91
|
||||
ln: 154, col: 0 xoff: 0 yoff: 92
|
||||
ln: 155, col: 0 xoff: 0 yoff: 93
|
||||
ln: 156, col: 0 xoff: 0 yoff: 94
|
||||
ln: 157, col: 0 xoff: 0 yoff: 95
|
||||
ln: 158, col: 0 xoff: 0 yoff: 96
|
||||
ln: 159, col: 0 xoff: 0 yoff: 97
|
||||
ln: 160, col: 0 xoff: 0 yoff: 98
|
||||
ln: 161, col: 0 xoff: 0 yoff: 99
|
||||
ln: 162, col: 0 xoff: 0 yoff: 100
|
||||
ln: 163, col: 0 xoff: 0 yoff: 101
|
||||
ln: 164, col: 0 xoff: 0 yoff: 102
|
||||
ln: 165, col: 0 xoff: 0 yoff: 103
|
||||
ln: 164, col: 0 xoff: 0 yoff: 104
|
||||
ln: 163, col: 0 xoff: 0 yoff: 104
|
||||
ln: 162, col: 0 xoff: 0 yoff: 104
|
||||
ln: 161, col: 0 xoff: 0 yoff: 104
|
||||
ln: 160, col: 0 xoff: 0 yoff: 104
|
||||
ln: 159, col: 0 xoff: 0 yoff: 104
|
||||
ln: 158, col: 0 xoff: 0 yoff: 104
|
||||
ln: 157, col: 0 xoff: 0 yoff: 104
|
||||
ln: 156, col: 0 xoff: 0 yoff: 104
|
||||
ln: 155, col: 0 xoff: 0 yoff: 104
|
||||
ln: 154, col: 0 xoff: 0 yoff: 104
|
||||
ln: 153, col: 0 xoff: 0 yoff: 104
|
||||
ln: 152, col: 0 xoff: 0 yoff: 104
|
||||
ln: 151, col: 0 xoff: 0 yoff: 104
|
||||
ln: 150, col: 0 xoff: 0 yoff: 104
|
||||
ln: 149, col: 0 xoff: 0 yoff: 104
|
||||
ln: 148, col: 0 xoff: 0 yoff: 104
|
||||
ln: 147, col: 0 xoff: 0 yoff: 104
|
||||
ln: 146, col: 0 xoff: 0 yoff: 104
|
||||
ln: 145, col: 0 xoff: 0 yoff: 104
|
||||
ln: 144, col: 0 xoff: 0 yoff: 104
|
||||
ln: 143, col: 0 xoff: 0 yoff: 104
|
||||
ln: 142, col: 0 xoff: 0 yoff: 104
|
||||
ln: 141, col: 0 xoff: 0 yoff: 104
|
||||
ln: 140, col: 0 xoff: 0 yoff: 104
|
||||
ln: 139, col: 0 xoff: 0 yoff: 104
|
||||
ln: 138, col: 0 xoff: 0 yoff: 104
|
||||
ln: 137, col: 0 xoff: 0 yoff: 104
|
||||
ln: 136, col: 0 xoff: 0 yoff: 104
|
||||
ln: 135, col: 0 xoff: 0 yoff: 104
|
||||
ln: 134, col: 0 xoff: 0 yoff: 104
|
||||
ln: 133, col: 0 xoff: 0 yoff: 104
|
||||
ln: 132, col: 0 xoff: 0 yoff: 104
|
||||
ln: 131, col: 0 xoff: 0 yoff: 104
|
||||
ln: 130, col: 0 xoff: 0 yoff: 104
|
||||
ln: 129, col: 0 xoff: 0 yoff: 104
|
||||
ln: 128, col: 0 xoff: 0 yoff: 104
|
||||
ln: 127, col: 0 xoff: 0 yoff: 104
|
||||
ln: 126, col: 0 xoff: 0 yoff: 104
|
||||
ln: 125, col: 0 xoff: 0 yoff: 104
|
||||
ln: 124, col: 0 xoff: 0 yoff: 104
|
||||
ln: 123, col: 0 xoff: 0 yoff: 104
|
||||
ln: 122, col: 0 xoff: 0 yoff: 104
|
||||
ln: 121, col: 0 xoff: 0 yoff: 104
|
||||
ln: 120, col: 0 xoff: 0 yoff: 104
|
||||
ln: 119, col: 0 xoff: 0 yoff: 104
|
||||
ln: 118, col: 0 xoff: 0 yoff: 104
|
||||
ln: 117, col: 0 xoff: 0 yoff: 104
|
||||
ln: 116, col: 0 xoff: 0 yoff: 104
|
||||
ln: 115, col: 0 xoff: 0 yoff: 104
|
||||
ln: 114, col: 0 xoff: 0 yoff: 104
|
||||
ln: 113, col: 0 xoff: 0 yoff: 104
|
||||
ln: 112, col: 0 xoff: 0 yoff: 104
|
||||
ln: 111, col: 0 xoff: 0 yoff: 104
|
||||
ln: 110, col: 0 xoff: 0 yoff: 104
|
||||
ln: 109, col: 0 xoff: 0 yoff: 104
|
||||
ln: 108, col: 0 xoff: 0 yoff: 104
|
||||
ln: 107, col: 0 xoff: 0 yoff: 104
|
||||
ln: 106, col: 0 xoff: 0 yoff: 104
|
||||
ln: 105, col: 0 xoff: 0 yoff: 103
|
||||
ln: 104, col: 0 xoff: 0 yoff: 102
|
||||
ln: 103, col: 0 xoff: 0 yoff: 101
|
||||
ln: 102, col: 0 xoff: 0 yoff: 100
|
||||
ln: 101, col: 0 xoff: 0 yoff: 99
|
||||
ln: 100, col: 0 xoff: 0 yoff: 98
|
||||
ln: 99, col: 0 xoff: 0 yoff: 97
|
||||
ln: 98, col: 0 xoff: 0 yoff: 96
|
||||
ln: 97, col: 0 xoff: 0 yoff: 95
|
||||
ln: 96, col: 0 xoff: 0 yoff: 94
|
||||
ln: 97, col: 0 xoff: 0 yoff: 93
|
||||
ln: 98, col: 0 xoff: 0 yoff: 93
|
||||
ln: 99, col: 0 xoff: 0 yoff: 93
|
||||
ln: 100, col: 0 xoff: 0 yoff: 93
|
||||
ln: 101, col: 0 xoff: 0 yoff: 93
|
||||
ln: 102, col: 0 xoff: 0 yoff: 93
|
||||
ln: 103, col: 0 xoff: 0 yoff: 93
|
||||
ln: 104, col: 0 xoff: 0 yoff: 93
|
||||
ln: 105, col: 0 xoff: 0 yoff: 93
|
||||
ln: 106, col: 0 xoff: 0 yoff: 93
|
||||
ln: 107, col: 0 xoff: 0 yoff: 93
|
||||
ln: 108, col: 0 xoff: 0 yoff: 93
|
||||
ln: 109, col: 0 xoff: 0 yoff: 93
|
||||
ln: 110, col: 0 xoff: 0 yoff: 93
|
||||
ln: 111, col: 0 xoff: 0 yoff: 93
|
||||
ln: 112, col: 0 xoff: 0 yoff: 93
|
||||
ln: 113, col: 0 xoff: 0 yoff: 93
|
||||
ln: 114, col: 0 xoff: 0 yoff: 93
|
||||
ln: 115, col: 0 xoff: 0 yoff: 93
|
||||
ln: 116, col: 0 xoff: 0 yoff: 93
|
||||
ln: 117, col: 0 xoff: 0 yoff: 93
|
||||
ln: 118, col: 0 xoff: 0 yoff: 93
|
||||
ln: 119, col: 0 xoff: 0 yoff: 93
|
||||
ln: 120, col: 0 xoff: 0 yoff: 93
|
||||
ln: 121, col: 0 xoff: 0 yoff: 93
|
||||
ln: 122, col: 0 xoff: 0 yoff: 93
|
||||
ln: 123, col: 0 xoff: 0 yoff: 93
|
||||
ln: 124, col: 0 xoff: 0 yoff: 93
|
||||
ln: 125, col: 0 xoff: 0 yoff: 93
|
||||
ln: 126, col: 0 xoff: 0 yoff: 93
|
||||
ln: 127, col: 0 xoff: 0 yoff: 93
|
||||
ln: 128, col: 0 xoff: 0 yoff: 93
|
||||
ln: 129, col: 0 xoff: 0 yoff: 93
|
||||
ln: 130, col: 0 xoff: 0 yoff: 93
|
||||
ln: 131, col: 0 xoff: 0 yoff: 93
|
||||
ln: 132, col: 0 xoff: 0 yoff: 93
|
||||
ln: 133, col: 0 xoff: 0 yoff: 93
|
||||
ln: 134, col: 0 xoff: 0 yoff: 93
|
||||
ln: 135, col: 0 xoff: 0 yoff: 93
|
||||
ln: 136, col: 0 xoff: 0 yoff: 93
|
||||
ln: 137, col: 0 xoff: 0 yoff: 93
|
||||
ln: 138, col: 0 xoff: 0 yoff: 93
|
||||
ln: 139, col: 0 xoff: 0 yoff: 93
|
||||
ln: 140, col: 0 xoff: 0 yoff: 93
|
||||
ln: 141, col: 0 xoff: 0 yoff: 93
|
||||
ln: 142, col: 0 xoff: 0 yoff: 93
|
||||
ln: 143, col: 0 xoff: 0 yoff: 93
|
||||
ln: 144, col: 0 xoff: 0 yoff: 93
|
||||
ln: 145, col: 0 xoff: 0 yoff: 93
|
||||
ln: 146, col: 0 xoff: 0 yoff: 93
|
||||
ln: 147, col: 0 xoff: 0 yoff: 93
|
||||
ln: 148, col: 0 xoff: 0 yoff: 93
|
||||
ln: 149, col: 0 xoff: 0 yoff: 93
|
||||
ln: 150, col: 0 xoff: 0 yoff: 93
|
||||
ln: 151, col: 0 xoff: 0 yoff: 93
|
||||
ln: 152, col: 0 xoff: 0 yoff: 93
|
||||
ln: 153, col: 0 xoff: 0 yoff: 93
|
||||
ln: 154, col: 0 xoff: 0 yoff: 93
|
||||
ln: 155, col: 0 xoff: 0 yoff: 93
|
||||
ln: 156, col: 0 xoff: 0 yoff: 94
|
||||
ln: 157, col: 0 xoff: 0 yoff: 95
|
||||
ln: 158, col: 0 xoff: 0 yoff: 96
|
||||
ln: 159, col: 0 xoff: 0 yoff: 97
|
||||
ln: 160, col: 0 xoff: 0 yoff: 98
|
||||
ln: 161, col: 0 xoff: 0 yoff: 99
|
||||
ln: 162, col: 0 xoff: 0 yoff: 100
|
||||
ln: 163, col: 0 xoff: 0 yoff: 101
|
||||
ln: 164, col: 0 xoff: 0 yoff: 102
|
||||
ln: 165, col: 0 xoff: 0 yoff: 103
|
||||
ln: 166, col: 0 xoff: 0 yoff: 104
|
||||
ln: 167, col: 0 xoff: 0 yoff: 105
|
||||
ln: 168, col: 0 xoff: 0 yoff: 106
|
||||
ln: 169, col: 0 xoff: 0 yoff: 107
|
||||
ln: 170, col: 0 xoff: 0 yoff: 108
|
||||
ln: 171, col: 0 xoff: 0 yoff: 109
|
||||
ln: 172, col: 0 xoff: 0 yoff: 110
|
||||
ln: 173, col: 0 xoff: 0 yoff: 111
|
||||
ln: 174, col: 0 xoff: 0 yoff: 112
|
||||
ln: 175, col: 0 xoff: 0 yoff: 113
|
||||
ln: 176, col: 0 xoff: 0 yoff: 114
|
||||
ln: 177, col: 0 xoff: 0 yoff: 115
|
||||
ln: 178, col: 0 xoff: 0 yoff: 116
|
||||
ln: 179, col: 0 xoff: 0 yoff: 117
|
||||
ln: 180, col: 0 xoff: 0 yoff: 118
|
||||
ln: 181, col: 0 xoff: 0 yoff: 119
|
||||
ln: 182, col: 0 xoff: 0 yoff: 120
|
||||
ln: 183, col: 0 xoff: 0 yoff: 121
|
||||
ln: 184, col: 0 xoff: 0 yoff: 122
|
||||
ln: 185, col: 0 xoff: 0 yoff: 123
|
||||
ln: 186, col: 0 xoff: 0 yoff: 124
|
||||
ln: 187, col: 0 xoff: 0 yoff: 125
|
||||
ln: 188, col: 0 xoff: 0 yoff: 126
|
||||
ln: 189, col: 0 xoff: 0 yoff: 127
|
||||
ln: 190, col: 0 xoff: 0 yoff: 128
|
||||
ln: 191, col: 0 xoff: 0 yoff: 129
|
||||
ln: 192, col: 0 xoff: 0 yoff: 130
|
||||
ln: 193, col: 0 xoff: 0 yoff: 131
|
||||
ln: 194, col: 0 xoff: 0 yoff: 132
|
||||
ln: 195, col: 0 xoff: 0 yoff: 133
|
||||
ln: 196, col: 0 xoff: 0 yoff: 134
|
||||
ln: 197, col: 0 xoff: 0 yoff: 135
|
||||
ln: 198, col: 0 xoff: 0 yoff: 136
|
||||
ln: 199, col: 0 xoff: 0 yoff: 137
|
||||
ln: 200, col: 0 xoff: 0 yoff: 138
|
||||
ln: 201, col: 0 xoff: 0 yoff: 139
|
||||
ln: 202, col: 0 xoff: 0 yoff: 140
|
||||
ln: 203, col: 0 xoff: 0 yoff: 141
|
||||
ln: 204, col: 0 xoff: 0 yoff: 142
|
||||
ln: 205, col: 0 xoff: 0 yoff: 143
|
||||
ln: 206, col: 0 xoff: 0 yoff: 144
|
||||
ln: 207, col: 0 xoff: 0 yoff: 145
|
||||
ln: 208, col: 0 xoff: 0 yoff: 146
|
||||
ln: 209, col: 0 xoff: 0 yoff: 147
|
||||
ln: 210, col: 0 xoff: 0 yoff: 148
|
||||
ln: 211, col: 0 xoff: 0 yoff: 149
|
||||
ln: 212, col: 0 xoff: 0 yoff: 150
|
||||
ln: 213, col: 0 xoff: 0 yoff: 151
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 212, col: 0 xoff: 0 yoff: 152
|
||||
ln: 211, col: 0 xoff: 0 yoff: 152
|
||||
ln: 210, col: 0 xoff: 0 yoff: 152
|
||||
ln: 211, col: 0 xoff: 0 yoff: 152
|
||||
ln: 212, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 212, col: 0 xoff: 0 yoff: 152
|
||||
ln: 211, col: 0 xoff: 0 yoff: 152
|
||||
ln: 210, col: 0 xoff: 0 yoff: 152
|
||||
ln: 209, col: 0 xoff: 0 yoff: 152
|
||||
ln: 208, col: 0 xoff: 0 yoff: 152
|
||||
ln: 207, col: 0 xoff: 0 yoff: 152
|
||||
ln: 208, col: 0 xoff: 0 yoff: 152
|
||||
ln: 209, col: 0 xoff: 0 yoff: 152
|
||||
ln: 210, col: 0 xoff: 0 yoff: 152
|
||||
ln: 209, col: 0 xoff: 0 yoff: 152
|
||||
ln: 208, col: 0 xoff: 0 yoff: 152
|
||||
ln: 207, col: 0 xoff: 0 yoff: 152
|
||||
ln: 208, col: 0 xoff: 0 yoff: 152
|
||||
ln: 209, col: 0 xoff: 0 yoff: 152
|
||||
ln: 210, col: 0 xoff: 0 yoff: 152
|
||||
ln: 209, col: 0 xoff: 0 yoff: 152
|
||||
ln: 208, col: 0 xoff: 0 yoff: 152
|
||||
ln: 207, col: 0 xoff: 0 yoff: 152
|
||||
ln: 208, col: 0 xoff: 0 yoff: 152
|
||||
ln: 209, col: 0 xoff: 0 yoff: 152
|
||||
ln: 210, col: 0 xoff: 0 yoff: 152
|
||||
ln: 211, col: 0 xoff: 0 yoff: 152
|
||||
ln: 212, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 213, col: 0 xoff: 0 yoff: 152
|
||||
ln: 212, col: 0 xoff: 0 yoff: 152
|
||||
ln: 211, col: 0 xoff: 0 yoff: 152
|
||||
ln: 210, col: 0 xoff: 0 yoff: 152
|
||||
ln: 209, col: 0 xoff: 0 yoff: 152
|
||||
ln: 208, col: 0 xoff: 0 yoff: 152
|
||||
ln: 207, col: 0 xoff: 0 yoff: 152
|
||||
ln: 206, col: 0 xoff: 0 yoff: 152
|
||||
ln: 205, col: 0 xoff: 0 yoff: 152
|
||||
ln: 204, col: 0 xoff: 0 yoff: 152
|
||||
ln: 203, col: 0 xoff: 0 yoff: 152
|
||||
ln: 202, col: 0 xoff: 0 yoff: 152
|
||||
ln: 201, col: 0 xoff: 0 yoff: 152
|
||||
ln: 200, col: 0 xoff: 0 yoff: 152
|
||||
ln: 199, col: 0 xoff: 0 yoff: 152
|
||||
ln: 198, col: 0 xoff: 0 yoff: 152
|
||||
ln: 197, col: 0 xoff: 0 yoff: 152
|
||||
ln: 196, col: 0 xoff: 0 yoff: 152
|
||||
ln: 195, col: 0 xoff: 0 yoff: 152
|
||||
ln: 194, col: 0 xoff: 0 yoff: 152
|
||||
ln: 193, col: 0 xoff: 0 yoff: 152
|
||||
ln: 192, col: 0 xoff: 0 yoff: 152
|
||||
ln: 191, col: 0 xoff: 0 yoff: 152
|
||||
ln: 190, col: 0 xoff: 0 yoff: 152
|
||||
ln: 189, col: 0 xoff: 0 yoff: 152
|
||||
ln: 188, col: 0 xoff: 0 yoff: 152
|
||||
ln: 187, col: 0 xoff: 0 yoff: 152
|
||||
ln: 186, col: 0 xoff: 0 yoff: 152
|
||||
ln: 185, col: 0 xoff: 0 yoff: 152
|
||||
ln: 184, col: 0 xoff: 0 yoff: 152
|
||||
ln: 183, col: 0 xoff: 0 yoff: 152
|
||||
ln: 182, col: 0 xoff: 0 yoff: 152
|
||||
ln: 181, col: 0 xoff: 0 yoff: 152
|
||||
ln: 180, col: 0 xoff: 0 yoff: 152
|
||||
ln: 179, col: 0 xoff: 0 yoff: 152
|
||||
ln: 178, col: 0 xoff: 0 yoff: 152
|
||||
ln: 177, col: 0 xoff: 0 yoff: 152
|
||||
ln: 176, col: 0 xoff: 0 yoff: 152
|
||||
ln: 175, col: 0 xoff: 0 yoff: 152
|
||||
ln: 174, col: 0 xoff: 0 yoff: 152
|
||||
ln: 173, col: 0 xoff: 0 yoff: 152
|
||||
ln: 172, col: 0 xoff: 0 yoff: 152
|
||||
ln: 171, col: 0 xoff: 0 yoff: 152
|
||||
ln: 170, col: 0 xoff: 0 yoff: 152
|
||||
ln: 169, col: 0 xoff: 0 yoff: 152
|
||||
ln: 168, col: 0 xoff: 0 yoff: 152
|
||||
ln: 167, col: 0 xoff: 0 yoff: 152
|
||||
ln: 166, col: 0 xoff: 0 yoff: 152
|
||||
ln: 165, col: 0 xoff: 0 yoff: 152
|
||||
ln: 164, col: 0 xoff: 0 yoff: 152
|
||||
ln: 163, col: 0 xoff: 0 yoff: 152
|
||||
ln: 162, col: 0 xoff: 0 yoff: 152
|
||||
ln: 161, col: 0 xoff: 0 yoff: 152
|
||||
ln: 160, col: 0 xoff: 0 yoff: 152
|
||||
ln: 159, col: 0 xoff: 0 yoff: 152
|
||||
ln: 158, col: 0 xoff: 0 yoff: 152
|
||||
ln: 157, col: 0 xoff: 0 yoff: 152
|
||||
ln: 156, col: 0 xoff: 0 yoff: 152
|
||||
ln: 155, col: 0 xoff: 0 yoff: 152
|
||||
ln: 154, col: 0 xoff: 0 yoff: 152
|
||||
ln: 153, col: 0 xoff: 0 yoff: 151
|
||||
ln: 152, col: 0 xoff: 0 yoff: 150
|
||||
ln: 151, col: 0 xoff: 0 yoff: 149
|
||||
ln: 150, col: 0 xoff: 0 yoff: 148
|
||||
ln: 149, col: 0 xoff: 0 yoff: 147
|
||||
ln: 148, col: 0 xoff: 0 yoff: 146
|
||||
ln: 147, col: 0 xoff: 0 yoff: 145
|
||||
ln: 146, col: 0 xoff: 0 yoff: 144
|
||||
ln: 145, col: 0 xoff: 0 yoff: 143
|
||||
ln: 144, col: 0 xoff: 0 yoff: 142
|
||||
ln: 143, col: 0 xoff: 0 yoff: 141
|
||||
ln: 142, col: 0 xoff: 0 yoff: 140
|
||||
ln: 141, col: 0 xoff: 0 yoff: 139
|
||||
ln: 140, col: 0 xoff: 0 yoff: 138
|
||||
ln: 139, col: 0 xoff: 0 yoff: 137
|
||||
ln: 138, col: 0 xoff: 0 yoff: 136
|
||||
ln: 137, col: 0 xoff: 0 yoff: 135
|
||||
ln: 136, col: 0 xoff: 0 yoff: 134
|
||||
ln: 135, col: 0 xoff: 0 yoff: 133
|
||||
ln: 134, col: 0 xoff: 0 yoff: 132
|
||||
ln: 133, col: 0 xoff: 0 yoff: 131
|
||||
ln: 132, col: 0 xoff: 0 yoff: 130
|
||||
ln: 131, col: 0 xoff: 0 yoff: 129
|
||||
ln: 130, col: 0 xoff: 0 yoff: 128
|
||||
ln: 129, col: 0 xoff: 0 yoff: 127
|
||||
ln: 128, col: 0 xoff: 0 yoff: 126
|
||||
ln: 127, col: 0 xoff: 0 yoff: 125
|
||||
ln: 126, col: 0 xoff: 0 yoff: 124
|
||||
ln: 125, col: 0 xoff: 0 yoff: 123
|
||||
ln: 124, col: 0 xoff: 0 yoff: 122
|
||||
ln: 123, col: 0 xoff: 0 yoff: 121
|
||||
ln: 122, col: 0 xoff: 0 yoff: 120
|
||||
ln: 121, col: 0 xoff: 0 yoff: 119
|
||||
ln: 120, col: 0 xoff: 0 yoff: 118
|
||||
ln: 119, col: 0 xoff: 0 yoff: 117
|
||||
ln: 118, col: 0 xoff: 0 yoff: 116
|
||||
ln: 117, col: 0 xoff: 0 yoff: 115
|
||||
ln: 116, col: 0 xoff: 0 yoff: 114
|
||||
ln: 115, col: 0 xoff: 0 yoff: 113
|
||||
ln: 114, col: 0 xoff: 0 yoff: 112
|
||||
ln: 113, col: 0 xoff: 0 yoff: 111
|
||||
ln: 112, col: 0 xoff: 0 yoff: 110
|
||||
ln: 111, col: 0 xoff: 0 yoff: 109
|
||||
ln: 110, col: 0 xoff: 0 yoff: 108
|
||||
ln: 109, col: 0 xoff: 0 yoff: 107
|
||||
ln: 108, col: 0 xoff: 0 yoff: 106
|
||||
ln: 107, col: 0 xoff: 0 yoff: 105
|
||||
ln: 106, col: 0 xoff: 0 yoff: 104
|
||||
ln: 105, col: 0 xoff: 0 yoff: 103
|
||||
ln: 104, col: 0 xoff: 0 yoff: 102
|
||||
ln: 103, col: 0 xoff: 0 yoff: 101
|
||||
ln: 102, col: 0 xoff: 0 yoff: 100
|
||||
ln: 101, col: 0 xoff: 0 yoff: 99
|
||||
ln: 100, col: 0 xoff: 0 yoff: 98
|
||||
ln: 99, col: 0 xoff: 0 yoff: 97
|
||||
ln: 98, col: 0 xoff: 0 yoff: 96
|
||||
ln: 97, col: 0 xoff: 0 yoff: 95
|
||||
ln: 96, col: 0 xoff: 0 yoff: 94
|
||||
ln: 95, col: 0 xoff: 0 yoff: 93
|
||||
ln: 94, col: 0 xoff: 0 yoff: 92
|
||||
ln: 93, col: 0 xoff: 0 yoff: 91
|
||||
ln: 92, col: 0 xoff: 0 yoff: 90
|
||||
ln: 91, col: 0 xoff: 0 yoff: 89
|
||||
ln: 90, col: 0 xoff: 0 yoff: 88
|
||||
ln: 89, col: 0 xoff: 0 yoff: 87
|
||||
ln: 88, col: 0 xoff: 0 yoff: 86
|
||||
ln: 87, col: 0 xoff: 0 yoff: 85
|
||||
ln: 86, col: 0 xoff: 0 yoff: 84
|
||||
ln: 85, col: 0 xoff: 0 yoff: 83
|
||||
ln: 84, col: 0 xoff: 0 yoff: 82
|
||||
ln: 83, col: 0 xoff: 0 yoff: 81
|
||||
ln: 82, col: 0 xoff: 0 yoff: 80
|
||||
ln: 81, col: 0 xoff: 0 yoff: 79
|
||||
ln: 80, col: 0 xoff: 0 yoff: 78
|
||||
ln: 79, col: 0 xoff: 0 yoff: 77
|
||||
ln: 78, col: 0 xoff: 0 yoff: 76
|
||||
ln: 77, col: 0 xoff: 0 yoff: 75
|
||||
ln: 76, col: 0 xoff: 0 yoff: 74
|
||||
ln: 75, col: 0 xoff: 0 yoff: 73
|
||||
ln: 74, col: 0 xoff: 0 yoff: 72
|
||||
ln: 73, col: 0 xoff: 0 yoff: 71
|
||||
ln: 72, col: 0 xoff: 0 yoff: 70
|
||||
ln: 71, col: 0 xoff: 0 yoff: 69
|
||||
ln: 70, col: 0 xoff: 0 yoff: 68
|
||||
ln: 69, col: 0 xoff: 0 yoff: 67
|
||||
ln: 68, col: 0 xoff: 0 yoff: 66
|
||||
ln: 67, col: 0 xoff: 0 yoff: 65
|
||||
ln: 66, col: 0 xoff: 0 yoff: 64
|
||||
ln: 65, col: 0 xoff: 0 yoff: 63
|
||||
ln: 64, col: 0 xoff: 0 yoff: 62
|
||||
ln: 63, col: 0 xoff: 0 yoff: 61
|
||||
ln: 62, col: 0 xoff: 0 yoff: 60
|
||||
ln: 61, col: 0 xoff: 0 yoff: 59
|
||||
ln: 60, col: 0 xoff: 0 yoff: 58
|
||||
ln: 59, col: 0 xoff: 0 yoff: 57
|
||||
ln: 58, col: 0 xoff: 0 yoff: 56
|
||||
ln: 57, col: 0 xoff: 0 yoff: 55
|
||||
ln: 56, col: 0 xoff: 0 yoff: 54
|
||||
ln: 55, col: 0 xoff: 0 yoff: 53
|
||||
ln: 54, col: 0 xoff: 0 yoff: 52
|
||||
ln: 53, col: 0 xoff: 0 yoff: 51
|
||||
ln: 52, col: 0 xoff: 0 yoff: 50
|
||||
ln: 51, col: 0 xoff: 0 yoff: 49
|
||||
ln: 50, col: 0 xoff: 0 yoff: 48
|
||||
ln: 49, col: 0 xoff: 0 yoff: 47
|
||||
ln: 48, col: 0 xoff: 0 yoff: 46
|
||||
ln: 47, col: 0 xoff: 0 yoff: 45
|
||||
ln: 46, col: 0 xoff: 0 yoff: 44
|
||||
ln: 45, col: 0 xoff: 0 yoff: 43
|
||||
ln: 44, col: 0 xoff: 0 yoff: 42
|
||||
ln: 43, col: 0 xoff: 0 yoff: 41
|
||||
ln: 42, col: 0 xoff: 0 yoff: 40
|
||||
ln: 41, col: 0 xoff: 0 yoff: 39
|
||||
ln: 40, col: 0 xoff: 0 yoff: 38
|
||||
ln: 39, col: 0 xoff: 0 yoff: 37
|
||||
ln: 38, col: 0 xoff: 0 yoff: 36
|
||||
ln: 37, col: 0 xoff: 0 yoff: 35
|
||||
ln: 36, col: 0 xoff: 0 yoff: 34
|
||||
ln: 35, col: 0 xoff: 0 yoff: 33
|
||||
ln: 34, col: 0 xoff: 0 yoff: 32
|
||||
ln: 33, col: 0 xoff: 0 yoff: 31
|
||||
ln: 32, col: 0 xoff: 0 yoff: 30
|
||||
ln: 31, col: 0 xoff: 0 yoff: 29
|
||||
ln: 30, col: 0 xoff: 0 yoff: 28
|
||||
ln: 29, col: 0 xoff: 0 yoff: 27
|
||||
ln: 28, col: 0 xoff: 0 yoff: 26
|
||||
ln: 27, col: 0 xoff: 0 yoff: 25
|
||||
ln: 26, col: 0 xoff: 0 yoff: 24
|
||||
ln: 25, col: 0 xoff: 0 yoff: 23
|
||||
ln: 24, col: 0 xoff: 0 yoff: 22
|
||||
ln: 23, col: 0 xoff: 0 yoff: 21
|
||||
ln: 22, col: 0 xoff: 0 yoff: 20
|
||||
ln: 21, col: 0 xoff: 0 yoff: 19
|
||||
ln: 20, col: 0 xoff: 0 yoff: 18
|
||||
ln: 19, col: 0 xoff: 0 yoff: 17
|
||||
ln: 18, col: 0 xoff: 0 yoff: 16
|
||||
ln: 17, col: 0 xoff: 0 yoff: 15
|
||||
ln: 16, col: 0 xoff: 0 yoff: 14
|
||||
ln: 15, col: 0 xoff: 0 yoff: 13
|
||||
ln: 14, col: 0 xoff: 0 yoff: 12
|
||||
ln: 13, col: 0 xoff: 0 yoff: 11
|
||||
ln: 12, col: 0 xoff: 0 yoff: 10
|
||||
ln: 11, col: 0 xoff: 0 yoff: 9
|
||||
ln: 10, col: 0 xoff: 0 yoff: 8
|
||||
ln: 9, col: 0 xoff: 0 yoff: 7
|
||||
ln: 8, col: 0 xoff: 0 yoff: 6
|
||||
ln: 7, col: 0 xoff: 0 yoff: 5
|
||||
ln: 6, col: 0 xoff: 0 yoff: 4
|
||||
ln: 5, col: 0 xoff: 0 yoff: 3
|
||||
|
||||
+165
-17
@@ -6,12 +6,13 @@
|
||||
|
||||
void help() {
|
||||
printf("Usage:\n");
|
||||
printf(" cmd open <path/to/file> // opens the specified file\n");
|
||||
printf(" cmd rm <path/to/file> // deletes the specified file\n");
|
||||
printf(" cmd new <path/to/file> // creates a new empty file at the specified path\n");
|
||||
printf(" cmd mv <path/to/file> <new/path> // moves the specified file to the new path\n");
|
||||
printf(" cmd cp <path/to/file> <new/path> // copies the specified file to the new path\n");
|
||||
printf(" cmd len <path/to/file> // returns the length of the specified file\n");
|
||||
printf(" cmd open <file/path> // opens the specified file\n");
|
||||
printf(" cmd rm <file/path> // deletes the specified file\n");
|
||||
printf(" cmd new <file/path> // creates a new empty file at the specified path\n");
|
||||
printf(" cmd mv <old/path> <new/path> // moves the specified file to the new path\n");
|
||||
printf(" cmd cp <old/path> <new/path> // copies the specified file to the new path\n");
|
||||
printf(" cmd lenl <file/path> // returns the length of the specified file in lines\n");
|
||||
printf(" cmd lenc <file/path> // returns the length of the specified file in chars\n");
|
||||
printf(" cmd log // prints a list of all changes made to the file\n");
|
||||
}
|
||||
|
||||
@@ -33,9 +34,9 @@ int open_editor(char* filename) {
|
||||
|
||||
Editor editor;
|
||||
if (strcmp(filename, "") == 0) {
|
||||
editor = new_editor();
|
||||
editor = new_editor(str_from_chars(filename));
|
||||
} else {
|
||||
editor = editor_from(str_from_file(fopen(filename, "r")));
|
||||
editor = editor_from(str_from_file(fopen(filename, "r")), str_from_chars(filename));
|
||||
}
|
||||
while (true) {
|
||||
refresh();
|
||||
@@ -68,7 +69,6 @@ int open_editor(char* filename) {
|
||||
move_cursor(&editor, 1, 0);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%d\n", c);
|
||||
addchar(&editor, c);
|
||||
break;
|
||||
}
|
||||
@@ -76,12 +76,15 @@ int open_editor(char* filename) {
|
||||
switch (c) {
|
||||
case 'q':
|
||||
endwin();
|
||||
shutdown_editor(&editor);
|
||||
|
||||
return 0;
|
||||
case 'i':
|
||||
switch_mode(&editor);
|
||||
break;
|
||||
case 'w':
|
||||
editor.unsaved_changes = false;
|
||||
save_file(&editor);
|
||||
// TODO: write function to save the data to a file
|
||||
break;
|
||||
default:
|
||||
@@ -91,16 +94,161 @@ int open_editor(char* filename) {
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc == 1) {
|
||||
Editor e = new_editor();
|
||||
open_editor("");
|
||||
} else if (argc == 3) {
|
||||
if (strcmp(argv[1], "open") == 0) {
|
||||
fprintf(stderr, "starting editor openiing file %s", argv[2]);
|
||||
open_editor(argv[2]);
|
||||
// Copies a file from source to destination
|
||||
int copy_file(const char* source, const char* dest) {
|
||||
FILE* src = fopen(source, "rb");
|
||||
if (src == NULL) {
|
||||
fprintf(stderr, "Error: Could not open source file %s\n", source);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE* dst = fopen(dest, "wb");
|
||||
if (dst == NULL) {
|
||||
fclose(src);
|
||||
fprintf(stderr, "Error: Could not create destination file %s\n", dest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char buffer[8192];
|
||||
size_t bytes;
|
||||
while ((bytes = fread(buffer, 1, sizeof(buffer), src)) > 0) {
|
||||
if (fwrite(buffer, 1, bytes, dst) != bytes) {
|
||||
fclose(src);
|
||||
fclose(dst);
|
||||
fprintf(stderr, "Error: Write failed to %s\n", dest);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(src);
|
||||
fclose(dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Counts the number of characters in a file
|
||||
int count_chars(const char* filename) {
|
||||
FILE* file = fopen(filename, "r");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Error: Could not open file %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int ch;
|
||||
while ((ch = fgetc(file)) != EOF) {
|
||||
count++;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return count;
|
||||
}
|
||||
|
||||
// Counts the number of lines in a file
|
||||
int count_lines(const char* filename) {
|
||||
FILE* file = fopen(filename, "r");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Error: Could not open file %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int ch;
|
||||
int last_char = '\n'; // Handle empty files as 0 lines
|
||||
|
||||
while ((ch = fgetc(file)) != EOF) {
|
||||
if (ch == '\n') {
|
||||
count++;
|
||||
}
|
||||
last_char = ch;
|
||||
}
|
||||
|
||||
// Count last line if it doesn't end with newline
|
||||
if (last_char != '\n' && last_char != EOF) {
|
||||
count++;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return count;
|
||||
}
|
||||
|
||||
// Command types
|
||||
typedef enum {
|
||||
CMD_OPEN,
|
||||
CMD_RM,
|
||||
CMD_NEW,
|
||||
CMD_MV,
|
||||
CMD_CP,
|
||||
CMD_LENL,
|
||||
CMD_LENC,
|
||||
CMD_LOG,
|
||||
CMD_UNKNOWN
|
||||
} CommandType;
|
||||
|
||||
// Convert string to command type
|
||||
CommandType str_to_cmd(const char* cmd) {
|
||||
if (strcmp(cmd, "open") == 0) return CMD_OPEN;
|
||||
if (strcmp(cmd, "rm") == 0) return CMD_RM;
|
||||
if (strcmp(cmd, "new") == 0) return CMD_NEW;
|
||||
if (strcmp(cmd, "mv") == 0) return CMD_MV;
|
||||
if (strcmp(cmd, "cp") == 0) return CMD_CP;
|
||||
if (strcmp(cmd, "lenl") == 0) return CMD_LENL;
|
||||
if (strcmp(cmd, "lenc") == 0) return CMD_LENC;
|
||||
if (strcmp(cmd, "log") == 0) return CMD_LOG;
|
||||
return CMD_UNKNOWN;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
if (argc < 2) {
|
||||
help();
|
||||
return 1;
|
||||
}
|
||||
|
||||
CommandType cmd = str_to_cmd(argv[1]);
|
||||
|
||||
if (argc == 3) {
|
||||
switch (cmd) {
|
||||
case CMD_OPEN:
|
||||
open_editor(argv[2]);
|
||||
break;
|
||||
case CMD_RM:
|
||||
remove(argv[2]);
|
||||
break;
|
||||
case CMD_NEW:
|
||||
open_editor(argv[2]);
|
||||
break;
|
||||
case CMD_LENC:
|
||||
printf("%d\n", count_chars(argv[2]));
|
||||
break;
|
||||
case CMD_LENL:
|
||||
printf("%d\n", count_lines(argv[2]));
|
||||
break;
|
||||
default:
|
||||
help();
|
||||
}
|
||||
}
|
||||
|
||||
else if (argc == 4) {
|
||||
switch (cmd) {
|
||||
case CMD_MV:
|
||||
if (rename(argv[2], argv[3]) != 0) {
|
||||
fprintf(stderr, "Error: Failed to move file %s to %s\n", argv[2], argv[3]);
|
||||
}
|
||||
break;
|
||||
case CMD_CP:
|
||||
if (copy_file(argv[2], argv[3]) != 0) {
|
||||
fprintf(stderr, "Error: Failed to copy file %s to %s\n", argv[2], argv[3]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
help();
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
printf("invalid options\n");
|
||||
help();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user