Holiday coding log :)
[blender.git] / source / blender / editors / space_text / text_ops.c
index f60217ba8ac5604a64b9e504dbced0524c910cc5..83a1bfee0d81d33be7ea27a11d44301e2eea95cc 100644 (file)
@@ -44,6 +44,8 @@
 #include "BLI_blenlib.h"
 #include "BLI_utildefines.h"
 
+#include "BLF_translation.h"
+
 #include "PIL_time.h"
 
 #include "BKE_context.h"
@@ -93,7 +95,7 @@ static int text_edit_poll(bContext *C)
                return 0;
 
        if (text->id.lib) {
-               // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata");
+               // BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata");
                return 0;
        }
 
@@ -109,7 +111,7 @@ static int text_space_edit_poll(bContext *C)
                return 0;
 
        if (text->id.lib) {
-               // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata");
+               // BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata");
                return 0;
        }
 
@@ -129,7 +131,7 @@ static int text_region_edit_poll(bContext *C)
                return 0;
 
        if (text->id.lib) {
-               // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata");
+               // BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata");
                return 0;
        }
 
@@ -167,7 +169,7 @@ static int text_new_exec(bContext *C, wmOperator *UNUSED(op))
        PointerRNA ptr, idptr;
        PropertyRNA *prop;
 
-       text = add_empty_text("Text");
+       text = BKE_text_add("Text");
 
        /* hook into UI */
        uiIDContextProperty(C, &ptr, &prop);
@@ -236,7 +238,7 @@ static int text_open_exec(bContext *C, wmOperator *op)
 
        RNA_string_get(op->ptr, "filepath", str);
 
-       text = add_text(str, G.main->name);
+       text = BKE_text_load(str, G.main->name);
 
        if (!text) {
                if (op->customdata) MEM_freeN(op->customdata);
@@ -310,7 +312,8 @@ void TEXT_OT_open(wmOperatorType *ot)
        ot->flag = OPTYPE_UNDO;
        
        /* properties */
-       WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE | PYSCRIPTFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);  //XXX TODO, relative_path
+       WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE | PYSCRIPTFILE, FILE_SPECIAL, FILE_OPENFILE,
+                                      WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);  //XXX TODO, relative_path
        RNA_def_boolean(ot->srna, "internal", 0, "Make internal", "Make text file internal after loading");
 }
 
@@ -320,7 +323,7 @@ static int text_reload_exec(bContext *C, wmOperator *op)
 {
        Text *text = CTX_data_edit_text(C);
 
-       if (!reopen_text(text)) {
+       if (!BKE_text_reload(text)) {
                BKE_report(op->reports, RPT_ERROR, "Could not reopen file");
                return OPERATOR_CANCELLED;
        }
@@ -379,8 +382,8 @@ static int text_unlink_exec(bContext *C, wmOperator *UNUSED(op))
                }
        }
 
-       unlink_text(bmain, text);
-       free_libblock(&bmain->text, text);
+       BKE_text_unlink(bmain, text);
+       BKE_libblock_free(&bmain->text, text);
 
        text_drawcache_tag_update(st, 1);
        WM_event_add_notifier(C, NC_TEXT | NA_REMOVED, NULL);
@@ -462,7 +465,8 @@ static void txt_write_file(Text *text, ReportList *reports)
        
        fp = BLI_fopen(filepath, "w");
        if (fp == NULL) {
-               BKE_reportf(reports, RPT_ERROR, "Unable to save \"%s\": %s", filepath, errno ? strerror(errno) : "Unknown error writing file");
+               BKE_reportf(reports, RPT_ERROR, "Unable to save '%s': %s",
+                           filepath, errno ? strerror(errno) : TIP_("unknown error writing file"));
                return;
        }
 
@@ -481,7 +485,8 @@ static void txt_write_file(Text *text, ReportList *reports)
        }
        else {
                text->mtime = 0;
-               BKE_reportf(reports, RPT_WARNING, "Unable to stat \"%s\": %s", filepath, errno ? strerror(errno) : "Unknown error starrng file");
+               BKE_reportf(reports, RPT_WARNING, "Unable to stat '%s': %s",
+                           filepath, errno ? strerror(errno) : TIP_("unknown error stating file"));
        }
        
        if (text->flags & TXT_ISDIRTY)
