utf8 processing without struct
This commit is contained in:
+67
-119
@@ -9,60 +9,25 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
extern char *strdup(const char *);
|
||||
extern ssize_t getline(char **restrict lineptr, size_t *restrict n,
|
||||
FILE *restrict stream);
|
||||
extern int ftruncate(int fd, off_t length);
|
||||
extern struct editorConfig E;
|
||||
|
||||
// Convert utf_8_char_t array to byte string
|
||||
char *editorRowsToString(int *buffer_len) {
|
||||
int tot_len = 0;
|
||||
int j, i;
|
||||
char *buf;
|
||||
char *p;
|
||||
|
||||
// Calculate total byte length (not character count)
|
||||
for (j = 0; j < E.numrows; ++j) {
|
||||
// Count actual bytes in each character
|
||||
for (i = 0; i < E.row[j].size; i++) {
|
||||
tot_len += E.row[j].chars[i].len;
|
||||
}
|
||||
tot_len++; // For newline
|
||||
}
|
||||
|
||||
*buffer_len = tot_len;
|
||||
buf = malloc(tot_len);
|
||||
if (!buf) return NULL;
|
||||
|
||||
p = buf;
|
||||
for (j = 0; j < E.numrows; ++j) {
|
||||
// Copy each character's bytes
|
||||
for (i = 0; i < E.row[j].size; i++) {
|
||||
for (int k = 0; k < E.row[j].chars[i].len; k++) {
|
||||
*p++ = E.row[j].chars[i].c[k];
|
||||
}
|
||||
}
|
||||
*p++ = '\n';
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void editorCloseFile(void) {
|
||||
void editorCloseFile(void)
|
||||
{
|
||||
// Free all rows
|
||||
for (int i = 0; i < E.numrows; i++) {
|
||||
editorFreeRow(&E.row[i]);
|
||||
for (int i = 0; i < E.numrows; i++)
|
||||
{
|
||||
editorFreeRow(&E.rows[i]);
|
||||
}
|
||||
|
||||
|
||||
E.cursor_x = 0;
|
||||
E.cursor_y = 0;
|
||||
E.rx = 0;
|
||||
E.row_offset = 0;
|
||||
E.col_offset = 0;
|
||||
E.numrows = 0;
|
||||
free(E.row);
|
||||
E.row = NULL;
|
||||
free(E.rows);
|
||||
E.rows = NULL;
|
||||
E.dirty = 0;
|
||||
free(E.filename);
|
||||
E.filename = NULL;
|
||||
@@ -70,11 +35,13 @@ void editorCloseFile(void) {
|
||||
E.status_msg_time = 0;
|
||||
}
|
||||
|
||||
void editorOpen(char *filename) {
|
||||
FILE *fp;
|
||||
void editorOpen(char* filename)
|
||||
{
|
||||
FILE* fp;
|
||||
|
||||
// Test if a file is already open
|
||||
if (E.filename != NULL) {
|
||||
if (E.filename != NULL)
|
||||
{
|
||||
editorCloseFile();
|
||||
}
|
||||
E.state = READ_AND_WRITE;
|
||||
@@ -82,136 +49,117 @@ void editorOpen(char *filename) {
|
||||
E.filename = strdup(filename);
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "reading file %s\n", filename);
|
||||
if (!fp)
|
||||
{
|
||||
// File doesn't exist - that's okay, we'll create it on save
|
||||
E.dirty = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
char *line = NULL;
|
||||
size_t line_cap = 0;
|
||||
ssize_t line_len;
|
||||
char* line = NULL;
|
||||
size_t line_len;
|
||||
|
||||
while ((line_len = getline(&line, &line_cap, fp)) != -1) {
|
||||
while ((line_len = getline(&line, &line_len, fp)) != -1)
|
||||
{
|
||||
fprintf(stderr, "%s %d", line, line_len);
|
||||
// Strip newline characters
|
||||
while (line_len > 0 &&
|
||||
(line[line_len - 1] == '\n' || line[line_len - 1] == '\r')) {
|
||||
(line[line_len - 1] == '\n' || line[line_len - 1] == '\r'))
|
||||
{
|
||||
--line_len;
|
||||
}
|
||||
fprintf(stderr, "len %d\n", line_len);
|
||||
// editorInsertRow will convert bytes to utf_8_char_t
|
||||
editorInsertRow(E.numrows, line, line_len);
|
||||
fprintf(stderr, "row number : %d\n", E.numrows);
|
||||
editorInsertRow(E.numrows, line, (int) line_len);
|
||||
}
|
||||
free(line);
|
||||
fclose(fp);
|
||||
E.dirty = 0;
|
||||
}
|
||||
|
||||
void editorSave() {
|
||||
void editorSave()
|
||||
{
|
||||
int len;
|
||||
char *buf;
|
||||
char* buf;
|
||||
int fd;
|
||||
|
||||
if (E.filename == NULL) {
|
||||
|
||||
if (E.filename == NULL)
|
||||
{
|
||||
E.filename = editorPrompt("Save as: %s (ESC to cancel)", "", 1);
|
||||
if (E.filename == NULL) {
|
||||
if (E.filename == NULL)
|
||||
{
|
||||
editorSetStatusMessage("Save aborted");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
buf = editorRowsToString(&len);
|
||||
if (!buf) {
|
||||
editorSetStatusMessage("Can't save! Memory error");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fd = open(E.filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd != -1) {
|
||||
if (write(fd, buf, len) == len) {
|
||||
close(fd);
|
||||
free(buf);
|
||||
E.dirty = 0;
|
||||
editorSetStatusMessage("%d bytes written to disk", len);
|
||||
return;
|
||||
}
|
||||
close(fd);
|
||||
for (int i = 0; i < E.numrows; i++)
|
||||
{
|
||||
write(fd, E.rows[i].chars, E.rows[i].size);
|
||||
write(fd, "\n", 1);
|
||||
// fputc('\n', fp);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
editorSetStatusMessage("Can't save! I/O error: %s", strerror(errno));
|
||||
close(fd);
|
||||
|
||||
E.dirty = 0;
|
||||
editorSetStatusMessage("%d bytes written to disk", len);
|
||||
}
|
||||
|
||||
// Helper to convert utf_8_char_t array to byte string for searching
|
||||
static char *row_to_string(erow *row) {
|
||||
// Calculate byte length
|
||||
int byte_len = 0;
|
||||
for (int i = 0; i < row->rsize; i++) {
|
||||
byte_len += row->render[i].len;
|
||||
}
|
||||
|
||||
char *str = malloc(byte_len + 1);
|
||||
if (!str) return NULL;
|
||||
|
||||
// Convert to bytes
|
||||
int pos = 0;
|
||||
for (int i = 0; i < row->rsize; i++) {
|
||||
for (int j = 0; j < row->render[i].len; j++) {
|
||||
str[pos++] = row->render[i].c[j];
|
||||
}
|
||||
}
|
||||
str[pos] = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void editorFind() {
|
||||
char *query = editorPrompt("Search: %s (ESC to cancel)", "", 0);
|
||||
void editorFind()
|
||||
{
|
||||
char* query = editorPrompt("Search: %s (ESC to cancel)", "", 0);
|
||||
if (query == NULL) return;
|
||||
|
||||
|
||||
int saved_cursor_x = E.cursor_x;
|
||||
int saved_cursor_y = E.cursor_y;
|
||||
int saved_row_offset = E.row_offset;
|
||||
int saved_col_offset = E.col_offset;
|
||||
|
||||
#if 0
|
||||
// Search from current position forward
|
||||
for (int i = E.cursor_y; i < E.numrows; i++) {
|
||||
erow *row = &E.row[i];
|
||||
|
||||
for (int i = E.cursor_y; i < E.numrows; i++)
|
||||
{
|
||||
row_t* row = &E.rows[i];
|
||||
|
||||
// Convert row to byte string for searching
|
||||
char *render_str = row_to_string(row);
|
||||
char* render_str = row_to_string(row);
|
||||
if (!render_str) continue;
|
||||
|
||||
char *match = strstr(render_str, query);
|
||||
if (match) {
|
||||
|
||||
char* match = strstr(render_str, query);
|
||||
if (match)
|
||||
{
|
||||
E.cursor_y = i;
|
||||
|
||||
|
||||
// Find the character index from byte position
|
||||
int byte_pos = match - render_str;
|
||||
int char_idx = 0;
|
||||
int current_byte = 0;
|
||||
|
||||
for (char_idx = 0; char_idx < row->rsize; char_idx++) {
|
||||
|
||||
for (char_idx = 0; char_idx < row->rsize; char_idx++)
|
||||
{
|
||||
if (current_byte >= byte_pos) break;
|
||||
current_byte += row->render[char_idx].len;
|
||||
}
|
||||
|
||||
|
||||
E.cursor_x = editorRowRxToCx(row, char_idx);
|
||||
E.row_offset = E.numrows; // Force scroll
|
||||
|
||||
|
||||
free(render_str);
|
||||
free(query);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
free(render_str);
|
||||
}
|
||||
|
||||
|
||||
// Not found - restore cursor position
|
||||
E.cursor_x = saved_cursor_x;
|
||||
E.cursor_y = saved_cursor_y;
|
||||
E.row_offset = saved_row_offset;
|
||||
E.col_offset = saved_col_offset;
|
||||
|
||||
#endif
|
||||
editorSetStatusMessage("Not found: %s", query);
|
||||
free(query);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user