add utf8_char_t struct
This commit is contained in:
+149
-157
@@ -1,200 +1,147 @@
|
||||
#include "../include/input.h"
|
||||
#include "../include/define.h"
|
||||
#include "../include/editor_op.h"
|
||||
#include "../include/output.h"
|
||||
#include "../include/define.h"
|
||||
#include "include/data.h"
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern struct editorConfig E;
|
||||
|
||||
char * file_completion(const char *path) {
|
||||
DIR * dir;
|
||||
struct dirent *entry;
|
||||
char directory[128];
|
||||
char predict[128];
|
||||
int predict_len = 0;
|
||||
char *file_completion(const char *path) {
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
char directory[128];
|
||||
char predict[128];
|
||||
int predict_len = 0;
|
||||
|
||||
if (path[strlen(path) - 1] == '/') {
|
||||
return path;
|
||||
return strdup(path);
|
||||
}
|
||||
|
||||
// Find dir name
|
||||
char * last_slash = strrchr(path, '/');
|
||||
if (last_slash) {
|
||||
size_t dir_len = last_slash - path + 1; // length of dir_path
|
||||
strncpy(directory, path, dir_len);
|
||||
predict_len = strlen(path) - dir_len - 1;
|
||||
strncpy(predict, last_slash + 1, predict_len);
|
||||
directory[dir_len] = '\0';
|
||||
predict[predict_len] = '\0';
|
||||
fprintf(stderr, "%s %s\n", directory, predict);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find dir name
|
||||
char *last_slash = strrchr(path, '/');
|
||||
if (last_slash) {
|
||||
size_t dir_len = last_slash - path + 1;
|
||||
strncpy(directory, path, dir_len);
|
||||
predict_len = strlen(path) - dir_len;
|
||||
strncpy(predict, last_slash + 1, predict_len);
|
||||
directory[dir_len] = '\0';
|
||||
predict[predict_len] = '\0';
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir = opendir(directory);
|
||||
if (!dir)
|
||||
return NULL;
|
||||
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (strncmp(entry->d_name, predict, predict_len) == 0) {
|
||||
static char full_path[128];
|
||||
snprintf(full_path, sizeof(full_path), "%s%s", directory, entry->d_name);
|
||||
|
||||
struct stat st;
|
||||
if (stat(full_path, &st) == 0 && S_ISDIR(st.st_mode)) {
|
||||
strcat(full_path, "/"); // add slash for directories
|
||||
}
|
||||
|
||||
return strdup(full_path);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup when no more entries
|
||||
closedir(dir);
|
||||
dir = NULL;
|
||||
return NULL;
|
||||
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (strncmp(entry->d_name, predict, predict_len) == 0) {
|
||||
static char full_path[128];
|
||||
snprintf(full_path, sizeof(full_path), "%s%s", directory, entry->d_name);
|
||||
|
||||
struct stat st;
|
||||
if (stat(full_path, &st) == 0 && S_ISDIR(st.st_mode)) {
|
||||
strcat(full_path, "/");
|
||||
}
|
||||
closedir(dir);
|
||||
return strdup(full_path);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn char * editorPrompt(struct editorConfig *E, char *prompt, char bPathMode)
|
||||
* \brief Return user input in a prompt when enter is hit. */
|
||||
|
||||
char *editorPrompt(char *prompt, char * placeHolder, char bPathMode) {
|
||||
char *editorPrompt(char *prompt, char *placeHolder, char bPathMode) {
|
||||
size_t buf_size = 128;
|
||||
char *buf = malloc(buf_size);
|
||||
size_t buf_len = 0;
|
||||
int c = 0;
|
||||
buf[0] = '\0';
|
||||
strcpy(buf, placeHolder);
|
||||
buf_len = strlen(placeHolder);
|
||||
strcpy(buf, placeHolder);
|
||||
buf_len = strlen(placeHolder);
|
||||
|
||||
while (1) {
|
||||
editorSetStatusMessage(prompt, buf);
|
||||
editorSetStatusMessage(prompt, buf);
|
||||
editorRefreshScreen();
|
||||
c = editorReadKey();
|
||||
if (c == DEL_KEY || c == CTRL_KEY('h') || c == BACKSPACE) {
|
||||
|
||||
KeyInfo *key = editorReadKey();
|
||||
|
||||
// Handle backspace/delete
|
||||
if (key->type == KEY_SPECIAL && (key->data.special == 127 || key->data.special == 8)) {
|
||||
if (buf_len != 0) {
|
||||
buf[--buf_len] = '\0';
|
||||
}
|
||||
} else if (c == ESCAPE) {
|
||||
}
|
||||
// Handle Ctrl+H (backspace)
|
||||
else if (key->type == KEY_CTRL && key->data.ctrl_char == 'H') {
|
||||
if (buf_len != 0) {
|
||||
buf[--buf_len] = '\0';
|
||||
}
|
||||
}
|
||||
// Handle ESC
|
||||
else if (key->type == KEY_SPECIAL && key->data.special == 27) {
|
||||
editorSetStatusMessage("");
|
||||
free(buf);
|
||||
return NULL;
|
||||
} else if (c == '\r') {
|
||||
}
|
||||
// Handle Enter
|
||||
else if (key->type == KEY_SPECIAL && (key->data.special == 13 || key->data.special == 10)) {
|
||||
if (buf_len != 0) {
|
||||
editorSetStatusMessage("");
|
||||
return buf;
|
||||
}
|
||||
} else if (bPathMode && c == '\t') {
|
||||
char path[128];
|
||||
char * pwd;
|
||||
if (buf[0] != '/') {
|
||||
pwd = getenv("PWD");
|
||||
fprintf(stderr, "%s\n", pwd);
|
||||
memcpy(path, pwd, strlen(pwd));
|
||||
path[strlen(pwd)] = '/';
|
||||
strncat(path, buf, buf_len);
|
||||
} else {
|
||||
strcpy(path, buf);
|
||||
}
|
||||
memset(buf, 0, 128);
|
||||
buf_len = 0;
|
||||
strcpy(buf, file_completion(path));
|
||||
buf_len = strlen(buf);
|
||||
buf[buf_len] = '\0';
|
||||
|
||||
} else if (!iscntrl(c) && c < 128) {
|
||||
}
|
||||
// Handle Tab for path completion
|
||||
else if (bPathMode && key->type == KEY_SPECIAL && key->data.special == 9) {
|
||||
char path[128];
|
||||
char *pwd;
|
||||
if (buf[0] != '/') {
|
||||
pwd = getenv("PWD");
|
||||
snprintf(path, sizeof(path), "%s/%s", pwd, buf);
|
||||
} else {
|
||||
strcpy(path, buf);
|
||||
}
|
||||
|
||||
char *completion = file_completion(path);
|
||||
if (completion) {
|
||||
memset(buf, 0, buf_size);
|
||||
strcpy(buf, completion);
|
||||
buf_len = strlen(buf);
|
||||
free(completion);
|
||||
}
|
||||
}
|
||||
// Handle regular characters (ASCII only for prompts)
|
||||
else if (key->type == KEY_CHAR && key->data.codepoint < 128) {
|
||||
if (buf_len == buf_size - 1) {
|
||||
buf_size *= 2;
|
||||
buf = realloc(buf, buf_size);
|
||||
}
|
||||
buf[buf_len++] = c;
|
||||
buf[buf_len++] = (char)key->data.codepoint;
|
||||
buf[buf_len] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *key_to_string(int key) {
|
||||
static char key_str[32];
|
||||
|
||||
char tmp[10];
|
||||
sprintf(tmp, "%d", key);
|
||||
|
||||
|
||||
// First test enter key
|
||||
|
||||
if (key == '\r') {
|
||||
strcpy(key_str, "ENTER");
|
||||
} else if (key >= 1 && key <= 26) { // CTRL keys
|
||||
snprintf(key_str, sizeof(key_str), "CTRL-%c", 'a' + key - 1);
|
||||
} else {
|
||||
switch (key) {
|
||||
case ARROW_UP:
|
||||
strcpy(key_str, "ARROW-UP");
|
||||
break;
|
||||
case ARROW_DOWN:
|
||||
strcpy(key_str, "ARROW-DOWN");
|
||||
break;
|
||||
case ARROW_LEFT:
|
||||
strcpy(key_str, "ARROW-LEFT");
|
||||
break;
|
||||
case ARROW_RIGHT:
|
||||
strcpy(key_str, "ARROW-RIGHT");
|
||||
break;
|
||||
case PAGE_UP:
|
||||
strcpy(key_str, "PAGE-UP");
|
||||
fprintf(stderr, "pagr up\n");
|
||||
break;
|
||||
case PAGE_DOWN:
|
||||
strcpy(key_str, "PAGE-DOWN");
|
||||
break;
|
||||
case DEL_KEY:
|
||||
fprintf(stderr, "delete key\n");
|
||||
strcpy(key_str, "DEL");
|
||||
|
||||
break;
|
||||
case BACKSPACE:
|
||||
strcpy(key_str, "BACKSPACE");
|
||||
break;
|
||||
case '\r':
|
||||
strcpy(key_str, "ENTER");
|
||||
break;
|
||||
case '\x1b':
|
||||
strcpy(key_str, "ESCAPE");
|
||||
break;
|
||||
case BEG_LINE:
|
||||
strcpy(key_str, "HOME");
|
||||
break;
|
||||
case END_LINE:
|
||||
strcpy(key_str, "END");
|
||||
break;
|
||||
default:
|
||||
// For regular characters
|
||||
if (isprint(key)) {
|
||||
snprintf(key_str, sizeof(key_str), "%c", key);
|
||||
} else {
|
||||
snprintf(key_str, sizeof(key_str), "KEY-%d", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return key_str;
|
||||
}
|
||||
|
||||
|
||||
void editorMoveCursor(int key) {
|
||||
void editorMoveCursor(KeyInfo *key) {
|
||||
if (key->type != KEY_ARROW) return;
|
||||
|
||||
erow *row = (E.cursor_y >= E.numrows) ? NULL : &E.row[E.cursor_y];
|
||||
int row_len;
|
||||
switch (key) {
|
||||
case ARROW_RIGHT:
|
||||
|
||||
switch (key->data.arrow) {
|
||||
case 'C': // Right
|
||||
if (row && E.cursor_x < row->size) {
|
||||
++E.cursor_x;
|
||||
} else if (row && E.cursor_x == row->size) {
|
||||
@@ -202,17 +149,17 @@ void editorMoveCursor(int key) {
|
||||
E.cursor_x = 0;
|
||||
}
|
||||
break;
|
||||
case ARROW_DOWN:
|
||||
case 'B': // Down
|
||||
if (E.cursor_y < E.numrows) {
|
||||
++E.cursor_y;
|
||||
}
|
||||
break;
|
||||
case ARROW_UP:
|
||||
case 'A': // Up
|
||||
if (E.cursor_y != 0) {
|
||||
--E.cursor_y;
|
||||
}
|
||||
break;
|
||||
case ARROW_LEFT:
|
||||
case 'D': // Left
|
||||
if (E.cursor_x != 0) {
|
||||
--E.cursor_x;
|
||||
} else if (E.cursor_y > 0) {
|
||||
@@ -229,28 +176,73 @@ void editorMoveCursor(int key) {
|
||||
}
|
||||
}
|
||||
|
||||
int executeKeyBind(char *key_sequence) {
|
||||
int i;
|
||||
for (i = 0; i < E.number_of_keybinds; ++i) {
|
||||
if (!strcmp(key_sequence, E.key_binds[i].key_sequence)) {
|
||||
KeyInfo *stringToCodepoint(const char *string) {
|
||||
KeyInfo *key = (KeyInfo *)malloc(sizeof(KeyInfo));
|
||||
// test control key
|
||||
if (!strncmp("CTRL", string, 4)) {
|
||||
key->type = KEY_CTRL;
|
||||
key->data.ctrl_char = toupper(string[6]) + 64;
|
||||
} else if (!strncmp("ARROW", string, 5)) {
|
||||
key->type = KEY_ARROW;
|
||||
if (!strcmp("UP", string + 7)) {
|
||||
key->data.arrow = 'A';
|
||||
} else if (!strcmp("DOWN", string + 7)) {
|
||||
key->data.arrow = 'B';
|
||||
} else if (!strcmp("RIGHT", string + 7)) {
|
||||
key->data.arrow = 'C';
|
||||
} else if (!strcmp("LEFT", string + 7)) {
|
||||
key->data.arrow = 'D';
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static int key_match(KeyInfo *a, KeyInfo *b) {
|
||||
if (a->type != b->type) return 0;
|
||||
if (a->modifiers != b->modifiers) return 0;
|
||||
|
||||
fprintf(stderr, "lisp function %s\n", key_sequence);
|
||||
// It's a symbol, create a function call
|
||||
lisp_eval(lisp_cons(E.key_binds[i].command, lisp_null(), E.ctx),
|
||||
&E.ctx_error, E.ctx);
|
||||
return 1;
|
||||
switch (a->type) {
|
||||
case KEY_CTRL:
|
||||
return toupper(a->data.ctrl_char) == toupper(b->data.ctrl_char);
|
||||
case KEY_ALT:
|
||||
return a->data.alt_char == b->data.alt_char;
|
||||
case KEY_ARROW:
|
||||
return a->data.arrow == b->data.arrow;
|
||||
case KEY_FUNCTION:
|
||||
return a->data.function_num == b->data.function_num;
|
||||
case KEY_CHAR:
|
||||
return a->data.codepoint == b->data.codepoint;
|
||||
case KEY_SPECIAL:
|
||||
case KEY_NAVIGATION:
|
||||
return a->data.special == b->data.special;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int executeKeyBind(KeyInfo *key_sequence) {
|
||||
for (int i = 0; i < E.number_of_keybinds; ++i) {
|
||||
fprintf(stderr, "Keybind found\n");
|
||||
if (key_match(key_sequence, E.key_binds[i].key_sequence)) {
|
||||
// Execute the lisp command
|
||||
lisp_eval(lisp_cons(E.key_binds[i].command, lisp_null(), E.ctx),
|
||||
&E.ctx_error, E.ctx);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void editorProcessKeypress() {
|
||||
int c = editorReadKey();
|
||||
KeyInfo *key = editorReadKey();
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
if (executeKeyBind(key_to_string(c))) {
|
||||
if (executeKeyBind(key)) {
|
||||
fprintf(stderr, "Keybinds found\n");
|
||||
return;
|
||||
}
|
||||
editorInsertChar(c);
|
||||
editorInsertChar(&key->c);
|
||||
E.quit_times_buffer = E.constantes.QUIT_TIMES;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user