Adding splitting screen and buffer switching
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
* @file split_screen.c
|
||||
* @brief Split screen implementation
|
||||
*/
|
||||
|
||||
#include "../include/split_screen.h"
|
||||
#include "../include/buffer.h"
|
||||
#include "../include/editor_op.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
extern struct editorConfig E;
|
||||
|
||||
/**
|
||||
* @brief Initializes split screen system with single fullscreen pane
|
||||
*/
|
||||
void splitScreenInit(void) {
|
||||
E.layout.mode = SPLIT_NONE;
|
||||
E.layout.num_panes = 1;
|
||||
E.layout.active_pane = 0;
|
||||
|
||||
E.layout.panes = malloc(sizeof(EditorPane) * 2);
|
||||
|
||||
// Initialize single fullscreen pane
|
||||
E.layout.panes[0].buffer_id = -1; // No buffer for now
|
||||
E.layout.panes[0].start_row = 0;
|
||||
E.layout.panes[0].start_col = 0;
|
||||
E.layout.panes[0].height = E.screenrows - 2; // Leave room for status bar
|
||||
E.layout.panes[0].width = E.screencols;
|
||||
E.layout.panes[0].cursor_x = 0;
|
||||
E.layout.panes[0].cursor_y = 0;
|
||||
E.layout.panes[0].row_offset = 0;
|
||||
E.layout.panes[0].col_offset = 0;
|
||||
E.layout.panes[0].is_active = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Splits screen vertically (left-right)
|
||||
* @param buffer_id_left Buffer ID for left pane
|
||||
* @param buffer_id_right Buffer ID for right pane
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int splitScreenVertical(int buffer_id_left, int buffer_id_right) {
|
||||
// Verify both buffers exist
|
||||
if (bufferFindById(buffer_id_left) == NULL ||
|
||||
bufferFindById(buffer_id_right) == NULL) {
|
||||
editorSetStatusMessage("Error: invalid buffer IDs");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Reallocate panes array
|
||||
E.layout.panes = realloc(E.layout.panes, sizeof(EditorPane) * 2);
|
||||
E.layout.mode = SPLIT_VERTICAL;
|
||||
E.layout.num_panes = 2;
|
||||
E.layout.active_pane = 0;
|
||||
|
||||
int half_width = E.screencols / 2;
|
||||
int pane_height = E.screenrows - 2; // Leave room for status bar
|
||||
|
||||
// Left pane
|
||||
E.layout.panes[0].buffer_id = buffer_id_left;
|
||||
E.layout.panes[0].start_row = 0;
|
||||
E.layout.panes[0].start_col = 0;
|
||||
E.layout.panes[0].height = pane_height;
|
||||
E.layout.panes[0].width = half_width;
|
||||
E.layout.panes[0].cursor_x = 0;
|
||||
E.layout.panes[0].cursor_y = 0;
|
||||
E.layout.panes[0].row_offset = 0;
|
||||
E.layout.panes[0].col_offset = 0;
|
||||
E.layout.panes[0].is_active = 1;
|
||||
|
||||
// Right pane
|
||||
E.layout.panes[1].buffer_id = buffer_id_right;
|
||||
E.layout.panes[1].start_row = 0;
|
||||
E.layout.panes[1].start_col = half_width;
|
||||
E.layout.panes[1].height = pane_height;
|
||||
E.layout.panes[1].width = E.screencols - half_width;
|
||||
E.layout.panes[1].cursor_x = 0;
|
||||
E.layout.panes[1].cursor_y = 0;
|
||||
E.layout.panes[1].row_offset = 0;
|
||||
E.layout.panes[1].col_offset = 0;
|
||||
E.layout.panes[1].is_active = 0;
|
||||
|
||||
editorSetStatusMessage("Vertical split: %d | %d", buffer_id_left, buffer_id_right);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Splits screen horizontally (top-bottom)
|
||||
* @param buffer_id_top Buffer ID for top pane
|
||||
* @param buffer_id_bottom Buffer ID for bottom pane
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int splitScreenHorizontal(int buffer_id_top, int buffer_id_bottom) {
|
||||
// Verify both buffers exist
|
||||
if (bufferFindById(buffer_id_top) == NULL ||
|
||||
bufferFindById(buffer_id_bottom) == NULL) {
|
||||
editorSetStatusMessage("Error: invalid buffer IDs");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Reallocate panes array
|
||||
E.layout.panes = realloc(E.layout.panes, sizeof(EditorPane) * 2);
|
||||
E.layout.mode = SPLIT_HORIZONTAL;
|
||||
E.layout.num_panes = 2;
|
||||
E.layout.active_pane = 0;
|
||||
|
||||
int half_height = (E.screenrows - 2) / 2; // Account for status bar
|
||||
|
||||
// Top pane
|
||||
E.layout.panes[0].buffer_id = buffer_id_top;
|
||||
E.layout.panes[0].start_row = 0;
|
||||
E.layout.panes[0].start_col = 0;
|
||||
E.layout.panes[0].height = half_height;
|
||||
E.layout.panes[0].width = E.screencols;
|
||||
E.layout.panes[0].cursor_x = 0;
|
||||
E.layout.panes[0].cursor_y = 0;
|
||||
E.layout.panes[0].row_offset = 0;
|
||||
E.layout.panes[0].col_offset = 0;
|
||||
E.layout.panes[0].is_active = 1;
|
||||
|
||||
// Bottom pane
|
||||
E.layout.panes[1].buffer_id = buffer_id_bottom;
|
||||
E.layout.panes[1].start_row = half_height;
|
||||
E.layout.panes[1].start_col = 0;
|
||||
E.layout.panes[1].height = E.screenrows - 2 - half_height;
|
||||
E.layout.panes[1].width = E.screencols;
|
||||
E.layout.panes[1].cursor_x = 0;
|
||||
E.layout.panes[1].cursor_y = 0;
|
||||
E.layout.panes[1].row_offset = 0;
|
||||
E.layout.panes[1].col_offset = 0;
|
||||
E.layout.panes[1].is_active = 0;
|
||||
|
||||
editorSetStatusMessage("Horizontal split: %d / %d", buffer_id_top, buffer_id_bottom);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns to single buffer fullscreen
|
||||
*/
|
||||
void splitScreenUnify(void) {
|
||||
E.layout.mode = SPLIT_NONE;
|
||||
E.layout.num_panes = 1;
|
||||
E.layout.active_pane = 0;
|
||||
|
||||
E.layout.panes[0].start_row = 0;
|
||||
E.layout.panes[0].start_col = 0;
|
||||
E.layout.panes[0].height = E.screenrows - 2;
|
||||
E.layout.panes[0].width = E.screencols;
|
||||
E.layout.panes[0].is_active = 1;
|
||||
|
||||
editorSetStatusMessage("Unified view");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Switches active pane (focus moves between splits)
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int splitScreenSwitchPane(void) {
|
||||
if (E.layout.num_panes < 2) {
|
||||
editorSetStatusMessage("No split to switch");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Deactivate current pane
|
||||
E.layout.panes[E.layout.active_pane].is_active = 0;
|
||||
|
||||
// Move to next pane
|
||||
E.layout.active_pane = (E.layout.active_pane + 1) % E.layout.num_panes;
|
||||
|
||||
// Activate new pane
|
||||
E.layout.panes[E.layout.active_pane].is_active = 1;
|
||||
|
||||
editorSetStatusMessage("Switched to pane %d (buffer %d)",
|
||||
E.layout.active_pane,
|
||||
E.layout.panes[E.layout.active_pane].buffer_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the active pane's buffer
|
||||
* @param buffer_id New buffer ID for active pane
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int splitScreenSetPaneBuffer(int buffer_id) {
|
||||
if (bufferFindById(buffer_id) == NULL) {
|
||||
editorSetStatusMessage("Error: invalid buffer ID");
|
||||
return -1;
|
||||
}
|
||||
|
||||
EditorPane *active = &E.layout.panes[E.layout.active_pane];
|
||||
active->buffer_id = buffer_id;
|
||||
active->cursor_x = 0;
|
||||
active->cursor_y = 0;
|
||||
active->row_offset = 0;
|
||||
active->col_offset = 0;
|
||||
|
||||
editorSetStatusMessage("Pane %d now showing buffer %d",
|
||||
E.layout.active_pane, buffer_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets current screen layout
|
||||
* @return Pointer to current ScreenLayout
|
||||
*/
|
||||
ScreenLayout *splitScreenGetLayout(void) {
|
||||
return &E.layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets active pane
|
||||
* @return Pointer to active EditorPane
|
||||
*/
|
||||
EditorPane *splitScreenGetActivePane(void) {
|
||||
if (E.layout.num_panes == 0) return NULL;
|
||||
return &E.layout.panes[E.layout.active_pane];
|
||||
}
|
||||
Reference in New Issue
Block a user