@@ -570,7 +575,8 @@ void TEXT_OT_save_as(wmOperatorType *ot)
        ot->poll = text_edit_poll;
 
        /* properties */
-       WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE | PYSCRIPTFILE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);  //XXX TODO, relative_path
+       WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE | PYSCRIPTFILE, FILE_SPECIAL, FILE_SAVE,
+                                      WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);  //XXX TODO, relative_path
 }
 
 /******************* run script operator *********************/
@@ -600,12 +606,17 @@ static int text_run_script(bContext *C, ReportList *reports)
 
        /* Don't report error messages while live editing */
        if (!is_live) {
-               if (text->curl != curl_prev || curc_prev != text->curc) {
-                       text_update_cursor_moved(C);
-                       WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+               /* text may have freed its self */
+               if (CTX_data_edit_text(C) == text) {
+                       if (text->curl != curl_prev || curc_prev != text->curc) {
+                               text_update_cursor_moved(C);
+                               WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+                       }
                }
 
                BKE_report(reports, RPT_ERROR, "Python script fail, look in the console for now...");
+
+               return OPERATOR_FINISHED;
        }
 #else
        (void)C;
@@ -830,7 +841,7 @@ void TEXT_OT_paste(wmOperatorType *ot)
 
 static int text_duplicate_line_exec(bContext *C, wmOperator *UNUSED(op))
 {
-       Text *text= CTX_data_edit_text(C);
+       Text *text = CTX_data_edit_text(C);
        
        txt_duplicate_line(text);
        
@@ -965,21 +976,17 @@ static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op))
 {
        Text *text = CTX_data_edit_text(C);
 
-       if (txt_has_sel(text)) {
-               text_drawcache_tag_update(CTX_wm_space_text(C), 0);
+       text_drawcache_tag_update(CTX_wm_space_text(C), 0);
 
-               txt_order_cursors(text);
-               txt_unindent(text);
+       txt_order_cursors(text);
+       txt_unindent(text);
 
-               text_update_edited(text);
-
-               text_update_cursor_moved(C);
-               WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+       text_update_edited(text);
 
-               return OPERATOR_FINISHED;
-       }
+       text_update_cursor_moved(C);
+       WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
 
-       return OPERATOR_CANCELLED;
+       return OPERATOR_FINISHED;
 }
 
 void TEXT_OT_unindent(wmOperatorType *ot)
@@ -1130,7 +1137,8 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
        
        tmp = text->lines.first;
        
-       //first convert to all space, this make it a lot easier to convert to tabs because there is no mixtures of ' ' && '\t'
+       /* first convert to all space, this make it a lot easier to convert to tabs
+        * because there is no mixtures of ' ' && '\t' */
        while (tmp) {
                text_check_line = tmp->line;
                number = flatten_string(st, &fs, text_check_line) + 1;
@@ -1156,7 +1164,7 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
                        }
                        else {
                                new_line[j] = text_check_line[a];
-                               ++j;
+                               j++;
                        }
                }
                new_line[j] = '\0';
@@ -1208,12 +1216,12 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
                                        if (!number) { //found all number of space to equal a tab
                                                new_line[extra] = '\t';
                                                a = a + (st->tabnumber - 1);
-                                               ++extra;
+                                               extra++;
                                                
                                        }
                                        else { //not adding a tab
                                                new_line[extra] = text_check_line[a];
-                                               ++extra;
+                                               extra++;
                                        }
                                }
                                new_line[extra] = '\0';
@@ -1331,102 +1339,44 @@ void TEXT_OT_select_word(wmOperatorType *ot)
        ot->poll = text_edit_poll;
 }
 
-/******************* previous marker operator *********************/
+/********************* move lines operators ***********************/
 
