add utf8_char_t struct
This commit is contained in:
+106
-25
@@ -1,4 +1,6 @@
|
||||
#include "../include/row_op.h"
|
||||
#include "include/data.h"
|
||||
#include "include/define.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -6,11 +8,29 @@
|
||||
|
||||
extern struct editorConfig E;
|
||||
|
||||
static int is_tab(utf_8_char_t *ch) {
|
||||
return ch->len == 1 && ch->c[0] == '\t';
|
||||
}
|
||||
|
||||
// Helper function to check if two utf_8_char_t are equal
|
||||
static int utf8_char_equal(utf_8_char_t *a, utf_8_char_t *b) {
|
||||
if (a->len != b->len) return 0;
|
||||
return memcmp(a->c, b->c, a->len) == 0;
|
||||
}
|
||||
|
||||
// Helper function to create a space character
|
||||
static utf_8_char_t make_space() {
|
||||
utf_8_char_t space;
|
||||
space.c[0] = ' ';
|
||||
space.len = 1;
|
||||
return space;
|
||||
}
|
||||
|
||||
int editorRowCxToRx(erow *row, int cursor_x) {
|
||||
int render_x = 0;
|
||||
int i;
|
||||
for (i = 0; i < cursor_x; ++i) {
|
||||
if (row->chars[i] == '\t') {
|
||||
if (is_tab(&row->chars[i])) {
|
||||
render_x += (E.constantes.TAB_LENGTH - 1) - (render_x % E.constantes.TAB_LENGTH);
|
||||
}
|
||||
render_x++;
|
||||
@@ -22,7 +42,7 @@ int editorRowRxToCx(erow *row, int rx) {
|
||||
int cur_rx = 0;
|
||||
int cx;
|
||||
for (cx = 0; cx < row->size; cx++) {
|
||||
if (row->chars[cx] == '\t')
|
||||
if (is_tab(&row->chars[cx]))
|
||||
cur_rx += (E.constantes.TAB_LENGTH - 1) - (cur_rx % E.constantes.TAB_LENGTH);
|
||||
cur_rx++;
|
||||
if (cur_rx > rx) return cx;
|
||||
@@ -39,40 +59,42 @@ void editorUpdateRow(erow *row) {
|
||||
int i, i_render;
|
||||
int tabs = 0;
|
||||
|
||||
// counting number of tabs
|
||||
|
||||
// Count number of tabs
|
||||
for (i = 0; i < row->size; ++i) {
|
||||
tabs +=
|
||||
(row->chars[i] == '\t'); /**< increment tabs of 1 if chars[i] is one. */
|
||||
if (is_tab(&row->chars[i])) {
|
||||
tabs++;
|
||||
}
|
||||
}
|
||||
|
||||
free(row->render);
|
||||
row->render = malloc(row->size + tabs * (E.constantes.TAB_LENGTH - 1) +
|
||||
1); /**< Tabs needs E.constantes.TAB_LENGTH chars so E.constantes.TAB_LENGTH - 1
|
||||
more than the first already counted. */
|
||||
// Allocate space for utf_8_char_t array
|
||||
row->render = malloc(sizeof(utf_8_char_t) * (row->size + tabs * (E.constantes.TAB_LENGTH - 1)));
|
||||
|
||||
if (!row->render) {
|
||||
row->rsize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// end of counting
|
||||
i_render = 0;
|
||||
for (i = 0; i < row->size; ++i) {
|
||||
if (row->chars[i] == '\t') {
|
||||
row->render[i_render++] = ' ';
|
||||
if (is_tab(&row->chars[i])) {
|
||||
// Replace tab with spaces
|
||||
row->render[i_render++] = make_space();
|
||||
while (i_render % E.constantes.TAB_LENGTH) {
|
||||
row->render[i_render++] =
|
||||
' '; /**< Addind the right amount of spaces for tabs */
|
||||
row->render[i_render++] = make_space();
|
||||
}
|
||||
} else {
|
||||
row->render[i_render++] = row->chars[i];
|
||||
}
|
||||
}
|
||||
row->render[i_render] = '\0'; // Don't forget the end of string character.
|
||||
row->rsize = i_render;
|
||||
}
|
||||
|
||||
void editorInsertRow(int at, char *s, size_t len) {
|
||||
if (at < 0 || at > E.numrows) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
erow *tmp = (erow *)realloc(E.row, sizeof(erow) * (E.numrows + 1));
|
||||
if (!tmp) {
|
||||
return;
|
||||
@@ -80,19 +102,78 @@ void editorInsertRow(int at, char *s, size_t len) {
|
||||
E.row = tmp;
|
||||
memmove(&E.row[at + 1], &E.row[at], sizeof(erow) * (E.numrows - at));
|
||||
|
||||
E.row[at].size = len;
|
||||
E.row[at].chars = malloc(len + 1);
|
||||
memcpy(E.row[at].chars, s, len);
|
||||
E.row[at].chars[len] = '\0';
|
||||
|
||||
// Initialize the new row
|
||||
E.row[at].size = 0;
|
||||
E.row[at].chars = NULL;
|
||||
E.row[at].rsize = 0;
|
||||
E.row[at].render = NULL;
|
||||
|
||||
// Count UTF-8 characters first
|
||||
int char_count = 0;
|
||||
int i = 0;
|
||||
while (i < len) {
|
||||
unsigned char first = (unsigned char)s[i];
|
||||
int char_len;
|
||||
|
||||
if ((first & 0x80) == 0) {
|
||||
char_len = 1;
|
||||
} else if ((first & 0xE0) == 0xC0) {
|
||||
char_len = 2;
|
||||
} else if ((first & 0xF0) == 0xE0) {
|
||||
char_len = 3;
|
||||
} else if ((first & 0xF8) == 0xF0) {
|
||||
char_len = 4;
|
||||
} else {
|
||||
char_len = 1; // Invalid, treat as single byte
|
||||
}
|
||||
|
||||
i += char_len;
|
||||
char_count++;
|
||||
}
|
||||
|
||||
// Allocate for the actual number of characters
|
||||
if (char_count > 0) {
|
||||
E.row[at].chars = malloc(sizeof(utf_8_char_t) * char_count);
|
||||
if (!E.row[at].chars) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Now convert to utf_8_char_t array
|
||||
i = 0;
|
||||
E.row[at].size = 0;
|
||||
while (i < len && E.row[at].size < char_count) {
|
||||
utf_8_char_t ch;
|
||||
|
||||
unsigned char first = (unsigned char)s[i];
|
||||
if ((first & 0x80) == 0) {
|
||||
ch.len = 1;
|
||||
} else if ((first & 0xE0) == 0xC0) {
|
||||
ch.len = 2;
|
||||
} else if ((first & 0xF0) == 0xE0) {
|
||||
ch.len = 3;
|
||||
} else if ((first & 0xF8) == 0xF0) {
|
||||
ch.len = 4;
|
||||
} else {
|
||||
ch.len = 1;
|
||||
}
|
||||
|
||||
// Copy bytes
|
||||
for (int j = 0; j < ch.len && i < len; j++) {
|
||||
ch.c[j] = s[i++];
|
||||
}
|
||||
|
||||
E.row[at].chars[E.row[at].size++] = ch;
|
||||
}
|
||||
|
||||
editorUpdateRow(&E.row[at]);
|
||||
|
||||
|
||||
++E.numrows;
|
||||
++E.dirty;
|
||||
}
|
||||
|
||||
|
||||
void editorFreeRow(erow *row) {
|
||||
free(row->render);
|
||||
free(row->chars);
|
||||
@@ -112,16 +193,17 @@ void editorDelRow(int at) {
|
||||
* \fn editorRowInsertChar(erow *row, int at, int c)
|
||||
* \param at Index of where we want to insert the char */
|
||||
|
||||
void editorRowInsertChar(erow *row, int at, int c) {
|
||||
void editorRowInsertChar(erow *row, int at, utf_8_char_t c) {
|
||||
if (E.state == READ_ONLY)
|
||||
return;
|
||||
if (at < 0 || at > row->size) {
|
||||
at = row->size;
|
||||
}
|
||||
row->chars = realloc(row->chars, row->size + 2);
|
||||
row->chars = realloc(row->chars, row->size + 1);
|
||||
memmove(&row->chars[at + 1], &row->chars[at], row->size - at + 1);
|
||||
++row->size;
|
||||
++(row->size);
|
||||
row->chars[at] = c;
|
||||
fprintf(stderr, "Row insert : %s %d\n", c.c, c.len);
|
||||
editorUpdateRow(row);
|
||||
++E.dirty;
|
||||
}
|
||||
@@ -130,7 +212,6 @@ void editorRowAppendString(erow *row, char *s, size_t len) {
|
||||
row->chars = realloc(row->chars, row->size + len + 1);
|
||||
memcpy(&row->chars[row->size], s, len);
|
||||
row->size += len;
|
||||
row->chars[row->size] = '\0';
|
||||
editorUpdateRow(row);
|
||||
++E.dirty;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user