2.5: Text edit mode operators back. Took me a while getting
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 17 Feb 2009 19:55:20 +0000 (19:55 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 17 Feb 2009 19:55:20 +0000 (19:55 +0000)
them nicely repeatable, and splitting up the big edit_text
operator into individual operator so it's all nicely scriptable,
documented, configurable, etc..

* Insert Text, Line Break, Insert Lorem
* Toggle Case, Set Case, Toggle Style, Set Style, Set Material
* Copy Text, Cut Text, Paste Text, Paste File, Paste Buffer
* Move, Move Select, Delete
* Change Spacing, Change Character

Notes

* Text (datablock) to Object doesn't work yet, will need to
  implement text editor context for that.
* Some shortcut keys don't work because screen/wm overrides them,
  ctrl+x, ctrl+left/right. That override goes top down which works
  well for some cases, but here we need to override in the other
  direction.
* There's no unicode support in RNA, or the user interface code
  for that matter, but text strings can contain these characters.
  At the moment it stores a UTF-8 string in char arrays, which is
  supposed to be nicely compatible with ascii. Seems reasonable to
  add support for UTF-8 in the interface code, python bindings, ..
  eventually?

14 files changed:
source/blender/blenkernel/intern/font.c
source/blender/editors/curve/curve_intern.h
source/blender/editors/curve/curve_ops.c
source/blender/editors/curve/editcurve.c
source/blender/editors/curve/editfont.c
source/blender/editors/include/ED_curve.h
source/blender/editors/include/ED_screen.h
source/blender/editors/include/UI_interface.h
source/blender/editors/interface/interface_regions.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_ops.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/space_view3d/view3d_header.c

index 8f8a8fba98387b5ac8a4c969b44e75787facce3b..ced8d3bdebb3b071d65728aaa5c106e7f29e6627 100644 (file)
@@ -658,7 +658,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
        VChar *che;
        struct chartrans *chartransdata=NULL, *ct;
        float *f, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4;
-       float twidth;
+       float twidth, maxlen= 0;
        int i, slen, j;
        int curbox;
        int selstart, selend;
@@ -826,8 +826,6 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode)
                        }
                }
                if(ascii== '\n' || ascii== '\r' || ascii==0 || ct->dobreak) {
-                       float maxlen;
-                       
                        ct->xof= xof;
                        ct->yof= yof;
                        ct->linenr= lnr;
index 82e6b39196b2628fba353e6a058c1a0586b71d42..68223633011418ee706cb8b729ca406e32864a19 100644 (file)
@@ -36,29 +36,57 @@ struct wmOperatorType;
 char *ED_lorem;
 
 /* editfont.c */
-void FONT_OT_textedit(struct wmOperatorType *ot);
+enum { DEL_ALL, DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_SELECTION, DEL_NEXT_SEL, DEL_PREV_SEL };
+enum { CASE_LOWER, CASE_UPPER };
+enum { LINE_BEGIN, LINE_END, PREV_CHAR, NEXT_CHAR, PREV_WORD, NEXT_WORD,
+       PREV_LINE, NEXT_LINE, PREV_PAGE, NEXT_PAGE };
+
+void FONT_OT_insert_text(struct wmOperatorType *ot);
+void FONT_OT_line_break(struct wmOperatorType *ot);
+void FONT_OT_insert_lorem(struct wmOperatorType *ot);
+void FONT_OT_text_to_object(struct wmOperatorType *ot);
+
+void FONT_OT_toggle_case(struct wmOperatorType *ot);
+void FONT_OT_set_case(struct wmOperatorType *ot);
+void FONT_OT_toggle_style(struct wmOperatorType *ot);
+void FONT_OT_set_style(struct wmOperatorType *ot);
+void FONT_OT_set_material(struct wmOperatorType *ot);
+
+void FONT_OT_copy_text(struct wmOperatorType *ot);
+void FONT_OT_cut_text(struct wmOperatorType *ot);
+void FONT_OT_paste_text(struct wmOperatorType *ot);
+void FONT_OT_paste_file(struct wmOperatorType *ot);
+void FONT_OT_paste_buffer(struct wmOperatorType *ot);
+
+void FONT_OT_move(struct wmOperatorType *ot);
+void FONT_OT_move_select(struct wmOperatorType *ot);
+void FONT_OT_delete(struct wmOperatorType *ot);
+
+void FONT_OT_change_character(struct wmOperatorType *ot);
+void FONT_OT_change_spacing(struct wmOperatorType *ot);
 
 /* editcurve.c */
+void CURVE_OT_hide(struct wmOperatorType *ot);
+void CURVE_OT_reveal(struct wmOperatorType *ot);
+
 void CURVE_OT_separate(struct wmOperatorType *ot);
-void CURVE_OT_switch_direction(struct wmOperatorType *ot);
+void CURVE_OT_duplicate(struct wmOperatorType *ot);
+void CURVE_OT_delete(struct wmOperatorType *ot);
+
 void CURVE_OT_set_weight(struct wmOperatorType *ot);
 void CURVE_OT_set_radius(struct wmOperatorType *ot);
+void CURVE_OT_set_spline_type(struct wmOperatorType *ot);
+void CURVE_OT_set_handle_type(struct wmOperatorType *ot);
+void CURVE_OT_set_smooth(struct wmOperatorType *ot);
+void CURVE_OT_clear_tilt(struct wmOperatorType *ot);
+
 void CURVE_OT_smooth(struct wmOperatorType *ot);
 void CURVE_OT_smooth_radius(struct wmOperatorType *ot);
+
 void CURVE_OT_de_select_first(struct wmOperatorType *ot);
 void CURVE_OT_de_select_last(struct wmOperatorType *ot);
 void CURVE_OT_de_select_all(struct wmOperatorType *ot);
-void CURVE_OT_hide(struct wmOperatorType *ot);
-void CURVE_OT_reveal(struct wmOperatorType *ot);
 void CURVE_OT_select_inverse(struct wmOperatorType *ot);
-void CURVE_OT_subdivide(struct wmOperatorType *ot);
-void CURVE_OT_set_spline_type(struct wmOperatorType *ot);
-void CURVE_OT_set_handle_type(struct wmOperatorType *ot);
-void CURVE_OT_make_segment(struct wmOperatorType *ot);
-void CURVE_OT_spin(struct wmOperatorType *ot);
-void CURVE_OT_add_vertex(struct wmOperatorType *ot);
-void CURVE_OT_extrude(struct wmOperatorType *ot);
-void CURVE_OT_toggle_cyclic(struct wmOperatorType *ot);
 void CURVE_OT_select_linked(struct wmOperatorType *ot);
 void CURVE_OT_select_row(struct wmOperatorType *ot);
 void CURVE_OT_select_next(struct wmOperatorType *ot);
@@ -67,10 +95,14 @@ void CURVE_OT_select_more(struct wmOperatorType *ot);
 void CURVE_OT_select_less(struct wmOperatorType *ot);
 void CURVE_OT_select_random(struct wmOperatorType *ot);
 void CURVE_OT_select_every_nth(struct wmOperatorType *ot);
-void CURVE_OT_duplicate(struct wmOperatorType *ot);
-void CURVE_OT_delete(struct wmOperatorType *ot);
-void CURVE_OT_set_smooth(struct wmOperatorType *ot);
-void CURVE_OT_clear_tilt(struct wmOperatorType *ot);
+
+void CURVE_OT_switch_direction(struct wmOperatorType *ot);
+void CURVE_OT_subdivide(struct wmOperatorType *ot);
+void CURVE_OT_make_segment(struct wmOperatorType *ot);
+void CURVE_OT_spin(struct wmOperatorType *ot);
+void CURVE_OT_add_vertex(struct wmOperatorType *ot);
+void CURVE_OT_extrude(struct wmOperatorType *ot);
+void CURVE_OT_toggle_cyclic(struct wmOperatorType *ot);
 
 void CURVE_OT_specials_menu(struct wmOperatorType *ot);
 
index c7eed88023f494bb6a4d847df0a66fa539248f92..8958dc9b6d7de879bd6ed5e190b5f30fddec120f 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "DNA_curve_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
@@ -95,7 +96,29 @@ void CURVE_OT_specials_menu(wmOperatorType *ot)
 
 void ED_operatortypes_curve(void)
 {
-       WM_operatortype_append(FONT_OT_textedit);
+       WM_operatortype_append(FONT_OT_insert_text);
+       WM_operatortype_append(FONT_OT_line_break);
+       WM_operatortype_append(FONT_OT_insert_lorem);
+       WM_operatortype_append(FONT_OT_text_to_object);
+
+       WM_operatortype_append(FONT_OT_toggle_case);
+       WM_operatortype_append(FONT_OT_set_case);
+       WM_operatortype_append(FONT_OT_toggle_style);
+       WM_operatortype_append(FONT_OT_set_style);
+       WM_operatortype_append(FONT_OT_set_material);
+
+       WM_operatortype_append(FONT_OT_copy_text);
+       WM_operatortype_append(FONT_OT_cut_text);
+       WM_operatortype_append(FONT_OT_paste_text);
+       WM_operatortype_append(FONT_OT_paste_file);
+       WM_operatortype_append(FONT_OT_paste_buffer);
+
+       WM_operatortype_append(FONT_OT_move);
+       WM_operatortype_append(FONT_OT_move_select);
+       WM_operatortype_append(FONT_OT_delete);
+
+       WM_operatortype_append(FONT_OT_change_character);
+       WM_operatortype_append(FONT_OT_change_spacing);
 
        WM_operatortype_append(CURVE_OT_hide);
        WM_operatortype_append(CURVE_OT_reveal);
@@ -143,7 +166,47 @@ void ED_keymap_curve(wmWindowManager *wm)
        ListBase *keymap= WM_keymap_listbase(wm, "Font", 0, 0);
        
        /* only set in editmode font, by space_view3d listener */
-       WM_keymap_add_item(keymap, "FONT_OT_textedit", KM_TEXTINPUT, KM_ANY, KM_ANY, 0);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_toggle_style", BKEY, KM_PRESS, KM_CTRL, 0)->ptr, "style", CU_BOLD);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_toggle_style", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "style", CU_ITALIC);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_toggle_style", UKEY, KM_PRESS, KM_CTRL, 0)->ptr, "style", CU_UNDERLINE);
+
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_delete", DELKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_NEXT_SEL);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_delete", BACKSPACEKEY, KM_PRESS, 0, 0)->ptr, "type", DEL_PREV_SEL);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_delete", BACKSPACEKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_ALL);
+
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", HOMEKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_BEGIN);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", ENDKEY, KM_PRESS, 0, 0)->ptr, "type", LINE_END);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_CHAR);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_CHAR);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", PREV_WORD);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", NEXT_WORD);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_LINE);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_LINE);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", PAGEUPKEY, KM_PRESS, 0, 0)->ptr, "type", PREV_PAGE);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move", PAGEDOWNKEY, KM_PRESS, 0, 0)->ptr, "type", NEXT_PAGE);
+
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", HOMEKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", LINE_BEGIN);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", ENDKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", LINE_END);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_CHAR);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", NEXT_CHAR);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", LEFTARROWKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "type", PREV_WORD);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", RIGHTARROWKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "type", NEXT_WORD);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", UPARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_LINE);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", NEXT_LINE);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", PREV_PAGE);
+       RNA_enum_set(WM_keymap_add_item(keymap, "FONT_OT_move_select", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "type", NEXT_PAGE);
+
+       RNA_int_set(WM_keymap_add_item(keymap, "FONT_OT_change_spacing", LEFTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "delta", -1);
+       RNA_int_set(WM_keymap_add_item(keymap, "FONT_OT_change_spacing", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "delta", 1);
+       RNA_int_set(WM_keymap_add_item(keymap, "FONT_OT_change_character", UPARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "delta", 1);
+       RNA_int_set(WM_keymap_add_item(keymap, "FONT_OT_change_character", DOWNARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "delta", -1);
+
+       WM_keymap_add_item(keymap, "FONT_OT_copy_text", CKEY, KM_PRESS, KM_CTRL, 0);
+       WM_keymap_add_item(keymap, "FONT_OT_cut_text", XKEY, KM_PRESS, KM_CTRL, 0);
+       WM_keymap_add_item(keymap, "FONT_OT_paste_text", PKEY, KM_PRESS, KM_CTRL, 0);
+
+       WM_keymap_add_item(keymap, "FONT_OT_line_break", RETKEY, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "FONT_OT_insert_text", KM_TEXTINPUT, KM_ANY, KM_ANY, 0); // last!
 
        /* only set in editmode curve, by space_view3d listener */
        keymap= WM_keymap_listbase(wm, "Curve", 0, 0);
index 4ef642381f0f76fd91da1d58f25ab08faf4d2de3..f66c8261535fb660878183abd57c8aa2dda23baf 100644 (file)
@@ -4724,7 +4724,7 @@ int join_curve(bContext *C, wmOperator *op, int type)
 
 /************ add primitive, used by object/ module ****************/
 
-Nurb *addNurbprim(bContext *C, int type, int newname)
+Nurb *add_nurbs_primitive(bContext *C, int type, int newname)
 {
        static int xzproj= 0;   /* this function calls itself... */
        Scene *scene= CTX_data_scene(C);
@@ -5022,7 +5022,7 @@ Nurb *addNurbprim(bContext *C, int type, int newname)
                                rename_id((ID *)obedit->data, "SurfTube");
                        }
 
-                       nu= addNurbprim(C, CU_NURBS|CU_PRIM_CIRCLE, 0);  /* circle */
+                       nu= add_nurbs_primitive(C, CU_NURBS|CU_PRIM_CIRCLE, 0);  /* circle */
                        nu->resolu= 4;
                        nu->flag= CU_SMOOTH;
                        BLI_addtail(editnurb, nu); /* temporal for extrude and translate */
@@ -5101,7 +5101,7 @@ Nurb *addNurbprim(bContext *C, int type, int newname)
                        }
 
                        xzproj= 1;
-                       nu= addNurbprim(C, CU_NURBS|CU_PRIM_CIRCLE, 0);  /* circle */
+                       nu= add_nurbs_primitive(C, CU_NURBS|CU_PRIM_CIRCLE, 0);  /* circle */
                        xzproj= 0;
                        nu->resolu= 4;
                        nu->resolv= 4;
index 431637f77c6dbaf1f17c63f298c8b116198a3461..edc1f8aecaebe6ce832be22b156b64a30fe95e73 100644 (file)
 #include "BKE_curve.h"
 #include "BKE_depsgraph.h"
 #include "BKE_font.h"
-#include "BKE_object.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_report.h"
 #include "BKE_utildefines.h"
 
+#include "RNA_access.h"
+#include "RNA_define.h"
+
 #include "WM_api.h"
 #include "WM_types.h"
 
 #include "ED_curve.h"
 #include "ED_object.h"
+#include "ED_screen.h"
 #include "ED_util.h"
 
 #include "curve_intern.h"
 
-/* XXX */
-static void error() {}
-static int okee() {return 0;}
-/* XXX */
-
-
 #define MAXTEXT        32766
 
-int textediting=0;
+/************************* utilities ******************************/
 
 static char findaccent(char char1, unsigned int code)
 {
@@ -231,7 +230,7 @@ static int insert_into_textbuf(Object *obedit, unsigned long c)
 {
        Curve *cu= obedit->data;
        
-       if (cu->len<MAXTEXT-1) {
+       if(cu->len<MAXTEXT-1) {
                EditFont *ef= cu->editfont;
                int x;
 
@@ -240,7 +239,7 @@ static int insert_into_textbuf(Object *obedit, unsigned long c)
                ef->textbuf[cu->pos]= c;
                ef->textbufinfo[cu->pos] = cu->curinfo;
                ef->textbufinfo[cu->pos].kern = 0;
-               if (obedit->actcol>0)
+               if(obedit->actcol>0)
                        ef->textbufinfo[cu->pos].mat_nr = obedit->actcol;
                else
                        ef->textbufinfo[cu->pos].mat_nr = 0;
@@ -252,61 +251,119 @@ static int insert_into_textbuf(Object *obedit, unsigned long c)
                update_string(cu);
 
                return 1;
-       } else {
-               return 0;
        }
+       else
+               return 0;
+}
+
+static void text_update_edited(bContext *C, Scene *scene, Object *obedit, int recalc, int mode)
+{
+       Curve *cu= obedit->data;
+       EditFont *ef= cu->editfont;
+
+       if(cu->pos)
+               cu->curinfo = ef->textbufinfo[cu->pos-1];
+       else
+               cu->curinfo = ef->textbufinfo[0];
+       
+       if(obedit->totcol>0)
+               obedit->actcol= ef->textbufinfo[cu->pos-1].mat_nr;
+
+       update_string(cu);
+       BKE_text_to_curve(scene, obedit, mode);
+
+       if(recalc)
+               DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
 }
 
-void add_lorem(Scene *scene)
+/********************** insert lorem operator *********************/
+
+static int insert_lorem_exec(bContext *C, wmOperator *op)
 {
-       Object *obedit= scene->obedit;
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
        char *p, *p2;
        int i;
        static char *lastlorem;
        
-       if (lastlorem)
+       if(lastlorem)
                p= lastlorem;
        else
                p= ED_lorem;
        
        i= rand()/(RAND_MAX/6)+4;       
                
-       for (p2=p; *p2 && i; p2++) {
+       for(p2=p; *p2 && i; p2++) {
                insert_into_textbuf(obedit, *p2);
-               if (*p2=='.') i--;
+
+               if(*p2=='.')
+                       i--;
        }
+
        lastlorem = p2+1;
-       if (strlen(lastlorem)<5) lastlorem = ED_lorem;
+       if(strlen(lastlorem)<5)
+               lastlorem = ED_lorem;
        
        insert_into_textbuf(obedit, '\n');
        insert_into_textbuf(obedit, '\n');      
+
        DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+       return OPERATOR_FINISHED;
+}
 
+void FONT_OT_insert_lorem(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Insert Lorem";
+       ot->idname= "FONT_OT_insert_lorem";
+       
+       /* api callbacks */
+       ot->exec= insert_lorem_exec;
+       ot->poll= ED_operator_editfont;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-void load_3dtext_fs(Scene *scene, char *file) 
+/******************* paste file operator ********************/
+
+/* note this handles both ascii and utf8 unicode, previously
+ * there were 3 functions that did effectively the same thing. */
+
+static int paste_file(bContext *C, ReportList *reports, char *filename)
 {
-       Curve *cu= scene->obedit->data;
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       Curve *cu= obedit->data;
        EditFont *ef= cu->editfont;
        FILE *fp;
        int filelen;
        char *strp;
 
-       fp= fopen(file, "r");
-       if (!fp) return;
+       fp= fopen(filename, "r");
+
+       if(!fp) {
+               if(reports)
+                       BKE_reportf(reports, RPT_ERROR, "Failed to open file %s.", filename);
+               return OPERATOR_CANCELLED;
+       }
 
        fseek(fp, 0L, SEEK_END);
        filelen = ftell(fp);
-       fseek(fp, 0L, SEEK_SET);        
+       fseek(fp, 0L, SEEK_SET);
 
-       strp = MEM_callocN(filelen+4, "tempstr");       
+       strp= MEM_callocN(filelen+4, "tempstr");
 
+       // fread() instead of read(), because windows read() converts text
+       // to DOS \r\n linebreaks, causing double linebreaks in the 3d text
        filelen = fread(strp, 1, filelen, fp);
        fclose(fp);
        strp[filelen]= 0;
-       
-       if(cu->len+filelen<MAXTEXT)
-       {
+
+       if(cu->len+filelen<MAXTEXT) {
                int tmplen;
                wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
                tmplen = utf8towchar(mem, strp);
@@ -317,15 +374,99 @@ void load_3dtext_fs(Scene *scene, char *file)
        }
        MEM_freeN(strp);
 
-       update_string(cu);
+       text_update_edited(C, scene, obedit, 1, 0);
+
+       return OPERATOR_FINISHED;
+}
+
+static int paste_file_exec(bContext *C, wmOperator *op)
+{
+       char *filename;
+       int retval;
+       
+       filename= RNA_string_get_alloc(op->ptr, "filename", NULL, 0);
+       retval= paste_file(C, op->reports, filename);
+       MEM_freeN(filename);
+
+       return retval;
+}
+
+static int paste_file_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       if(RNA_property_is_set(op->ptr, "filename"))
+               return paste_file_exec(C, op);
+
+       WM_event_add_fileselect(C, op); 
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+void FONT_OT_paste_file(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Paste File";
+       ot->idname= "FONT_OT_paste_file";
+       
+       /* api callbacks */
+       ot->exec= paste_file_exec;
+       ot->invoke= paste_file_invoke;
+       ot->poll= ED_operator_editfont;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_string_file_path(ot->srna, "filename", "", 0, "Filename", "File path of text file to load.");
+}
+
+/******************* paste buffer operator ********************/
+
+static int paste_buffer_exec(bContext *C, wmOperator *op)
+{
+       char *filename;
+
+#ifdef WIN32
+       filename= "C:\\windows\\temp\\cutbuf.txt";
+
+//     The following is more likely to work on all Win32 installations.
+//     suggested by Douglas Toltzman. Needs windows include files...
+/*
+       char tempFileName[MAX_PATH];
+       DWORD pathlen;
+       static const char cutbufname[]="cutbuf.txt";
 
-       DAG_object_flush_update(scene, scene->obedit, OB_RECALC_DATA);
+       if((pathlen=GetTempPath(sizeof(tempFileName),tempFileName)) > 0 &&
+               pathlen + sizeof(cutbufname) <= sizeof(tempFileName))
+       {
+               strcat(tempFileName,cutbufname);
+               filename= tempFilename;
+       }
+*/
+#else
+       filename= "/tmp/.cutbuffer";
+#endif
+
+       return paste_file(C, NULL, filename);
 }
 
+void FONT_OT_paste_buffer(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Paste Buffer";
+       ot->idname= "FONT_OT_paste_buffer";
+       
+       /* api callbacks */
+       ot->exec= paste_buffer_exec;
+       ot->poll= ED_operator_editfont;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
 
-void txt_export_to_object(Scene *scene, struct Text *text)
+/******************* XXX text to object operator ********************/
+
+static void txt_export_to_object(Scene *scene, Object *obedit, Text *text)
 {
-       Object *obedit= scene->obedit; // XXX
        ID *id;
        Curve *cu;
        struct TextLine *tmp;
@@ -337,7 +478,7 @@ void txt_export_to_object(Scene *scene, struct Text *text)
 
        id = (ID *)text;
 
-       if (obedit && obedit->type==OB_FONT) return;
+       if(obedit && obedit->type==OB_FONT) return;
 // XXX check_editmode(OB_FONT);
        
        add_object(scene, OB_FONT);
@@ -351,7 +492,7 @@ void txt_export_to_object(Scene *scene, struct Text *text)
 /*     
 //             renames object, careful with long filenames.
 
-       if (text->name) {
+       if(text->name) {
        //ID *find_id(char *type, char *name)   
                BLI_split_dirfile(text->name, sdir, sfile);
 //             rename_id((ID *)obedit, sfile);
@@ -394,14 +535,10 @@ void txt_export_to_object(Scene *scene, struct Text *text)
 
        make_editText(obedit);
        ED_object_exit_editmode(NULL, EM_FREEDATA|EM_WAITCURSOR); // XXX
-
 }
 
-
-void txt_export_to_objects(struct Text *text)
+static void txt_export_to_objects(Scene *scene, Object *obedit, Text *text)
 {
-       Scene *scene= NULL; // XXX
-       Object *obedit= NULL; // XXX
        RegionView3D *rv3d= NULL; // XXX
        ID *id;
        Curve *cu;
@@ -414,7 +551,7 @@ void txt_export_to_objects(struct Text *text)
 
        id = (ID *)text;
 
-       if (obedit && obedit->type==OB_FONT) return;
+       if(obedit && obedit->type==OB_FONT) return;
 // XXX check_editmode(OB_FONT);
 
        curline = text->lines.first;
@@ -473,27 +610,58 @@ void txt_export_to_objects(struct Text *text)
        }
 }
 
+static int text_to_object_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       Text *text= NULL; /// XXX retrieve this ..
+
+       if(RNA_boolean_get(op->ptr, "split_lines"))
+               txt_export_to_objects(scene, obedit, text);
+       else
+               txt_export_to_object(scene, obedit, text);
+
+       return OPERATOR_FINISHED;
+}
+
+void FONT_OT_text_to_object(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Text to Object";
+       ot->idname= "FONT_OT_text_to_object";
+       
+       /* api callbacks */
+       ot->exec= text_to_object_exec;
+       ot->poll= ED_operator_editfont; // XXX not correct
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_boolean(ot->srna, "split_lines", 0, "Split Lines", "Create one object per line in the text.");
+}
+
+/********************** utilities ***************************/
+
 static short next_word(Curve *cu)
 {
        short s;
-       for (s=cu->pos; (cu->str[s]) && (cu->str[s]!=' ') && (cu->str[s]!='\n') &&
+       for(s=cu->pos; (cu->str[s]) && (cu->str[s]!=' ') && (cu->str[s]!='\n') &&
                        (cu->str[s]!=1) && (cu->str[s]!='\r'); s++);
-       if (cu->str[s]) return(s+1); else return(s);
+       if(cu->str[s]) return(s+1); else return(s);
 }
 
 static short prev_word(Curve *cu)
 {
        short s;
        
-       if (cu->pos==0) return(0);
-       for (s=cu->pos-2; (cu->str[s]) && (cu->str[s]!=' ') && (cu->str[s]!='\n') &&
+       if(cu->pos==0) return(0);
+       for(s=cu->pos-2; (cu->str[s]) && (cu->str[s]!=' ') && (cu->str[s]!='\n') &&
                        (cu->str[s]!=1) && (cu->str[s]!='\r'); s--);
-       if (cu->str[s]) return(s+1); else return(s);
+       if(cu->str[s]) return(s+1); else return(s);
 }
 
-
-
-static int killselection(Object *obedit, int ins)      /* 1 == new character */
+static int kill_selection(Object *obedit, int ins)     /* 1 == new character */
 {
        Curve *cu= obedit->data;
        EditFont *ef= cu->editfont;
@@ -502,30 +670,173 @@ static int killselection(Object *obedit, int ins)        /* 1 == new character */
        int getfrom;
 
        direction = BKE_font_getselection(obedit, &selstart, &selend);
-       if (direction) {
+       if(direction) {
                int size;
-               if (ins) offset = 1;
-               if (cu->pos >= selstart) cu->pos = selstart+offset;
-               if ((direction == -1) && ins) {
+               if(ins) offset = 1;
+               if(cu->pos >= selstart) cu->pos = selstart+offset;
+               if((direction == -1) && ins) {
                        selstart++;
                        selend++;
                }
                getfrom = selend+offset;
-               if (ins==0) getfrom++;
+               if(ins==0) getfrom++;
                size = (cu->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset*sizeof(wchar_t));
                memmove(ef->textbuf+selstart, ef->textbuf+getfrom, size);
                memmove(ef->textbufinfo+selstart, ef->textbufinfo+getfrom, ((cu->len-selstart)+offset)*sizeof(CharInfo));
                cu->len -= (selend-selstart)+offset;
                cu->selstart = cu->selend = 0;
        }
+
        return(direction);
 }
 
-static void copyselection(Object *obedit)
+/******************* set style operator ********************/
+
+static EnumPropertyItem style_items[]= {
+       {CU_BOLD, "BOLD", "Bold", ""},
+       {CU_ITALIC, "ITALIC", "Italic", ""},
+       {CU_UNDERLINE, "UNDERLINE", "Underline", ""},
+       {0, NULL, NULL, NULL}};
+
+static int set_style(bContext *C, int style, int clear)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       Curve *cu= obedit->data;
+       EditFont *ef= cu->editfont;
+       int i, selstart, selend;
+
+       if(!BKE_font_getselection(obedit, &selstart, &selend))
+               return OPERATOR_CANCELLED;
+
+       for(i=selstart; i<=selend; i++) {
+               if(clear)
+                       ef->textbufinfo[i].flag &= ~style;
+               else
+                       ef->textbufinfo[i].flag |= style;
+       }
+
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+       return OPERATOR_FINISHED;
+}
+
+static int set_style_exec(bContext *C, wmOperator *op)
+{
+       int style, clear;
+
+       style= RNA_enum_get(op->ptr, "style");
+       clear= RNA_enum_get(op->ptr, "clear");
+
+       return set_style(C, style, clear);
+}
+
+void FONT_OT_set_style(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Set Style";
+       ot->idname= "FONT_OT_set_style";
+       
+       /* api callbacks */
+       ot->exec= set_style_exec;
+       ot->poll= ED_operator_editfont;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_enum(ot->srna, "style", style_items, CU_BOLD, "Style", "Style to set selection to.");
+       RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear style rather than setting it.");
+}
+
+/******************* toggle style operator ********************/
+
+static int toggle_style_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       Curve *cu= obedit->data;
+       int style, clear, selstart, selend;
+
+       if(!BKE_font_getselection(obedit, &selstart, &selend))
+               return OPERATOR_CANCELLED;
+       
+       style= RNA_enum_get(op->ptr, "style");
+
+       cu->curinfo.flag ^= style;
+       clear= (cu->curinfo.flag & style) == 0;
+
+       return set_style(C, style, clear);
+}
+
+void FONT_OT_toggle_style(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Toggle Style";
+       ot->idname= "FONT_OT_toggle_style";
+       
+       /* api callbacks */
+       ot->exec= toggle_style_exec;
+       ot->poll= ED_operator_editfont;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_enum(ot->srna, "style", style_items, CU_BOLD, "Style", "Style to set selection to.");
+}
+
+/******************* set material operator ********************/
+
+static int set_material_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       Curve *cu= obedit->data;
+       EditFont *ef= cu->editfont;
+       int i, mat_nr, selstart, selend;
+
+       if(!BKE_font_getselection(obedit, &selstart, &selend))
+               return OPERATOR_CANCELLED;
+
+       if(RNA_property_is_set(op->ptr, "index"))
+               mat_nr= RNA_int_get(op->ptr, "index");
+       else
+               mat_nr= obedit->actcol;
+
+       for(i=selstart; i<=selend; i++)
+               ef->textbufinfo[i].mat_nr = mat_nr;
+
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, obedit);
+
+       return OPERATOR_FINISHED;
+}
+
+void FONT_OT_set_material(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Set Material";
+       ot->idname= "FONT_OT_set_material";
+       
+       /* api callbacks */
+       ot->exec= set_material_exec;
+       ot->poll= ED_operator_editfont;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Material Index", "Material slot index.", 0, INT_MAX);
+}
+
+/******************* copy text operator ********************/
+
+static void copy_selection(Object *obedit)
 {
        int selstart, selend;
        
-       if (BKE_font_getselection(obedit, &selstart, &selend)) {
+       if(BKE_font_getselection(obedit, &selstart, &selend)) {
                Curve *cu= obedit->data;
                EditFont *ef= cu->editfont;
                
@@ -535,17 +846,70 @@ static void copyselection(Object *obedit)
        }
 }
 
-static void pasteselection(Object *obedit)
+static int copy_text_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit= CTX_data_edit_object(C);
+
+       copy_selection(obedit);
+
+       return OPERATOR_FINISHED;
+}
+
+void FONT_OT_copy_text(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Copy Text";
+       ot->idname= "FONT_OT_copy_text";
+       
+       /* api callbacks */
+       ot->exec= copy_text_exec;
+       ot->poll= ED_operator_editfont;
+}
+
+/******************* cut text operator ********************/
+
+static int cut_text_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       int selstart, selend;
+
+       if(!BKE_font_getselection(obedit, &selstart, &selend))
+               return OPERATOR_CANCELLED;
+
+       copy_selection(obedit);
+       kill_selection(obedit, 0);
+
+       text_update_edited(C, scene, obedit, 1, 0);
+
+       return OPERATOR_FINISHED;
+}
+
+void FONT_OT_cut_text(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Cut Text";
+       ot->idname= "FONT_OT_cut_text";
+       
+       /* api callbacks */
+       ot->exec= cut_text_exec;
+       ot->poll= ED_operator_editfont;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******************* paste text operator ********************/
+
+static int paste_selection(Object *obedit, ReportList *reports)
 {
        Curve *cu= obedit->data;
        EditFont *ef= cu->editfont;
-
        int len= wcslen(ef->copybuf);
 
        // Verify that the copy buffer => [copy buffer len] + cu->len < MAXTEXT
-       if(cu->len + len <= MAXTEXT)
-       {
-               if (len) {      
+       if(cu->len + len <= MAXTEXT) {
+               if(len) {       
                        int size = (cu->len * sizeof(wchar_t)) - (cu->pos*sizeof(wchar_t)) + sizeof(wchar_t);
                        memmove(ef->textbuf+cu->pos+len, ef->textbuf+cu->pos, size);
                        memcpy(ef->textbuf+cu->pos, ef->copybuf, len * sizeof(wchar_t));
@@ -555,521 +919,567 @@ static void pasteselection(Object *obedit)
                
                        cu->len += len;
                        cu->pos += len;
-               }
-       }
-       else
-       {
-               error("Text too long");
-       }
-}
 
-int style_to_sel(Object *obedit, int style, int toggle) 
-{
-       int selstart, selend;
-       int i;
-       
-       if (obedit && (obedit->type == OB_FONT)) {
-               Curve *cu= obedit->data;
-               EditFont *ef= cu->editfont;
-               
-               if (BKE_font_getselection(obedit, &selstart, &selend)) {
-                       for (i=selstart; i<=selend; i++) {
-                               if (toggle==0) {
-                                       ef->textbufinfo[i].flag &= ~style;
-                               } else {
-                                       ef->textbufinfo[i].flag |= style;
-                               }
-                       }
                        return 1;
                }
        }
-       return 0;
-}
-
-int mat_to_sel(Object *obedit) 
-{
-       int selstart, selend;
-       int i;
+       else
+               BKE_report(reports, RPT_WARNING, "Text too long.");
        
-       if (obedit && (obedit->type == OB_FONT)) {
-               Curve *cu= obedit->data;
-               EditFont *ef= cu->editfont;
-               
-               if (BKE_font_getselection(obedit, &selstart, &selend)) {
-                       for (i=selstart; i<=selend; i++) {
-                               ef->textbufinfo[i].mat_nr = obedit->actcol;
-                       }
-                       return 1;
-               }
-       }
        return 0;
 }
 
-static int do_textedit(bContext *C, wmOperator *op, wmEvent *evt)
+static int paste_text_exec(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
-       Curve *cu= obedit->data;
-       EditFont *ef= cu->editfont;
-       static int accentcode= 0;
-       int x, doit=0, cursmove=0;
-       unsigned long ascii = evt->ascii;
-       int alt= evt->alt, shift= evt->shift, ctrl= evt->ctrl;
-       int event= evt->type, val= evt->val;
-       short kern;
-       
-       /* tab should exit editmode, but we allow it to be typed using modifier keys */
-       if(event==TABKEY) {
-               if((alt||ctrl||shift) == 0)
-                       return OPERATOR_PASS_THROUGH;
-               else
-                       ascii= 9;
-       }
-       if(event==BACKSPACEKEY)
-               ascii= 0;
 
-       if(val && ascii) {
-               
-               /* handle case like TAB (==9) */
-               if( (ascii > 31 && ascii < 254 && ascii != 127) || (ascii==13) || (ascii==10) || (ascii==8)) {
+       if(!paste_selection(obedit, op->reports))
+               return OPERATOR_CANCELLED;
+
+       text_update_edited(C, scene, obedit, 1, 0);
+
+       return OPERATOR_FINISHED;
+}
+
+void FONT_OT_paste_text(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Paste Text";
+       ot->idname= "FONT_OT_paste_text";
        
-                       if(accentcode) {
-                               if(cu->pos>0) ef->textbuf[cu->pos-1]= findaccent(ef->textbuf[cu->pos-1], ascii);
-                               accentcode= 0;
-                       }
-                       else if(cu->len<MAXTEXT-1) {
-                               if(alt ) {
-                               
-                                       /* might become obsolete, apple has default values for this, other OS's too? */
-                               
-                                       if(ascii=='t') ascii= 137;
-                                       else if(ascii=='c') ascii= 169;
-                                       else if(ascii=='f') ascii= 164;
-                                       else if(ascii=='g') ascii= 176;
-                                       else if(ascii=='l') ascii= 163;
-                                       else if(ascii=='r') ascii= 174;
-                                       else if(ascii=='s') ascii= 223;
-                                       else if(ascii=='v') ascii= 1001;
-                                       else if(ascii=='y') ascii= 165;
-                                       else if(ascii=='.') ascii= 138;
-                                       else if(ascii=='1') ascii= 185;
-                                       else if(ascii=='2') ascii= 178;
-                                       else if(ascii=='3') ascii= 179;
-                                       else if(ascii=='%') ascii= 139;
-                                       else if(ascii=='?') ascii= 191;
-                                       else if(ascii=='!') ascii= 161;
-                                       else if(ascii=='x') ascii= 215;
-                                       else if(ascii=='>') ascii= 187;
-                                       else if(ascii=='<') ascii= 171;
-                               }
-                               if(ascii==1001) {
-                                       int file, filelen;
-                                       char *strp;
-                                       
-/* this should be solved by clipboard support */
-#ifdef __WIN32_DISABLED 
-                                       file= open("C:\\windows\\temp\\cutbuf", O_BINARY|O_RDONLY);
-#else
-                                       file= open("/tmp/.cutbuffer", O_BINARY|O_RDONLY);
-#endif
-                                       if(file>0) {
-                                       
-                                               filelen = BLI_filesize(file);
-                                       
-                                               strp= MEM_mallocN(filelen+4, "tempstr");
-                                               read(file, strp, filelen);
-                                               close(file);
-                                               strp[filelen]= 0;
-
-                                               if(cu->len+filelen<MAXTEXT) {
-                                                       int tmplen;
-                                                       wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
-                                                       tmplen = utf8towchar(mem, strp);
-                                                       wcscat(ef->textbuf, mem);
-                                                       MEM_freeN(mem);
-                                                       cu->len += tmplen;
-                                                       cu->pos= cu->len;
-                                               }
-                                               MEM_freeN(strp);
-                                       }
-                               }
-                               else {
-                                       insert_into_textbuf(obedit, ascii);
-                               }
-                       }
-                       
-                       killselection(obedit, 1);
-                       
-                       doit= 1;
-               }
-               else
-               {
-                       insert_into_textbuf(obedit, ascii);
-                       doit = 1;
-               }
-       }
-       else if(val) {
-               cursmove= 0;
-               
-               switch(event) {
-               case ENDKEY:
-                       if ((shift) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;                
-                       while(cu->pos<cu->len) {
-                               if( ef->textbuf[cu->pos]==0) break;
-                               if( ef->textbuf[cu->pos]=='\n') break;
-                               if( ef->textbufinfo[cu->pos].flag & CU_WRAP ) break;
-                               cu->pos++;
-                       }
-                       cursmove=FO_CURS;
-                       break;
+       /* api callbacks */
+       ot->exec= paste_text_exec;
+       ot->poll= ED_operator_editfont;
 
-               case HOMEKEY:
-                       if ((shift) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ move operator ************************/
+
+static EnumPropertyItem move_type_items[]= {
+       {LINE_BEGIN, "LINE_BEGIN", "Line Begin", ""},
+       {LINE_END, "LINE_END", "Line End", ""},
+       {PREV_CHAR, "PREVIOUS_CHARACTER", "Previous Character", ""},
+       {NEXT_CHAR, "NEXT_CHARACTER", "Next Character", ""},
+       {PREV_WORD, "PREVIOUS_WORD", "Previous Word", ""},
+       {NEXT_WORD, "NEXT_WORD", "Next Word", ""},
+       {PREV_LINE, "PREVIOUS_LINE", "Previous Line", ""},
+       {NEXT_LINE, "NEXT_LINE", "Next Line", ""},
+       {PREV_PAGE, "PREVIOUS_PAGE", "Previous Page", ""},
+       {NEXT_PAGE, "NEXT_PAGE", "Next Page", ""},
+       {0, NULL, NULL, NULL}};
+
+static int move_cursor(bContext *C, int type, int select)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       Curve *cu= obedit->data;
+       EditFont *ef= cu->editfont;
+       int cursmove= 0;
+
+       switch(type) {
+               case LINE_BEGIN:
+                       if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
                        while(cu->pos>0) {
-                               if( ef->textbuf[cu->pos-1]=='\n') break;
-                               if( ef->textbufinfo[cu->pos-1].flag & CU_WRAP ) break;                          
+                               if(ef->textbuf[cu->pos-1]=='\n') break;
+                               if(ef->textbufinfo[cu->pos-1].flag & CU_WRAP ) break;                           
                                cu->pos--;
                        }               
                        cursmove=FO_CURS;
                        break;
                        
-               case RETKEY:
-                       if(ctrl) {
-                               insert_into_textbuf(obedit, 1);
-                               if (ef->textbuf[cu->pos]!='\n') insert_into_textbuf(obedit, '\n');                              
-                       }
-                       else {
-                               insert_into_textbuf(obedit, '\n');
-                       }
-                       cu->selstart = cu->selend = 0;
-                       doit= 1;
-                       break;
-
-               case RIGHTARROWKEY:     
-                       if ((shift) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
-                       if (ctrl) {
-                               cu->pos= next_word(cu);
-                               cursmove= FO_CURS;                              
-                       } 
-                       else if (alt) {
-                               kern = ef->textbufinfo[cu->pos-1].kern;
-                               kern += 1;
-                               if (kern>20) kern = 20;
-                               ef->textbufinfo[cu->pos-1].kern = kern;
-                               doit = 1;
-                       }
-                       else {
+               case LINE_END:
+                       if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;                
+                       while(cu->pos<cu->len) {
+                               if(ef->textbuf[cu->pos]==0) break;
+                               if(ef->textbuf[cu->pos]=='\n') break;
+                               if(ef->textbufinfo[cu->pos].flag & CU_WRAP ) break;
                                cu->pos++;
-                               cursmove= FO_CURS;                              
                        }
-
+                       cursmove=FO_CURS;
                        break;
-                       
-               case LEFTARROWKEY:
-                       if ((shift) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
-                       if (ctrl) {
-                               cu->pos= prev_word(cu);
-                               cursmove= FO_CURS;
-                       } 
-                       else if (alt) {
-                               kern = ef->textbufinfo[cu->pos-1].kern;
-                               kern -= 1;
-                               if (kern<-20) kern = -20;
-                               ef->textbufinfo[cu->pos-1].kern = kern;
-                               doit = 1;
-                       }
-                       else {
-                               cu->pos--;
-                               cursmove=FO_CURS;
-                       }
+
+               case PREV_WORD:
+                       if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+                       cu->pos= prev_word(cu);
+                       cursmove= FO_CURS;
                        break;
 
-               case UPARROWKEY:
-                       if ((shift) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
-                       if(alt) {
-                               if (cu->pos && ef->textbuf[cu->pos - 1] < 255) {
-                                       ef->textbuf[cu->pos - 1]++;
-                                       doit= 1;
-                               }
-                       }
-                       else cursmove=FO_CURSUP;
+               case NEXT_WORD:
+                       if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+                       cu->pos= next_word(cu);
+                       cursmove= FO_CURS;                              
                        break;
-                       
-               case PAGEUPKEY:
-                       if ((shift) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
-                       cursmove=FO_PAGEUP;
+
+               case PREV_CHAR:
+                       if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+                       cu->pos--;
+                       cursmove=FO_CURS;
                        break;
-                       
-               case DOWNARROWKEY:
-                       if ((shift) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
-                       if(alt) {
-                               if (cu->pos && ef->textbuf[cu->pos - 1] > 1) {
-                                       ef->textbuf[cu->pos - 1]--;
-                                       doit= 1;
-                               }
-                       }
-                       else cursmove= FO_CURSDOWN;
+
+               case NEXT_CHAR: 
+                       if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+                       cu->pos++;
+                       cursmove= FO_CURS;                              
+
                        break;
 
-               case PAGEDOWNKEY:
-                       if ((shift) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
-                       cursmove=FO_PAGEDOWN;
+               case PREV_LINE:
+                       if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+                       cursmove=FO_CURSUP;
                        break;
                        
-               case BACKSPACEKEY:
-                       if(cu->len!=0) {
-                               if(alt) {
-                                       if(cu->pos>0) accentcode= 1;
-                               }
-                               else if (ctrl) {
-                                       cu->len = cu->pos = 0;
-                                       ef->textbuf[0]= 0;
-                                       doit= 1;
-                               }
-                               else {
-                                       if (killselection(obedit, 0)==0) {
-                                               if (cu->pos>0) {
-                                                       for(x=cu->pos;x<=cu->len;x++) ef->textbuf[x-1]= ef->textbuf[x];
-                                                       for(x=cu->pos;x<=cu->len;x++) ef->textbufinfo[x-1]= ef->textbufinfo[x];                                 
-                                                       cu->pos--;
-                                                       ef->textbuf[--cu->len]='\0';
-                                                       doit=1;
-                                               }
-                                       } else doit=1;
-                               }
-                       }
+               case NEXT_LINE:
+                       if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+                       cursmove= FO_CURSDOWN;
                        break;
 
-               case DELKEY:
-                       if(cu->len!=0) {
-                               if (killselection(obedit, 0)==0) {
-                                       if(cu->pos<cu->len) {                                   
-                                               for(x=cu->pos;x<cu->len;x++) ef->textbuf[x]= ef->textbuf[x+1];
-                                               for(x=cu->pos;x<cu->len;x++) ef->textbufinfo[x]= ef->textbufinfo[x+1];                                  
-                                               ef->textbuf[--cu->len]='\0';
-                                               doit=1;
-                                       }
-                               } else doit=1;
-                       }
-                       break;
-               
-               case IKEY:
-                       if (ctrl) {
-                               cu->curinfo.flag ^= CU_ITALIC;
-                               if (style_to_sel(obedit, CU_ITALIC, cu->curinfo.flag & CU_ITALIC)) doit= 1;                             
-                       }
+               case PREV_PAGE:
+                       if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+                       cursmove=FO_PAGEUP;
                        break;
 
-               case BKEY:
-                       if (ctrl) {
-                               cu->curinfo.flag ^= CU_BOLD;
-                               if (style_to_sel(obedit, CU_BOLD, cu->curinfo.flag & CU_BOLD)) doit= 1;
-                       }
-                       break;                  
-                       
-               case UKEY:
-                       if (ctrl) {
-                               cu->curinfo.flag ^= CU_UNDERLINE;
-                               if (style_to_sel(obedit, CU_UNDERLINE, cu->curinfo.flag & CU_UNDERLINE)) doit= 1;
-                       }
-                       break;
-                       
-               case XKEY:
-                       if (ctrl) {
-                               copyselection(obedit);
-                               killselection(obedit, 0);
-                               doit= 1;
-                       }
-                       break;
-                       
-               case CKEY:
-                       if (ctrl) {
-                               copyselection(obedit);
-                       }
-                       break;                          
-                       
-               case VKEY:
-                       if (ctrl) {
-                               pasteselection(obedit);
-                               doit= 1;
-                       }
+               case NEXT_PAGE:
+                       if((select) && (cu->selstart==0)) cu->selstart = cu->selend = cu->pos+1;
+                       cursmove=FO_PAGEDOWN;
                        break;
-               default:
-                       return OPERATOR_PASS_THROUGH;
-               }
-                       
-               if(cursmove) {
-                       if ((shift)==0) {
-                               if (cu->selstart) {
-                                       cu->selstart = cu->selend = 0;
-                                       update_string(cu);
-                                       BKE_text_to_curve(scene, obedit, FO_SELCHANGE);
-                               }
-                       }
-                       if(cu->pos>cu->len) cu->pos= cu->len;
-                       else if(cu->pos>=MAXTEXT) cu->pos= MAXTEXT;
-                       else if(cu->pos<0) cu->pos= 0;
-               }
        }
-       if(doit || cursmove) {
-       
-               if (cu->pos) {
-                       cu->curinfo = ef->textbufinfo[cu->pos-1];
-               } else cu->curinfo = ef->textbufinfo[0];
                
-               if (obedit->totcol>0) {
-                       obedit->actcol = ef->textbufinfo[cu->pos-1].mat_nr;
-               }
-               update_string(cu);
-               BKE_text_to_curve(scene, obedit, cursmove);
-               if (cursmove && (shift)) {
-                       cu->selend = cu->pos;
-                       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       if(!cursmove)
+               return OPERATOR_CANCELLED;
+
+       if(select == 0) {
+               if(cu->selstart) {
+                       cu->selstart = cu->selend = 0;
+                       update_string(cu);
+                       BKE_text_to_curve(scene, obedit, FO_SELCHANGE);
                }
-               if(cursmove==0) {
-                       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
-               }                       
+       }
 
-               WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, NULL); // XXX better note
+       if(cu->pos>cu->len) cu->pos= cu->len;
+       else if(cu->pos>=MAXTEXT) cu->pos= MAXTEXT;
+       else if(cu->pos<0) cu->pos= 0;
+
+       text_update_edited(C, scene, obedit, select, cursmove);
+
+       if(select)
+               cu->selend = cu->pos;
 
-       }
        return OPERATOR_FINISHED;
 }
 
-static int font_editmode(bContext *C)
+static int move_exec(bContext *C, wmOperator *op)
 {
-       Object *obedit= CTX_data_edit_object(C);
-       if(obedit && obedit->type==OB_FONT)
-               return 1;
-       return 0;
+       int type= RNA_enum_get(op->ptr, "type");
+
+       return move_cursor(C, type, 0);
 }
 
-void FONT_OT_textedit(wmOperatorType *ot)
+void FONT_OT_move(wmOperatorType *ot)
 {
+       /* identifiers */
+       ot->name= "Move Cursor";
+       ot->idname= "FONT_OT_move";
        
+       /* api callbacks */
+       ot->exec= move_exec;
+       ot->poll= ED_operator_editfont;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to.");
+}
+
+/******************* move select operator ********************/
+
+static int move_select_exec(bContext *C, wmOperator *op)
+{
+       int type= RNA_enum_get(op->ptr, "type");
+
+       return move_cursor(C, type, 1);
+}
+
+void FONT_OT_move_select(wmOperatorType *ot)
+{
        /* identifiers */
-       ot->name= "Edit Text";
-       ot->idname= "FONT_OT_textedit";
+       ot->name= "Move Select";
+       ot->idname= "FONT_OT_move_select";
        
        /* api callbacks */
-       ot->invoke= do_textedit;
+       ot->exec= move_select_exec;
+       ot->poll= ED_operator_editfont;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to, to make a selection.");
+}
+
+/************************* change spacing **********************/
+
+static int change_spacing_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       Curve *cu= obedit->data;
+       EditFont *ef= cu->editfont;
+       int kern, delta= RNA_int_get(op->ptr, "delta");
+
+       kern = ef->textbufinfo[cu->pos-1].kern;
+       kern += delta;
+       CLAMP(kern, -20, 20);
+
+       if(ef->textbufinfo[cu->pos-1].kern == kern)
+               return OPERATOR_CANCELLED;
+
+       ef->textbufinfo[cu->pos-1].kern = kern;
+
+       text_update_edited(C, scene, obedit, 1, 0);
+
+       return OPERATOR_FINISHED;
+}
+
+void FONT_OT_change_spacing(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Change Spacing";
+       ot->idname= "FONT_OT_change_spacing";
        
-       ot->poll= font_editmode;
+       /* api callbacks */
+       ot->exec= change_spacing_exec;
+       ot->poll= ED_operator_editfont;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_int(ot->srna, "delta", 1, -20, 20, "Delta", "Amount to decrease or increasing character spacing with.", -20, 20);
+}
+
+/************************* change character **********************/
+
+static int change_character_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       Curve *cu= obedit->data;
+       EditFont *ef= cu->editfont;
+       int character, delta= RNA_int_get(op->ptr, "delta");
+
+       if(cu->pos <= 0)
+               return OPERATOR_CANCELLED;
+
+       character= ef->textbuf[cu->pos - 1];
+       character += delta;
+       CLAMP(character, 0, 255);
+
+       if(character == ef->textbuf[cu->pos - 1])
+               return OPERATOR_CANCELLED;
+
+       ef->textbuf[cu->pos - 1]= character;
+
+       text_update_edited(C, scene, obedit, 1, 0);
+
+       return OPERATOR_FINISHED;
+}
+
+void FONT_OT_change_character(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Change Character";
+       ot->idname= "FONT_OT_change_character";
        
-       ot->flag = OPTYPE_UNDO;
+       /* api callbacks */
+       ot->exec= change_character_exec;
+       ot->poll= ED_operator_editfont;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_int(ot->srna, "delta", 1, -255, 255, "Delta", "Number to increase or decrease character code with.", -255, 255);
 }
 
+/******************* line break operator ********************/
 
-void paste_unicodeText(Scene *scene, char *filename)
+static int line_break_exec(bContext *C, wmOperator *op)
 {
-       Object *obedit= scene->obedit; // XXX
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
        Curve *cu= obedit->data;
        EditFont *ef= cu->editfont;
-       int filelen, doit= 0;
-       char *strp;
-       FILE *fp = NULL;
+       int ctrl= RNA_enum_get(op->ptr, "ctrl");
 
-       fp= fopen(filename, "r");
+       if(ctrl) {
+               insert_into_textbuf(obedit, 1);
+               if(ef->textbuf[cu->pos]!='\n')
+                       insert_into_textbuf(obedit, '\n');
+       }
+       else
+               insert_into_textbuf(obedit, '\n');
 
-       if(fp) {
+       cu->selstart = cu->selend = 0;
 
-               fseek( fp, 0L, SEEK_END );
-               filelen = ftell( fp );
-               fseek( fp, 0L, SEEK_SET );
-                       
-               strp= MEM_mallocN(filelen+4, "tempstr");
-               //fread() instead of read(),
-               //because windows read() converts text to DOS \r\n linebreaks
-               //causing double linebreaks in the 3d text
-               filelen = fread(strp, 1, filelen, fp);
-               fclose(fp);
-               strp[filelen]= 0;
-
-
-               if(cu->len+filelen<MAXTEXT) 
-               {
-                       int tmplen;
-                       wchar_t *mem = MEM_callocN((sizeof(wchar_t)*filelen)+(4*sizeof(wchar_t)), "temporary");
-                       tmplen = utf8towchar(mem, strp);
-//                     mem =utf8s2wc(strp);
-                       wcscat(ef->textbuf, mem);
-                       MEM_freeN(mem);
-                       cu->len += tmplen;
-                       cu->pos= cu->len;
-               }
-               MEM_freeN(strp);
-               doit = 1;
+       text_update_edited(C, scene, obedit, 1, 0);
+
+       return OPERATOR_FINISHED;
+}
+
+void FONT_OT_line_break(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Line Break";
+       ot->idname= "FONT_OT_line_break";
+       
+       /* api callbacks */
+       ot->exec= line_break_exec;
+       ot->poll= ED_operator_editfont;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_boolean(ot->srna, "ctrl", 0, "Ctrl", ""); // XXX what is this?
+}
+
+/******************* delete operator **********************/
+
+static EnumPropertyItem delete_type_items[]= {
+       {DEL_ALL, "ALL", "All", ""},
+       {DEL_NEXT_CHAR, "NEXT_CHARACTER", "Next Character", ""},
+       {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", "Previous Character", ""},
+       {DEL_SELECTION, "SELECTION", "Selection", ""},
+       {DEL_NEXT_SEL, "NEXT_OR_SELECTION", "Next or Selection", ""},
+       {DEL_PREV_SEL, "PREVIOUS_OR_SELECTION", "Previous or Selection", ""},
+       {0, NULL, NULL, NULL}};
+
+static int delete_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       Curve *cu= obedit->data;
+       EditFont *ef= cu->editfont;
+       int x, selstart, selend, type= RNA_enum_get(op->ptr, "type");
+
+       if(cu->len == 0)
+               return OPERATOR_CANCELLED;
+
+       if(BKE_font_getselection(obedit, &selstart, &selend)) {
+               if(type == DEL_NEXT_SEL) type= DEL_SELECTION;
+               else if(type == DEL_PREV_SEL) type= DEL_SELECTION;
        }
-       if(doit) {
-               update_string(cu);
-               BKE_text_to_curve(scene, obedit, 0);
-               DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       else {
+               if(type == DEL_NEXT_SEL) type= DEL_NEXT_CHAR;
+               else if(type == DEL_PREV_SEL) type= DEL_PREV_CHAR;
+       }
+
+       switch(type) {
+               case DEL_ALL:
+                       cu->len = cu->pos = 0;
+                       ef->textbuf[0]= 0;
+                       break;
+               case DEL_SELECTION:
+                       if(!kill_selection(obedit, 0))
+                               return OPERATOR_CANCELLED;
+                       break;
+               case DEL_PREV_CHAR:
+                       if(cu->pos<=0)
+                               return OPERATOR_CANCELLED;
+
+                       for(x=cu->pos;x<=cu->len;x++)
+                               ef->textbuf[x-1]= ef->textbuf[x];
+                       for(x=cu->pos;x<=cu->len;x++)
+                               ef->textbufinfo[x-1]= ef->textbufinfo[x];                                       
+
+                       cu->pos--;
+                       ef->textbuf[--cu->len]='\0';
+                       break;
+               case DEL_NEXT_CHAR:
+                       if(cu->pos>=cu->len)
+                               return OPERATOR_CANCELLED;
+
+                       for(x=cu->pos;x<cu->len;x++)
+                               ef->textbuf[x]= ef->textbuf[x+1];
+                       for(x=cu->pos;x<cu->len;x++)
+                               ef->textbufinfo[x]= ef->textbufinfo[x+1];                                       
+
+                       ef->textbuf[--cu->len]='\0';
+                       break;
+               default:
+                       return OPERATOR_CANCELLED;
        }
+
+       text_update_edited(C, scene, obedit, 1, 0);
+
+       return OPERATOR_FINISHED;
+}
+
+void FONT_OT_delete(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Delete";
+       ot->idname= "FONT_OT_delete";
+       
+       /* api callbacks */
+       ot->exec= delete_exec;
+       ot->poll= ED_operator_editfont;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_enum(ot->srna, "type", delete_type_items, DEL_ALL, "Type", "Which part of the text to delete.");
 }
 
-void paste_editText(Scene *scene)
+/*********************** insert text operator *************************/
+
+static int insert_text_exec(bContext *C, wmOperator *op)
 {
-       Object *obedit= scene->obedit; // XXX
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
+       char *inserted_utf8;
+       wchar_t *inserted_text, first;
+       int len;
+
+       if(!RNA_property_is_set(op->ptr, "text"))
+               return OPERATOR_CANCELLED;
+       
+       inserted_utf8= RNA_string_get_alloc(op->ptr, "text", NULL, 0);
+       len= strlen(inserted_utf8);
+
+       inserted_text= MEM_callocN(sizeof(wchar_t)*(len+1), "FONT_insert_text");
+       utf8towchar(inserted_text, inserted_utf8);
+       first= inserted_text[0];
+
+       MEM_freeN(inserted_text);
+       MEM_freeN(inserted_utf8);
+
+       if(!first)
+               return OPERATOR_CANCELLED;
+
+       insert_into_textbuf(obedit, first);
+       kill_selection(obedit, 1);
+       text_update_edited(C, scene, obedit, 1, 0);
+
+       return OPERATOR_FINISHED;
+}
+
+static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
        Curve *cu= obedit->data;
        EditFont *ef= cu->editfont;
-       int filelen, doit= 0;
-       char *strp;
-       FILE *fp = NULL;
+       static int accentcode= 0;
+       unsigned long ascii = evt->ascii;
+       int alt= evt->alt, shift= evt->shift, ctrl= evt->ctrl;
+       int event= evt->type, val= evt->val;
+       wchar_t inserted_text[2]= {0};
 
-#ifdef WIN32
-       fp= fopen("C:\\windows\\temp\\cutbuf.txt", "r");
+       if(RNA_property_is_set(op->ptr, "text"))
+               return insert_text_exec(C, op);
+       
+       /* tab should exit editmode, but we allow it to be typed using modifier keys */
+       if(event==TABKEY) {
+               if((alt||ctrl||shift) == 0)
+                       return OPERATOR_PASS_THROUGH;
+               else
+                       ascii= 9;
+       }
+       else if(event==BACKSPACEKEY)
+               ascii= 0;
 
-//     The following is more likely to work on all Win32 installations.
-//     suggested by Douglas Toltzman. Needs windows include files...
-/*
-       char tempFileName[MAX_PATH];
-       DWORD pathlen;
-       static const char cutbufname[]="cutbuf.txt";
+       if(val && ascii) {
+               /* handle case like TAB (== 9) */
+               if((ascii > 31 && ascii < 254 && ascii != 127) || (ascii==13) || (ascii==10) || (ascii==8)) {
+                       if(accentcode) {
+                               if(cu->pos>0) {
+                                       inserted_text[0]= findaccent(ef->textbuf[cu->pos-1], ascii);
+                                       ef->textbuf[cu->pos-1]= inserted_text[0];
+                               }
+                               accentcode= 0;
+                       }
+                       else if(cu->len<MAXTEXT-1) {
+                               if(alt) {
+                                       /* might become obsolete, apple has default values for this, other OS's too? */
+                                       if(ascii=='t') ascii= 137;
+                                       else if(ascii=='c') ascii= 169;
+                                       else if(ascii=='f') ascii= 164;
+                                       else if(ascii=='g') ascii= 176;
+                                       else if(ascii=='l') ascii= 163;
+                                       else if(ascii=='r') ascii= 174;
+                                       else if(ascii=='s') ascii= 223;
+                                       else if(ascii=='y') ascii= 165;
+                                       else if(ascii=='.') ascii= 138;
+                                       else if(ascii=='1') ascii= 185;
+                                       else if(ascii=='2') ascii= 178;
+                                       else if(ascii=='3') ascii= 179;
+                                       else if(ascii=='%') ascii= 139;
+                                       else if(ascii=='?') ascii= 191;
+                                       else if(ascii=='!') ascii= 161;
+                                       else if(ascii=='x') ascii= 215;
+                                       else if(ascii=='>') ascii= 187;
+                                       else if(ascii=='<') ascii= 171;
+                               }
 
-       if ((pathlen=GetTempPath(sizeof(tempFileName),tempFileName)) > 0 &&
-               pathlen + sizeof(cutbufname) <= sizeof(tempFileName))
-       {
-               strcat(tempFileName,cutbufname);
-               file= open(tempFileName, O_BINARY|O_RDONLY);
+                               inserted_text[0]= ascii;
+                               insert_into_textbuf(obedit, ascii);
+                       }
+                       
+                       kill_selection(obedit, 1);
+                       text_update_edited(C, scene, obedit, 1, 0);
+               }
+               else {
+                       inserted_text[0]= ascii;
+                       insert_into_textbuf(obedit, ascii);
+                       text_update_edited(C, scene, obedit, 1, 0);
+               }
        }
-*/
-#else
-       fp= fopen("/tmp/.cutbuffer", "r");
-#endif
+       else if(val && event == BACKSPACEKEY) {
+               if(alt && cu->len!=0 && cu->pos>0)
+                       accentcode= 1;
 
-       if(fp) {
-               
-               fseek(fp, 0L, SEEK_END);                
-               filelen = ftell( fp );
-               fseek(fp, 0L, SEEK_SET);
-                               
-               strp= MEM_mallocN(filelen+4, "tempstr");
-               // fread() instead of read(),
-               // because windows read() converts text to DOS \r\n linebreaks
-               // causing double linebreaks in the 3d text
-               filelen = fread(strp, 1, filelen, fp);
-               fclose(fp);
-               strp[filelen]= 0;
-               
-               if(cu->len+filelen<MAXTEXT) {
-                       int tmplen;
-                       wchar_t *mem = MEM_callocN((sizeof(wchar_t) * filelen) + (4 * sizeof(wchar_t)), "temporary");
-                       tmplen = utf8towchar(mem, strp);
-                       wcscat(ef->textbuf, mem);
-                       MEM_freeN(mem);
-                       cu->len += tmplen;
-                       cu->pos= cu->len;
-               }
-               MEM_freeN(strp);
-               doit = 1;
+               return OPERATOR_PASS_THROUGH;
        }
-       if(doit) {
-               update_string(cu);
-               BKE_text_to_curve(scene, obedit, 0);
-               DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       else
+               return OPERATOR_PASS_THROUGH;
+
+       if(inserted_text[0]) {
+               /* store as utf8 in RNA string */
+               char inserted_utf8[8] = {0};
+
+               wcs2utf8s(inserted_utf8, inserted_text);
+               RNA_string_set(op->ptr, "text", inserted_utf8);
        }
+
+       return OPERATOR_FINISHED;
+}
+
+void FONT_OT_insert_text(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Insert Text";
+       ot->idname= "FONT_OT_insert_text";
+       
+       /* api callbacks */
+       ot->exec= insert_text_exec;
+       ot->invoke= insert_text_invoke;
+       ot->poll= ED_operator_editfont;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_string(ot->srna, "text", "", 0, "Text", "Text to insert at the cursor position.");
 }
 
+/***************** editmode enter/exit ********************/
+
 void make_editText(Object *obedit)
 {
        Curve *cu= obedit->data;
@@ -1097,17 +1507,15 @@ void make_editText(Object *obedit)
 
        if(cu->pos>cu->len) cu->pos= cu->len;
 
-       if (cu->pos) {
+       if(cu->pos)
                cu->curinfo = ef->textbufinfo[cu->pos-1];
-       } else cu->curinfo = ef->textbufinfo[0];
+       else
+               cu->curinfo = ef->textbufinfo[0];
        
        // Convert to UTF-8
        update_string(cu);
-       
-       textediting= 1;
 }
 
-
 void load_editText(Object *obedit)
 {
        Curve *cu= obedit->data;
@@ -1129,117 +1537,119 @@ void load_editText(Object *obedit)
        
        /* this memory system is weak... */
        
-       if (cu->selboxes) {
+       if(cu->selboxes) {
                MEM_freeN(cu->selboxes);
                cu->selboxes= NULL;
        }
-       
-       textediting= 0;
-
 }
 
-void remake_editText(Object *obedit)
-{
-       Curve *cu= obedit->data;
-       EditFont *ef= cu->editfont;
-               
-       if(okee("Reload original text")==0) return;
-       
-       // Copy the oldstr to textbuf temporary global variable
-       wcscpy(ef->textbuf, ef->oldstr);
-       memcpy(ef->textbufinfo, ef->oldstrinfo, (cu->len)*sizeof(CharInfo));
-
-       // Set the object length and position   
-       cu= obedit->data;
-       cu->len= wcslen(ef->textbuf);
-       if(cu->pos>cu->len) cu->pos= cu->len;
-
-       update_string(cu);
-       
-}
-
-
 void free_editText(Object *obedit)
 {
        BKE_free_editfont((Curve *)obedit->data);
-
-       textediting= 0;
 }
 
+/********************** set case operator *********************/
 
-void add_primitiveFont(int dummy_argument)
-{
-       Scene *scene= NULL; // XXX
-       Object *obedit= scene->obedit;
-       Curve *cu;
+static EnumPropertyItem case_items[]= {
+       {CASE_LOWER, "LOWER", "Lower", ""},
+       {CASE_UPPER, "UPPER", "Upper", ""},
+       {0, NULL, NULL, NULL}};
 
-       if (obedit && obedit->type==OB_FONT) return;
-// XXX check_editmode(OB_FONT);
-       
-// XXX add_object_draw(OB_FONT);
-       ED_object_base_init_from_view(NULL, BASACT); // XXX
-       
-       where_is_object(scene, BASACT->object);
-       
-       cu= BASACT->object->data;
-       
-       cu->vfont= cu->vfontb= cu->vfonti= cu->vfontbi= get_builtin_font();
-       cu->vfont->id.us+=4;
-       cu->str= MEM_mallocN(12, "str");
-       strcpy(cu->str, "Text");
-       cu->pos= 4;
-       cu->strinfo= MEM_callocN(12*sizeof(CharInfo), "strinfo");
-       cu->totbox= cu->actbox= 1;
-       cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "textbox");
-       cu->tb[0].w = cu->tb[0].h = 0.0;
-       
-//     if (U.flag & USER_ADD_EDITMODE) 
-//             enter_editmode(EM_WAITCURSOR);
-
-}
-
-void to_upper(Scene *scene)
+static int set_case(bContext *C, int ccase)
 {
-       Object *obedit= scene->obedit; // XXX
+       Scene *scene= CTX_data_scene(C);
+       Object *obedit= CTX_data_edit_object(C);
        Curve *cu= obedit->data;
        EditFont *ef= cu->editfont;
-       int len, ok;
        wchar_t *str;
-       
-       if(obedit==0) {
-               return;
-       }
-       
-       ok= 0;
-       cu= obedit->data;
+       int len;
        
        len= wcslen(ef->textbuf);
        str= ef->textbuf;
        while(len) {
-               if( *str>=97 && *str<=122) {
-                       ok= 1;
+               if(*str>='a' && *str<='z')
                        *str-= 32;
-               }
                len--;
                str++;
        }
        
-       if(ok==0) {
+       if(ccase == CASE_LOWER) {
                len= wcslen(ef->textbuf);
                str= ef->textbuf;
                while(len) {
-                       if( *str>=65 && *str<=90) {
+                       if(*str>='A' && *str<='Z') {
                                *str+= 32;
                        }
                        len--;
                        str++;
                }
        }
-       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
 
-       update_string(cu);
+       text_update_edited(C, scene, obedit, 1, 0);
+
+       return OPERATOR_FINISHED;
+}
+
+static int set_case_exec(bContext *C, wmOperator *op)
+{
+       return set_case(C, RNA_enum_get(op->ptr, "case"));
+}
+
+void FONT_OT_set_case(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Set Case";
+       ot->idname= "FONT_OT_set_case";
+       
+       /* api callbacks */
+       ot->exec= set_case_exec;
+       ot->poll= ED_operator_editfont;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case.");
+}
+
+/********************** toggle case operator *********************/
+
+static int toggle_case_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       Curve *cu= obedit->data;
+       EditFont *ef= cu->editfont;
+       wchar_t *str;
+       int len, ccase= CASE_UPPER;
+       
+       len= wcslen(ef->textbuf);
+       str= ef->textbuf;
+       while(len) {
+               if(*str>='a' && *str<='z') {
+                       ccase= CASE_LOWER;
+                       break;
+               }
+
+               len--;
+               str++;
+       }
+       
+       return set_case(C, ccase);
 }
 
+void FONT_OT_toggle_case(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Toggle Case";
+       ot->idname= "FONT_OT_toggle_case";
+       
+       /* api callbacks */
+       ot->exec= toggle_case_exec;
+       ot->poll= ED_operator_editfont;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
 
 /* **************** undo for font object ************** */
 
@@ -1258,7 +1668,6 @@ static void undoFont_to_editFont(void *strv, void *ecu)
        cu->selstart = cu->selend = 0;
        
        update_string(cu);
-       
 }
 
 static void *editFont_to_undoFont(void *ecu)
@@ -1300,6 +1709,3 @@ void undo_push_font(bContext *C, char *name)
        undo_editmode_push(C, name, get_undoFont, free_undoFont, undoFont_to_editFont, editFont_to_undoFont, NULL);
 }
 
-
-
-/***/
index 3d428dbf75407444ea83cf3764272cc393ca166f..b79d69e7d0756ad06e51b3b9a692cee4c73e4257 100644 (file)
@@ -49,13 +49,12 @@ void        free_editNurb   (struct Object *obedit);
 
 void   mouse_nurb              (struct bContext *C, short mval[2], int extend);
 
-struct Nurb *addNurbprim(struct bContext *C, int type, int newname);
+struct Nurb *add_nurbs_primitive(struct bContext *C, int type, int newname);
 
 /* editfont.h */
 void   undo_push_font  (struct bContext *C, char *name);
 void   make_editText   (struct Object *obedit);
 void   load_editText   (struct Object *obedit);
-void   remake_editText (struct Object *obedit);
 void   free_editText   (struct Object *obedit);
 
 #endif /* ED_CURVE_H */
index 3ec472a90855bc98c8eefb442828e0effa172941..d93f0546524b746cf1f9e1598e8dfd311c444b59 100644 (file)
@@ -119,6 +119,7 @@ int         ED_operator_editarmature(struct bContext *C);
 int            ED_operator_editcurve(struct bContext *C);
 int            ED_operator_editsurf(struct bContext *C);
 int            ED_operator_editsurfcurve(struct bContext *C);
+int            ED_operator_editfont(struct bContext *C);
 int            ED_operator_uvedit(struct bContext *C);
 int            ED_operator_uvmap(struct bContext *C);
 int            ED_operator_posemode(struct bContext *C);
index 7826c0b86b22bb53d447830679f289f596fc9803..936508cdc632361f345ab667eae2a96a3fb7fa07 100644 (file)
@@ -217,6 +217,7 @@ void uiMenuItemBooleanO(uiMenuItem *head, const char *name, int icon, char *opna
 void uiMenuItemsEnumO(uiMenuItem *head, char *opname, char *propname);
 void uiMenuItemIntO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, int value);
 void uiMenuItemFloatO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, float value);
+void uiMenuItemStringO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, char *value);
 void uiMenuItemO(uiMenuItem *head, int icon, char *opname);
 
 void uiMenuItemBooleanR(uiMenuItem *head, struct PointerRNA *ptr, char *propname);
index 5bca01ef16d4df6432f14f8339c97ad66ebf0925..5365c3e09f09dbd88d13228aebeac567959d65ab 100644 (file)
@@ -1661,17 +1661,18 @@ static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiPopupBlockHandle *handle,
 /* type, internal */
 #define MENU_ITEM_TITLE                                0
 #define MENU_ITEM_ITEM                         1
-#define MENU_ITEM_OPNAME                       2
-#define MENU_ITEM_OPNAME_BOOL          3
-#define MENU_ITEM_OPNAME_ENUM          4
-#define MENU_ITEM_OPNAME_INT           5
-#define MENU_ITEM_OPNAME_FLOAT         6
-#define MENU_ITEM_RNA_BOOL                     7
-#define MENU_ITEM_RNA_ENUM                     8
-#define MENU_ITEM_LEVEL                                9
-#define MENU_ITEM_LEVEL_OPNAME_ENUM    10
-#define MENU_ITEM_LEVEL_RNA_ENUM       11
-#define MENU_ITEM_SEPARATOR                    12
+#define MENU_ITEM_SEPARATOR                    2
+#define MENU_ITEM_OPNAME                       10
+#define MENU_ITEM_OPNAME_BOOL          11
+#define MENU_ITEM_OPNAME_ENUM          12
+#define MENU_ITEM_OPNAME_INT           13
+#define MENU_ITEM_OPNAME_FLOAT         14
+#define MENU_ITEM_OPNAME_STRING                15
+#define MENU_ITEM_RNA_BOOL                     20
+#define MENU_ITEM_RNA_ENUM                     21
+#define MENU_ITEM_LEVEL                                30
+#define MENU_ITEM_LEVEL_OPNAME_ENUM    31
+#define MENU_ITEM_LEVEL_RNA_ENUM       32
 
 struct uiMenuItem {
        struct uiMenuItem *next, *prev;
@@ -1685,6 +1686,7 @@ struct uiMenuItem {
        
        int retval, enumval, boolval, intval;
        float fltval;
+       char *strval;
        int opcontext;
        uiMenuHandleFunc eventfunc;
        void *argv;
@@ -1878,6 +1880,12 @@ static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiPopupBlockHandle *handle,
                        
                        y1 -= MENU_BUTTON_HEIGHT;
                }
+               else if(item->type==MENU_ITEM_OPNAME_STRING) {
+                       but= uiDefIconTextButO(block, BUTM, item->opname, item->opcontext, item->icon, item->name, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, "");
+                       RNA_string_set(uiButGetOperatorPtrRNA(but), item->propname, item->strval);
+                       
+                       y1 -= MENU_BUTTON_HEIGHT;
+               }
                else if(item->type==MENU_ITEM_OPNAME) {
                        uiDefIconTextButO(block, BUTM, item->opname, item->opcontext, item->icon, NULL, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, NULL);
                        y1 -= MENU_BUTTON_HEIGHT;
@@ -2074,6 +2082,17 @@ void uiMenuItemBooleanO(uiMenuItem *head, const char *name, int icon, char *opna
        item->type = MENU_ITEM_OPNAME_BOOL;
 }
 
+/* single operator item with property */
+void uiMenuItemStringO(uiMenuItem *head, const char *name, int icon, char *opname, char *propname, char *value)
+{
+       uiMenuItem *item= ui_menu_add_item(head, name, icon, 0);
+       
+       item->opname= opname; // static!
+       item->propname= propname; // static!
+       item->strval= value;
+       item->type = MENU_ITEM_OPNAME_STRING;
+}
+
 /* add all operator items with property */
 void uiMenuItemsEnumO(uiMenuItem *head, char *opname, char *propname)
 {
index fa4265e8475b92e8aaa23de6379c03830d188e07..d928f6762fffead9fb00927ee05cbd51e35f8a94 100644 (file)
@@ -442,8 +442,9 @@ static int object_add_curve_exec(bContext *C, wmOperator *op)
        }
        else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
        
-       nu= addNurbprim(C, RNA_enum_get(op->ptr, "type"), newob);
-       editnurb= curve_get_editcurve(CTX_data_edit_object(C));
+       obedit= CTX_data_edit_object(C);
+       nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
+       editnurb= curve_get_editcurve(obedit);
        BLI_addtail(editnurb, nu);
        
        /* userdef */
@@ -513,8 +514,9 @@ static int object_add_surface_exec(bContext *C, wmOperator *op)
        }
        else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
        
-       nu= addNurbprim(C, RNA_enum_get(op->ptr, "type"), newob);
-       editnurb= curve_get_editcurve(CTX_data_edit_object(C));
+       obedit= CTX_data_edit_object(C);
+       nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
+       editnurb= curve_get_editcurve(obedit);
        BLI_addtail(editnurb, nu);
        
        /* userdef */
@@ -545,6 +547,38 @@ void OBJECT_OT_surface_add(wmOperatorType *ot)
        RNA_def_enum(ot->srna, "type", prop_surface_types, 0, "Primitive", "");
 }
 
+static int object_add_text_exec(bContext *C, wmOperator *op)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       
+       if(obedit && obedit->type==OB_FONT)
+               return OPERATOR_CANCELLED;
+
+       object_add_type(C, OB_FONT);
+       obedit= CTX_data_active_object(C);
+
+       if(U.flag & USER_ADD_EDITMODE)
+               ED_object_enter_editmode(C, 0);
+       
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+       
+       return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_text_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Text";
+       ot->idname= "OBJECT_OT_text_add";
+       
+       /* api callbacks */
+       ot->exec= object_add_text_exec;
+       ot->poll= ED_operator_scene_editable;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 static int object_add_armature_exec(bContext *C, wmOperator *op)
 {
        Object *obedit= CTX_data_edit_object(C);
@@ -557,7 +591,7 @@ static int object_add_armature_exec(bContext *C, wmOperator *op)
        }
        else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
        
-       //nu= addNurbprim(C, RNA_enum_get(op->ptr, "type"), newob);
+       //nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
        //editnurb= curve_get_editcurve(CTX_data_edit_object(C));
        //BLI_addtail(editnurb, nu);
        
@@ -593,6 +627,7 @@ static int object_add_primitive_invoke(bContext *C, wmOperator *op, wmEvent *eve
        uiMenuLevelEnumO(head, "OBJECT_OT_mesh_add", "type");
        uiMenuLevelEnumO(head, "OBJECT_OT_curve_add", "type");
        uiMenuLevelEnumO(head, "OBJECT_OT_surface_add", "type");
+       uiMenuItemO(head, 0, "OBJECT_OT_text_add");
        uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_MBALL);
        uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_CAMERA);
        uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_LAMP);
index f1b1c9668032bab7f80a995e9c2c63695e40d56f..e1673cd1bbc18ea25dc457a25250d5dc052ce7b7 100644 (file)
@@ -70,6 +70,7 @@ void OBJECT_OT_delete(struct wmOperatorType *ot);
 void OBJECT_OT_mesh_add(struct wmOperatorType *ot);
 void OBJECT_OT_curve_add(struct wmOperatorType *ot);
 void OBJECT_OT_surface_add(struct wmOperatorType *ot);
+void OBJECT_OT_text_add(struct wmOperatorType *ot);
        /* only used as menu */
 void OBJECT_OT_primitive_add(struct wmOperatorType *ot);
 
index 15515d8abc431e9d9eab88863237dd69231ca6e0..b2fd0bc348128b151bd4ce82c3c72ed0ae2d7209 100644 (file)
@@ -93,6 +93,7 @@ void ED_operatortypes_object(void)
        WM_operatortype_append(OBJECT_OT_delete);
        WM_operatortype_append(OBJECT_OT_mesh_add);
        WM_operatortype_append(OBJECT_OT_curve_add);
+       WM_operatortype_append(OBJECT_OT_text_add);
        WM_operatortype_append(OBJECT_OT_surface_add);
        WM_operatortype_append(OBJECT_OT_object_add);
        WM_operatortype_append(OBJECT_OT_primitive_add);
index da7a4c71b24c24446ccf45be74405fce4c92fa5c..8c997b98b326470775fe9e9b41eeb0e497458660 100644 (file)
@@ -240,9 +240,6 @@ int ED_operator_editsurfcurve(bContext *C)
        if(obedit && ELEM(obedit->type, OB_CURVE, OB_SURF))
                return NULL != ((Curve *)obedit->data)->editnurb;
        return 0;
-
-       // XXX this test was in many tools, still needed?
-       // if(v3d==0 || (v3d->lay & obedit->lay)==0 ) return 0;
 }
 
 
@@ -262,6 +259,14 @@ int ED_operator_editsurf(bContext *C)
        return 0;
 }
 
+int ED_operator_editfont(bContext *C)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       if(obedit && obedit->type==OB_FONT)
+               return NULL != ((Curve *)obedit->data)->editfont;
+       return 0;
+}
+
 /* *************************** action zone operator ************************** */
 
 /* operator state vars used:  
index b41dec913adce97c8e800c0fed43c270af99cedb..d0b0449c0d9fe3baf7385f6966eaaff648d0bc3a 100644 (file)
@@ -3408,149 +3408,43 @@ static uiBlock *view3d_edit_metaballmenu(bContext *C, ARegion *ar, void *arg_unu
        return block;
 }
 
-static void do_view3d_edit_text_charsmenu(bContext *C, void *arg, int event)
+static void view3d_edit_text_charsmenu(bContext *C, uiMenuItem *head, void *arg_unused)
 {
-#if 0
-       switch(event) {
-       case 0: /* copyright */
-               do_textedit(0,0,169);
-               break;
-       case 1: /* registered trademark */
-               do_textedit(0,0,174);
-               break;
-       case 2: /* degree sign */
-               do_textedit(0,0,176);
-               break;
-       case 3: /* Multiplication Sign */
-               do_textedit(0,0,215);
-               break;
-       case 4: /* Circle */
-               do_textedit(0,0,138);
-               break;
-       case 5: /* superscript 1 */
-               do_textedit(0,0,185);
-               break;
-       case 6: /* superscript 2 */
-               do_textedit(0,0,178);
-               break;
-       case 7: /* superscript 3 */
-               do_textedit(0,0,179);
-               break;
-       case 8: /* double >> */
-               do_textedit(0,0,187);
-               break;
-       case 9: /* double << */
-               do_textedit(0,0,171);
-               break;
-       case 10: /* Promillage */
-               do_textedit(0,0,139);
-               break;
-       case 11: /* dutch florin */
-               do_textedit(0,0,164);
-               break;
-       case 12: /* british pound */
-               do_textedit(0,0,163);
-               break;
-       case 13: /* japanese yen*/
-               do_textedit(0,0,165);
-               break;
-       case 14: /* german S */
-               do_textedit(0,0,223);
-               break;
-       case 15: /* spanish question mark */
-               do_textedit(0,0,191);
-               break;
-       case 16: /* spanish exclamation mark */
-               do_textedit(0,0,161);
-               break;
-               }
-#endif
-}
+       /* the character codes are specified in UTF-8 */
 
-static uiBlock *view3d_edit_text_charsmenu(bContext *C, ARegion *ar, void *arg_unused)
-{
-       uiBlock *block;
-       short yco = 20, menuwidth = 120;
+       uiMenuItemStringO(head, "Copyright|Alt C", 0, "FONT_OT_insert_text", "text", "\xC2\xA9");
+       uiMenuItemStringO(head, "Registered Trademark|Alt R", 0, "FONT_OT_insert_text", "text", "\xC2\xAE");
 
-       block= uiBeginBlock(C, ar, "view3d_edit_text_charsmenu", UI_EMBOSSP, UI_HELV);
-       uiBlockSetButmFunc(block, do_view3d_edit_text_charsmenu, NULL);
-       
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Copyright|Alt C",                        0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Registered Trademark|Alt R",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
-       
-       uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
-       
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Degree Sign|Alt G",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Multiplication Sign|Alt x",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Circle|Alt .",                   0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Superscript 1|Alt 1",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Superscript 2|Alt 2",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Superscript 3|Alt 3",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Double >>|Alt >",                        0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Double <<|Alt <",                        0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 9, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Promillage|Alt %",                       0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+       uiMenuSeparator(head);
+
+       uiMenuItemStringO(head, "Degree Sign|Alt G", 0, "FONT_OT_insert_text", "text", "\xC2\xB0");
+       uiMenuItemStringO(head, "Multiplication Sign|Alt x", 0, "FONT_OT_insert_text", "text", "\xC3\x97");
+       uiMenuItemStringO(head, "Circle|Alt .", 0, "FONT_OT_insert_text", "text", "\xC2\x8A");
+       uiMenuItemStringO(head, "Superscript 1|Alt 1", 0, "FONT_OT_insert_text", "text", "\xC2\xB9");
+       uiMenuItemStringO(head, "Superscript 2|Alt 2", 0, "FONT_OT_insert_text", "text", "\xC2\xB2");
+       uiMenuItemStringO(head, "Superscript 3|Alt 3", 0, "FONT_OT_insert_text", "text", "\xC2\xB3");
+       uiMenuItemStringO(head, "Double >>|Alt >", 0, "FONT_OT_insert_text", "text", "\xC2\xBB");
+       uiMenuItemStringO(head, "Double <<|Alt <", 0, "FONT_OT_insert_text", "text", "\xC2\xAB");
+       uiMenuItemStringO(head, "Promillage|Alt %", 0, "FONT_OT_insert_text", "text", "\xE2\x80\xB0");
        
-       uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+       uiMenuSeparator(head);
        
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Dutch Florin|Alt F",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "British Pound|Alt L",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Japanese Yen|Alt Y",                     0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, "");
+       uiMenuItemStringO(head, "Dutch Florin|Alt F", 0, "FONT_OT_insert_text", "text", "\xC2\xA4");
+       uiMenuItemStringO(head, "British Pound|Alt L", 0, "FONT_OT_insert_text", "text", "\xC2\xA3");
+       uiMenuItemStringO(head, "Japanese Yen|Alt Y", 0, "FONT_OT_insert_text", "text", "\xC2\xA5");
        
-       uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+       uiMenuSeparator(head);
        
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "German S|Alt S",                 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Spanish Question Mark|Alt ?",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Spanish Exclamation Mark|Alt !",                 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, "");
-               
-       uiBlockSetDirection(block, UI_RIGHT);
-       uiTextBoundsBlock(block, 60);
-               
-       return block;
+       uiMenuItemStringO(head, "German S|Alt S", 0, "FONT_OT_insert_text", "text", "\xC3\x9F");
+       uiMenuItemStringO(head, "Spanish Question Mark|Alt ?", 0, "FONT_OT_insert_text", "text", "\xC2\xBF");
+       uiMenuItemStringO(head, "Spanish Exclamation Mark|Alt !", 0, "FONT_OT_insert_text", "text", "\xC2\xA1");
 }
 
-static void do_view3d_edit_textmenu(bContext *C, void *arg, int event)
+static void view3d_edit_textmenu(bContext *C, uiMenuItem *head, void *arg_unused)
 {
-#if 0
-       switch(event) {
-                                                                       
-       case 0: /* Undo Editing */
-               remake_editText();
-               break;
-       case 1: /* paste from file buffer */
-               paste_editText();
-               break;
-       }
-#endif
-}
-
-static uiBlock *view3d_edit_textmenu(bContext *C, ARegion *ar, void *arg_unused)
-{
-       uiBlock *block;
-       short yco= 0, menuwidth=120;
-       
-       block= uiBeginBlock(C, ar, "view3d_edit_textmenu", UI_EMBOSSP, UI_HELV);
-       uiBlockSetButmFunc(block, do_view3d_edit_textmenu, NULL);
-       
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Undo Editing|U",         0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, "");
-       
-       uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
-       
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Paste From Buffer File|Alt V",                   0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
-       
-       uiDefBut(block, SEPR, 0, "",                            0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
-       
-       uiDefIconTextBlockBut(block, view3d_edit_text_charsmenu, NULL, ICON_RIGHTARROW_THIN, "Special Characters", 0, yco-=20, 120, 19, "");
-
-       if(ar->alignment==RGN_ALIGN_TOP) {
-               uiBlockSetDirection(block, UI_DOWN);
-       }
-       else {
-               uiBlockSetDirection(block, UI_TOP);
-               uiBlockFlipOrder(block);
-       }
-
-       uiTextBoundsBlock(block, 50);
-       return block;
+       uiMenuItemO(head, 0, "FONT_OT_paste_file");
+       uiMenuSeparator(head);
+       uiMenuLevel(head, "Special Characters", view3d_edit_text_charsmenu);
 }
 
 static void do_view3d_edit_latticemenu(bContext *C, void *arg, int event)
@@ -3578,9 +3472,6 @@ static void do_view3d_edit_latticemenu(bContext *C, void *arg, int event)
                if(scene->proportional) scene->proportional= 0;
                else scene->proportional= 1;
                break;
-       case 6:
-               uv_autocalc_tface();
-               break;
        case 7: /* delete keyframe */
                common_deletekey();
                break;
@@ -5319,7 +5210,7 @@ static void view3d_header_pulldowns(const bContext *C, uiBlock *block, Object *o
                } else if (ob && (ob->type == OB_CURVE || ob->type == OB_SURF)) {
                        uiDefMenuBut(block, view3d_select_curvemenu, NULL, "Select", xco, yco-2, xmax-3, 24, "");
                } else if (ob && ob->type == OB_FONT) {
-                       uiDefPulldownBut(block, view3d_select_meshmenu, NULL, "Select", xco, yco-2, xmax-3, 24, "");
+                       xmax= 0;
                } else if (ob && ob->type == OB_MBALL) {
                        uiDefPulldownBut(block, view3d_select_metaballmenu, NULL, "Select",     xco,yco-2, xmax-3, 24, "");
                } else if (ob && ob->type == OB_LATTICE) {
@@ -5359,7 +5250,7 @@ static void view3d_header_pulldowns(const bContext *C, uiBlock *block, Object *o
                        xco+= xmax;
                } else if (ob && ob->type == OB_FONT) {
                        xmax= GetButStringLength("Text");
-                       uiDefPulldownBut(block, view3d_edit_textmenu, NULL, "Text",     xco,yco-2, xmax-3, 24, "");
+                       uiDefMenuBut(block, view3d_edit_textmenu, NULL, "Text", xco, yco-2, xmax-3, 24, "");
                        xco+= xmax;
                } else if (ob && ob->type == OB_MBALL) {
                        xmax= GetButStringLength("Metaball");