-static int text_previous_marker_exec(bContext *C, wmOperator *UNUSED(op))
+static int move_lines_exec(bContext *C, wmOperator *op)
 {
        Text *text = CTX_data_edit_text(C);
-       TextMarker *mrk;
-       int lineno;
-
-       lineno = txt_get_span(text->lines.first, text->curl);
-       mrk = text->markers.last;
-       while (mrk && (mrk->lineno > lineno || (mrk->lineno == lineno && mrk->end > text->curc)))
-               mrk = mrk->prev;
-       if (!mrk) mrk = text->markers.last;
-       if (mrk) {
-               txt_move_to(text, mrk->lineno, mrk->start, 0);
-               txt_move_to(text, mrk->lineno, mrk->end, 1);
-       }
-
-       text_update_cursor_moved(C);
-       WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
-
-       return OPERATOR_FINISHED;
-}
-
-void TEXT_OT_previous_marker(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name = "Previous Marker";
-       ot->idname = "TEXT_OT_previous_marker";
-       ot->description = "Move to previous marker";
+       const int direction = RNA_enum_get(op->ptr, "direction");
        
-       /* api callbacks */
-       ot->exec = text_previous_marker_exec;
-       ot->poll = text_edit_poll;
-}
-
-/******************* next marker operator *********************/
-
-static int text_next_marker_exec(bContext *C, wmOperator *UNUSED(op))
-{
-       Text *text = CTX_data_edit_text(C);
-       TextMarker *mrk;
-       int lineno;
-
-       lineno = txt_get_span(text->lines.first, text->curl);
-       mrk = text->markers.first;
-       while (mrk && (mrk->lineno < lineno || (mrk->lineno == lineno && mrk->start <= text->curc)))
-               mrk = mrk->next;
-       if (!mrk) mrk = text->markers.first;
-       if (mrk) {
-               txt_move_to(text, mrk->lineno, mrk->start, 0);
-               txt_move_to(text, mrk->lineno, mrk->end, 1);
-       }
-
-       text_update_cursor_moved(C);
-       WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
-
-       return OPERATOR_FINISHED;
-}
-
-void TEXT_OT_next_marker(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name = "Next Marker";
-       ot->idname = "TEXT_OT_next_marker";
-       ot->description = "Move to next marker";
+       txt_move_lines(text, direction);
        
-       /* api callbacks */
-       ot->exec = text_next_marker_exec;
-       ot->poll = text_edit_poll;
-}
-
-/******************* clear all markers operator *********************/
-
-static int text_clear_all_markers_exec(bContext *C, wmOperator *UNUSED(op))
-{
-       Text *text = CTX_data_edit_text(C);
-
-       txt_clear_markers(text, 0, 0);
-
        text_update_cursor_moved(C);
        WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
 
+       /* run the script while editing, evil but useful */
+       if (CTX_wm_space_text(C)->live_edit)
+               text_run_script(C, NULL);
+       
        return OPERATOR_FINISHED;
 }
 
-void TEXT_OT_markers_clear(wmOperatorType *ot)
+void TEXT_OT_move_lines(wmOperatorType *ot)
 {
+       static EnumPropertyItem direction_items[] = {
+               {TXT_MOVE_LINE_UP, "UP", 0, "Up", ""},
+               {TXT_MOVE_LINE_DOWN, "DOWN", 0, "Down", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
        /* identifiers */
-       ot->name = "Clear All Markers";
-       ot->idname = "TEXT_OT_markers_clear";
-       ot->description = "Clear all markers";
+       ot->name = "Move Lines";
+       ot->idname = "TEXT_OT_move_lines";
+       ot->description = "Move the currently selected line(s) up/down";
        
        /* api callbacks */
-       ot->exec = text_clear_all_markers_exec;
+       ot->exec = move_lines_exec;
        ot->poll = text_edit_poll;
+
+       /* properties */
+       RNA_def_enum(ot->srna, "direction", direction_items, 1, "Direction", "");
 }
 
 /************************ move operator ************************/
@@ -1458,7 +1408,7 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int
        end = max;
        chop = loop = 1;
 
-       for (i = 0, j = 0; loop; j += BLI_str_utf8_size(linein->line + j)) {
+       for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe(linein->line + j)) {
                int chars;
                /* Mimic replacement of tabs */
                ch = linein->line[j];
@@ -1619,16 +1569,15 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel)
        Text *text = st->text;
        TextLine **linep;
        int *charp;
-       int oldl, oldc, i, j, max, start, end, endj, chop, loop;
+       int oldc, i, j, max, start, end, endj, chop, loop;
        char ch;
 
        text_update_character_width(st);
 
-       if (sel) linep = &text->sell, charp = &text->selc;
-       else linep = &text->curl, charp = &text->curc;
+       if (sel) { linep = &text->sell; charp = &text->selc; }
+       else     { linep = &text->curl; charp = &text->curc; }
 
        oldc = *charp;
-       oldl = txt_get_span(text->lines.first, *linep);
 
        max = wrap_width(st, ar);
 
@@ -1637,7 +1586,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel)
        chop = loop = 1;
        *charp = 0;
 
-       for (i = 0, j = 0; loop; j += BLI_str_utf8_size((*linep)->line + j)) {
+       for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) {
                int chars;
                /* Mimic replacement of tabs */
                ch = (*linep)->line[j];
@@ -1679,7 +1628,6 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel)
        }
 
        if (!sel) txt_pop_sel(text);
