mirror of
https://github.com/d0k3/GodMode9.git
synced 2026-05-30 22:36:55 +00:00
Adding clipboard select/cut/copy/paste support.
This commit is contained in:
parent
d65a5b6771
commit
04072d5b62
@ -222,7 +222,7 @@ static char KeyboardWait(TouchBox* swkbd, bool uppercase, const bool multi_line)
|
|||||||
else if (pressed & BUTTON_B) return KEY_ESCAPE;
|
else if (pressed & BUTTON_B) return KEY_ESCAPE;
|
||||||
else if (pressed & BUTTON_A) return KEY_ENTER;
|
else if (pressed & BUTTON_A) return KEY_ENTER;
|
||||||
else if (pressed & BUTTON_X) return KEY_BKSPC;
|
else if (pressed & BUTTON_X) return KEY_BKSPC;
|
||||||
else if (pressed & BUTTON_Y) return multi_line ? KEY_CAPS : KEY_INSERT;
|
else if (pressed & BUTTON_Y) return multi_line ? KEY_CLIP : KEY_INSERT;
|
||||||
else if (!multi_line && pressed & BUTTON_R1) return KEY_CAPS;
|
else if (!multi_line && pressed & BUTTON_R1) return KEY_CAPS;
|
||||||
else if (pressed & BUTTON_RIGHT) return KEY_RIGHT;
|
else if (pressed & BUTTON_RIGHT) return KEY_RIGHT;
|
||||||
else if (pressed & BUTTON_LEFT) return KEY_LEFT;
|
else if (pressed & BUTTON_LEFT) return KEY_LEFT;
|
||||||
@ -392,14 +392,14 @@ bool ShowKeyboard(char* inputstr, const u32 max_size, const char *format, ...) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char ShowMultiLineKeyboard(TouchBox* swkbd_alphabet, TouchBox* swkbd_special, TouchBox* swkbd_numpad, TouchBox** swkbd, TouchBox** swkbd_prev, u32* uppercase) {
|
char ShowMultiLineKeyboard(const char* instructions, TouchBox* swkbd_alphabet, TouchBox* swkbd_special, TouchBox* swkbd_numpad, TouchBox** swkbd, TouchBox** swkbd_prev, u32* uppercase) {
|
||||||
if (!*swkbd) {
|
if (instructions) {
|
||||||
u32 str_width = GetDrawStringWidth(STR_TEXTEDITOR_CONTROLS_KEYBOARD);
|
u32 str_width = GetDrawStringWidth(instructions);
|
||||||
if (str_width < (24 * FONT_WIDTH_EXT)) str_width = 24 * FONT_WIDTH_EXT;
|
if (str_width < (24 * FONT_WIDTH_EXT)) str_width = 24 * FONT_WIDTH_EXT;
|
||||||
u32 str_x = (str_width >= SCREEN_WIDTH_BOT) ? 0 : (SCREEN_WIDTH_BOT - str_width) / 2;
|
u32 str_x = (str_width >= SCREEN_WIDTH_BOT) ? 0 : (SCREEN_WIDTH_BOT - str_width) / 2;
|
||||||
ClearScreen(BOT_SCREEN, COLOR_STD_BG);
|
ClearScreen(BOT_SCREEN, COLOR_STD_BG);
|
||||||
DrawStringF(BOT_SCREEN, str_x, 20, COLOR_STD_FONT, COLOR_STD_BG, "%s", STR_TEXTEDITOR_CONTROLS_KEYBOARD);
|
DrawStringF(BOT_SCREEN, str_x, 20, COLOR_STD_FONT, COLOR_STD_BG, "%s", instructions);
|
||||||
*swkbd = swkbd_alphabet;
|
*swkbd_prev = NULL; // Force keyboard redraw
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle keyboard
|
// handle keyboard
|
||||||
|
|||||||
@ -23,6 +23,7 @@ enum {
|
|||||||
KEY_UNICODE = 0x8C,
|
KEY_UNICODE = 0x8C,
|
||||||
KEY_UP = 0x8D,
|
KEY_UP = 0x8D,
|
||||||
KEY_DOWN = 0x8E,
|
KEY_DOWN = 0x8E,
|
||||||
|
KEY_CLIP = 0x8F,
|
||||||
KEY_TXTBOX = 0xFF
|
KEY_TXTBOX = 0xFF
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -108,4 +109,4 @@ enum {
|
|||||||
#define ShowKeyboardOrPrompt (TouchIsCalibrated() ? ShowKeyboard : ShowStringPrompt)
|
#define ShowKeyboardOrPrompt (TouchIsCalibrated() ? ShowKeyboard : ShowStringPrompt)
|
||||||
bool PRINTF_ARGS(3) ShowKeyboard(char* inputstr, u32 max_size, const char *format, ...);
|
bool PRINTF_ARGS(3) ShowKeyboard(char* inputstr, u32 max_size, const char *format, ...);
|
||||||
bool BuildKeyboard(TouchBox* swkbd, const char* keys, const u8* layout, bool multi_line);
|
bool BuildKeyboard(TouchBox* swkbd, const char* keys, const u8* layout, bool multi_line);
|
||||||
char ShowMultiLineKeyboard(TouchBox* swkbd_alphabet, TouchBox* swkbd_special, TouchBox* swkbd_numpad, TouchBox** swkbd, TouchBox** swkbd_prev, u32* uppercase);
|
char ShowMultiLineKeyboard(const char* instructions, TouchBox* swkbd_alphabet, TouchBox* swkbd_special, TouchBox* swkbd_numpad, TouchBox** swkbd, TouchBox** swkbd_prev, u32* uppercase);
|
||||||
|
|||||||
@ -336,7 +336,7 @@ static inline u32 line_len_chars(const char* text, u32 len, u32 ww, const char*
|
|||||||
static inline const char* line_seek_chars(const char* text, u32 len, u32 ww, const char* line, int add) {
|
static inline const char* line_seek_chars(const char* text, u32 len, u32 ww, const char* line, int add) {
|
||||||
// safety check
|
// safety check
|
||||||
if ((line <= text && add <= 0) || (line >= text + len && add >= 0)) return line;
|
if ((line <= text && add <= 0) || (line >= text + len && add >= 0)) return line;
|
||||||
|
|
||||||
const char* l0 = line;
|
const char* l0 = line;
|
||||||
|
|
||||||
if (!ww) { // non wordwrapped mode
|
if (!ww) { // non wordwrapped mode
|
||||||
@ -1671,7 +1671,7 @@ bool ValidateText(const char* text, u32 len) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemTextView(const char* text, u32 len, const char* line0, int off_disp_chars, int lno, u32 ww, u32 mno, bool is_script, const char* cursor) {
|
void MemTextView(const char* text, u32 len, const char* line0, int off_disp_chars, int lno, u32 ww, u32 mno, bool is_script, const char* cursor, const char* cursor_end) {
|
||||||
// block placements
|
// block placements
|
||||||
u32 x_txt = (TV_LNOS >= 0) ? TV_HPAD + ((TV_LNOS+1)*FONT_WIDTH_EXT) : TV_HPAD;
|
u32 x_txt = (TV_LNOS >= 0) ? TV_HPAD + ((TV_LNOS+1)*FONT_WIDTH_EXT) : TV_HPAD;
|
||||||
u32 x_lno = TV_HPAD;
|
u32 x_lno = TV_HPAD;
|
||||||
@ -1738,7 +1738,97 @@ void MemTextView(const char* text, u32 len, const char* line0, int off_disp_char
|
|||||||
else DrawStringF(TOP_SCREEN, x_lno, y, COLOR_TVOFFSL, COLOR_STD_BG, "%*.*s", TV_LNOS, TV_LNOS, " ");
|
else DrawStringF(TOP_SCREEN, x_lno, y, COLOR_TVOFFSL, COLOR_STD_BG, "%*.*s", TV_LNOS, TV_LNOS, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursor) {
|
const int x_txt_end = x_txt + TV_LLEN_DISP * FONT_WIDTH_EXT;
|
||||||
|
bool draw_ar_select = false, draw_al_select = false;
|
||||||
|
|
||||||
|
// account for selections drawn across lines
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt, y - 1, COLOR_STD_BG);
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt_end - 1, y - 1, COLOR_STD_BG);
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt, y + FONT_HEIGHT_EXT, COLOR_STD_BG);
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt_end - 1, y + FONT_HEIGHT_EXT, COLOR_STD_BG);
|
||||||
|
|
||||||
|
// draw cursor / selection
|
||||||
|
if (cursor_end) {
|
||||||
|
int x_hline_start = -1, x_hline_end = -1;
|
||||||
|
|
||||||
|
u32 cursor_line_offset_chars = chars_between_pointers(ptr + off_disp_bytes, cursor);
|
||||||
|
bool draw_cursor = cursor >= ptr + off_disp_bytes && cursor <= ptr + off_disp_bytes + ncpy_bytes && cursor_line_offset_chars < TV_LLEN_DISP
|
||||||
|
&& (cursor != ptr + off_disp_bytes + ncpy_bytes || is_newline(cursor) || cursor == text + len);
|
||||||
|
if (draw_cursor) {
|
||||||
|
x_hline_start = x_txt + cursor_line_offset_chars * FONT_WIDTH_EXT;
|
||||||
|
DrawRectangle(TOP_SCREEN, x_hline_start, y, 1, FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
} else if (cursor < ptr + off_disp_bytes) x_hline_start = x_txt;
|
||||||
|
|
||||||
|
const char* cursor_end_prev = GetPrevChar(cursor_end);
|
||||||
|
u32 cursor_end_line_offset_chars = chars_between_pointers(ptr + off_disp_bytes, cursor_end_prev);
|
||||||
|
bool draw_cursor_end = cursor_end_prev >= ptr + off_disp_bytes && cursor_end_prev <= ptr + off_disp_bytes + ncpy_bytes && cursor_end_line_offset_chars < TV_LLEN_DISP
|
||||||
|
&& (!ww || cursor_end_prev != ptr + off_disp_bytes + ncpy_bytes || is_newline(cursor_end_prev));
|
||||||
|
if (draw_cursor_end) {
|
||||||
|
x_hline_end = x_txt + (cursor_end_line_offset_chars + 1) * FONT_WIDTH_EXT;
|
||||||
|
DrawRectangle(TOP_SCREEN, x_hline_end - ((cursor_end_line_offset_chars == TV_LLEN_DISP - 1) ? 1 : 0), y, 1, FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
cursor_end = NULL; // prevent cursor from being drawn multiple times at the end of the screen
|
||||||
|
} else if (cursor_end_prev >= ptr + off_disp_bytes + ncpy_bytes) x_hline_end = x_txt_end;
|
||||||
|
|
||||||
|
if (draw_cursor && draw_cursor_end) {
|
||||||
|
DrawRectangle(TOP_SCREEN, x_hline_start, y, x_hline_end - x_hline_start, 1, COLOR_YELLOW);
|
||||||
|
DrawRectangle(TOP_SCREEN, x_hline_start, y + FONT_HEIGHT_EXT - 1, x_hline_end - x_hline_start, 1, COLOR_YELLOW);
|
||||||
|
} else if (draw_cursor) {
|
||||||
|
DrawRectangle(TOP_SCREEN, x_hline_start, y, x_txt_end - x_hline_start, 1, COLOR_YELLOW);
|
||||||
|
if (cursor_end > ptr_next) {
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt, y + FONT_HEIGHT_EXT - 1, x_hline_start - x_txt, 1, COLOR_YELLOW);
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt, y + FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt_end - 1, y + FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
} else {
|
||||||
|
DrawRectangle(TOP_SCREEN, x_hline_start, y + FONT_HEIGHT_EXT - 1, x_txt_end - x_hline_start, 1, COLOR_YELLOW);
|
||||||
|
cursor_end = NULL;
|
||||||
|
}
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt_end - 1, y, 1, FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
draw_ar_select = true;
|
||||||
|
} else if (draw_cursor_end) {
|
||||||
|
if (cursor < ptr) {
|
||||||
|
DrawRectangle(TOP_SCREEN, x_hline_end, y, x_txt_end - x_hline_end, 1, COLOR_YELLOW);
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt, y - 1, COLOR_YELLOW);
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt_end - 1, y - 1, COLOR_YELLOW);
|
||||||
|
} else {
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt, y, x_hline_end - x_txt, 1, COLOR_YELLOW);
|
||||||
|
}
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt, y + FONT_HEIGHT_EXT - 1, x_hline_end - x_txt, 1, COLOR_YELLOW);
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt, y, 1, FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
draw_al_select = true;
|
||||||
|
} else if (cursor < ptr_next) {
|
||||||
|
if (cursor < ptr + off_disp_bytes) {
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt, y, 1, FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
if (cursor >= ptr) DrawRectangle(TOP_SCREEN, x_txt, y, x_txt_end - x_txt, 1, COLOR_YELLOW);
|
||||||
|
else {
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt, y - 1, COLOR_YELLOW);
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt_end - 1, y - 1, COLOR_YELLOW);
|
||||||
|
}
|
||||||
|
draw_al_select = true;
|
||||||
|
} else if (cursor >= ptr + off_disp_bytes + ncpy_bytes) {
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt_end - 1, y, 1, FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt, y + FONT_HEIGHT_EXT - 1, x_txt_end - x_txt, 1, COLOR_YELLOW);
|
||||||
|
draw_ar_select = true;
|
||||||
|
}
|
||||||
|
if (cursor_end_prev < ptr + off_disp_bytes) {
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt, y, 1, FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt, y, x_txt_end - x_txt, 1, COLOR_YELLOW);
|
||||||
|
cursor_end = NULL;
|
||||||
|
draw_al_select = true;
|
||||||
|
} else if (cursor_end_prev >= ptr + off_disp_bytes + ncpy_bytes) {
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt_end - 1, y, 1, FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
if (cursor_end_prev < ptr_next) {
|
||||||
|
DrawRectangle(TOP_SCREEN, x_txt, y + FONT_HEIGHT_EXT - 1, x_txt_end - x_txt, 1, COLOR_YELLOW);
|
||||||
|
cursor_end = NULL;
|
||||||
|
} else {
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt, y + FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
DrawPixel(TOP_SCREEN, x_txt_end - 1, y + FONT_HEIGHT_EXT, COLOR_YELLOW);
|
||||||
|
}
|
||||||
|
draw_ar_select = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cursor_end) cursor = NULL;
|
||||||
|
} else if (cursor) {
|
||||||
u32 cursor_line_offset_chars = chars_between_pointers(ptr + off_disp_bytes, cursor);
|
u32 cursor_line_offset_chars = chars_between_pointers(ptr + off_disp_bytes, cursor);
|
||||||
if (cursor >= ptr + off_disp_bytes && cursor <= ptr + off_disp_bytes + ncpy_bytes && cursor_line_offset_chars < TV_LLEN_DISP
|
if (cursor >= ptr + off_disp_bytes && cursor <= ptr + off_disp_bytes + ncpy_bytes && cursor_line_offset_chars < TV_LLEN_DISP
|
||||||
&& (cursor != ptr + off_disp_bytes + ncpy_bytes || is_newline(cursor) || cursor == text + len)) {
|
&& (cursor != ptr + off_disp_bytes + ncpy_bytes || is_newline(cursor) || cursor == text + len)) {
|
||||||
@ -1758,8 +1848,8 @@ void MemTextView(const char* text, u32 len, const char* line0, int off_disp_char
|
|||||||
}
|
}
|
||||||
|
|
||||||
// colorize arrows
|
// colorize arrows
|
||||||
if (al) DrawStringF(TOP_SCREEN, x_al, y, COLOR_TVOFFS, COLOR_TRANSPARENT, "%s", al_str);
|
if (al) DrawStringF(TOP_SCREEN, x_al, y, draw_al_select ? COLOR_TINTEDYELLOW : COLOR_TVOFFS, COLOR_TRANSPARENT, "%s", al_str);
|
||||||
if (ar) DrawStringF(TOP_SCREEN, x_ar, y, COLOR_TVOFFS, COLOR_TRANSPARENT, "%s", ar_str);
|
if (ar) DrawStringF(TOP_SCREEN, x_ar, y, draw_ar_select ? COLOR_TINTEDYELLOW : COLOR_TVOFFS, COLOR_TRANSPARENT, "%s", ar_str);
|
||||||
|
|
||||||
// advance pointer / line number
|
// advance pointer / line number
|
||||||
for (const char* c = ptr; c < ptr_next; c++) if (*c == '\n') ++nln;
|
for (const char* c = ptr; c < ptr_next; c++) if (*c == '\n') ++nln;
|
||||||
@ -1818,13 +1908,17 @@ bool MemTextViewer(const char* text, u32 len, u32 start, bool as_script, u32 max
|
|||||||
bool crlf = is_crlf(text);
|
bool crlf = is_crlf(text);
|
||||||
bool display_view_instructions = true;
|
bool display_view_instructions = true;
|
||||||
const char* cursor = NULL;
|
const char* cursor = NULL;
|
||||||
|
const char* cursor_end = NULL;
|
||||||
|
const char** last_cursor = &cursor;
|
||||||
|
char* clipboard = NULL;
|
||||||
|
const char* instructions = NULL;
|
||||||
const char* line0 = text;
|
const char* line0 = text;
|
||||||
int lcurr = 1; // Current line number
|
int lcurr = 1; // Current line number
|
||||||
int off_disp_chars = 0; // non-word-wrapped offset
|
int off_disp_chars = 0; // non-word-wrapped offset
|
||||||
for (; lcurr < (int) start; line0 = line_seek_chars(text, len, 0, line0, 1), lcurr++);
|
for (; lcurr < (int) start; line0 = line_seek_chars(text, len, 0, line0, 1), lcurr++);
|
||||||
while (true) {
|
while (true) {
|
||||||
// display text on screen
|
// display text on screen
|
||||||
MemTextView(text, len, line0, off_disp_chars, lcurr, ww, 0, as_script, cursor);
|
MemTextView(text, len, line0, off_disp_chars, lcurr, ww, 0, as_script, cursor, cursor_end);
|
||||||
|
|
||||||
const char* line0_next = line0;
|
const char* line0_next = line0;
|
||||||
|
|
||||||
@ -1848,8 +1942,9 @@ bool MemTextViewer(const char* text, u32 len, u32 start, bool as_script, u32 max
|
|||||||
cursor = line0;
|
cursor = line0;
|
||||||
off_disp_chars = 0;
|
off_disp_chars = 0;
|
||||||
uppercase = 0;
|
uppercase = 0;
|
||||||
swkbd = NULL;
|
swkbd = swkbd_alphabet;
|
||||||
swkbd_prev = NULL;
|
swkbd_prev = NULL;
|
||||||
|
instructions = clipboard ? STR_TEXTEDITOR_CONTROLS_CLIPBOARD : STR_TEXTEDITOR_CONTROLS_KEYBOARD;
|
||||||
}
|
}
|
||||||
else if (switched && pad_state & BUTTON_X) {
|
else if (switched && pad_state & BUTTON_X) {
|
||||||
u64 lnext64 = ShowNumberPrompt(lcurr, STR_CURRENT_LINE_N_ENTER_NEW_LINE_BELOW, lcurr);
|
u64 lnext64 = ShowNumberPrompt(lcurr, STR_CURRENT_LINE_N_ENTER_NEW_LINE_BELOW, lcurr);
|
||||||
@ -1861,48 +1956,73 @@ bool MemTextViewer(const char* text, u32 len, u32 start, bool as_script, u32 max
|
|||||||
line0_next = line_start(text, len, ww, line0);
|
line0_next = line_start(text, len, ww, line0);
|
||||||
} else if (pad_state & (BUTTON_B|BUTTON_START)) break;
|
} else if (pad_state & (BUTTON_B|BUTTON_START)) break;
|
||||||
} else { // edit mode
|
} else { // edit mode
|
||||||
char key_pressed = ShowMultiLineKeyboard(swkbd_alphabet, swkbd_special, swkbd_numpad, &swkbd, &swkbd_prev, &uppercase);
|
char key_pressed = ShowMultiLineKeyboard(instructions, swkbd_alphabet, swkbd_special, swkbd_numpad, &swkbd, &swkbd_prev, &uppercase);
|
||||||
|
instructions = NULL;
|
||||||
char key_character = 0;
|
char key_character = 0;
|
||||||
bool switched = HID_ReadState() & BUTTON_R1;
|
u32 pad_state = HID_ReadState();
|
||||||
|
bool switched = pad_state & BUTTON_R1;
|
||||||
|
bool selected = pad_state & BUTTON_L1 || (cursor_end && switched);
|
||||||
|
const char** prev_last_cursor = last_cursor;
|
||||||
|
last_cursor = &cursor;
|
||||||
if (key_pressed == KEY_ESCAPE) {
|
if (key_pressed == KEY_ESCAPE) {
|
||||||
cursor = NULL;
|
cursor = NULL;
|
||||||
|
cursor_end = NULL;
|
||||||
display_view_instructions = true;
|
display_view_instructions = true;
|
||||||
} else if (key_pressed == KEY_DOWN) {
|
} else if (key_pressed == KEY_DOWN) {
|
||||||
const char* cursor_line_start = line_start(text, len, ww, cursor);
|
const char** down_cursor = selected ? last_cursor = &cursor_end : &cursor;
|
||||||
u32 cursor_chars_from_line_start = chars_between_pointers(cursor_line_start, cursor);
|
if (!*down_cursor) *down_cursor = cursor;
|
||||||
cursor = line_seek_chars(text, len, ww, cursor_line_start, switched ? TV_NLIN_DISP : 1);
|
const char* down_cursor_char = down_cursor == &cursor_end && cursor_end > cursor ? GetPrevChar(*down_cursor) : *down_cursor;
|
||||||
cursor = line_start(text, len, ww, cursor);
|
const char* cursor_line_start = line_start(text, len, ww, down_cursor_char);
|
||||||
const char* next_line_start = line_seek_chars(text, len, ww, cursor, 1);
|
u32 cursor_chars_from_line_start = chars_between_pointers(cursor_line_start, down_cursor_char);
|
||||||
for (u32 i = 0; GetNextChar(cursor) < next_line_start && i < cursor_chars_from_line_start; IncChar(&cursor), ++i);
|
*down_cursor = line_seek_chars(text, len, ww, cursor_line_start, switched ? TV_NLIN_DISP : 1);
|
||||||
|
*down_cursor = line_start(text, len, ww, *down_cursor);
|
||||||
|
const char* next_line_start = line_seek_chars(text, len, ww, *down_cursor, 1);
|
||||||
|
if (down_cursor == &cursor_end) for (u32 i = 0; *down_cursor < next_line_start && i <= cursor_chars_from_line_start; IncChar(down_cursor), ++i);
|
||||||
|
else for (u32 i = 0; GetNextChar(*down_cursor) < next_line_start && i < cursor_chars_from_line_start; IncChar(down_cursor), ++i);
|
||||||
|
if (!selected) cursor_end = NULL;
|
||||||
} else if (key_pressed == KEY_UP) {
|
} else if (key_pressed == KEY_UP) {
|
||||||
|
if (selected && !cursor_end) cursor_end = cursor;
|
||||||
const char* cursor_line_start = line_start(text, len, ww, cursor);
|
const char* cursor_line_start = line_start(text, len, ww, cursor);
|
||||||
u32 cursor_chars_from_line_start = chars_between_pointers(cursor_line_start, cursor);
|
u32 cursor_chars_from_line_start = chars_between_pointers(cursor_line_start, cursor);
|
||||||
cursor = line_seek_chars(text, len, ww, cursor_line_start, -(switched ? TV_NLIN_DISP : 1));
|
cursor = line_seek_chars(text, len, ww, cursor_line_start, -(switched ? TV_NLIN_DISP : 1));
|
||||||
const char* next_line_start = line_seek_chars(text, len, ww, cursor, 1);
|
const char* next_line_start = line_seek_chars(text, len, ww, cursor, 1);
|
||||||
for (u32 i = 0; GetNextChar(cursor) < next_line_start && i < cursor_chars_from_line_start; IncChar(&cursor), ++i);
|
for (u32 i = 0; GetNextChar(cursor) < next_line_start && i < cursor_chars_from_line_start; IncChar(&cursor), ++i);
|
||||||
|
if (!selected) cursor_end = NULL;
|
||||||
} else if (key_pressed == KEY_RIGHT) {
|
} else if (key_pressed == KEY_RIGHT) {
|
||||||
|
const char** right_cursor = selected ? last_cursor = &cursor_end : &cursor;
|
||||||
|
if (!*right_cursor) *right_cursor = cursor;
|
||||||
if (switched) {
|
if (switched) {
|
||||||
const char* cursor_line_start = line_start(text, len, ww, cursor);
|
const char* cursor_line_start = line_start(text, len, ww, right_cursor == &cursor_end && cursor_end > cursor ? GetPrevChar(*right_cursor) : *right_cursor);
|
||||||
const char* next_line_start = line_seek_chars(text, len, ww, cursor_line_start, 1);
|
const char* next_line_start = line_seek_chars(text, len, ww, cursor_line_start, 1);
|
||||||
if (next_line_start == text + len && (!ww || chars_between_pointers(cursor_line_start, next_line_start) != TV_LLEN_DISP)) IncChar(&next_line_start);
|
if (right_cursor == &cursor && next_line_start == text + len && (!ww || chars_between_pointers(cursor_line_start, next_line_start) != TV_LLEN_DISP))
|
||||||
while (GetNextChar(cursor) < next_line_start && !is_newline(cursor)) IncChar(&cursor);
|
IncChar(&next_line_start);
|
||||||
|
if (right_cursor == &cursor_end) for (u32 chars = 0; *right_cursor < next_line_start && chars < TV_LLEN_DISP; ++chars) IncChar(right_cursor);
|
||||||
|
else for (u32 chars = 0; GetNextChar(*right_cursor) < next_line_start && !is_newline(*right_cursor) && chars < TV_LLEN_DISP; ++chars) IncChar(right_cursor);
|
||||||
}
|
}
|
||||||
else if (cursor < text + len) IncChar(&cursor);
|
else if (*right_cursor < text + len) IncChar(right_cursor);
|
||||||
|
if (!selected) cursor_end = NULL;
|
||||||
} else if (key_pressed == KEY_LEFT) {
|
} else if (key_pressed == KEY_LEFT) {
|
||||||
|
if (selected && !cursor_end) cursor_end = cursor;
|
||||||
if (switched) {
|
if (switched) {
|
||||||
const char* cursor_line_start = line_start(text, len, ww, cursor);
|
const char* cursor_line_start = line_start(text, len, ww, cursor);
|
||||||
while (cursor > cursor_line_start) DecChar(&cursor);
|
while (cursor > cursor_line_start) DecChar(&cursor);
|
||||||
}
|
}
|
||||||
else if (cursor > text) DecChar(&cursor);
|
else if (cursor > text) DecChar(&cursor);
|
||||||
|
if (!selected) cursor_end = NULL;
|
||||||
} else if (key_pressed == KEY_BKSPC) {
|
} else if (key_pressed == KEY_BKSPC) {
|
||||||
if (cursor > text) {
|
if (cursor_end && cursor_end > cursor) {
|
||||||
|
memmove((char *) cursor, cursor_end, text + len - cursor_end + 1);
|
||||||
|
len -= cursor_end - cursor;
|
||||||
|
cursor_end = NULL;
|
||||||
|
} else if (cursor > text) {
|
||||||
u32 size = GetPrevCharSize(cursor);
|
u32 size = GetPrevCharSize(cursor);
|
||||||
memmove((char *) cursor - size, cursor, text + len - cursor + 1);
|
memmove((char *) cursor - size, cursor, text + len - cursor + 1);
|
||||||
len -= size;
|
len -= size;
|
||||||
cursor -= size;
|
cursor -= size;
|
||||||
}
|
}
|
||||||
} else if (key_pressed == KEY_UNICODE) {
|
} else if (key_pressed == KEY_UNICODE) {
|
||||||
if (cursor >= text + 4 && cursor <= text + len) {
|
if (cursor_end) last_cursor = prev_last_cursor;
|
||||||
|
else if (cursor >= text + 4 && cursor <= text + len) {
|
||||||
u16 codepoint = 0;
|
u16 codepoint = 0;
|
||||||
for (const char *c = cursor - 4; c < cursor; c++) {
|
for (const char *c = cursor - 4; c < cursor; c++) {
|
||||||
if ((*c >= '0' && *c <= '9') || (*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f')) {
|
if ((*c >= '0' && *c <= '9') || (*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f')) {
|
||||||
@ -1926,9 +2046,52 @@ bool MemTextViewer(const char* text, u32 len, u32 start, bool as_script, u32 max
|
|||||||
len -= 4 - char_size;
|
len -= 4 - char_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (key_pressed == KEY_CLIP) { // clipboard
|
||||||
|
if (clipboard) {
|
||||||
|
if (switched) { // clear
|
||||||
|
free(clipboard);
|
||||||
|
clipboard = NULL;
|
||||||
|
instructions = STR_TEXTEDITOR_CONTROLS_KEYBOARD;
|
||||||
|
last_cursor = prev_last_cursor;
|
||||||
|
} else { // paste
|
||||||
|
int clip_size = strlen(clipboard);
|
||||||
|
int select_size = cursor_end ? cursor_end - cursor : 0;
|
||||||
|
if (clip_size && len - select_size + clip_size <= max_len) {
|
||||||
|
if (clip_size != select_size) {
|
||||||
|
const char* select_end = cursor_end ? cursor_end : cursor;
|
||||||
|
memmove((char *) cursor + clip_size, select_end, text + len - select_end + 1);
|
||||||
|
}
|
||||||
|
memcpy((char *) cursor, clipboard, clip_size);
|
||||||
|
cursor += clip_size;
|
||||||
|
cursor_end = NULL;
|
||||||
|
len += clip_size - select_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (cursor_end && cursor_end > cursor) { // copy
|
||||||
|
int select_size = cursor_end - cursor;
|
||||||
|
clipboard = malloc(select_size + 1);
|
||||||
|
if (clipboard) {
|
||||||
|
memcpy(clipboard, cursor, select_size);
|
||||||
|
clipboard[select_size] = '\0';
|
||||||
|
if (switched) { // cut
|
||||||
|
memmove((char *) cursor, cursor_end, text + len - cursor_end + 1);
|
||||||
|
len -= select_size;
|
||||||
|
cursor_end = NULL;
|
||||||
|
} else last_cursor = prev_last_cursor;
|
||||||
|
instructions = STR_TEXTEDITOR_CONTROLS_CLIPBOARD;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (key_pressed == KEY_ENTER) key_character = crlf ? '\r' : '\n';
|
} else if (key_pressed == KEY_ENTER) key_character = crlf ? '\r' : '\n';
|
||||||
else if (key_pressed < 0x80) key_character = key_pressed;
|
else if (key_pressed < 0x80) key_character = key_pressed;
|
||||||
|
|
||||||
|
// delete selection if typing standard char
|
||||||
|
if (key_character && cursor_end && cursor_end > cursor) {
|
||||||
|
memmove((char *) cursor, cursor_end, text + len - cursor_end + 1);
|
||||||
|
len -= cursor_end - cursor;
|
||||||
|
cursor_end = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// type standard char
|
||||||
if (key_character && len + (key_character == '\r' ? 1 : 0) < max_len) {
|
if (key_character && len + (key_character == '\r' ? 1 : 0) < max_len) {
|
||||||
if (uppercase == 1) {
|
if (uppercase == 1) {
|
||||||
uppercase = 0;
|
uppercase = 0;
|
||||||
@ -1941,14 +2104,18 @@ bool MemTextViewer(const char* text, u32 len, u32 start, bool as_script, u32 max
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursor && !ww) {
|
if (cursor_end <= cursor) cursor_end = NULL;
|
||||||
const char* cursor_line_start = line_start(text, len, ww, cursor);
|
|
||||||
u32 cursor_chars_from_line_start = chars_between_pointers(cursor_line_start, cursor);
|
// adjust screen to view last cursor moved
|
||||||
|
const char* last_cursor_value = cursor_end && last_cursor == &cursor_end ? GetPrevChar(cursor_end) : cursor;
|
||||||
|
if (last_cursor_value && !ww) {
|
||||||
|
const char* cursor_line_start = line_start(text, len, ww, last_cursor_value);
|
||||||
|
u32 cursor_chars_from_line_start = chars_between_pointers(cursor_line_start, last_cursor_value);
|
||||||
if (cursor_chars_from_line_start < off_disp_chars + strlen(al_str)) off_disp_chars = cursor_chars_from_line_start - strlen(al_str);
|
if (cursor_chars_from_line_start < off_disp_chars + strlen(al_str)) off_disp_chars = cursor_chars_from_line_start - strlen(al_str);
|
||||||
if (cursor_chars_from_line_start >= off_disp_chars + TV_LLEN_DISP - strlen(ar_str)) off_disp_chars = cursor_chars_from_line_start + strlen(ar_str) - TV_LLEN_DISP + 1;
|
if (cursor_chars_from_line_start >= off_disp_chars + TV_LLEN_DISP - strlen(ar_str)) off_disp_chars = cursor_chars_from_line_start + strlen(ar_str) - TV_LLEN_DISP + 1;
|
||||||
}
|
}
|
||||||
while (cursor && cursor < line0_next) line0_next = line_seek_chars(text, len, ww, line0_next, -1);
|
while (last_cursor_value && last_cursor_value < line0_next) line0_next = line_seek_chars(text, len, ww, line0_next, -1);
|
||||||
while (cursor && line0_next < line_seek_chars(text, len, ww, GetNextChar(cursor), -TV_NLIN_DISP)) line0_next = line_seek_chars(text, len, ww, line0_next, 1);
|
while (last_cursor_value && line0_next < line_seek_chars(text, len, ww, GetNextChar(last_cursor_value), -TV_NLIN_DISP)) line0_next = line_seek_chars(text, len, ww, line0_next, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// find last allowed lines (ww and nonww)
|
// find last allowed lines (ww and nonww)
|
||||||
@ -1979,6 +2146,8 @@ bool MemTextViewer(const char* text, u32 len, u32 start, bool as_script, u32 max
|
|||||||
if (off_disp_chars < 0 || ww) off_disp_chars = 0;
|
if (off_disp_chars < 0 || ww) off_disp_chars = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (clipboard) free(clipboard);
|
||||||
|
|
||||||
// check for user edits
|
// check for user edits
|
||||||
if (text_cpy) {
|
if (text_cpy) {
|
||||||
if (save_path) {
|
if (save_path) {
|
||||||
@ -2014,7 +2183,7 @@ bool MemToCViewer(const char* text, u32 len, const char* title) {
|
|||||||
|
|
||||||
// clear screens / view start of readme on top
|
// clear screens / view start of readme on top
|
||||||
ClearScreenF(true, true, COLOR_STD_BG);
|
ClearScreenF(true, true, COLOR_STD_BG);
|
||||||
MemTextView(text, len, text, 0, 1, ww, 0, false, NULL);
|
MemTextView(text, len, text, 0, 1, ww, 0, false, NULL, NULL);
|
||||||
|
|
||||||
// parse text for markdown captions
|
// parse text for markdown captions
|
||||||
u32 n_captions = 0;
|
u32 n_captions = 0;
|
||||||
@ -2055,15 +2224,15 @@ bool MemToCViewer(const char* text, u32 len, const char* title) {
|
|||||||
u32 pad_state = InputWait(0);
|
u32 pad_state = InputWait(0);
|
||||||
if ((cursor >= 0) && (pad_state & BUTTON_A)) {
|
if ((cursor >= 0) && (pad_state & BUTTON_A)) {
|
||||||
if (!MemTextViewer(text, len, lineno[cursor], false, 0, NULL)) return false;
|
if (!MemTextViewer(text, len, lineno[cursor], false, 0, NULL)) return false;
|
||||||
MemTextView(text, len, captions[cursor], 0, lineno[cursor], ww, 0, false, NULL);
|
MemTextView(text, len, captions[cursor], 0, lineno[cursor], ww, 0, false, NULL, NULL);
|
||||||
} else if (pad_state & BUTTON_B) {
|
} else if (pad_state & BUTTON_B) {
|
||||||
break;
|
break;
|
||||||
} else if (pad_state & BUTTON_UP) {
|
} else if (pad_state & BUTTON_UP) {
|
||||||
cursor = (cursor <= 0) ? ((int) n_captions - 1) : cursor - 1;
|
cursor = (cursor <= 0) ? ((int) n_captions - 1) : cursor - 1;
|
||||||
MemTextView(text, len, captions[cursor], 0, lineno[cursor], ww, 0, false, NULL);
|
MemTextView(text, len, captions[cursor], 0, lineno[cursor], ww, 0, false, NULL, NULL);
|
||||||
} else if (pad_state & BUTTON_DOWN) {
|
} else if (pad_state & BUTTON_DOWN) {
|
||||||
if (++cursor >= (int) n_captions) cursor = 0;
|
if (++cursor >= (int) n_captions) cursor = 0;
|
||||||
MemTextView(text, len, captions[cursor], 0, lineno[cursor], ww, 0, false, NULL);
|
MemTextView(text, len, captions[cursor], 0, lineno[cursor], ww, 0, false, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2198,11 +2367,11 @@ bool ExecuteGM9Script(const char* path_script) {
|
|||||||
}
|
}
|
||||||
if (show_preview) {
|
if (show_preview) {
|
||||||
if (lno <= (TV_NLIN_DISP/2)) {
|
if (lno <= (TV_NLIN_DISP/2)) {
|
||||||
MemTextView(script, script_size, script, 0, 1, 0, lno, true, NULL);
|
MemTextView(script, script_size, script, 0, 1, 0, lno, true, NULL, NULL);
|
||||||
} else {
|
} else {
|
||||||
const char* ptr_view = line_seek_chars(script, script_size, 0, ptr, -(TV_NLIN_DISP/2));
|
const char* ptr_view = line_seek_chars(script, script_size, 0, ptr, -(TV_NLIN_DISP/2));
|
||||||
u32 lno_view = lno - (TV_NLIN_DISP/2);
|
u32 lno_view = lno - (TV_NLIN_DISP/2);
|
||||||
MemTextView(script, script_size, ptr_view, 0, lno_view, 0, lno, true, NULL);
|
MemTextView(script, script_size, ptr_view, 0, lno_view, 0, lno, true, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -795,7 +795,8 @@
|
|||||||
"ERROR_TEXT_FILE_TOO_BIG": "Error: Text file is too large.\nText file size is %u bytes.\nMax file size is %i bytes.",
|
"ERROR_TEXT_FILE_TOO_BIG": "Error: Text file is too large.\nText file size is %u bytes.\nMax file size is %i bytes.",
|
||||||
"TEXTVIEWER_CONTROLS_DETAILS": "Textviewer Controls:\n \n↑↓→←(+R) - Scroll\nR+Y - Toggle wordwrap\nR+X - Goto line #\nB - Exit\n",
|
"TEXTVIEWER_CONTROLS_DETAILS": "Textviewer Controls:\n \n↑↓→←(+R) - Scroll\nR+Y - Toggle wordwrap\nR+X - Goto line #\nB - Exit\n",
|
||||||
"TEXTEDITOR_CONTROLS_DETAILS": "Text Editor Controls:\n \n↑↓→←(+R) - Scroll\nR+Y - Toggle wordwrap\nR+X - Goto line #\nA - Enter edit mode\nB - Exit\n",
|
"TEXTEDITOR_CONTROLS_DETAILS": "Text Editor Controls:\n \n↑↓→←(+R) - Scroll\nR+Y - Toggle wordwrap\nR+X - Goto line #\nA - Enter edit mode\nB - Exit\n",
|
||||||
"TEXTEDITOR_CONTROLS_KEYBOARD": "Text Editor Controls:\n \n↑↓→←(+R) - Move cursor\nY - Caps / Capslock\nX - Delete char\nA - Insert newline\nB - Enter view mode\n",
|
"TEXTEDITOR_CONTROLS_KEYBOARD": "Text Editor Controls:\n \n↑↓→←(+R) - Move cursor\nX - Delete char\nA - Insert newline\nL+↑↓→← - Select text\nY - COPY / [+R] CUT\nB - Enter view mode\n",
|
||||||
|
"TEXTEDITOR_CONTROLS_CLIPBOARD": "Text Editor Controls:\n \n↑↓→←(+R) - Move cursor\nX - Delete char\nA - Insert newline\nL+↑↓→← - Select text\nY - PASTE / [+R] CLEAR\nB - Enter view mode\n",
|
||||||
"TEXT_EDITS_SAVE_CHANGES": "You made text edits.\nWrite changes to file?",
|
"TEXT_EDITS_SAVE_CHANGES": "You made text edits.\nWrite changes to file?",
|
||||||
"CURRENT_LINE_N_ENTER_NEW_LINE_BELOW": "Current line: %i\nEnter new line below.",
|
"CURRENT_LINE_N_ENTER_NEW_LINE_BELOW": "Current line: %i\nEnter new line below.",
|
||||||
"PREVIEW_DISABLED": "(preview disabled)",
|
"PREVIEW_DISABLED": "(preview disabled)",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user