forked from bartvdbraak/blender
Integrate font objects copy/paste with system clipboard
When pasting text, the style (bold, material, ...) is maintained, if it was originally copied from Blender. This fixes the issue of missing copy/paste options for font objects (they were present back in Blender 2.49) Reviewers: Severin, campbellbarton, brecht
This commit is contained in:
parent
9c21015c26
commit
a143aeaeae
@ -56,9 +56,6 @@ typedef struct EditFontSelBox {
|
||||
} EditFontSelBox;
|
||||
|
||||
typedef struct EditFont {
|
||||
wchar_t *copybuf;
|
||||
struct CharInfo *copybufinfo;
|
||||
|
||||
wchar_t *textbuf;
|
||||
struct CharInfo *textbufinfo;
|
||||
|
||||
@ -96,6 +93,12 @@ bool BKE_vfont_to_curve(struct Main *bmain, struct Object *ob, int mode);
|
||||
int BKE_vfont_select_get(struct Object *ob, int *r_start, int *r_end);
|
||||
void BKE_vfont_select_clamp(struct Object *ob);
|
||||
|
||||
void BKE_vfont_clipboard_free(void);
|
||||
void BKE_vfont_clipboard_set(const wchar_t *text_buf, const struct CharInfo *info_buf, const size_t len);
|
||||
void BKE_vfont_clipboard_get(
|
||||
wchar_t **r_text_buf, struct CharInfo **r_info_buf,
|
||||
size_t *r_len_utf8, size_t *r_len_wchar);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -109,10 +109,6 @@ void BKE_curve_editfont_free(Curve *cu)
|
||||
MEM_freeN(ef->textbuf);
|
||||
if (ef->textbufinfo)
|
||||
MEM_freeN(ef->textbufinfo);
|
||||
if (ef->copybuf)
|
||||
MEM_freeN(ef->copybuf);
|
||||
if (ef->copybufinfo)
|
||||
MEM_freeN(ef->copybufinfo);
|
||||
if (ef->selboxes)
|
||||
MEM_freeN(ef->selboxes);
|
||||
|
||||
|
@ -1261,3 +1261,77 @@ bool BKE_vfont_to_curve(Main *bmain, Object *ob, int mode)
|
||||
|
||||
return BKE_vfont_to_curve_ex(bmain, ob, mode, &cu->nurb, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/** \name VFont Clipboard
|
||||
* \{ */
|
||||
|
||||
static struct {
|
||||
wchar_t *text_buffer;
|
||||
CharInfo *info_buffer;
|
||||
size_t len_wchar;
|
||||
size_t len_utf8;
|
||||
} g_vfont_clipboard = {NULL};
|
||||
|
||||
void BKE_vfont_clipboard_free(void)
|
||||
{
|
||||
MEM_SAFE_FREE(g_vfont_clipboard.text_buffer);
|
||||
MEM_SAFE_FREE(g_vfont_clipboard.info_buffer);
|
||||
g_vfont_clipboard.len_wchar = 0;
|
||||
g_vfont_clipboard.len_utf8 = 0;
|
||||
}
|
||||
|
||||
void BKE_vfont_clipboard_set(const wchar_t *text_buf, const CharInfo *info_buf, const size_t len)
|
||||
{
|
||||
wchar_t *text;
|
||||
CharInfo *info;
|
||||
|
||||
/* clean previous buffers*/
|
||||
BKE_vfont_clipboard_free();
|
||||
|
||||
text = MEM_mallocN((len + 1) * sizeof(wchar_t), __func__);
|
||||
if (text == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
info = MEM_mallocN(len * sizeof(CharInfo), __func__);
|
||||
if (info == NULL) {
|
||||
MEM_freeN(text);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(text, text_buf, len * sizeof(wchar_t));
|
||||
text[len] = '\0';
|
||||
memcpy(info, info_buf, len * sizeof(CharInfo));
|
||||
|
||||
/* store new buffers */
|
||||
g_vfont_clipboard.text_buffer = text;
|
||||
g_vfont_clipboard.info_buffer = info;
|
||||
g_vfont_clipboard.len_utf8 = BLI_wstrlen_utf8(text);
|
||||
g_vfont_clipboard.len_wchar = len;
|
||||
}
|
||||
|
||||
void BKE_vfont_clipboard_get(
|
||||
wchar_t **r_text_buf, CharInfo **r_info_buf,
|
||||
size_t *r_len_utf8, size_t *r_len_wchar)
|
||||
{
|
||||
if (r_text_buf) {
|
||||
*r_text_buf = g_vfont_clipboard.text_buffer;
|
||||
}
|
||||
|
||||
if (r_info_buf) {
|
||||
*r_info_buf = g_vfont_clipboard.info_buffer;
|
||||
}
|
||||
|
||||
if (r_len_wchar) {
|
||||
*r_len_wchar = g_vfont_clipboard.len_wchar;
|
||||
}
|
||||
|
||||
if (r_len_utf8) {
|
||||
*r_len_utf8 = g_vfont_clipboard.len_utf8;
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -79,7 +79,6 @@ void FONT_OT_text_copy(struct wmOperatorType *ot);
|
||||
void FONT_OT_text_cut(struct wmOperatorType *ot);
|
||||
void FONT_OT_text_paste(struct wmOperatorType *ot);
|
||||
void FONT_OT_text_paste_from_file(struct wmOperatorType *ot);
|
||||
void FONT_OT_text_paste_from_clipboard(struct wmOperatorType *ot);
|
||||
|
||||
void FONT_OT_move(struct wmOperatorType *ot);
|
||||
void FONT_OT_move_select(struct wmOperatorType *ot);
|
||||
|
@ -66,7 +66,6 @@ void ED_operatortypes_curve(void)
|
||||
WM_operatortype_append(FONT_OT_text_cut);
|
||||
WM_operatortype_append(FONT_OT_text_paste);
|
||||
WM_operatortype_append(FONT_OT_text_paste_from_file);
|
||||
WM_operatortype_append(FONT_OT_text_paste_from_clipboard);
|
||||
|
||||
WM_operatortype_append(FONT_OT_move);
|
||||
WM_operatortype_append(FONT_OT_move_select);
|
||||
|
@ -414,65 +414,6 @@ void FONT_OT_text_paste_from_file(wmOperatorType *ot)
|
||||
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Paste From Clipboard */
|
||||
|
||||
static int paste_from_clipboard(bContext *C, ReportList *reports)
|
||||
{
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
char *strp;
|
||||
int filelen;
|
||||
int retval;
|
||||
|
||||
strp = WM_clipboard_text_get(false, &filelen);
|
||||
if (strp == NULL) {
|
||||
BKE_report(reports, RPT_ERROR, "Clipboard empty");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if ((filelen <= MAXTEXT) && font_paste_utf8(C, strp, filelen)) {
|
||||
text_update_edited(C, obedit, FO_EDIT);
|
||||
retval = OPERATOR_FINISHED;
|
||||
}
|
||||
else {
|
||||
BKE_report(reports, RPT_ERROR, "Clipboard too long");
|
||||
retval = OPERATOR_CANCELLED;
|
||||
}
|
||||
MEM_freeN(strp);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int paste_from_clipboard_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = paste_from_clipboard(C, op->reports);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void FONT_OT_text_paste_from_clipboard(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Paste Clipboard";
|
||||
ot->description = "Paste contents from system clipboard";
|
||||
ot->idname = "FONT_OT_text_paste_from_clipboard";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = paste_from_clipboard_exec;
|
||||
ot->poll = ED_operator_editfont;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
WM_operator_properties_filesel(
|
||||
ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT, FILE_SPECIAL, FILE_OPENFILE,
|
||||
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
|
||||
}
|
||||
|
||||
/******************* text to object operator ********************/
|
||||
|
||||
static void txt_add_object(bContext *C, TextLine *firstline, int totline, const float offset[3])
|
||||
@ -761,10 +702,21 @@ static void copy_selection(Object *obedit)
|
||||
if (BKE_vfont_select_get(obedit, &selstart, &selend)) {
|
||||
Curve *cu = obedit->data;
|
||||
EditFont *ef = cu->editfont;
|
||||
|
||||
memcpy(ef->copybuf, ef->textbuf + selstart, ((selend - selstart) + 1) * sizeof(wchar_t));
|
||||
ef->copybuf[(selend - selstart) + 1] = 0;
|
||||
memcpy(ef->copybufinfo, ef->textbufinfo + selstart, ((selend - selstart) + 1) * sizeof(CharInfo));
|
||||
char *buf = NULL;
|
||||
wchar_t *text_buf;
|
||||
size_t len_utf8;
|
||||
|
||||
/* internal clipboard (for style) */
|
||||
BKE_vfont_clipboard_set(ef->textbuf + selstart, ef->textbufinfo + selstart, selend - selstart + 1);
|
||||
BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL);
|
||||
|
||||
/* system clipboard */
|
||||
buf = MEM_mallocN(len_utf8 + 1, __func__);
|
||||
if (buf) {
|
||||
BLI_strncpy_wchar_as_utf8(buf, text_buf, len_utf8 + 1);
|
||||
WM_clipboard_text_set(buf, false);
|
||||
MEM_freeN(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -826,11 +778,13 @@ void FONT_OT_text_cut(wmOperatorType *ot)
|
||||
|
||||
static bool paste_selection(Object *obedit, ReportList *reports)
|
||||
{
|
||||
Curve *cu = obedit->data;
|
||||
EditFont *ef = cu->editfont;
|
||||
int len = wcslen(ef->copybuf);
|
||||
wchar_t *text_buf;
|
||||
CharInfo *info_buf;
|
||||
size_t len;
|
||||
|
||||
if (font_paste_wchar(obedit, ef->copybuf, len, ef->copybufinfo)) {
|
||||
BKE_vfont_clipboard_get(&text_buf, &info_buf, NULL, &len);
|
||||
|
||||
if (font_paste_wchar(obedit, text_buf, len, info_buf)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@ -842,13 +796,68 @@ static bool paste_selection(Object *obedit, ReportList *reports)
|
||||
static int paste_text_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
int retval;
|
||||
size_t len_utf8;
|
||||
wchar_t *text_buf;
|
||||
|
||||
if (!paste_selection(obedit, op->reports))
|
||||
/* Store both clipboards as utf8 for comparison,
|
||||
* Give priority to the internal 'vfont' clipboard with its 'CharInfo' text styles
|
||||
* as long as its synchronized with the systems clipboard. */
|
||||
struct {
|
||||
char *buf;
|
||||
int len;
|
||||
} clipboard_system = {NULL}, clipboard_vfont = {NULL};
|
||||
|
||||
clipboard_system.buf = WM_clipboard_text_get(false, &clipboard_system.len);
|
||||
|
||||
if (clipboard_system.buf == NULL) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
text_update_edited(C, obedit, FO_EDIT);
|
||||
BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
if (text_buf) {
|
||||
clipboard_vfont.buf = MEM_mallocN(len_utf8 + 1, __func__);
|
||||
|
||||
if (clipboard_vfont.buf == NULL) {
|
||||
MEM_freeN(clipboard_system.buf);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
BLI_strncpy_wchar_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1);
|
||||
}
|
||||
|
||||
if (clipboard_vfont.buf && STREQ(clipboard_vfont.buf, clipboard_system.buf)) {
|
||||
retval = paste_selection(obedit, op->reports) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
||||
}
|
||||
else {
|
||||
if ((clipboard_system.len <= MAXTEXT) &&
|
||||
font_paste_utf8(C, clipboard_system.buf, clipboard_system.len))
|
||||
{
|
||||
text_update_edited(C, obedit, FO_EDIT);
|
||||
retval = OPERATOR_FINISHED;
|
||||
}
|
||||
else {
|
||||
BKE_report(op->reports, RPT_ERROR, "Clipboard too long");
|
||||
retval = OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* free the existent clipboard buffer */
|
||||
BKE_vfont_clipboard_free();
|
||||
}
|
||||
|
||||
if (retval != OPERATOR_CANCELLED) {
|
||||
text_update_edited(C, obedit, FO_EDIT);
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
if (clipboard_vfont.buf) {
|
||||
MEM_freeN(clipboard_vfont.buf);
|
||||
}
|
||||
|
||||
MEM_freeN(clipboard_system.buf);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void FONT_OT_text_paste(wmOperatorType *ot)
|
||||
@ -1482,8 +1491,6 @@ void ED_curve_editfont_make(Object *obedit)
|
||||
|
||||
ef->textbuf = MEM_callocN((MAXTEXT + 4) * sizeof(wchar_t), "texteditbuf");
|
||||
ef->textbufinfo = MEM_callocN((MAXTEXT + 4) * sizeof(CharInfo), "texteditbufinfo");
|
||||
ef->copybuf = MEM_callocN((MAXTEXT + 4) * sizeof(wchar_t), "texteditcopybuf");
|
||||
ef->copybufinfo = MEM_callocN((MAXTEXT + 4) * sizeof(CharInfo), "texteditcopybufinfo");
|
||||
}
|
||||
|
||||
/* Convert the original text to wchar_t */
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "BKE_mball_tessellate.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_font.h"
|
||||
|
||||
#include "BKE_addon.h"
|
||||
#include "BKE_appdir.h"
|
||||
@ -504,6 +505,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
|
||||
BKE_sequencer_free_clipboard(); /* sequencer.c */
|
||||
BKE_tracking_clipboard_free();
|
||||
BKE_mask_clipboard_free();
|
||||
BKE_vfont_clipboard_free();
|
||||
|
||||
#ifdef WITH_COMPOSITOR
|
||||
COM_deinitialize();
|
||||
|
Loading…
Reference in New Issue
Block a user