-       txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, oldl, *charp);
 }
 
 static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel)
@@ -1687,16 +1635,15 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel)
        Text *text = st->text;
        TextLine **linep;
        int *charp;
-       int oldl, oldc, i, j, max, start, end, endj, chop, loop;
+       int oldc, i, j, max, start, end, endj, chop, loop;
        char ch;
 
        text_update_character_width(st);
 
-       if (sel) linep = &text->sell, charp = &text->selc;
-       else linep = &text->curl, charp = &text->curc;
+       if (sel) { linep = &text->sell; charp = &text->selc; }
+       else     { linep = &text->curl; charp = &text->curc; }
 
        oldc = *charp;
-       oldl = txt_get_span(text->lines.first, *linep);
 
        max = wrap_width(st, ar);
 
@@ -1705,7 +1652,7 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel)
        chop = loop = 1;
        *charp = 0;
 
-       for (i = 0, j = 0; loop; j += BLI_str_utf8_size((*linep)->line + j)) {
+       for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) {
                int chars;
                /* Mimic replacement of tabs */
                ch = (*linep)->line[j];
@@ -1745,7 +1692,6 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel)
        }
 
        if (!sel) txt_pop_sel(text);
-       txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, oldl, *charp);
 }
 
 static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel)
@@ -1753,22 +1699,17 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel)
        Text *text = st->text;
        TextLine **linep;
        int *charp;
-       int oldl, oldc, offl, offc, col, newl;
+       int offl, offc, col;
 
        text_update_character_width(st);
 
-       if (sel) linep = &text->sell, charp = &text->selc;
-       else linep = &text->curl, charp = &text->curc;
-
-       /* store previous position */
-       oldc = *charp;
-       newl = oldl = txt_get_span(text->lines.first, *linep);
+       if (sel) { linep = &text->sell; charp = &text->selc; }
+       else     { linep = &text->curl; charp = &text->curc; }
 
        wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc);
        col = text_get_char_pos(st, (*linep)->line, *charp) + offc;
        if (offl) {
                *charp = text_get_cursor_rel(st, ar, *linep, offl - 1, col);
-               newl = BLI_findindex(&text->lines, linep);
        }
        else {
                if ((*linep)->prev) {
@@ -1777,13 +1718,11 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel)
                        *linep = (*linep)->prev;
                        visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
                        *charp = text_get_cursor_rel(st, ar, *linep, visible_lines - 1, col);
-                       newl--;
                }
                else *charp = 0;
        }
 
        if (!sel) txt_pop_sel(text);
-       txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, newl, *charp);
 }
 
 static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel)
@@ -1791,35 +1730,28 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel)
        Text *text = st->text;
        TextLine **linep;
        int *charp;
-       int oldl, oldc, offl, offc, col, newl, visible_lines;
+       int offl, offc, col, visible_lines;
 
        text_update_character_width(st);
 
-       if (sel) linep = &text->sell, charp = &text->selc;
-       else linep = &text->curl, charp = &text->curc;
-
-       /* store previous position */
-       oldc = *charp;
-       newl = oldl = txt_get_span(text->lines.first, *linep);
+       if (sel) { linep = &text->sell; charp = &text->selc; }
+       else     { linep = &text->curl; charp = &text->curc; }
 
        wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc);
        col = text_get_char_pos(st, (*linep)->line, *charp) + offc;
        visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
        if (offl < visible_lines - 1) {
                *charp = text_get_cursor_rel(st, ar, *linep, offl + 1, col);
-               newl = BLI_findindex(&text->lines, linep);
        }
        else {
                if ((*linep)->next) {
                        *linep = (*linep)->next;
                        *charp = text_get_cursor_rel(st, ar, *linep, 0, col);
-                       newl++;
                }
                else *charp = (*linep)->len;
        }
 
        if (!sel) txt_pop_sel(text);
-       txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, newl, *charp);
 }
 
 /* Moves the cursor vertically by the specified number of lines.
@@ -1831,12 +1763,10 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel)
 static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, int sel)
 {
        TextLine **linep;
-       int oldl, oldc, *charp;
+       int *charp;
        
-       if (sel) linep = &text->sell, charp = &text->selc;
-       else linep = &text->curl, charp = &text->curc;
-       oldl = txt_get_span(text->lines.first, *linep);
-       oldc = *charp;
+       if (sel) { linep = &text->sell; charp = &text->selc; }
+       else     { linep = &text->curl; charp = &text->curc; }
 
        if (st && ar && st->wordwrap) {
                int rell, relc;
@@ -1859,7 +1789,6 @@ static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, int s
        if (*charp > (*linep)->len) *charp = (*linep)->len;
 
        if (!sel) txt_pop_sel(text);
-       txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, *linep), *charp);
 }
 
 static int text_move_cursor(bContext *C, int type, int select)
@@ -1903,7 +1832,7 @@ static int text_move_cursor(bContext *C, int type, int select)
                        txt_move_left(text, select);
                        break;
 
-               case NEXT_CHAR: 
+               case NEXT_CHAR:
                        txt_move_right(text, select);
                        break;
 
@@ -2177,10 +2106,10 @@ static void text_scroll_apply(bContext *C, wmOperator *op, wmEvent *event)
 
        if (!tsc->scrollbar) {
                txtdelta[0] = -tsc->delta[0] / st->cwidth;
-               txtdelta[1] = tsc->delta[1] / st->lheight;
+               txtdelta[1] = tsc->delta[1] / (st->lheight_dpi + TXT_LINE_SPACING);
 
                tsc->delta[0] %= st->cwidth;
-               tsc->delta[1] %= st->lheight;
+               tsc->delta[1] %= (st->lheight_dpi + TXT_LINE_SPACING);
        }
        else {
                txtdelta[1] = -tsc->delta[1] * st->pix_per_line;
@@ -2275,7 +2204,7 @@ static int text_scroll_invoke(bContext *C, wmOperator *op, wmEvent *event)
                tsc->old[1] = event->y;
                /* Sensitivity of scroll set to 4pix per line/char */
                tsc->delta[0] = (event->x - event->prevx) * st->cwidth / 4;
-               tsc->delta[1] = (event->y - event->prevy) * st->lheight / 4;
+               tsc->delta[1] = (event->y - event->prevy) * st->lheight_dpi / 4;
                tsc->first = 0;
                tsc->scrollbar = 0;
                text_scroll_apply(C, op, event);
@@ -2367,8 +2296,8 @@ static int text_scroll_bar_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
        /* jump scroll, works in v2d but needs to be added here too :S */
        if (event->type == MIDDLEMOUSE) {
-               tsc->old[0] = ar->winrct.xmin + (st->txtbar.xmax + st->txtbar.xmin) / 2;
-               tsc->old[1] = ar->winrct.ymin + (st->txtbar.ymax + st->txtbar.ymin) / 2;
+               tsc->old[0] = ar->winrct.xmin + BLI_rcti_cent_x(&st->txtbar);
+               tsc->old[1] = ar->winrct.ymin + BLI_rcti_cent_y(&st->txtbar);
 
                tsc->delta[0] = 0;
                tsc->delta[1] = 0;
@@ -2417,7 +2346,7 @@ static int flatten_len(SpaceText *st, const char *str)
 {
        int i, total = 0;
 
-       for (i = 0; str[i]; i += BLI_str_utf8_size(str + i)) {
+       for (i = 0; str[i]; i += BLI_str_utf8_size_safe(str + i)) {
                if (str[i] == '\t') {
                        total += st->tabnumber - total % st->tabnumber;
                }
@@ -2430,7 +2359,7 @@ static int flatten_len(SpaceText *st, const char *str)
 static int flatten_index_to_offset(SpaceText *st, const char *str, int index)
 {
        int i, j;
-       for (i = 0, j = 0; i < index; j += BLI_str_utf8_size(str + j))
+       for (i = 0, j = 0; i < index; j += BLI_str_utf8_size_safe(str + j))
                if (str[j] == '\t')
                        i += st->tabnumber - i % st->tabnumber;
                else
@@ -2474,7 +2403,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
                int j = 0, curs = 0, endj = 0;   /* mem */
                int chop = 1;                    /* flags */
                
-               for (; loop; j += BLI_str_utf8_size(linep->line + j)) {
+               for (; loop; j += BLI_str_utf8_size_safe(linep->line + j)) {
                        int chars;
                        
                        /* Mimic replacement of tabs */
@@ -2566,7 +2495,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in
 
        if (linep && charp != -1) {
                if (sel) { text->sell = linep; text->selc = charp; }
-               else { text->curl = linep; text->curc = charp; }
+               else     { text->curl = linep; text->curc = charp; }
        }
 }
 
@@ -2574,7 +2503,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int
 {
        Text *text = st->text;
        text_update_character_width(st);
-       y = (ar->winy - 2 - y) / st->lheight;
+       y = (ar->winy - 2 - y) / (st->lheight_dpi + TXT_LINE_SPACING);
 
        if (st->showlinenrs) x -= TXT_OFFSET + TEXTXLOC;
        else x -= TXT_OFFSET;
@@ -2591,7 +2520,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int
                int w;
                
                if (sel) { linep = &text->sell; charp = &text->selc; }
-               else { linep = &text->curl; charp = &text->curc; }
+               else     { linep = &text->curl; charp = &text->curc; }
                
                y -= txt_get_span(text->lines.first, *linep) - st->top;
                
@@ -2624,7 +2553,7 @@ static void text_cursor_set_apply(bContext *C, wmOperator *op, wmEvent *event)
 
                text_update_cursor_moved(C);
                WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
-       } 
+       }
        else if (!st->wordwrap && (event->mval[0] < 0 || event->mval[0] > ar->winx)) {
                if (event->mval[0] > ar->winx) st->left++;
                else if (event->mval[0] < 0 && st->left > 0) st->left--;
@@ -2634,7 +2563,7 @@ static void text_cursor_set_apply(bContext *C, wmOperator *op, wmEvent *event)
                text_update_cursor_moved(C);
                WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
                // XXX PIL_sleep_ms(10);
-       } 
+       }
        else {
                text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1);
 
@@ -2643,7 +2572,7 @@ static void text_cursor_set_apply(bContext *C, wmOperator *op, wmEvent *event)
 
                ssel->old[0] = event->mval[0];
                ssel->old[1] = event->mval[1];
-       } 
+       }
 }
 
 static void text_cursor_set_exit(bContext *C, wmOperator *op)
@@ -2651,7 +2580,6 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op)
        SpaceText *st = CTX_wm_space_text(C);
        Text *text = st->text;
        SetSelection *ssel = op->customdata;
-       int linep2, charp2;
        char *buffer;
 
        if (txt_has_sel(text)) {
@@ -2660,12 +2588,6 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op)
                MEM_freeN(buffer);
        }
 
-       linep2 = txt_get_span(st->text->lines.first, st->text->sell);
-       charp2 = st->text->selc;
-               
-       if (ssel->sell != linep2 || ssel->selc != charp2)
-               txt_undo_add_toop(st->text, UNDO_STO, ssel->sell, ssel->selc, linep2, charp2);
-
        text_update_cursor_moved(C);
        WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
 
@@ -2741,19 +2663,12 @@ void TEXT_OT_selection_set(wmOperatorType *ot)
 static int text_cursor_set_exec(bContext *C, wmOperator *op)
 {
        SpaceText *st = CTX_wm_space_text(C);
-       Text *text = st->text;
        ARegion *ar = CTX_wm_region(C);
        int x = RNA_int_get(op->ptr, "x");
        int y = RNA_int_get(op->ptr, "y");
-       int oldl, oldc;
-
-       oldl = txt_get_span(text->lines.first, text->curl);
-       oldc = text->curc;
 
        text_cursor_set_to_pos(st, ar, x, y, 0);
 
-       txt_undo_add_toop(text, UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, text->curl), text->curc);
-
        text_update_cursor_moved(C);
        WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
 
@@ -2848,7 +2763,7 @@ static int text_insert_exec(bContext *C, wmOperator *op)
        SpaceText *st = CTX_wm_space_text(C);
        Text *text = CTX_data_edit_text(C);
        char *str;
-       int done = 0;
+       int done = FALSE;
        size_t i = 0;
        unsigned int code;
 
@@ -2888,8 +2803,11 @@ static int text_insert_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
        // if (!RNA_struct_property_is_set(op->ptr, "text")) { /* always set from keymap XXX */
        if (!RNA_string_length(op->ptr, "text")) {
-               /* if alt/ctrl/super are pressed pass through */
-               if (event->ctrl || event->oskey) {
+               /* if alt/ctrl/super are pressed pass through except for utf8 character event
+                * (when input method are used for utf8 inputs, the user may assign key event
+                * including alt/ctrl/super like ctrl+m to commit utf8 string.  in such case,
+                * the modifiers in the utf8 character event make no sense.) */
+               if ((event->ctrl || event->oskey) && !event->utf8_buf[0]) {
                        return OPERATOR_PASS_THROUGH;
                }
                else {
@@ -2897,7 +2815,7 @@ static int text_insert_invoke(bContext *C, wmOperator *op, wmEvent *event)
                        size_t len;
                        
                        if (event->utf8_buf[0]) {
-                               len = BLI_str_utf8_size(event->utf8_buf);
+                               len = BLI_str_utf8_size_safe(event->utf8_buf);
                                memcpy(str, event->utf8_buf, len);
                        }
                        else {
@@ -2942,14 +2860,13 @@ void TEXT_OT_insert(wmOperatorType *ot)
 /* mode */
 #define TEXT_FIND       0
 #define TEXT_REPLACE    1
-#define TEXT_MARK_ALL   2
 
 static int text_find_and_replace(bContext *C, wmOperator *op, short mode)
 {
        Main *bmain = CTX_data_main(C);
        SpaceText *st = CTX_wm_space_text(C);
-       Text *start = NULL, *text = st->text;
-       int flags, first = 1;
+       Text *text = st->text;
+       int flags;
        int found = 0;
        char *tmp;
 
@@ -2958,79 +2875,48 @@ static int text_find_and_replace(bContext *C, wmOperator *op, short mode)
 
        flags = st->flags;
        if (flags & ST_FIND_ALL)
-               flags ^= ST_FIND_WRAP;
+               flags &= ~ST_FIND_WRAP;
 
-       do {
-               int proceed = 0;
+       /* Replace current */
+       if (mode != TEXT_FIND && txt_has_sel(text)) {
+               tmp = txt_sel_to_buf(text);
 
-               if (first) {
-                       if (text->markers.first)
-                               WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+               if (flags & ST_MATCH_CASE) found = strcmp(st->findstr, tmp) == 0;
+               else found = BLI_strcasecmp(st->findstr, tmp) == 0;
 
-                       txt_clear_markers(text, TMARK_GRP_FINDALL, 0);
-               }
-
-               first = 0;
-               
-               /* Replace current */
-               if (mode != TEXT_FIND && txt_has_sel(text)) {
-                       tmp = txt_sel_to_buf(text);
-
-                       if (flags & ST_MATCH_CASE) proceed = strcmp(st->findstr, tmp) == 0;
-                       else proceed = BLI_strcasecmp(st->findstr, tmp) == 0;
-
-                       if (proceed) {
-                               if (mode == TEXT_REPLACE) {
-                                       txt_insert_buf(text, st->replacestr);
-                                       if (text->curl && text->curl->format) {
-                                               MEM_freeN(text->curl->format);
-                                               text->curl->format = NULL;
-                                       }
-                                       text_update_cursor_moved(C);
-                                       WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
-                                       text_drawcache_tag_update(CTX_wm_space_text(C), 1);
-                               }
-                               else if (mode == TEXT_MARK_ALL) {
-                                       unsigned char color[4];
-                                       UI_GetThemeColor4ubv(TH_SHADE2, color);
-
-                                       if (txt_find_marker(text, text->curl, text->selc, TMARK_GRP_FINDALL, 0)) {
-                                               if (tmp) MEM_freeN(tmp), tmp = NULL;
-                                               break;
-                                       }
-
-                                       txt_add_marker(text, text->curl, text->curc, text->selc, color, TMARK_GRP_FINDALL, TMARK_EDITALL);
-                                       text_update_cursor_moved(C);
-                                       WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+               if (found) {
+                       if (mode == TEXT_REPLACE) {
+                               txt_insert_buf(text, st->replacestr);
+                               if (text->curl && text->curl->format) {
+                                       MEM_freeN(text->curl->format);
+                                       text->curl->format = NULL;
                                }
+                               text_update_cursor_moved(C);
+                               WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
+                               text_drawcache_tag_update(CTX_wm_space_text(C), 1);
                        }
-                       MEM_freeN(tmp);
-                       tmp = NULL;
                }
+               MEM_freeN(tmp);
+               tmp = NULL;
+       }
 
-               /* Find next */
-               if (txt_find_string(text, st->findstr, flags & ST_FIND_WRAP, flags & ST_MATCH_CASE)) {
-                       text_update_cursor_moved(C);
-                       WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
-               }
-               else if (flags & ST_FIND_ALL) {
-                       if (text == start) break;
-                       if (!start) start = text;
-                       if (text->id.next)
-                               text = st->text = text->id.next;
-                       else
-                               text = st->text = bmain->text.first;
-                       txt_move_toline(text, 0, 0);
-                       text_update_cursor_moved(C);
-                       WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
-                       first = 1;
-               }
-               else {
-                       if (!found && !proceed) BKE_reportf(op->reports, RPT_ERROR, "Text not found: %s", st->findstr);
-                       break;
-               }
-               found = 1;
-       } while (mode == TEXT_MARK_ALL);
+       /* Find next */
+       if (txt_find_string(text, st->findstr, flags & ST_FIND_WRAP, flags & ST_MATCH_CASE)) {
+               text_update_cursor_moved(C);
+               WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
+       }
+       else if (flags & ST_FIND_ALL) {
+               if (text->id.next)
+                       text = st->text = text->id.next;
+               else
+                       text = st->text = bmain->text.first;
+               txt_move_toline(text, 0, 0);
+               text_update_cursor_moved(C);
+               WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
+       }
+       else {
+               if (!found) BKE_reportf(op->reports, RPT_ERROR, "Text not found: %s", st->findstr);
+       }
 
        return OPERATOR_FINISHED;
 }
@@ -3071,25 +2957,6 @@ void TEXT_OT_replace(wmOperatorType *ot)
        ot->poll = text_space_edit_poll;
 }
 
-/******************* mark all operator *********************/
-
-static int text_mark_all_exec(bContext *C, wmOperator *op)
-{
-       return text_find_and_replace(C, op, TEXT_MARK_ALL);
-}
-
-void TEXT_OT_mark_all(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name = "Mark All";
-       ot->idname = "TEXT_OT_mark_all";
-       ot->description = "Mark all specified text";
-       
-       /* api callbacks */
-       ot->exec = text_mark_all_exec;
-       ot->poll = text_space_edit_poll;
-}
-
 /******************* find set selected *********************/
 
 static int text_find_set_selected_exec(bContext *C, wmOperator *op)
@@ -3304,7 +3171,7 @@ void TEXT_OT_to_3d_object(wmOperatorType *ot)
        /* identifiers */
        ot->name = "To 3D Object";
        ot->idname = "TEXT_OT_to_3d_object";
-       ot->description = "Create 3d text object from active text data block";
+       ot->description = "Create 3D text object from active text data block";
        
        /* api callbacks */
        ot->exec = text_to_3d_object_exec;