Adding splitting screen and buffer switching
This commit is contained in:
+231
-15
@@ -1,20 +1,236 @@
|
||||
/**
|
||||
* @file buffer.c
|
||||
* @brief Buffer management implementation for multiple open files
|
||||
*/
|
||||
|
||||
#include "../include/buffer.h"
|
||||
#include "../include/file_io.h"
|
||||
#include "../include/editor_op.h"
|
||||
#include "../include/data.h"
|
||||
#include "include/split_screen.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int new_buffer(enum buffer_type type, char *filename, int x, int y, int width,
|
||||
int height) {
|
||||
// Create a new buffer
|
||||
extern struct editorConfig E;
|
||||
|
||||
struct buffer_t *buffer = &E.buffers[E.number_of_buffer];
|
||||
buffer->type = type;
|
||||
|
||||
if (type == FILE_BUFF) {
|
||||
strcpy(buffer->filename, filename);
|
||||
}
|
||||
buffer->width = width, buffer->height = height;
|
||||
buffer->x = x, buffer->y = y;
|
||||
|
||||
|
||||
|
||||
return 1;
|
||||
/**
|
||||
* @brief Finds a buffer by filename
|
||||
* @param filename The filename to search for
|
||||
* @return Buffer ID if found, -1 if not found
|
||||
*/
|
||||
static int bufferFindByFilename(const char *filename) {
|
||||
for (int i = 0; i < E.number_of_buffer; i++) {
|
||||
if (E.buffers[i].filename != NULL &&
|
||||
strcmp(E.buffers[i].filename, filename) == 0) {
|
||||
return E.buffers[i].buffer_id;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finds a buffer by ID
|
||||
* @param buffer_id The buffer ID to find
|
||||
* @return Pointer to buffer, NULL if not found
|
||||
*/
|
||||
struct buffer_t *bufferFindById(int buffer_id) {
|
||||
for (int i = 0; i < E.number_of_buffer; i++) {
|
||||
if (E.buffers[i].buffer_id == buffer_id) {
|
||||
return &E.buffers[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new buffer for a file
|
||||
* @details Allocates buffer slot, loads file content, saves buffer metadata.
|
||||
* If file is already open, switches to existing buffer instead.
|
||||
* @param filename Path to the file
|
||||
* @return Buffer ID on success, -1 on failure
|
||||
*/
|
||||
int bufferCreate(const char *filename) {
|
||||
// Check if file is already open
|
||||
int existing_id = bufferFindByFilename(filename);
|
||||
if (existing_id != -1) {
|
||||
return bufferSwitch(existing_id);
|
||||
}
|
||||
|
||||
// Check if we have space for more buffers
|
||||
if (E.number_of_buffer >= 64) {
|
||||
editorSetStatusMessage("Error: maximum buffers reached (64)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Initialize new buffer
|
||||
struct buffer_t *new_buf = &E.buffers[E.number_of_buffer];
|
||||
new_buf->buffer_id = E.number_of_buffer;
|
||||
new_buf->filename = strdup(filename);
|
||||
new_buf->type = FILE_BUFF;
|
||||
new_buf->state = READ_AND_WRITE;
|
||||
new_buf->x = 0;
|
||||
new_buf->y = 0;
|
||||
new_buf->row_offset = 0;
|
||||
new_buf->col_offset = 0;
|
||||
new_buf->dirty = 0; // New file starts clean
|
||||
|
||||
// Load file content using existing editorOpen
|
||||
editorOpen(new_buf);
|
||||
|
||||
E.number_of_buffer++;
|
||||
|
||||
editorSetStatusMessage("Opened: %s (buffer %d)", filename, new_buf->buffer_id);
|
||||
return new_buf->buffer_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Switches to a specific buffer by ID
|
||||
* @details Saves current buffer state, loads target buffer content and state.
|
||||
* @param buffer_id The buffer ID to switch to
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int bufferSwitch(int buffer_id) {
|
||||
struct buffer_t *target = bufferFindById(buffer_id);
|
||||
if (target == NULL) {
|
||||
E.layout.panes[E.layout.active_pane].buffer_id = buffer_id;
|
||||
editorSetStatusMessage("Error: buffer not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
editorSetStatusMessage("Switched to: %s (buffer %d)",
|
||||
target->filename, buffer_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Closes a buffer by ID
|
||||
* @details Frees buffer resources and removes from buffer list.
|
||||
* Prompts to save unsaved changes. If closing current buffer,
|
||||
* switches to next available buffer.
|
||||
* @param buffer_id The buffer ID to close
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int bufferClose(int buffer_id) {
|
||||
struct buffer_t *buf = bufferFindById(buffer_id);
|
||||
if (buf == NULL) {
|
||||
editorSetStatusMessage("Error: buffer not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
EditorPane * active = splitScreenGetActivePane();
|
||||
|
||||
// If this is the current buffer, find next buffer to switch to
|
||||
if (active->buffer_id == buffer_id) {
|
||||
int next_id = -1;
|
||||
|
||||
// Try to switch to next buffer
|
||||
for (int i = 0; i < E.number_of_buffer; i++) {
|
||||
if (E.buffers[i].buffer_id != buffer_id) {
|
||||
next_id = E.buffers[i].buffer_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (next_id != -1) {
|
||||
bufferSwitch(next_id);
|
||||
} else {
|
||||
// No other buffers, clear editor
|
||||
editorCloseFile();
|
||||
}
|
||||
}
|
||||
|
||||
// Free buffer resources
|
||||
free(buf->filename);
|
||||
buf->filename = NULL;
|
||||
buf->buffer_id = -1;
|
||||
|
||||
// Remove from buffer list by shifting
|
||||
for (int i = 0; i < E.number_of_buffer; i++) {
|
||||
if (E.buffers[i].buffer_id == buffer_id) {
|
||||
for (int j = i; j < E.number_of_buffer - 1; j++) {
|
||||
E.buffers[j] = E.buffers[j + 1];
|
||||
}
|
||||
E.number_of_buffer--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
editorSetStatusMessage("Closed buffer %d", buffer_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current active buffer
|
||||
* @return Pointer to current buffer_t, NULL if none
|
||||
*/
|
||||
struct buffer_t *bufferGetCurrent(void) {
|
||||
EditorPane * active = splitScreenGetActivePane();
|
||||
return bufferFindById(active->buffer_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lists all open buffers
|
||||
* @details Prints buffer information to status message
|
||||
* @return Number of open buffers
|
||||
*/
|
||||
int bufferListAll(void) {
|
||||
if (E.number_of_buffer == 0) {
|
||||
editorSetStatusMessage("No buffers open");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char buf[256] = "";
|
||||
int offset = 0;
|
||||
EditorPane * active = splitScreenGetActivePane();
|
||||
|
||||
for (int i = 0; i < E.number_of_buffer; i++) {
|
||||
struct buffer_t *b = &E.buffers[i];
|
||||
char marker = (b->buffer_id == active->buffer_id) ? '*' : ' ';
|
||||
offset += snprintf(&buf[offset], sizeof(buf) - offset,
|
||||
"%c%d:%s ", marker, b->buffer_id,
|
||||
b->filename ? b->filename : "[No Name]");
|
||||
}
|
||||
|
||||
editorSetStatusMessage("Buffers: %s", buf);
|
||||
return E.number_of_buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Saves current buffer to disk
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int bufferSave(void) {
|
||||
EditorPane * active = splitScreenGetActivePane();
|
||||
if (active->buffer_id == -1) {
|
||||
editorSetStatusMessage("Error: no buffer active");
|
||||
return -1;
|
||||
}
|
||||
|
||||
editorSave();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Saves all buffers to disk
|
||||
* @details Iterates through all buffers, saves each one
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int bufferSaveAll(void) {
|
||||
int saved = 0;
|
||||
int failed = 0;
|
||||
|
||||
for (int i = 0; i < E.number_of_buffer; i++) {
|
||||
if (bufferSwitch(E.buffers[i].buffer_id) == 0) {
|
||||
if (E.dirty && bufferSave() == 0) {
|
||||
saved++;
|
||||
}
|
||||
} else {
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
editorSetStatusMessage("Saved %d buffers (%d failed)", saved, failed);
|
||||
return (failed == 0) ? 0 : -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user