diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index 5dcc6f8d981..0711c423d1c 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -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 diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index b518a1fc4a4..79199f86fa9 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -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); diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index e8bfa27c662..0a887dcf676 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -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; + } +} + +/** \} */ diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h index ce7487f5a90..1af0b49bd86 100644 --- a/source/blender/editors/curve/curve_intern.h +++ b/source/blender/editors/curve/curve_intern.h @@ -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); diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c index 4828fb3ec5f..1fbd57d20ef 100644 --- a/source/blender/editors/curve/curve_ops.c +++ b/source/blender/editors/curve/curve_ops.c @@ -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); diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 807334dd2bd..7c1fe0cadf0 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -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 */ diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index b6b4f42e1b7..4dc60a9b729 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -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();