initial implementation of selection and copying

This commit is contained in:
cy384 2021-01-22 19:47:48 -05:00
parent df6ccd0449
commit 28c6f50531
4 changed files with 163 additions and 6 deletions

View File

@ -15,6 +15,9 @@
#include <vterm.h>
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
char key_to_vterm[256] = { VTERM_KEY_NONE };
void setup_key_translation(void)
@ -149,9 +152,41 @@ inline int idx2qd(VTermColor c)
}
}
// p is in window local coordinates
void mouse_click(Point p, bool click)
void point_to_cell(Point p, int* x, int* y)
{
*x = p.h / con.cell_width;
*y = p.v / con.cell_height;
if (*x > con.size_x) *x = con.size_x;
if (*y > con.size_y) *y = con.size_y;
}
void damage_selection(void)
{
// damage all rows that have part of the selection (TODO make this better)
Rect topleft = cell_rect(0, MIN(con.select_start_y, con.select_end_y), (con.win->portRect));
Rect bottomright = cell_rect(con.size_x, MAX(con.select_start_y, con.select_end_y), (con.win->portRect));
UnionRect(&topleft, &bottomright, &topleft);
InvalRect(&topleft);
}
void update_selection_end(void)
{
Point new_mouse;
GetMouse(&new_mouse);
point_to_cell(new_mouse, &con.select_end_x, &con.select_end_y);
damage_selection();
}
// p is in window local coordinates
void mouse_click(Point p, int click)
{
static Point last_click;
con.mouse_state = click;
if (con.mouse_mode == CLICK_SEND)
{
int row = p.v / con.cell_height;
@ -161,8 +196,72 @@ void mouse_click(Point p, bool click)
}
else if (con.mouse_mode == CLICK_SELECT)
{
// TODO: implement text selection
if (click)
{
// damage the old selection so it gets wiped from the screen
damage_selection();
last_click = p;
point_to_cell(p, &con.select_start_x, &con.select_start_y);
point_to_cell(p, &con.select_end_x, &con.select_end_y);
update_selection_end();
}
else
{
int a, b, c, d;
point_to_cell(last_click, &a, &b);
point_to_cell(p, &c, &d);
// if in same cell, cancel the selection
if (a == c && b == d)
{
con.select_start_x = -1;
con.select_start_y = -1;
con.select_end_x = -1;
con.select_end_y = -1;
}
update_selection_end();
}
}
}
size_t get_selection(char** selection)
{
int a = con.select_start_x + con.select_start_y * con.size_x;
int b = con.select_end_x + con.select_end_y * con.size_x;
ssize_t len = MAX(a,b) - MIN(a,b) + 1;
if (len == 0)
{
*selection = NULL;
return 0;
}
char* output = malloc(sizeof(char) * len);
int start_row = MIN(con.select_start_y, con.select_end_y);
int start_col = MIN(con.select_start_x, con.select_end_x);
//int end_row = MAX(con.select_start_y, con.select_end_y);
//int end_col = MAX(con.select_start_x, con.select_end_x);
VTermPos pos = {.row = 0, .col = 0};
ScreenCell* vtsc = NULL;
for(int i = 0; i < len; i++)
{
pos.col = (start_col + i) % con.size_x;
pos.row = (start_row + (i / con.size_x));
vtsc = vterm_screen_unsafe_get_cell(con.vts, pos);
output[i] = (char)vtsc->chars[0];
}
output[len-1] = '\0';
*selection = output;
return len;
}
void draw_screen_color(Rect* r)
@ -208,6 +307,32 @@ void draw_screen_color(Rect* r)
ScreenCell* vtsc = NULL;
VTermPos pos = {.row = 0, .col = 0};
int i = 0;
int select_start = -1;
int select_end = -1;
if (con.mouse_mode == CLICK_SELECT && con.mouse_state) update_selection_end();
if (con.mouse_mode == CLICK_SELECT && con.select_start_x != -1)
{
int a = con.select_start_x + con.select_start_y * con.size_x;
int b = con.select_end_x + con.select_end_y * con.size_x;
if (a < b)
{
select_start = a;
select_end = b;
}
else
{
select_start = b;
select_end = a;
}
select_start = MIN(a,b);
select_end = MAX(a,b);
}
for(pos.row = minRow; pos.row < maxRow; pos.row++)
{
for (pos.col = minCol; pos.col < maxCol; pos.col++)
@ -233,6 +358,11 @@ void draw_screen_color(Rect* r)
{
InvertRect(&cr);
}
if (i < select_end && i >= select_start)
{
InvertRect(&cr);
}
i++;
}
}

View File

@ -17,6 +17,8 @@ void printf_i(const char* c, ...);
void check_cursor(void);
void mouse_click(Point p, bool click);
void mouse_click(Point p, int click);
void update_console_colors(void);
size_t get_selection(char** selection);

View File

@ -25,7 +25,7 @@
#include <stdio.h>
// sinful globals
struct ssheven_console con = { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 1, CLICK_SELECT, NULL, NULL };
struct ssheven_console con = { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, CLICK_SELECT, NULL, NULL };
struct ssheven_ssh_connection ssh_con = { NULL, NULL, kOTInvalidEndpointRef, NULL, NULL };
struct preferences prefs;
@ -288,6 +288,19 @@ void ssh_paste(void)
DisposeHandle(buf);
}
void ssh_copy(void)
{
OSErr e = ZeroScrap();
if (e != noErr) printf_i("Failed to ZeroScrap!");
char* selection = NULL;
size_t len = get_selection(&selection);
if (selection == NULL || len == 0) return;
e = PutScrap(len, 'TEXT', selection);
if (e != noErr) printf_i("Failed to PutScrap!");
}
int qd_color_to_menu_item(int qd_color)
{
switch (qd_color)
@ -417,6 +430,7 @@ int process_menu_select(int32_t result)
break;
case MENU_EDIT:
if (item == 4) ssh_copy();
if (item == 5) ssh_paste();
break;
@ -479,6 +493,9 @@ int handle_keypress(EventRecord* event)
case 'v':
ssh_paste();
break;
case 'c':
ssh_copy();
break;
default:
break;
}
@ -1088,7 +1105,7 @@ int main(int argc, char** argv)
menu = GetMenuHandle(MENU_EDIT);
DisableItem(menu, 1);
DisableItem(menu, 3);
DisableItem(menu, 4);
//DisableItem(menu, 4);
DisableItem(menu, 5);
DisableItem(menu, 6);
DisableItem(menu, 7);

View File

@ -37,6 +37,14 @@ struct ssheven_console
long int last_cursor_blink;
int cursor_visible;
int select_start_x;
int select_start_y;
int select_end_x;
int select_end_y;
int mouse_state; // 1 for down, 0 for up
enum { CLICK_SEND, CLICK_SELECT } mouse_mode;
VTerm* vterm;