Integrate font objects copy/paste with system clipboard
authorDalai Felinto <dfelinto@gmail.com>
Fri, 12 Feb 2016 12:57:58 +0000 (10:57 -0200)
committerDalai Felinto <dfelinto@gmail.com>
Fri, 12 Feb 2016 13:05:05 +0000 (11:05 -0200)
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

source/blender/blenkernel/BKE_font.h
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/font.c
source/blender/editors/curve/curve_intern.h
source/blender/editors/curve/curve_ops.c
source/blender/editors/curve/editfont.c
source/blender/windowmanager/intern/wm_init_exit.c

index 5dcc6f8d981a046b722b4d4bd764a3d60a3758ca..0711c423d1c13cd7cbfd07aa66893c23510ee814 100644 (file)
@@ -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
index b518a1fc4a4ed094fc0bf872e2469a8a5bdcb223..79199f86fa92f4e0691635c063f0a1484b40ce41 100644 (file)
@@ -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);
 
index e8bfa27c6625dd5e86680df8ea51a678b98967cf..0a887dcf676e44a220769f63ae4f763a7d6d1156 100644 (file)
@@ -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;
+       }
+}
+
+/** \} */
index ce7487f5a90673ce3c80e6fb515f6c379fcc2deb..1af0b49bd86c1f4ff9717f917a6098b02d89acc5 100644 (file)
@@ -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);
index 4828fb3ec5f22c149d7299b0eb6b944ad6065671..1fbd57d20ef150b1a5148f86082d3d611c432e7d 100644 (file)
@@ -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);
index 807334dd2bd2e2d0bffeecfd781aba129e84126d..7c1fe0cadf054766132596da242088c8d98d6204 100644 (file)
@@ -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;
+
+       BKE_vfont_clipboard_get(&text_buf, &info_buf, NULL, &len);
 
-       if (font_paste_wchar(obedit, ef->copybuf, len, ef->copybufinfo)) {
+       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;
+
+       /* 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 (!paste_selection(obedit, op->reports))
+       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 */
index b6b4f42e1b78c2a54672e0d373ccaf91ebe7e0a6..4dc60a9b7299521042317149c10d701f77a1b2dd 100644 (file)
@@ -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();