221 lines
6.5 KiB
C
221 lines
6.5 KiB
C
/**
|
|
* @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>
|
|
|
|
#include "include/utils.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 = bAlloc(sizeof(EditorPane) * 2);
|
|
|
|
// Initialize single fullscreen pane
|
|
E.layout.panes[0].buffer_id = -1; // No buffer for now
|
|
E.layout.panes[0].origin_y = 0;
|
|
E.layout.panes[0].origin_x = 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].y_offset = 0;
|
|
E.layout.panes[0].x_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;
|
|
}
|
|
|
|
// bReallocate panes array
|
|
E.layout.panes = bRealloc(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; // Leave room for status bar
|
|
|
|
// Left pane
|
|
E.layout.panes[0].buffer_id = buffer_id_left;
|
|
E.layout.panes[0].origin_y = 0;
|
|
E.layout.panes[0].origin_x = 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].y_offset = 0;
|
|
E.layout.panes[0].x_offset = 0;
|
|
E.layout.panes[0].is_active = 1;
|
|
|
|
// Right pane
|
|
E.layout.panes[1].buffer_id = buffer_id_right;
|
|
E.layout.panes[1].origin_y = 0;
|
|
E.layout.panes[1].origin_x = 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].y_offset = 0;
|
|
E.layout.panes[1].x_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;
|
|
}
|
|
|
|
// bReallocate panes array
|
|
E.layout.panes = bRealloc(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].origin_y = 0;
|
|
E.layout.panes[0].origin_x = 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].y_offset = 0;
|
|
E.layout.panes[0].x_offset = 0;
|
|
E.layout.panes[0].is_active = 1;
|
|
|
|
// Bottom pane
|
|
E.layout.panes[1].buffer_id = buffer_id_bottom;
|
|
E.layout.panes[1].origin_y = half_height;
|
|
E.layout.panes[1].origin_x = 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].x_offset = 0;
|
|
E.layout.panes[1].y_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].origin_x = 0;
|
|
E.layout.panes[0].origin_y = 0;
|
|
E.layout.panes[0].height = E.screenrows;
|
|
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->origin_x = 0;
|
|
active->origin_y = 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];
|
|
}
|