Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b6b3d1766 | |||
| 3d49a0e2eb |
@@ -86,3 +86,7 @@
|
|||||||
(map-key "\"" editor-split-screen-vertical "user")
|
(map-key "\"" editor-split-screen-vertical "user")
|
||||||
(map-key "o" editor-switch-next-pane "user")
|
(map-key "o" editor-switch-next-pane "user")
|
||||||
(map-key "*" editor-unify-panes "user")
|
(map-key "*" editor-unify-panes "user")
|
||||||
|
(map-key "CTRL-y" editor-paste "no-prefix")
|
||||||
|
(map-key "CTRL-k" editor-cut-end-line "no-prefix")
|
||||||
|
(map-key "a" editor-move-cursor-beg-buffer "user")
|
||||||
|
(map-key "z" editor-move-cursor-end-buffer "user")
|
||||||
|
|||||||
+7
-1
@@ -57,7 +57,13 @@ int bufferSaveAll(void);
|
|||||||
|
|
||||||
void bufferFind(struct buffer_t *buf);
|
void bufferFind(struct buffer_t *buf);
|
||||||
void bufferFindReverse(struct buffer_t* buf);
|
void bufferFindReverse(struct buffer_t* buf);
|
||||||
|
void bufferInsertNewLine();
|
||||||
|
void bufferInsertBytes(const char *src, int n);
|
||||||
|
void bufferDelBytes();
|
||||||
|
void bufferRowInsertBytes(struct buffer_t *buffer, row_t *row, int at, const char *src, int n);
|
||||||
|
void bufferRowDelByte(struct buffer_t *buffer, row_t *row, int at, int n);
|
||||||
|
void bufferInsertRow(struct buffer_t *buffer, int at, char *s, size_t len);
|
||||||
|
void bufferFreeRow(row_t *row);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+6
-2
@@ -45,12 +45,16 @@ Lisp editorSwitchNextPane(Lisp args, LispError *e, LispContext ctx);
|
|||||||
Lisp editorUnifiedPanes(Lisp args, LispError *e, LispContext ctx);
|
Lisp editorUnifiedPanes(Lisp args, LispError *e, LispContext ctx);
|
||||||
|
|
||||||
|
|
||||||
|
Lisp editorPaste(Lisp args, LispError *e, LispContext ctx);
|
||||||
|
Lisp editorCutEndLine(Lisp args, LispError *e, LispContext ctx);
|
||||||
|
|
||||||
|
Lisp editorMoveBegBuffer(Lisp args, LispError *e, LispContext ctx);
|
||||||
|
Lisp editorMoveEndBuffer(Lisp args, LispError *e, LispContext ctx);
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void free_structs(void);
|
void free_structs(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,6 +19,13 @@ typedef struct row {
|
|||||||
char *chars; /**< Characters of the line */
|
char *chars; /**< Characters of the line */
|
||||||
} row_t;
|
} row_t;
|
||||||
|
|
||||||
|
typedef struct context_buffer_t
|
||||||
|
{
|
||||||
|
int editor_x, editor_y;
|
||||||
|
int width, height;
|
||||||
|
row_t *rows;
|
||||||
|
} ContextBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Split modes for screen layout
|
* @brief Split modes for screen layout
|
||||||
*/
|
*/
|
||||||
@@ -113,6 +120,8 @@ struct editorConfig {
|
|||||||
|
|
||||||
row_t *rows; /**< Store all the rows printed */
|
row_t *rows; /**< Store all the rows printed */
|
||||||
|
|
||||||
|
ContextBuffer* context_buffers;
|
||||||
|
|
||||||
int dirty;
|
int dirty;
|
||||||
|
|
||||||
char *status_msg;
|
char *status_msg;
|
||||||
|
|||||||
+12
-2
@@ -2,15 +2,17 @@
|
|||||||
#define DEFINE_H_
|
#define DEFINE_H_
|
||||||
|
|
||||||
#define CTRL_KEY(k) ((k) & 0x1f)
|
#define CTRL_KEY(k) ((k) & 0x1f)
|
||||||
|
#define ALT(k) ((k) | 0x200) // set bit 9 to mark as Option combo
|
||||||
|
|
||||||
|
|
||||||
#define ESCAPE '\x1b'
|
#define ESCAPE '\x1b'
|
||||||
#define CURSOR_TOP_LEFT "\x1b[H"
|
#define CURSOR_TOP_LEFT "\x1b[H"
|
||||||
#define HIDE_CURSOR "\x1b[?25l"
|
#define HIDE_CURSOR "\x1b[?25l"
|
||||||
#define SHOW_CURSOR "\x1b[?25h"
|
#define SHOW_CURSOR "\x1b[?25h"
|
||||||
#define ERASE_END_LINE "\x1b[K"
|
#define ERASE_END_LINE "\x1b[K"
|
||||||
#define TAB "\x9"
|
#define TAB "\t"
|
||||||
#define SPACE "\x20"
|
#define SPACE "\x20"
|
||||||
// #define APP_DEBUG
|
#define APP_DEBUG
|
||||||
|
|
||||||
enum editorKey_e {
|
enum editorKey_e {
|
||||||
BACKSPACE = 127,
|
BACKSPACE = 127,
|
||||||
@@ -29,4 +31,12 @@ enum editorKey_e {
|
|||||||
|
|
||||||
#define BELUGA_VERSION "2.4"
|
#define BELUGA_VERSION "2.4"
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define CLIPBOARD_COPY_CMD "pbcopy"
|
||||||
|
#define CLIPBOARD_PASTE_CMD "pbpaste"
|
||||||
|
#else
|
||||||
|
#define CLIPBOARD_COPY_CMD "xclip -selection clipboard"
|
||||||
|
#define CLIPBOARD_PASTE_CMD "xclip -selection clipboard -o"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // DEFINE_H_
|
#endif // DEFINE_H_
|
||||||
|
|||||||
+4
-3
@@ -3,10 +3,11 @@
|
|||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
|
||||||
void bufferInsertNewLine();
|
|
||||||
void bufferInsertBytes(char *src, int n);
|
|
||||||
void editorSetStatusMessage(const char *fmt, ...);
|
void editorSetStatusMessage(const char *fmt, ...);
|
||||||
void bufferDelBytes();
|
int editorRowCharCount(row_t *row, int x);
|
||||||
|
int editorRowCxToByte(const row_t *row, int cursor_x);
|
||||||
|
char *editorGetClipboard(void);
|
||||||
|
void editorSetClipboard(const char *text, int len);
|
||||||
|
|
||||||
|
|
||||||
#endif // EDITOR_OP_H_
|
#endif // EDITOR_OP_H_
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
#define FILE_IO_H_
|
#define FILE_IO_H_
|
||||||
|
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "row_op.h"
|
|
||||||
#include "terminal.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
char *editorPrompt(char *prompt, char * PlaceHolder, char bPathMode);
|
char *editorPrompt(char *prompt, char * PlaceHolder, char bPathMode);
|
||||||
|
|
||||||
const char *file_completion(const char *path);
|
const char *fileCompletion(const char *path);
|
||||||
|
|
||||||
int editorMoveCursor(int key);
|
int editorMoveCursor(int key);
|
||||||
|
|
||||||
|
|||||||
+3
-6
@@ -8,11 +8,8 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
void bufferInsertRow(struct buffer_t *buffer, int at, char *s, size_t len);
|
|
||||||
int editorRowCxToByte(const row_t *row, int cursor_x);
|
|
||||||
void bufferFreeRow(row_t *row);
|
|
||||||
int editorRowCharCount(row_t *row, int x);
|
|
||||||
void bufferRowInsertBytes(struct buffer_t *buffer, row_t *row, int at, char *src, int n);
|
|
||||||
void bufferRowDelByte(struct buffer_t *buffer, row_t *row, int at, int n);
|
|
||||||
|
|
||||||
#endif // ROW_OP_H_
|
#endif // ROW_OP_H_
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#ifndef SYNTAX_HIGHLIGHTER_H_
|
#ifndef SYNTAX_HIGHLIGHTER_H_
|
||||||
#define SYNTAX_HIGHLIGHTER_H_
|
#define SYNTAX_HIGHLIGHTER_H_
|
||||||
|
|
||||||
#include "color.h"
|
|
||||||
|
|
||||||
// Color codes that only affect foreground, preserving your background color
|
// Color codes that only affect foreground, preserving your background color
|
||||||
#define COLOR_RESET "\x1b[39m" // Reset all (4 bytes)
|
#define COLOR_RESET "\x1b[39m" // Reset all (4 bytes)
|
||||||
@@ -20,4 +19,3 @@ typedef enum {
|
|||||||
char *highlight_line(const char * line, int *length);
|
char *highlight_line(const char * line, int *length);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
/* includes */
|
/* includes */
|
||||||
|
|
||||||
#include "data.h"
|
|
||||||
#include "define.h"
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -31,7 +29,7 @@ int getCursorPosition(int *rows, int *cols);
|
|||||||
|
|
||||||
int getWindowSize(int *rows, int *cols);
|
int getWindowSize(int *rows, int *cols);
|
||||||
|
|
||||||
char *key_to_string(int key);
|
char *keyToString(int key);
|
||||||
|
|
||||||
void appDebug(const char *fmt, ...);
|
void appDebug(const char *fmt, ...);
|
||||||
|
|
||||||
|
|||||||
@@ -11,13 +11,10 @@
|
|||||||
|
|
||||||
#include "include/buffer.h"
|
#include "include/buffer.h"
|
||||||
#include "include/split_screen.h"
|
#include "include/split_screen.h"
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "include/data.h"
|
#include "include/data.h"
|
||||||
#include "include/file_io.h"
|
|
||||||
#include "include/init.h"
|
#include "include/init.h"
|
||||||
#include "include/input.h"
|
#include "include/input.h"
|
||||||
#include "include/editor_op.h"
|
#include "include/editor_op.h"
|
||||||
|
|||||||
@@ -30,4 +30,6 @@ src_files = files(
|
|||||||
executable('beluga',
|
executable('beluga',
|
||||||
src_files,
|
src_files,
|
||||||
dependencies: [m]
|
dependencies: [m]
|
||||||
|
)
|
||||||
|
dependencies: [m]
|
||||||
)
|
)
|
||||||
|
|||||||
+153
-3
@@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
#include "include/input.h"
|
#include "include/input.h"
|
||||||
|
|
||||||
extern struct editorConfig E;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Finds a buffer by filename
|
* @brief Finds a buffer by filename
|
||||||
@@ -284,7 +283,6 @@ void bufferFind(struct buffer_t* buf)
|
|||||||
{
|
{
|
||||||
appDebug("searching\n");
|
appDebug("searching\n");
|
||||||
char* query = editorPrompt("Search: %s (ESC to cancel)", "", 0);
|
char* query = editorPrompt("Search: %s (ESC to cancel)", "", 0);
|
||||||
EditorPane* active = splitScreenGetActivePane();
|
|
||||||
|
|
||||||
if (query == NULL)
|
if (query == NULL)
|
||||||
return;
|
return;
|
||||||
@@ -306,7 +304,6 @@ void bufferFindReverse(struct buffer_t* buf)
|
|||||||
{
|
{
|
||||||
appDebug("searching\n");
|
appDebug("searching\n");
|
||||||
char* query = editorPrompt("Reverse search: %s (ESC to cancel)", "", 0);
|
char* query = editorPrompt("Reverse search: %s (ESC to cancel)", "", 0);
|
||||||
EditorPane* active = splitScreenGetActivePane();
|
|
||||||
|
|
||||||
if (query == NULL)
|
if (query == NULL)
|
||||||
return;
|
return;
|
||||||
@@ -325,3 +322,156 @@ void bufferFindReverse(struct buffer_t* buf)
|
|||||||
}
|
}
|
||||||
free(query);
|
free(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bufferInsertRow(struct buffer_t *buffer, int at, char *s, size_t len) {
|
||||||
|
if (at < 0 || at > buffer->numrows)
|
||||||
|
return;
|
||||||
|
|
||||||
|
row_t *tmp = realloc(buffer->row, sizeof(row_t) * (buffer->numrows + 1));
|
||||||
|
if (!tmp)
|
||||||
|
return;
|
||||||
|
buffer->row = tmp;
|
||||||
|
|
||||||
|
/* Shift existing rows to make room at 'at' — no at++ */
|
||||||
|
if (at < buffer->numrows) {
|
||||||
|
memmove(&buffer->row[at + 1], &buffer->row[at],
|
||||||
|
sizeof(row_t) * (buffer->numrows - at)); /* not -at+1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->row[at].size = len;
|
||||||
|
buffer->row[at].cap = len + 1;
|
||||||
|
buffer->row[at].chars = malloc(len + 1);
|
||||||
|
if (!buffer->row[at].chars)
|
||||||
|
return;
|
||||||
|
memcpy(buffer->row[at].chars, s, len);
|
||||||
|
buffer->row[at].chars[len] = '\0'; /* always NUL-terminate */
|
||||||
|
|
||||||
|
buffer->numrows++;
|
||||||
|
buffer->dirty++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bufferFreeRow(row_t *row) { free(row->chars); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn editorRowInsertChar(erow *row, int at, int c)
|
||||||
|
* \param at Index of where we want to insert the char */
|
||||||
|
|
||||||
|
void bufferRowInsertBytes(struct buffer_t *buffer, row_t *row, int at,
|
||||||
|
const char *src, int n) {
|
||||||
|
if (buffer->state == READ_ONLY)
|
||||||
|
return;
|
||||||
|
if (row->size + n + 1 > row->cap) {
|
||||||
|
row->cap = (row->size + n + 1) * 2;
|
||||||
|
row->chars = realloc(row->chars, row->cap);
|
||||||
|
}
|
||||||
|
memmove(row->chars + at + n, row->chars + at, row->size - at);
|
||||||
|
memcpy(row->chars + at, src, n);
|
||||||
|
row->size += n;
|
||||||
|
row->chars = realloc(row->chars, row->size + 2);
|
||||||
|
++buffer->dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn bufferRowDelChar(struct bufferConfig *E, frow *frow, int at)
|
||||||
|
* \brief Delete the a char at the chosen position on the given row
|
||||||
|
* \param at Index of the char to delete
|
||||||
|
* \param row Row on operation is made */
|
||||||
|
void bufferRowDelByte(struct buffer_t *buffer, row_t *row, int at, int n) {
|
||||||
|
if (buffer->state == READ_ONLY)
|
||||||
|
return;
|
||||||
|
if (at < 0 || at >= row->size)
|
||||||
|
return;
|
||||||
|
memmove(row->chars + at, row->chars + at + n, row->size - at - n);
|
||||||
|
row->size -= n;
|
||||||
|
row->chars[row->size] = '\0';
|
||||||
|
buffer->x -= n;
|
||||||
|
++buffer->dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bufferInsertBytes(const char* src, int n)
|
||||||
|
{
|
||||||
|
appDebug("bufferInsertBytes \r\n");
|
||||||
|
EditorPane* active = splitScreenGetActivePane();
|
||||||
|
struct buffer_t* buf = bufferFindById(active->buffer_id);
|
||||||
|
if (buf->y == buf->numrows)
|
||||||
|
{
|
||||||
|
bufferInsertRow(buf, buf->numrows, "", 0);
|
||||||
|
}
|
||||||
|
bufferRowInsertBytes(buf, &buf->row[buf->y], buf->x, src, n);
|
||||||
|
buf->x += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bufferDelBytes(void)
|
||||||
|
{
|
||||||
|
EditorPane* active = splitScreenGetActivePane();
|
||||||
|
struct buffer_t* buf = bufferFindById(active->buffer_id);
|
||||||
|
|
||||||
|
/* Nothing to delete */
|
||||||
|
if (buf->numrows == 0) return;
|
||||||
|
if (buf->x == 0 && buf->y == 0) return;
|
||||||
|
|
||||||
|
/* Use row_offset, not col_offset, for row indexing */
|
||||||
|
row_t* r = &buf->row[buf->y];
|
||||||
|
|
||||||
|
if (buf->x > 0)
|
||||||
|
{
|
||||||
|
int byte_end = editorRowCxToByte(r, buf->x);
|
||||||
|
int byte_start = editorRowCxToByte(r, buf->x - 1);
|
||||||
|
int char_width = byte_end - byte_start; /* byte width of the character */
|
||||||
|
|
||||||
|
bufferRowDelByte(buf, r, byte_start, char_width);
|
||||||
|
E.dirty = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Merge current row into the previous one */
|
||||||
|
row_t* prev = &buf->row[buf->y - 1]; // FIX: was buf->y (same as r)
|
||||||
|
int prev_char_count = editorRowCharCount(prev, prev->size);
|
||||||
|
|
||||||
|
bufferRowInsertBytes(buf, prev, prev->size, r->chars, r->size);
|
||||||
|
free(r->chars);
|
||||||
|
r->chars = NULL;
|
||||||
|
|
||||||
|
memmove(&buf->row[buf->y],
|
||||||
|
&buf->row[buf->y + 1],
|
||||||
|
sizeof(row_t) * (buf->numrows - buf->y - 1));
|
||||||
|
buf->numrows--;
|
||||||
|
|
||||||
|
active->cursor_x = prev_char_count;
|
||||||
|
buf->x = prev_char_count;
|
||||||
|
active->cursor_y--;
|
||||||
|
buf->y--;
|
||||||
|
E.dirty = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bufferInsertNewLine(void) {
|
||||||
|
appDebug("Inserting new line\n");
|
||||||
|
EditorPane *active = splitScreenGetActivePane();
|
||||||
|
struct buffer_t *buf = bufferFindById(active->buffer_id);
|
||||||
|
|
||||||
|
appDebug("buf x %d\n", buf->x);
|
||||||
|
|
||||||
|
if (buf->y >= buf->numrows) {
|
||||||
|
/* Cursor is past the last row: just append a blank line */
|
||||||
|
bufferInsertRow(buf, buf->numrows, "", 0);
|
||||||
|
} else {
|
||||||
|
row_t *row = &buf->row[buf->y];
|
||||||
|
|
||||||
|
/* Insert the tail (from cursor to end) as a new row below */
|
||||||
|
bufferInsertRow(buf, buf->y + 1, &row->chars[buf->x], row->size - buf->x);
|
||||||
|
|
||||||
|
/* Re-fetch: realloc inside bufferInsertRow may have moved the array */
|
||||||
|
row = &buf->row[buf->y];
|
||||||
|
|
||||||
|
/* Truncate the current row at the cursor */
|
||||||
|
row->size = buf->x;
|
||||||
|
row->chars[row->size] = '\0';
|
||||||
|
/* Do NOT touch row->cap — the allocation is still valid */
|
||||||
|
}
|
||||||
|
|
||||||
|
buf->y++;
|
||||||
|
buf->x = 0;
|
||||||
|
appDebug("Insert new line done\n");
|
||||||
|
}
|
||||||
+49
-4
@@ -13,8 +13,9 @@
|
|||||||
#include "../include/editor_op.h"
|
#include "../include/editor_op.h"
|
||||||
#include "../include/file_io.h"
|
#include "../include/file_io.h"
|
||||||
#include "../include/input.h"
|
#include "../include/input.h"
|
||||||
#include "../include/row_op.h"
|
#include "../include/terminal.h"
|
||||||
#include "../include/split_screen.h"
|
#include "../include/split_screen.h"
|
||||||
|
#include "../include/completion.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -223,8 +224,6 @@ Lisp l_editorInsertNewLine(Lisp args, LispError *e, LispContext ctx) {
|
|||||||
* @note Uses E.constantes.TAB_LENGTH for indentation width
|
* @note Uses E.constantes.TAB_LENGTH for indentation width
|
||||||
*/
|
*/
|
||||||
Lisp l_editorInserTab(Lisp args, LispError *e, LispContext ctx) {
|
Lisp l_editorInserTab(Lisp args, LispError *e, LispContext ctx) {
|
||||||
EditorPane *active = splitScreenGetActivePane();
|
|
||||||
struct buffer_t *buf = bufferFindById(active->buffer_id);
|
|
||||||
for (int i = 0; i < E.constantes.TAB_LENGTH; ++i) {
|
for (int i = 0; i < E.constantes.TAB_LENGTH; ++i) {
|
||||||
bufferInsertBytes(" ", 1);
|
bufferInsertBytes(" ", 1);
|
||||||
}
|
}
|
||||||
@@ -359,7 +358,7 @@ Lisp editorOpenFile(Lisp args, LispError *e, LispContext ctx) {
|
|||||||
* @note Uses first character of the string argument
|
* @note Uses first character of the string argument
|
||||||
*/
|
*/
|
||||||
Lisp editorPrintC(Lisp args, LispError *e, LispContext ctx) {
|
Lisp editorPrintC(Lisp args, LispError *e, LispContext ctx) {
|
||||||
char *src = lisp_string(lisp_car(args));
|
const char *src = lisp_string(lisp_car(args));
|
||||||
bufferInsertBytes(src, strlen(src));
|
bufferInsertBytes(src, strlen(src));
|
||||||
return lisp_null();
|
return lisp_null();
|
||||||
}
|
}
|
||||||
@@ -514,3 +513,49 @@ Lisp editorPrefix(Lisp args, LispError *e, LispContext ctx) {
|
|||||||
64);
|
64);
|
||||||
return lisp_null();
|
return lisp_null();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lisp editorPaste(Lisp args, LispError *e, LispContext ctx)
|
||||||
|
{
|
||||||
|
const char *char_to_paste = editorGetClipboard();
|
||||||
|
appDebug("editor-paste, %s\n", char_to_paste);
|
||||||
|
bufferInsertBytes(char_to_paste, (int) strlen(char_to_paste));
|
||||||
|
return lisp_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp editorCutEndLine(Lisp args, LispError *e, LispContext ctx)
|
||||||
|
{
|
||||||
|
EditorPane *active = splitScreenGetActivePane();
|
||||||
|
struct buffer_t *buffer = bufferFindById(active->buffer_id);
|
||||||
|
int bytes_to_delete = buffer->row[buffer->y].size - buffer->x;
|
||||||
|
editorSetClipboard(&buffer->row[buffer->y].chars[buffer->x], bytes_to_delete);
|
||||||
|
buffer->x = buffer->row[buffer->y].size;
|
||||||
|
while (bytes_to_delete--)
|
||||||
|
{
|
||||||
|
bufferDelBytes();
|
||||||
|
}
|
||||||
|
return lisp_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp editorMoveBegBuffer(Lisp args, LispError *e, LispContext ctx)
|
||||||
|
{
|
||||||
|
EditorPane *active = splitScreenGetActivePane();
|
||||||
|
struct buffer_t *buffer = bufferFindById(active->buffer_id);
|
||||||
|
buffer->x = 0;
|
||||||
|
buffer->y = 0;
|
||||||
|
return lisp_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp editorMoveEndBuffer(Lisp args, LispError *e, LispContext ctx)
|
||||||
|
{
|
||||||
|
EditorPane *active = splitScreenGetActivePane();
|
||||||
|
struct buffer_t *buffer = bufferFindById(active->buffer_id);
|
||||||
|
buffer->x = buffer->row[buffer->numrows-1].size;
|
||||||
|
buffer->y = buffer->numrows-1;
|
||||||
|
return lisp_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
Lisp editorAutoComplete(Lisp args, LispError *e, LispContext ctx)
|
||||||
|
{
|
||||||
|
createContextBuffer(E.cursor_x - 2, E.cursor_y + 1, "hello");
|
||||||
|
return lisp_null();
|
||||||
|
}
|
||||||
+91
-81
@@ -31,90 +31,100 @@ void editorSetStatusMessage(const char* fmt, ...)
|
|||||||
E.status_msg_time = time(NULL);
|
E.status_msg_time = time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
void bufferInsertBytes(char* src, int n)
|
* @brief Moves the cursor based on arrow key input
|
||||||
{
|
* @details Updates cursor position (E.cursor_x, E.cursor_y) based on the given
|
||||||
appDebug("bufferInsertBytes \r\n");
|
* key direction. Handles line wrapping and boundary conditions. Prevents cursor
|
||||||
EditorPane* active = splitScreenGetActivePane();
|
* from exceeding line lengths.
|
||||||
struct buffer_t* buf = bufferFindById(active->buffer_id);
|
* @param key The arrow key code (ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT)
|
||||||
if (buf->y == buf->numrows)
|
* @return 1 if cursor movement was valid, 0 if cursor was constrained to line boundary
|
||||||
{
|
* @note Updates global editor state E
|
||||||
bufferInsertRow(buf, buf->numrows, "", 0);
|
*/
|
||||||
}
|
int editorMoveCursor(int key) {
|
||||||
bufferRowInsertBytes(buf, &buf->row[buf->y], buf->x, src, n);
|
|
||||||
buf->x += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bufferDelBytes(void)
|
|
||||||
{
|
|
||||||
EditorPane* active = splitScreenGetActivePane();
|
|
||||||
struct buffer_t* buf = bufferFindById(active->buffer_id);
|
|
||||||
|
|
||||||
/* Nothing to delete */
|
|
||||||
if (buf->numrows == 0) return;
|
|
||||||
if (buf->x == 0 && buf->y == 0) return;
|
|
||||||
|
|
||||||
/* Use row_offset, not col_offset, for row indexing */
|
|
||||||
row_t* r = &buf->row[buf->y];
|
|
||||||
|
|
||||||
if (buf->x > 0)
|
|
||||||
{
|
|
||||||
int byte_end = editorRowCxToByte(r, buf->x);
|
|
||||||
int byte_start = editorRowCxToByte(r, buf->x - 1);
|
|
||||||
int char_width = byte_end - byte_start; /* byte width of the character */
|
|
||||||
|
|
||||||
bufferRowDelByte(buf, r, byte_start, char_width);
|
|
||||||
E.dirty = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Merge current row into the previous one */
|
|
||||||
row_t* prev = &buf->row[buf->y - 1]; // FIX: was buf->y (same as r)
|
|
||||||
int prev_char_count = editorRowCharCount(prev, prev->size);
|
|
||||||
|
|
||||||
bufferRowInsertBytes(buf, prev, prev->size, r->chars, r->size);
|
|
||||||
free(r->chars);
|
|
||||||
r->chars = NULL;
|
|
||||||
|
|
||||||
memmove(&buf->row[buf->y],
|
|
||||||
&buf->row[buf->y + 1],
|
|
||||||
sizeof(row_t) * (buf->numrows - buf->y - 1));
|
|
||||||
buf->numrows--;
|
|
||||||
|
|
||||||
active->cursor_x = prev_char_count;
|
|
||||||
buf->x = prev_char_count;
|
|
||||||
active->cursor_y--;
|
|
||||||
buf->y--;
|
|
||||||
E.dirty = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bufferInsertNewLine(void) {
|
|
||||||
appDebug("Inserting new line\n");
|
|
||||||
EditorPane *active = splitScreenGetActivePane();
|
EditorPane *active = splitScreenGetActivePane();
|
||||||
struct buffer_t *buf = bufferFindById(active->buffer_id);
|
struct buffer_t *buf = bufferFindById(active->buffer_id);
|
||||||
|
|
||||||
appDebug("buf x %d\n", buf->x);
|
|
||||||
|
|
||||||
if (buf->y >= buf->numrows) {
|
|
||||||
/* Cursor is past the last row: just append a blank line */
|
|
||||||
bufferInsertRow(buf, buf->numrows, "", 0);
|
|
||||||
} else {
|
|
||||||
row_t *row = &buf->row[buf->y];
|
row_t *row = &buf->row[buf->y];
|
||||||
|
switch (key) {
|
||||||
/* Insert the tail (from cursor to end) as a new row below */
|
case ARROW_RIGHT:
|
||||||
bufferInsertRow(buf, buf->y + 1, &row->chars[buf->x], row->size - buf->x);
|
if (row && buf->x < row->size) {
|
||||||
|
int len = utf8Seqlen(row->chars[buf->x]);
|
||||||
/* Re-fetch: realloc inside bufferInsertRow may have moved the array */
|
buf->x += len;
|
||||||
row = &buf->row[buf->y];
|
} else if (row && buf->y < buf->numrows) {
|
||||||
|
|
||||||
/* Truncate the current row at the cursor */
|
|
||||||
row->size = buf->x;
|
|
||||||
row->chars[row->size] = '\0';
|
|
||||||
/* Do NOT touch row->cap — the allocation is still valid */
|
|
||||||
}
|
|
||||||
|
|
||||||
buf->y++;
|
buf->y++;
|
||||||
buf->x = 0;
|
buf->x = 0;
|
||||||
appDebug("Insert new line done\n");
|
}
|
||||||
|
break;
|
||||||
|
case ARROW_DOWN:
|
||||||
|
if (buf->y < buf->numrows) {
|
||||||
|
|
||||||
|
buf->y++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ARROW_UP:
|
||||||
|
if (buf->y != 0) {
|
||||||
|
--buf->y;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ARROW_LEFT:
|
||||||
|
if (buf->x != 0) {
|
||||||
|
--buf->x;
|
||||||
|
} else if (buf->y > 0) {
|
||||||
|
--buf->y;
|
||||||
|
buf->x = buf->row[buf->y].size;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *editorGetClipboard(void) {
|
||||||
|
FILE *pipe = popen(CLIPBOARD_PASTE_CMD, "r");
|
||||||
|
if (!pipe) return NULL;
|
||||||
|
|
||||||
|
size_t cap = 4096;
|
||||||
|
size_t len = 0;
|
||||||
|
char *buf = malloc(cap);
|
||||||
|
|
||||||
|
int c;
|
||||||
|
while ((c = fgetc(pipe)) != EOF) {
|
||||||
|
if (len + 1 >= cap) {
|
||||||
|
cap *= 2;
|
||||||
|
buf = realloc(buf, cap);
|
||||||
|
}
|
||||||
|
buf[len++] = (char)c;
|
||||||
|
}
|
||||||
|
buf[len] = '\0';
|
||||||
|
pclose(pipe);
|
||||||
|
return buf; // caller must free
|
||||||
|
}
|
||||||
|
|
||||||
|
void editorSetClipboard(const char *text, int len) {
|
||||||
|
FILE *pipe = popen(CLIPBOARD_COPY_CMD, "w");
|
||||||
|
if (!pipe) return;
|
||||||
|
fwrite(text, 1, len, pipe);
|
||||||
|
pclose(pipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
int editorRowCxToByte(const row_t *row, int cursor_x) {
|
||||||
|
int i = 0, col = 0;
|
||||||
|
while (col < cursor_x && i < row->size) {
|
||||||
|
int sl = utf8Seqlen((unsigned char)row->chars[i]);
|
||||||
|
if (sl < 1)
|
||||||
|
sl = 1;
|
||||||
|
col++;
|
||||||
|
i += sl;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int editorRowCharCount(row_t *row, int x) {
|
||||||
|
int n = 0, i = 0;
|
||||||
|
while (i < x && i < row->size) {
|
||||||
|
int sl = utf8Seqlen((unsigned char)row->chars[i]);
|
||||||
|
if (sl < 1)
|
||||||
|
sl = 1;
|
||||||
|
n++;
|
||||||
|
i += sl;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "../include/buffer.h"
|
#include "../include/buffer.h"
|
||||||
#include "../include/data.h"
|
#include "../include/data.h"
|
||||||
#include "../include/split_screen.h"
|
#include "../include/split_screen.h"
|
||||||
|
#include "../include/row_op.h"
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
+6
-2
@@ -45,6 +45,10 @@ void initBuiltins() {
|
|||||||
registerBuiltin("editor-split-screen-vertical", l_editorSplitScreenVertical);
|
registerBuiltin("editor-split-screen-vertical", l_editorSplitScreenVertical);
|
||||||
registerBuiltin("editor-switch-next-pane", editorSwitchNextPane);
|
registerBuiltin("editor-switch-next-pane", editorSwitchNextPane);
|
||||||
registerBuiltin("editor-unify-panes", editorUnifiedPanes);
|
registerBuiltin("editor-unify-panes", editorUnifiedPanes);
|
||||||
|
registerBuiltin("editor-paste", editorPaste);
|
||||||
|
registerBuiltin("editor-cut-end-line", editorCutEndLine);
|
||||||
|
registerBuiltin("editor-move-cursor-beg-buffer", editorMoveBegBuffer);
|
||||||
|
registerBuiltin("editor-move-cursor-end-buffer", editorMoveEndBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initConfig() {
|
void initConfig() {
|
||||||
@@ -64,7 +68,7 @@ void initConfig() {
|
|||||||
lisp_eval(E.ctx_data, &E.ctx_error, E.ctx);
|
lisp_eval(E.ctx_data, &E.ctx_error, E.ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_theme() {
|
void initTheme() {
|
||||||
E.constantes.THEME = (char *)lisp_string(
|
E.constantes.THEME = (char *)lisp_string(
|
||||||
lisp_eval(lisp_read("THEME", &E.ctx_error, E.ctx), &E.ctx_error, E.ctx));
|
lisp_eval(lisp_read("THEME", &E.ctx_error, E.ctx), &E.ctx_error, E.ctx));
|
||||||
if (strcmp(E.constantes.THEME, "dark") == 0) {
|
if (strcmp(E.constantes.THEME, "dark") == 0) {
|
||||||
@@ -130,7 +134,7 @@ void initEditor() {
|
|||||||
|
|
||||||
initConfig();
|
initConfig();
|
||||||
|
|
||||||
init_theme();
|
initTheme();
|
||||||
|
|
||||||
// To modify
|
// To modify
|
||||||
|
|
||||||
|
|||||||
+3
-62
@@ -5,7 +5,6 @@
|
|||||||
#include "include/data.h"
|
#include "include/data.h"
|
||||||
#include "include/buffer.h"
|
#include "include/buffer.h"
|
||||||
#include "include/data.h"
|
#include "include/data.h"
|
||||||
#include "include/row_op.h"
|
|
||||||
#include "include/split_screen.h"
|
#include "include/split_screen.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -41,7 +40,7 @@ extern struct editorConfig E;
|
|||||||
* @note Caller is responsible for freeing the returned string
|
* @note Caller is responsible for freeing the returned string
|
||||||
* @note Uses static buffer internally; may return stale pointers across calls
|
* @note Uses static buffer internally; may return stale pointers across calls
|
||||||
*/
|
*/
|
||||||
const char *file_completion(const char *path) {
|
const char *fileCompletion(const char *path) {
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
char directory[256];
|
char directory[256];
|
||||||
@@ -153,7 +152,7 @@ char *editorPrompt(char *prompt, char *placeHolder, char bPathMode) {
|
|||||||
}
|
}
|
||||||
memset(buf, 0, 256);
|
memset(buf, 0, 256);
|
||||||
buf_len = 0;
|
buf_len = 0;
|
||||||
char * buf_complete = (char *) file_completion(path);
|
char * buf_complete = (char *) fileCompletion(path);
|
||||||
strcpy(buf, buf_complete);
|
strcpy(buf, buf_complete);
|
||||||
free(buf_complete);
|
free(buf_complete);
|
||||||
buf_len = strlen(buf);
|
buf_len = strlen(buf);
|
||||||
@@ -170,65 +169,7 @@ char *editorPrompt(char *prompt, char *placeHolder, char bPathMode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Moves the cursor based on arrow key input
|
|
||||||
* @details Updates cursor position (E.cursor_x, E.cursor_y) based on the given
|
|
||||||
* key direction. Handles line wrapping and boundary conditions. Prevents cursor
|
|
||||||
* from exceeding line lengths.
|
|
||||||
* @param key The arrow key code (ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT)
|
|
||||||
* @return 1 if cursor movement was valid, 0 if cursor was constrained to line boundary
|
|
||||||
* @note Updates global editor state E
|
|
||||||
*/
|
|
||||||
int editorMoveCursor(int key) {
|
|
||||||
EditorPane *active = splitScreenGetActivePane();
|
|
||||||
struct buffer_t *buf = bufferFindById(active->buffer_id);
|
|
||||||
row_t *row = &buf->row[buf->y];
|
|
||||||
switch (key) {
|
|
||||||
case ARROW_RIGHT:
|
|
||||||
if (row && buf->x < row->size) {
|
|
||||||
int len = utf8Seqlen(row->chars[buf->x]);
|
|
||||||
buf->x += len;
|
|
||||||
} else if (row && buf->y < buf->numrows) {
|
|
||||||
buf->y++;
|
|
||||||
buf->x = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ARROW_DOWN:
|
|
||||||
if (buf->y < buf->numrows) {
|
|
||||||
|
|
||||||
buf->y++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ARROW_UP:
|
|
||||||
if (buf->y != 0) {
|
|
||||||
--buf->y;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ARROW_LEFT:
|
|
||||||
if (buf->x != 0) {
|
|
||||||
--buf->x;
|
|
||||||
} else if (buf->y > 0) {
|
|
||||||
--buf->y;
|
|
||||||
buf->x = buf->row[buf->y].size;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
fprintf(stderr, "acx: %d acy %d aox %d aoy %d bx %d by %d ah %d aw %d\n",
|
|
||||||
active->cursor_x,
|
|
||||||
active->cursor_y,
|
|
||||||
active->x_offset,
|
|
||||||
active->y_offset,
|
|
||||||
buf->x,
|
|
||||||
buf->y,
|
|
||||||
active->height,
|
|
||||||
active->width
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Executes the command bound to a key sequence
|
* @brief Executes the command bound to a key sequence
|
||||||
@@ -272,7 +213,7 @@ void editorProcessKeypress() {
|
|||||||
int c = editorReadKey();
|
int c = editorReadKey();
|
||||||
char key_sequence[8];
|
char key_sequence[8];
|
||||||
|
|
||||||
if (executeKeyBind(key_to_string(c))) {
|
if (executeKeyBind(keyToString(c))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int seq_len = utf8Encode(c, key_sequence);
|
int seq_len = utf8Encode(c, key_sequence);
|
||||||
|
|||||||
+11
-17
@@ -8,6 +8,7 @@
|
|||||||
#include "../include/output.h"
|
#include "../include/output.h"
|
||||||
#include "../include/append_buffer.h"
|
#include "../include/append_buffer.h"
|
||||||
#include "../include/buffer.h"
|
#include "../include/buffer.h"
|
||||||
|
#include "../include/editor_op.h"
|
||||||
#include "../include/data.h"
|
#include "../include/data.h"
|
||||||
#include "../include/define.h"
|
#include "../include/define.h"
|
||||||
#include "../include/row_op.h"
|
#include "../include/row_op.h"
|
||||||
@@ -29,14 +30,9 @@ static void editorDrawPane(struct abuf* ab, EditorPane* pane)
|
|||||||
int file_row;
|
int file_row;
|
||||||
char pos_buf[32];
|
char pos_buf[32];
|
||||||
int pos_len;
|
int pos_len;
|
||||||
int chars_printed;
|
|
||||||
int start_offset;
|
|
||||||
int byte_len_to_print;
|
int byte_len_to_print;
|
||||||
int bytes_to_print;
|
int bytes_to_print;
|
||||||
char* highlighted;
|
char* highlighted;
|
||||||
char welcome[80];
|
|
||||||
int welcome_len;
|
|
||||||
int padding;
|
|
||||||
|
|
||||||
if (pane == NULL || pane->buffer_id < 0)
|
if (pane == NULL || pane->buffer_id < 0)
|
||||||
return;
|
return;
|
||||||
@@ -56,9 +52,8 @@ static void editorDrawPane(struct abuf* ab, EditorPane* pane)
|
|||||||
abAppend(ab, pos_buf, pos_len);
|
abAppend(ab, pos_buf, pos_len);
|
||||||
|
|
||||||
// Apply background color (6 bytes for RGB format)
|
// Apply background color (6 bytes for RGB format)
|
||||||
abAppend(ab, E.theme.BACKGROUND_COLOR, strlen(E.theme.BACKGROUND_COLOR));
|
abAppend(ab, E.theme.BACKGROUND_COLOR, (int) strlen(E.theme.BACKGROUND_COLOR));
|
||||||
|
|
||||||
chars_printed = 0;
|
|
||||||
|
|
||||||
// pane line is out of buffer
|
// pane line is out of buffer
|
||||||
if (file_row >= buf->numrows)
|
if (file_row >= buf->numrows)
|
||||||
@@ -75,7 +70,7 @@ static void editorDrawPane(struct abuf* ab, EditorPane* pane)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
start_offset = pane->x_offset;
|
|
||||||
|
|
||||||
if (buf->filename[strlen(buf->filename) - 1] == 'c' || buf->filename[strlen(buf->filename) - 1] == 'h')
|
if (buf->filename[strlen(buf->filename) - 1] == 'c' || buf->filename[strlen(buf->filename) - 1] == 'h')
|
||||||
{
|
{
|
||||||
@@ -135,7 +130,7 @@ static void editorDrawAllPanes(struct abuf* ab)
|
|||||||
{
|
{
|
||||||
char pos_buf[32];
|
char pos_buf[32];
|
||||||
snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", y + 1, divider_col);
|
snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", y + 1, divider_col);
|
||||||
abAppend(ab, pos_buf, strlen(pos_buf));
|
abAppend(ab, pos_buf, (int) strlen(pos_buf));
|
||||||
abAppend(ab, "\x1b[1m|\x1b[0m", 9); // Bold pipe divider
|
abAppend(ab, "\x1b[1m|\x1b[0m", 9); // Bold pipe divider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,7 +140,7 @@ static void editorDrawAllPanes(struct abuf* ab)
|
|||||||
int divider_row = layout->panes[0].height;
|
int divider_row = layout->panes[0].height;
|
||||||
char pos_buf[32];
|
char pos_buf[32];
|
||||||
snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", divider_row + 1, 1);
|
snprintf(pos_buf, sizeof(pos_buf), "\x1b[%d;%dH", divider_row + 1, 1);
|
||||||
abAppend(ab, pos_buf, strlen(pos_buf));
|
abAppend(ab, pos_buf, (int) strlen(pos_buf));
|
||||||
for (int x = 0; x < E.screencols; x++)
|
for (int x = 0; x < E.screencols; x++)
|
||||||
{
|
{
|
||||||
abAppend(ab, "\x1b[1m-\x1b[0m", 9); // Bold dash divider
|
abAppend(ab, "\x1b[1m-\x1b[0m", 9); // Bold dash divider
|
||||||
@@ -231,15 +226,13 @@ void editorScroll()
|
|||||||
|
|
||||||
char * basename(char *path)
|
char * basename(char *path)
|
||||||
{
|
{
|
||||||
int len = strlen(path);
|
int len = (int) strlen(path);
|
||||||
int flag=0;
|
|
||||||
|
|
||||||
|
|
||||||
for(int i=len-1; i>0; i--)
|
for(int i=len-1; i>0; i--)
|
||||||
{
|
{
|
||||||
if(path[i]=='/' )
|
if(path[i]=='/' )
|
||||||
{
|
{
|
||||||
flag=1;
|
|
||||||
path = path+i+1;
|
path = path+i+1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -323,7 +316,7 @@ void editorDrawStatusBar(struct abuf* ab)
|
|||||||
*/
|
*/
|
||||||
void editorDrawMessageBar(struct abuf* ab)
|
void editorDrawMessageBar(struct abuf* ab)
|
||||||
{
|
{
|
||||||
int msg_len = strlen(E.status_msg);
|
int msg_len = (int) strlen(E.status_msg);
|
||||||
abAppend(ab, ERASE_END_LINE, 3);
|
abAppend(ab, ERASE_END_LINE, 3);
|
||||||
if (msg_len > E.screencols)
|
if (msg_len > E.screencols)
|
||||||
{
|
{
|
||||||
@@ -335,6 +328,7 @@ void editorDrawMessageBar(struct abuf* ab)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Performs complete screen refresh and buffer synchronization
|
* @brief Performs complete screen refresh and buffer synchronization
|
||||||
* @details Clears screen, redraws all visible content (rows, status bar,
|
* @details Clears screen, redraws all visible content (rows, status bar,
|
||||||
@@ -354,7 +348,7 @@ void editorRefreshScreen()
|
|||||||
abAppend(&ab, HIDE_CURSOR, 6);
|
abAppend(&ab, HIDE_CURSOR, 6);
|
||||||
abAppend(&ab, CURSOR_TOP_LEFT, 3);
|
abAppend(&ab, CURSOR_TOP_LEFT, 3);
|
||||||
abAppend(&ab, E.theme.BACKGROUND_COLOR,
|
abAppend(&ab, E.theme.BACKGROUND_COLOR,
|
||||||
strlen(E.theme.BACKGROUND_COLOR)); // RGB background is 12 bytes
|
(int) strlen(E.theme.BACKGROUND_COLOR)); // RGB background is 12 bytes
|
||||||
|
|
||||||
// Draw all panes
|
// Draw all panes
|
||||||
editorScroll();
|
editorScroll();
|
||||||
@@ -363,16 +357,16 @@ void editorRefreshScreen()
|
|||||||
// Draw status bar and message bar
|
// Draw status bar and message bar
|
||||||
editorDrawStatusBar(&ab);
|
editorDrawStatusBar(&ab);
|
||||||
editorDrawMessageBar(&ab);
|
editorDrawMessageBar(&ab);
|
||||||
|
// editorDrawContextBuffer(&ab);
|
||||||
|
|
||||||
// Position cursor in active pane
|
// Position cursor in active pane
|
||||||
EditorPane* active = splitScreenGetActivePane();
|
EditorPane* active = splitScreenGetActivePane();
|
||||||
struct buffer_t* buffer = bufferGetCurrent();
|
|
||||||
if (active != NULL)
|
if (active != NULL)
|
||||||
{
|
{
|
||||||
snprintf(buf, sizeof(buf), "\x1b[%d;%dH",
|
snprintf(buf, sizeof(buf), "\x1b[%d;%dH",
|
||||||
active->cursor_y + active->origin_y + 1,
|
active->cursor_y + active->origin_y + 1,
|
||||||
active->cursor_x + active->origin_x + 1);
|
active->cursor_x + active->origin_x + 1);
|
||||||
abAppend(&ab, buf, strlen(buf));
|
abAppend(&ab, buf, (int) strlen(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
abAppend(&ab, SHOW_CURSOR, 6);
|
abAppend(&ab, SHOW_CURSOR, 6);
|
||||||
|
|||||||
+1
-89
@@ -1,100 +1,12 @@
|
|||||||
#include "../include/row_op.h"
|
#include "../include/row_op.h"
|
||||||
#include "../include/data.h"
|
#include "../include/data.h"
|
||||||
#include "../include/define.h"
|
#include "../include/utf8.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "include/terminal.h"
|
|
||||||
#include "include/utf8.h"
|
|
||||||
|
|
||||||
extern struct editorConfig E;
|
extern struct editorConfig E;
|
||||||
|
|
||||||
void bufferInsertRow(struct buffer_t *buffer, int at, char *s, size_t len) {
|
|
||||||
if (at < 0 || at > buffer->numrows)
|
|
||||||
return;
|
|
||||||
|
|
||||||
row_t *tmp = realloc(buffer->row, sizeof(row_t) * (buffer->numrows + 1));
|
|
||||||
if (!tmp)
|
|
||||||
return;
|
|
||||||
buffer->row = tmp;
|
|
||||||
|
|
||||||
/* Shift existing rows to make room at 'at' — no at++ */
|
|
||||||
if (at < buffer->numrows) {
|
|
||||||
memmove(&buffer->row[at + 1], &buffer->row[at],
|
|
||||||
sizeof(row_t) * (buffer->numrows - at)); /* not -at+1 */
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->row[at].size = len;
|
|
||||||
buffer->row[at].cap = len + 1;
|
|
||||||
buffer->row[at].chars = malloc(len + 1);
|
|
||||||
if (!buffer->row[at].chars)
|
|
||||||
return;
|
|
||||||
memcpy(buffer->row[at].chars, s, len);
|
|
||||||
buffer->row[at].chars[len] = '\0'; /* always NUL-terminate */
|
|
||||||
|
|
||||||
buffer->numrows++;
|
|
||||||
buffer->dirty++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bufferFreeRow(row_t *row) { free(row->chars); }
|
|
||||||
|
|
||||||
int editorRowCxToByte(const row_t *row, int cursor_x) {
|
|
||||||
int i = 0, col = 0;
|
|
||||||
while (col < cursor_x && i < row->size) {
|
|
||||||
int sl = utf8Seqlen((unsigned char)row->chars[i]);
|
|
||||||
if (sl < 1)
|
|
||||||
sl = 1;
|
|
||||||
col++;
|
|
||||||
i += sl;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \fn editorRowInsertChar(erow *row, int at, int c)
|
|
||||||
* \param at Index of where we want to insert the char */
|
|
||||||
|
|
||||||
void bufferRowInsertBytes(struct buffer_t *buffer, row_t *row, int at,
|
|
||||||
char *src, int n) {
|
|
||||||
if (buffer->state == READ_ONLY)
|
|
||||||
return;
|
|
||||||
if (row->size + n + 1 > row->cap) {
|
|
||||||
row->cap = (row->size + n + 1) * 2;
|
|
||||||
row->chars = realloc(row->chars, row->cap);
|
|
||||||
}
|
|
||||||
memmove(row->chars + at + n, row->chars + at, row->size - at);
|
|
||||||
memcpy(row->chars + at, src, n);
|
|
||||||
row->size += n;
|
|
||||||
row->chars = realloc(row->chars, row->size + 2);
|
|
||||||
++buffer->dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \fn bufferRowDelChar(struct bufferConfig *E, frow *frow, int at)
|
|
||||||
* \brief Delete the a char at the chosen position on the given row
|
|
||||||
* \param at Index of the char to delete
|
|
||||||
* \param row Row on operation is made */
|
|
||||||
void bufferRowDelByte(struct buffer_t *buffer, row_t *row, int at, int n) {
|
|
||||||
if (buffer->state == READ_ONLY)
|
|
||||||
return;
|
|
||||||
if (at < 0 || at >= row->size)
|
|
||||||
return;
|
|
||||||
memmove(row->chars + at, row->chars + at + n, row->size - at - n);
|
|
||||||
row->size -= n;
|
|
||||||
row->chars[row->size] = '\0';
|
|
||||||
buffer->x -= n;
|
|
||||||
++buffer->dirty;
|
|
||||||
}
|
|
||||||
int editorRowCharCount(row_t *row, int x) {
|
|
||||||
int n = 0, i = 0;
|
|
||||||
while (i < x && i < row->size) {
|
|
||||||
int sl = utf8Seqlen((unsigned char)row->chars[i]);
|
|
||||||
if (sl < 1)
|
|
||||||
sl = 1;
|
|
||||||
n++;
|
|
||||||
i += sl;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|||||||
+4
-2
@@ -46,7 +46,7 @@ void enableRawMode() {
|
|||||||
|
|
||||||
#include <ctype.h> /* isprint */
|
#include <ctype.h> /* isprint */
|
||||||
|
|
||||||
char *key_to_string(int key) {
|
char *keyToString(int key) {
|
||||||
static char key_str[32];
|
static char key_str[32];
|
||||||
|
|
||||||
if (key == '\r') {
|
if (key == '\r') {
|
||||||
@@ -111,7 +111,7 @@ int editorReadKey() {
|
|||||||
/* read first byte — may be start of UTF-8 or escape */
|
/* read first byte — may be start of UTF-8 or escape */
|
||||||
while (read(STDIN_FILENO, &c, 1) != 1)
|
while (read(STDIN_FILENO, &c, 1) != 1)
|
||||||
;
|
;
|
||||||
appDebug("f : %X\r\n", c);
|
appDebug("f : %hhu %ld\r\n", c, 0x200);
|
||||||
|
|
||||||
if (c == '\x1b') {
|
if (c == '\x1b') {
|
||||||
char seq[6];
|
char seq[6];
|
||||||
@@ -120,6 +120,8 @@ int editorReadKey() {
|
|||||||
return '\x1b';
|
return '\x1b';
|
||||||
if (read(STDIN_FILENO, &seq[1], 1) != 1)
|
if (read(STDIN_FILENO, &seq[1], 1) != 1)
|
||||||
return '\x1b';
|
return '\x1b';
|
||||||
|
appDebug("f2 : %s\r\n", seq);
|
||||||
|
|
||||||
if (seq[0] == '[') {
|
if (seq[0] == '[') {
|
||||||
if (seq[1] >= '0' && seq[1] <= '9') {
|
if (seq[1] >= '0' && seq[1] <= '9') {
|
||||||
if (read(STDIN_FILENO, &seq[2], 1) != 1)
|
if (read(STDIN_FILENO, &seq[2], 1) != 1)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../include/utf8.h"
|
#include "../include/utf8.h"
|
||||||
#include "../include/data.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user