Adding splitting screen and buffer switching
This commit is contained in:
+101
-99
@@ -7,8 +7,11 @@
|
||||
*/
|
||||
|
||||
#include "../include/file_io.h"
|
||||
#include "../include/input.h"
|
||||
#include "../include/editor_op.h"
|
||||
#include "../include/input.h"
|
||||
#include "include/buffer.h"
|
||||
#include "include/data.h"
|
||||
#include "include/split_screen.h"
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -31,96 +34,90 @@ extern struct editorConfig E;
|
||||
* Rows are separated by newline characters.
|
||||
* @note Caller is responsible for freeing the returned buffer
|
||||
*/
|
||||
char *editorRowsToString(int *buffer_len) {
|
||||
int tot_len = 0;
|
||||
int j;
|
||||
char *buf;
|
||||
char *p;
|
||||
char *bufferRowsToString(struct buffer_t *buf, int *buffer_len) {
|
||||
int tot_len = 0;
|
||||
int j;
|
||||
char *buffer;
|
||||
char *p;
|
||||
|
||||
for (j = 0; j < E.numrows; ++j) {
|
||||
tot_len += E.row[j].size + 1;
|
||||
}
|
||||
*buffer_len = tot_len;
|
||||
buf = malloc(tot_len);
|
||||
p = buf;
|
||||
for (j = 0; j < E.numrows; ++j) {
|
||||
memcpy(p, E.row[j].chars, E.row[j].size);
|
||||
p += E.row[j].size;
|
||||
*p = '\n';
|
||||
p++;
|
||||
}
|
||||
for (j = 0; j < buf->numrows; ++j) {
|
||||
tot_len += buf->row[j].size + 1;
|
||||
}
|
||||
*buffer_len = tot_len;
|
||||
buffer = malloc(tot_len);
|
||||
p = buffer;
|
||||
for (j = 0; j < buf->numrows; ++j) {
|
||||
memcpy(p, buf->row[j].chars, buf->row[j].size);
|
||||
p += buf->row[j].size;
|
||||
*p = '\n';
|
||||
p++;
|
||||
}
|
||||
|
||||
return buf;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Closes the current file and resets editor state
|
||||
* @details Clears all rows, resets cursor position, scroll offsets, and file metadata.
|
||||
* Does not prompt to save unsaved changes.
|
||||
* @details Clears all rows, resets cursor position, scroll offsets, and file
|
||||
* metadata. Does not prompt to save unsaved changes.
|
||||
* @note Updates global editor state E
|
||||
*/
|
||||
void editorCloseFile(void) {
|
||||
E.cursor_x = 0;
|
||||
E.cursor_y = 0;
|
||||
E.rx = 0;
|
||||
E.row_offset = 0;
|
||||
E.col_offset = 0;
|
||||
for (int i = 0; i < E.numrows; ++i) {
|
||||
free(E.row[i].chars);
|
||||
free(E.row[i].render);
|
||||
}
|
||||
E.numrows = 0;
|
||||
free(E.row);
|
||||
E.row = NULL;
|
||||
E.dirty = 0;
|
||||
free(E.filename);
|
||||
E.filename = NULL;
|
||||
E.status_msg[0] = '\0';
|
||||
E.status_msg_time = 0;
|
||||
EditorPane *active = splitScreenGetActivePane();
|
||||
struct buffer_t *buf = bufferFindById(active->buffer_id);
|
||||
active->cursor_x = 0;
|
||||
active->cursor_y = 0;
|
||||
active->rx = 0;
|
||||
active->row_offset = 0;
|
||||
active->col_offset = 0;
|
||||
for (int i = 0; i < buf->numrows; ++i) {
|
||||
free(buf->row[i].chars);
|
||||
free(buf->row[i].render);
|
||||
}
|
||||
buf->numrows = 0;
|
||||
free(buf->row);
|
||||
buf->row = NULL;
|
||||
buf->dirty = 0;
|
||||
free(buf->filename);
|
||||
buf->filename = NULL;
|
||||
E.status_msg[0] = '\0';
|
||||
E.status_msg_time = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Opens a file for editing
|
||||
* @details Loads file content into editor rows, one line per row. If another file
|
||||
* is already open, it is closed first (without saving). File is opened in a+
|
||||
* (read/append) mode to allow both reading and modification.
|
||||
* @details Loads file content into editor rows, one line per row. If another
|
||||
* file is already open, it is closed first (without saving). File is opened in
|
||||
* a+ (read/append) mode to allow both reading and modification.
|
||||
* @param filename Path to the file to open (relative or absolute)
|
||||
* @note Updates global editor state E
|
||||
* @note Calls die() on file open failure
|
||||
* @note Newline characters are stripped from loaded lines
|
||||
* @see editorInsertRow()
|
||||
*/
|
||||
void editorOpen(char *filename) {
|
||||
FILE *fp;
|
||||
void editorOpen(struct buffer_t* buffer) {
|
||||
FILE *fp;
|
||||
|
||||
// Test if a file is already open
|
||||
if (E.filename != NULL) {
|
||||
editorCloseFile();
|
||||
E.state = READ_AND_WRITE;
|
||||
}
|
||||
|
||||
E.filename = strdup(filename);
|
||||
|
||||
fp = fopen(filename, "a+");
|
||||
if (!fp)
|
||||
die("fopen");
|
||||
|
||||
char *line = NULL;
|
||||
size_t line_cap = 0;
|
||||
ssize_t line_len;
|
||||
|
||||
while ((line_len = getline(&line, &line_cap, fp)) != -1) {
|
||||
while (line_len > 0 &&
|
||||
(line[line_len - 1] == '\n' || line[line_len - 1] == '\r')) {
|
||||
--line_len;
|
||||
}
|
||||
editorInsertRow(E.numrows, line, line_len);
|
||||
free(line);
|
||||
line = NULL;
|
||||
fp = fopen(buffer->filename, "a+");
|
||||
if (!fp)
|
||||
die("fopen");
|
||||
|
||||
char *line = NULL;
|
||||
size_t line_cap = 0;
|
||||
ssize_t line_len;
|
||||
|
||||
while ((line_len = getline(&line, &line_cap, fp)) != -1) {
|
||||
while (line_len > 0 &&
|
||||
(line[line_len - 1] == '\n' || line[line_len - 1] == '\r')) {
|
||||
--line_len;
|
||||
}
|
||||
bufferInsertRow(buffer, buffer->numrows, line, line_len);
|
||||
free(line);
|
||||
fclose(fp);
|
||||
E.dirty = 0;
|
||||
line = NULL;
|
||||
}
|
||||
free(line);
|
||||
fclose(fp);
|
||||
E.dirty = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,32 +131,34 @@ void editorOpen(char *filename) {
|
||||
* @see editorRowsToString()
|
||||
*/
|
||||
void editorSave() {
|
||||
int len;
|
||||
char *buf;
|
||||
int fd;
|
||||
if (E.filename == NULL) {
|
||||
E.filename = editorPrompt("Save as: %s (ESC to cancel)", "", 1);
|
||||
if (E.filename == NULL) {
|
||||
editorSetStatusMessage("Save aborted");
|
||||
return;
|
||||
}
|
||||
EditorPane *active = splitScreenGetActivePane();
|
||||
struct buffer_t *buffer = bufferFindById(active->buffer_id);
|
||||
int len;
|
||||
char *buf;
|
||||
int fd;
|
||||
if (buffer->filename == NULL) {
|
||||
buffer->filename = editorPrompt("Save as: %s (ESC to cancel)", "", 1);
|
||||
if (buffer->filename == NULL) {
|
||||
editorSetStatusMessage("Save aborted");
|
||||
return;
|
||||
}
|
||||
buf = editorRowsToString(&len);
|
||||
fd = open(E.filename, O_RDWR | O_CREAT, 0644);
|
||||
if (fd != -1) {
|
||||
if (ftruncate(fd, len) != -1) {
|
||||
if (write(fd, buf, len) == len) {
|
||||
close(fd);
|
||||
free(buf);
|
||||
E.dirty = 0;
|
||||
editorSetStatusMessage("%d bytes written to disk", len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
buf = bufferRowsToString(buffer, &len);
|
||||
fd = open(buffer->filename, O_RDWR | O_CREAT, 0644);
|
||||
if (fd != -1) {
|
||||
if (ftruncate(fd, len) != -1) {
|
||||
if (write(fd, buf, len) == len) {
|
||||
close(fd);
|
||||
free(buf);
|
||||
E.dirty = 0;
|
||||
editorSetStatusMessage("%d bytes written to disk", len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
editorSetStatusMessage("Can't save! I/O error: %s", strerror(errno));
|
||||
close(fd);
|
||||
}
|
||||
free(buf);
|
||||
editorSetStatusMessage("Can't save! I/O error: %s", strerror(errno));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,18 +171,21 @@ void editorSave() {
|
||||
* @see editorPrompt()
|
||||
* @see editorRowRxToCx()
|
||||
*/
|
||||
void editorFind() {
|
||||
void bufferFind(struct buffer_t *buf) {
|
||||
fprintf(stderr, "searching\n");
|
||||
char *query = editorPrompt("Search: %s (ESC to cancel)", "", 0);
|
||||
if (query == NULL) return;
|
||||
EditorPane *active = splitScreenGetActivePane();
|
||||
|
||||
if (query == NULL)
|
||||
return;
|
||||
int i;
|
||||
for (i = E.cursor_y + 1; i < E.numrows; i++) {
|
||||
erow *row = &E.row[i];
|
||||
for (i = active->cursor_y + 1; i < buf->numrows; i++) {
|
||||
frow *row = &buf->row[i];
|
||||
char *match = strstr(row->render, query);
|
||||
if (match) {
|
||||
E.cursor_y = i;
|
||||
E.cursor_x = editorRowRxToCx(row, match - row->render);
|
||||
E.row_offset = E.numrows;
|
||||
active->cursor_y = i;
|
||||
active->cursor_x = bufferRowRxToCx(row, match - row->render);
|
||||
buf->row_offset = buf->numrows;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user