WIP - Text/Label tools: Ability to paste text clipboard
Lots still to do, but the basic functionality is there (thanks to SDL2's clipboard functions). For https://sourceforge.net/p/tuxpaint/feature-requests/95/
This commit is contained in:
parent
199f11ce31
commit
4de111df25
2 changed files with 137 additions and 40 deletions
|
|
@ -7,6 +7,18 @@ Various contributors (see below, and AUTHORS.txt)
|
||||||
https://tuxpaint.org/
|
https://tuxpaint.org/
|
||||||
|
|
||||||
2024.December.20 (0.9.35)
|
2024.December.20 (0.9.35)
|
||||||
|
* Text & Label Tool Improvements:
|
||||||
|
-------------------------------
|
||||||
|
+ WIP It is now possible to paste text from the copy/paste clipboard
|
||||||
|
into Tux Paint. If text goes beyond the right of the canvas,
|
||||||
|
a new line is created. If text goes beyond the bottom of the
|
||||||
|
canvas, the text is truncated there.
|
||||||
|
- TODO: Add a "paste" button to the On Screen Keyboards
|
||||||
|
- TODO: Improve word-wrapping (word-based, not character)
|
||||||
|
- TODO: Mention the feature in documentation
|
||||||
|
Closes https://sourceforge.net/p/tuxpaint/feature-requests/95/
|
||||||
|
Bill Kendrick <bill@newbreedsoftware.com>
|
||||||
|
|
||||||
* Other Improvements:
|
* Other Improvements:
|
||||||
-------------------
|
-------------------
|
||||||
+ Improved color picker: better behavior when clicking/tapping and
|
+ Improved color picker: better behavior when clicking/tapping and
|
||||||
|
|
|
||||||
165
src/tuxpaint.c
165
src/tuxpaint.c
|
|
@ -2110,6 +2110,7 @@ static void rect_xor(int x1, int y1, int x2, int y2);
|
||||||
static void circle_xor(int x, int y, int sz);
|
static void circle_xor(int x, int y, int sz);
|
||||||
static void draw_blinking_cursor(void);
|
static void draw_blinking_cursor(void);
|
||||||
static void hide_blinking_cursor(void);
|
static void hide_blinking_cursor(void);
|
||||||
|
static int text_label_tool_enter(int font_height);
|
||||||
|
|
||||||
static void reset_brush_counter(int force);
|
static void reset_brush_counter(int force);
|
||||||
|
|
||||||
|
|
@ -2262,7 +2263,7 @@ static void print_image(void);
|
||||||
static void do_print(void);
|
static void do_print(void);
|
||||||
static void strip_trailing_whitespace(char *buf);
|
static void strip_trailing_whitespace(char *buf);
|
||||||
static void strip_quotes(char *buf);
|
static void strip_quotes(char *buf);
|
||||||
static void do_render_cur_text(int do_blit);
|
static int do_render_cur_text(int do_blit);
|
||||||
static char *uppercase(const char *restrict const str);
|
static char *uppercase(const char *restrict const str);
|
||||||
static wchar_t *uppercase_w(const wchar_t *restrict const str);
|
static wchar_t *uppercase_w(const wchar_t *restrict const str);
|
||||||
static SDL_Surface *do_render_button_label(const char *const label);
|
static SDL_Surface *do_render_button_label(const char *const label);
|
||||||
|
|
@ -3155,6 +3156,64 @@ static void mainloop(void)
|
||||||
update_screen_rect(&r_tools);
|
update_screen_rect(&r_tools);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ((key == SDLK_v && (mod & KMOD_CTRL)) && !noshortcuts)
|
||||||
|
{
|
||||||
|
/* Ctrl-V - Paste */
|
||||||
|
if (cur_tool == TOOL_TEXT || cur_tool == TOOL_LABEL)
|
||||||
|
{
|
||||||
|
char * pasted_txt;
|
||||||
|
|
||||||
|
if (SDL_HasClipboardText())
|
||||||
|
{
|
||||||
|
pasted_txt = SDL_GetClipboardText();
|
||||||
|
if (pasted_txt != NULL /* it shouldn't be */)
|
||||||
|
{
|
||||||
|
if (pasted_txt[0] != '\0')
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
wchar_t *tmp;
|
||||||
|
|
||||||
|
DEBUG_PRINTF("Pasting: %s\n", pasted_txt);
|
||||||
|
|
||||||
|
n = strlen(pasted_txt) + 1;
|
||||||
|
tmp = alloca(sizeof(wchar_t) * n);
|
||||||
|
|
||||||
|
if (tmp != NULL)
|
||||||
|
{
|
||||||
|
int exceeded;
|
||||||
|
|
||||||
|
mbstowcs(tmp, pasted_txt, n); /* at most n wchar_t written */
|
||||||
|
exceeded = 0;
|
||||||
|
for (int i = 0; tmp[i] != '\0' && !exceeded; i++)
|
||||||
|
{
|
||||||
|
if (tmp[i] == '\n')
|
||||||
|
{
|
||||||
|
exceeded = text_label_tool_enter(TuxPaint_Font_FontHeight(getfonthandle(cur_font)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int txt_width;
|
||||||
|
|
||||||
|
texttool_str[texttool_len++] = tmp[i];
|
||||||
|
playsound(screen, 0, SND_KEYCLICK, 0, SNDPOS_CENTER, SNDDIST_NEAR);
|
||||||
|
txt_width = do_render_cur_text(0);
|
||||||
|
if (cursor_x + txt_width > canvas->w && texttool_len > 1)
|
||||||
|
{
|
||||||
|
texttool_str[texttool_len - 1] = '\0';
|
||||||
|
txt_width = do_render_cur_text(0);
|
||||||
|
exceeded = text_label_tool_enter(TuxPaint_Font_FontHeight(getfonthandle(cur_font)));
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
SDL_Delay(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_free(pasted_txt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (event.type == SDL_TEXTINPUT ||
|
else if (event.type == SDL_TEXTINPUT ||
|
||||||
(event.type == SDL_KEYDOWN &&
|
(event.type == SDL_KEYDOWN &&
|
||||||
(event.key.keysym.sym == SDLK_BACKSPACE ||
|
(event.key.keysym.sym == SDLK_BACKSPACE ||
|
||||||
|
|
@ -3263,38 +3322,7 @@ static void mainloop(void)
|
||||||
{
|
{
|
||||||
/* [Enter] to finish entering text */
|
/* [Enter] to finish entering text */
|
||||||
|
|
||||||
rec_undo_buffer();
|
text_label_tool_enter(font_height);
|
||||||
do_render_cur_text(1);
|
|
||||||
label_node_to_edit = NULL;
|
|
||||||
texttool_len = 0;
|
|
||||||
cursor_textwidth = 0;
|
|
||||||
if (cur_tool == TOOL_LABEL)
|
|
||||||
{
|
|
||||||
draw_fonts();
|
|
||||||
update_screen_rect(&r_toolopt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (been_saved)
|
|
||||||
{
|
|
||||||
been_saved = 0;
|
|
||||||
|
|
||||||
if (!disable_save)
|
|
||||||
tool_avail[TOOL_SAVE] = 1;
|
|
||||||
|
|
||||||
draw_toolbar();
|
|
||||||
update_screen_rect(&r_tools);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
cursor_x = cursor_left;
|
|
||||||
cursor_y = min(cursor_y + font_height, canvas->h - font_height);
|
|
||||||
|
|
||||||
/* Reposition the on-screen keyboard if we begin typing over it */
|
|
||||||
update_canvas_ex(kbd_rect.x, kbd_rect.y, kbd_rect.x + kbd_rect.w, kbd_rect.y + kbd_rect.h, 0);
|
|
||||||
update_screen_rect(&kbd_rect);
|
|
||||||
reposition_onscreen_keyboard(cursor_y);
|
|
||||||
|
|
||||||
playsound(screen, 0, SND_RETURN, 1, SNDPOS_RIGHT, SNDDIST_NEAR);
|
|
||||||
}
|
}
|
||||||
else if (cur_tool == TOOL_LABEL && label_node_to_edit)
|
else if (cur_tool == TOOL_LABEL && label_node_to_edit)
|
||||||
{
|
{
|
||||||
|
|
@ -20207,9 +20235,9 @@ void do_print(void)
|
||||||
/**
|
/**
|
||||||
* FIXME
|
* FIXME
|
||||||
*/
|
*/
|
||||||
static void do_render_cur_text(int do_blit)
|
static int do_render_cur_text(int do_blit)
|
||||||
{
|
{
|
||||||
int w, h;
|
int w, h, txt_width;
|
||||||
|
|
||||||
SDL_Color color = { color_hexes[cur_color][0],
|
SDL_Color color = { color_hexes[cur_color][0],
|
||||||
color_hexes[cur_color][1],
|
color_hexes[cur_color][1],
|
||||||
|
|
@ -20302,8 +20330,7 @@ static void do_render_cur_text(int do_blit)
|
||||||
}
|
}
|
||||||
/* FIXME: Is this SDL_Flip() still needed? Pere 2011.06.28 */
|
/* FIXME: Is this SDL_Flip() still needed? Pere 2011.06.28 */
|
||||||
SDL_Flip(screen);
|
SDL_Flip(screen);
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -20423,11 +20450,14 @@ static void do_render_cur_text(int do_blit)
|
||||||
free(str);
|
free(str);
|
||||||
|
|
||||||
if (tmp_surf != NULL)
|
if (tmp_surf != NULL)
|
||||||
|
{
|
||||||
|
txt_width = tmp_surf->w;
|
||||||
SDL_FreeSurface(tmp_surf);
|
SDL_FreeSurface(tmp_surf);
|
||||||
/* if (tmp_label != NULL) */
|
}
|
||||||
/* SDL_FreeSurface(tmp_label); */
|
else
|
||||||
// SDL_Delay(5000);
|
txt_width = 0;
|
||||||
|
|
||||||
|
return txt_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -32874,3 +32904,58 @@ void maybe_redraw_eraser_xor(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record an undo buffer snapshot, blit the current line of Text or Label
|
||||||
|
* tool text onto the * canvas, play the "carriage return" sound effect,
|
||||||
|
* and mark the image as unsaved.
|
||||||
|
*
|
||||||
|
* This happens when the user presses the [Enter]/[Return] key on
|
||||||
|
* a physical keyboard, clicks it in the on-screen keyboard, or
|
||||||
|
* a carriage return is part of some pasted clipboard text.
|
||||||
|
*
|
||||||
|
* FIXME: Params
|
||||||
|
*/
|
||||||
|
static int text_label_tool_enter(int font_height)
|
||||||
|
{
|
||||||
|
int exceeded;
|
||||||
|
|
||||||
|
rec_undo_buffer();
|
||||||
|
do_render_cur_text(1);
|
||||||
|
label_node_to_edit = NULL;
|
||||||
|
texttool_len = 0;
|
||||||
|
cursor_textwidth = 0;
|
||||||
|
if (cur_tool == TOOL_LABEL)
|
||||||
|
{
|
||||||
|
draw_fonts();
|
||||||
|
update_screen_rect(&r_toolopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (been_saved)
|
||||||
|
{
|
||||||
|
been_saved = 0;
|
||||||
|
|
||||||
|
if (!disable_save)
|
||||||
|
tool_avail[TOOL_SAVE] = 1;
|
||||||
|
|
||||||
|
draw_toolbar();
|
||||||
|
update_screen_rect(&r_tools);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cursor_x = cursor_left;
|
||||||
|
|
||||||
|
exceeded = 0;
|
||||||
|
if (cursor_y + font_height >= canvas->h)
|
||||||
|
exceeded = 1;
|
||||||
|
cursor_y = min(cursor_y + font_height, canvas->h - font_height);
|
||||||
|
|
||||||
|
/* Reposition the on-screen keyboard if we begin typing over it */
|
||||||
|
update_canvas_ex(kbd_rect.x, kbd_rect.y, kbd_rect.x + kbd_rect.w, kbd_rect.y + kbd_rect.h, 0);
|
||||||
|
update_screen_rect(&kbd_rect);
|
||||||
|
reposition_onscreen_keyboard(cursor_y);
|
||||||
|
|
||||||
|
playsound(screen, 0, SND_RETURN, 1, SNDPOS_RIGHT, SNDDIST_NEAR);
|
||||||
|
|
||||||
|
return exceeded;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue