diff options
Diffstat (limited to 'source/blender/editors/space_text/text_ops.c')
-rw-r--r-- | source/blender/editors/space_text/text_ops.c | 4689 |
1 files changed, 2416 insertions, 2273 deletions
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 2bf1dff63c1..c069fc600e8 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -21,7 +21,6 @@ * \ingroup sptext */ - #include <string.h> #include <errno.h> @@ -54,7 +53,7 @@ #include "RNA_define.h" #ifdef WITH_PYTHON -#include "BPY_extern.h" +# include "BPY_extern.h" #endif #include "text_intern.h" @@ -64,593 +63,610 @@ static void txt_screen_clamp(SpaceText *st, ARegion *ar); /************************ poll ***************************/ - BLI_INLINE int text_pixel_x_to_column(SpaceText *st, const int x) { - /* add half the char width so mouse cursor selection is inbetween letters */ - return (x + (st->cwidth / 2)) / st->cwidth; + /* add half the char width so mouse cursor selection is inbetween letters */ + return (x + (st->cwidth / 2)) / st->cwidth; } static bool text_new_poll(bContext *UNUSED(C)) { - return 1; + return 1; } static bool text_edit_poll(bContext *C) { - Text *text = CTX_data_edit_text(C); + Text *text = CTX_data_edit_text(C); - if (!text) - return 0; + if (!text) + return 0; - if (ID_IS_LINKED(text)) { - // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data"); - return 0; - } + if (ID_IS_LINKED(text)) { + // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data"); + return 0; + } - return 1; + return 1; } bool text_space_edit_poll(bContext *C) { - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); - if (!st || !text) - return 0; + if (!st || !text) + return 0; - if (ID_IS_LINKED(text)) { - // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data"); - return 0; - } + if (ID_IS_LINKED(text)) { + // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data"); + return 0; + } - return 1; + return 1; } static bool text_region_edit_poll(bContext *C) { - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); - ARegion *ar = CTX_wm_region(C); + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); + ARegion *ar = CTX_wm_region(C); - if (!st || !text) - return 0; + if (!st || !text) + return 0; - if (!ar || ar->regiontype != RGN_TYPE_WINDOW) - return 0; + if (!ar || ar->regiontype != RGN_TYPE_WINDOW) + return 0; - if (ID_IS_LINKED(text)) { - // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data"); - return 0; - } + if (ID_IS_LINKED(text)) { + // BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data"); + return 0; + } - return 1; + return 1; } /********************** updates *********************/ void text_update_line_edited(TextLine *line) { - if (!line) - return; + if (!line) + return; - /* we just free format here, and let it rebuild during draw */ - if (line->format) { - MEM_freeN(line->format); - line->format = NULL; - } + /* we just free format here, and let it rebuild during draw */ + if (line->format) { + MEM_freeN(line->format); + line->format = NULL; + } } void text_update_edited(Text *text) { - TextLine *line; + TextLine *line; - for (line = text->lines.first; line; line = line->next) - text_update_line_edited(line); + for (line = text->lines.first; line; line = line->next) + text_update_line_edited(line); } /******************* new operator *********************/ static int text_new_exec(bContext *C, wmOperator *UNUSED(op)) { - SpaceText *st = CTX_wm_space_text(C); - Main *bmain = CTX_data_main(C); - Text *text; - PointerRNA ptr, idptr; - PropertyRNA *prop; + SpaceText *st = CTX_wm_space_text(C); + Main *bmain = CTX_data_main(C); + Text *text; + PointerRNA ptr, idptr; + PropertyRNA *prop; - text = BKE_text_add(bmain, "Text"); + text = BKE_text_add(bmain, "Text"); - /* hook into UI */ - UI_context_active_but_prop_get_templateID(C, &ptr, &prop); + /* hook into UI */ + UI_context_active_but_prop_get_templateID(C, &ptr, &prop); - if (prop) { - RNA_id_pointer_create(&text->id, &idptr); - RNA_property_pointer_set(&ptr, prop, idptr); - RNA_property_update(C, &ptr, prop); - } - else if (st) { - st->text = text; - st->left = 0; - st->top = 0; - st->scroll_accum[0] = 0.0f; - st->scroll_accum[1] = 0.0f; - text_drawcache_tag_update(st, 1); - } + if (prop) { + RNA_id_pointer_create(&text->id, &idptr); + RNA_property_pointer_set(&ptr, prop, idptr); + RNA_property_update(C, &ptr, prop); + } + else if (st) { + st->text = text; + st->left = 0; + st->top = 0; + st->scroll_accum[0] = 0.0f; + st->scroll_accum[1] = 0.0f; + text_drawcache_tag_update(st, 1); + } - WM_event_add_notifier(C, NC_TEXT | NA_ADDED, text); + WM_event_add_notifier(C, NC_TEXT | NA_ADDED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_new(wmOperatorType *ot) { - /* identifiers */ - ot->name = "New Text"; - ot->idname = "TEXT_OT_new"; - ot->description = "Create a new text data-block"; + /* identifiers */ + ot->name = "New Text"; + ot->idname = "TEXT_OT_new"; + ot->description = "Create a new text data-block"; - /* api callbacks */ - ot->exec = text_new_exec; - ot->poll = text_new_poll; + /* api callbacks */ + ot->exec = text_new_exec; + ot->poll = text_new_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /******************* open operator *********************/ static void text_open_init(bContext *C, wmOperator *op) { - PropertyPointerRNA *pprop; + PropertyPointerRNA *pprop; - op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA"); - UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop); + op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA"); + UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop); } static void text_open_cancel(bContext *UNUSED(C), wmOperator *op) { - MEM_freeN(op->customdata); + MEM_freeN(op->customdata); } static int text_open_exec(bContext *C, wmOperator *op) { - SpaceText *st = CTX_wm_space_text(C); - Main *bmain = CTX_data_main(C); - Text *text; - PropertyPointerRNA *pprop; - PointerRNA idptr; - char str[FILE_MAX]; - const bool internal = RNA_boolean_get(op->ptr, "internal"); + SpaceText *st = CTX_wm_space_text(C); + Main *bmain = CTX_data_main(C); + Text *text; + PropertyPointerRNA *pprop; + PointerRNA idptr; + char str[FILE_MAX]; + const bool internal = RNA_boolean_get(op->ptr, "internal"); - RNA_string_get(op->ptr, "filepath", str); + RNA_string_get(op->ptr, "filepath", str); - text = BKE_text_load_ex(bmain, str, BKE_main_blendfile_path(bmain), internal); + text = BKE_text_load_ex(bmain, str, BKE_main_blendfile_path(bmain), internal); - if (!text) { - if (op->customdata) MEM_freeN(op->customdata); - return OPERATOR_CANCELLED; - } + if (!text) { + if (op->customdata) + MEM_freeN(op->customdata); + return OPERATOR_CANCELLED; + } - if (!op->customdata) - text_open_init(C, op); + if (!op->customdata) + text_open_init(C, op); - /* hook into UI */ - pprop = op->customdata; + /* hook into UI */ + pprop = op->customdata; - id_us_ensure_real(&text->id); + id_us_ensure_real(&text->id); - if (pprop->prop) { - RNA_id_pointer_create(&text->id, &idptr); - RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr); - RNA_property_update(C, &pprop->ptr, pprop->prop); - } - else if (st) { - st->text = text; - st->left = 0; - st->top = 0; - st->scroll_accum[0] = 0.0f; - st->scroll_accum[1] = 0.0f; - } + if (pprop->prop) { + RNA_id_pointer_create(&text->id, &idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr); + RNA_property_update(C, &pprop->ptr, pprop->prop); + } + else if (st) { + st->text = text; + st->left = 0; + st->top = 0; + st->scroll_accum[0] = 0.0f; + st->scroll_accum[1] = 0.0f; + } - text_drawcache_tag_update(st, 1); - WM_event_add_notifier(C, NC_TEXT | NA_ADDED, text); + text_drawcache_tag_update(st, 1); + WM_event_add_notifier(C, NC_TEXT | NA_ADDED, text); - MEM_freeN(op->customdata); + MEM_freeN(op->customdata); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int text_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Main *bmain = CTX_data_main(C); - Text *text = CTX_data_edit_text(C); - const char *path = (text && text->name) ? text->name : BKE_main_blendfile_path(bmain); + Main *bmain = CTX_data_main(C); + Text *text = CTX_data_edit_text(C); + const char *path = (text && text->name) ? text->name : BKE_main_blendfile_path(bmain); - if (RNA_struct_property_is_set(op->ptr, "filepath")) - return text_open_exec(C, op); + if (RNA_struct_property_is_set(op->ptr, "filepath")) + return text_open_exec(C, op); - text_open_init(C, op); - RNA_string_set(op->ptr, "filepath", path); - WM_event_add_fileselect(C, op); + text_open_init(C, op); + RNA_string_set(op->ptr, "filepath", path); + WM_event_add_fileselect(C, op); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } void TEXT_OT_open(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Open Text"; - ot->idname = "TEXT_OT_open"; - ot->description = "Open a new text data-block"; + /* identifiers */ + ot->name = "Open Text"; + ot->idname = "TEXT_OT_open"; + ot->description = "Open a new text data-block"; - /* api callbacks */ - ot->exec = text_open_exec; - ot->invoke = text_open_invoke; - ot->cancel = text_open_cancel; - ot->poll = text_new_poll; + /* api callbacks */ + ot->exec = text_open_exec; + ot->invoke = text_open_invoke; + ot->cancel = text_open_cancel; + ot->poll = text_new_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* properties */ - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT, FILE_SPECIAL, FILE_OPENFILE, - WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); //XXX TODO, relative_path - RNA_def_boolean(ot->srna, "internal", 0, "Make internal", "Make text file internal after loading"); + /* properties */ + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT, + FILE_SPECIAL, + FILE_OPENFILE, + WM_FILESEL_FILEPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); //XXX TODO, relative_path + RNA_def_boolean( + ot->srna, "internal", 0, "Make internal", "Make text file internal after loading"); } /******************* reload operator *********************/ static int text_reload_exec(bContext *C, wmOperator *op) { - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); - ARegion *ar = CTX_wm_region(C); + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); + ARegion *ar = CTX_wm_region(C); - /* store view & cursor state */ - const int orig_top = st->top; - const int orig_curl = BLI_findindex(&text->lines, text->curl); - const int orig_curc = text->curc; + /* store view & cursor state */ + const int orig_top = st->top; + const int orig_curl = BLI_findindex(&text->lines, text->curl); + const int orig_curc = text->curc; - if (!BKE_text_reload(text)) { - BKE_report(op->reports, RPT_ERROR, "Could not reopen file"); - return OPERATOR_CANCELLED; - } + if (!BKE_text_reload(text)) { + BKE_report(op->reports, RPT_ERROR, "Could not reopen file"); + return OPERATOR_CANCELLED; + } #ifdef WITH_PYTHON - if (text->compiled) - BPY_text_free_code(text); + if (text->compiled) + BPY_text_free_code(text); #endif - text_update_edited(text); - text_update_cursor_moved(C); - text_drawcache_tag_update(CTX_wm_space_text(C), 1); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_edited(text); + text_update_cursor_moved(C); + text_drawcache_tag_update(CTX_wm_space_text(C), 1); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - /* return to scroll position */ - st->top = orig_top; - txt_screen_clamp(st, ar); - /* return cursor */ - txt_move_to(text, orig_curl, orig_curc, false); + /* return to scroll position */ + st->top = orig_top; + txt_screen_clamp(st, ar); + /* return cursor */ + txt_move_to(text, orig_curl, orig_curc, false); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_reload(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Reload"; - ot->idname = "TEXT_OT_reload"; - ot->description = "Reload active text data-block from its file"; + /* identifiers */ + ot->name = "Reload"; + ot->idname = "TEXT_OT_reload"; + ot->description = "Reload active text data-block from its file"; - /* api callbacks */ - ot->exec = text_reload_exec; - ot->invoke = WM_operator_confirm; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_reload_exec; + ot->invoke = WM_operator_confirm; + ot->poll = text_edit_poll; } /******************* delete operator *********************/ static bool text_unlink_poll(bContext *C) { - /* it should be possible to unlink texts if they're lib-linked in... */ - return CTX_data_edit_text(C) != NULL; + /* it should be possible to unlink texts if they're lib-linked in... */ + return CTX_data_edit_text(C) != NULL; } static int text_unlink_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); + Main *bmain = CTX_data_main(C); + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); - /* make the previous text active, if its not there make the next text active */ - if (st) { - if (text->id.prev) { - st->text = text->id.prev; - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); - } - else if (text->id.next) { - st->text = text->id.next; - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); - } - } + /* make the previous text active, if its not there make the next text active */ + if (st) { + if (text->id.prev) { + st->text = text->id.prev; + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); + } + else if (text->id.next) { + st->text = text->id.next; + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); + } + } - BKE_id_delete(bmain, text); + BKE_id_delete(bmain, text); - text_drawcache_tag_update(st, 1); - WM_event_add_notifier(C, NC_TEXT | NA_REMOVED, NULL); + text_drawcache_tag_update(st, 1); + WM_event_add_notifier(C, NC_TEXT | NA_REMOVED, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_unlink(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Unlink"; - ot->idname = "TEXT_OT_unlink"; - ot->description = "Unlink active text data-block"; + /* identifiers */ + ot->name = "Unlink"; + ot->idname = "TEXT_OT_unlink"; + ot->description = "Unlink active text data-block"; - /* api callbacks */ - ot->exec = text_unlink_exec; - ot->invoke = WM_operator_confirm; - ot->poll = text_unlink_poll; + /* api callbacks */ + ot->exec = text_unlink_exec; + ot->invoke = WM_operator_confirm; + ot->poll = text_unlink_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /******************* make internal operator *********************/ static int text_make_internal_exec(bContext *C, wmOperator *UNUSED(op)) { - Text *text = CTX_data_edit_text(C); + Text *text = CTX_data_edit_text(C); - text->flags |= TXT_ISMEM | TXT_ISDIRTY; + text->flags |= TXT_ISMEM | TXT_ISDIRTY; - if (text->name) { - MEM_freeN(text->name); - text->name = NULL; - } + if (text->name) { + MEM_freeN(text->name); + text->name = NULL; + } - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_make_internal(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Make Internal"; - ot->idname = "TEXT_OT_make_internal"; - ot->description = "Make active text file internal"; + /* identifiers */ + ot->name = "Make Internal"; + ot->idname = "TEXT_OT_make_internal"; + ot->description = "Make active text file internal"; - /* api callbacks */ - ot->exec = text_make_internal_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_make_internal_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /******************* save operator *********************/ static bool text_save_poll(bContext *C) { - Text *text = CTX_data_edit_text(C); + Text *text = CTX_data_edit_text(C); - if (!text_edit_poll(C)) - return 0; + if (!text_edit_poll(C)) + return 0; - return (text->name != NULL && !(text->flags & TXT_ISMEM)); + return (text->name != NULL && !(text->flags & TXT_ISMEM)); } static void txt_write_file(Main *bmain, Text *text, ReportList *reports) { - FILE *fp; - TextLine *tmp; - BLI_stat_t st; - char filepath[FILE_MAX]; - - BLI_strncpy(filepath, text->name, FILE_MAX); - BLI_path_abs(filepath, BKE_main_blendfile_path(bmain)); - - fp = BLI_fopen(filepath, "w"); - if (fp == NULL) { - BKE_reportf(reports, RPT_ERROR, "Unable to save '%s': %s", - filepath, errno ? strerror(errno) : TIP_("unknown error writing file")); - return; - } - - for (tmp = text->lines.first; tmp; tmp = tmp->next) { - fputs(tmp->line, fp); - if (tmp->next) { - fputc('\n', fp); - } - } - - fclose(fp); - - if (BLI_stat(filepath, &st) == 0) { - text->mtime = st.st_mtime; - - /* report since this can be called from key-shortcuts */ - BKE_reportf(reports, RPT_INFO, "Saved Text '%s'", filepath); - } - else { - text->mtime = 0; - BKE_reportf(reports, RPT_WARNING, "Unable to stat '%s': %s", - filepath, errno ? strerror(errno) : TIP_("unknown error stating file")); - } - - text->flags &= ~TXT_ISDIRTY; + FILE *fp; + TextLine *tmp; + BLI_stat_t st; + char filepath[FILE_MAX]; + + BLI_strncpy(filepath, text->name, FILE_MAX); + BLI_path_abs(filepath, BKE_main_blendfile_path(bmain)); + + fp = BLI_fopen(filepath, "w"); + if (fp == NULL) { + BKE_reportf(reports, + RPT_ERROR, + "Unable to save '%s': %s", + filepath, + errno ? strerror(errno) : TIP_("unknown error writing file")); + return; + } + + for (tmp = text->lines.first; tmp; tmp = tmp->next) { + fputs(tmp->line, fp); + if (tmp->next) { + fputc('\n', fp); + } + } + + fclose(fp); + + if (BLI_stat(filepath, &st) == 0) { + text->mtime = st.st_mtime; + + /* report since this can be called from key-shortcuts */ + BKE_reportf(reports, RPT_INFO, "Saved Text '%s'", filepath); + } + else { + text->mtime = 0; + BKE_reportf(reports, + RPT_WARNING, + "Unable to stat '%s': %s", + filepath, + errno ? strerror(errno) : TIP_("unknown error stating file")); + } + + text->flags &= ~TXT_ISDIRTY; } static int text_save_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Text *text = CTX_data_edit_text(C); + Main *bmain = CTX_data_main(C); + Text *text = CTX_data_edit_text(C); - txt_write_file(bmain, text, op->reports); + txt_write_file(bmain, text, op->reports); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_save(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Save"; - ot->idname = "TEXT_OT_save"; - ot->description = "Save active text data-block"; + /* identifiers */ + ot->name = "Save"; + ot->idname = "TEXT_OT_save"; + ot->description = "Save active text data-block"; - /* api callbacks */ - ot->exec = text_save_exec; - ot->poll = text_save_poll; + /* api callbacks */ + ot->exec = text_save_exec; + ot->poll = text_save_poll; } /******************* save as operator *********************/ static int text_save_as_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Text *text = CTX_data_edit_text(C); - char str[FILE_MAX]; + Main *bmain = CTX_data_main(C); + Text *text = CTX_data_edit_text(C); + char str[FILE_MAX]; - if (!text) - return OPERATOR_CANCELLED; + if (!text) + return OPERATOR_CANCELLED; - RNA_string_get(op->ptr, "filepath", str); + RNA_string_get(op->ptr, "filepath", str); - if (text->name) MEM_freeN(text->name); - text->name = BLI_strdup(str); - text->flags &= ~TXT_ISMEM; + if (text->name) + MEM_freeN(text->name); + text->name = BLI_strdup(str); + text->flags &= ~TXT_ISMEM; - txt_write_file(bmain, text, op->reports); + txt_write_file(bmain, text, op->reports); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int text_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Main *bmain = CTX_data_main(C); - Text *text = CTX_data_edit_text(C); - const char *str; + Main *bmain = CTX_data_main(C); + Text *text = CTX_data_edit_text(C); + const char *str; - if (RNA_struct_property_is_set(op->ptr, "filepath")) - return text_save_as_exec(C, op); + if (RNA_struct_property_is_set(op->ptr, "filepath")) + return text_save_as_exec(C, op); - if (text->name) - str = text->name; - else if (text->flags & TXT_ISMEM) - str = text->id.name + 2; - else - str = BKE_main_blendfile_path(bmain); + if (text->name) + str = text->name; + else if (text->flags & TXT_ISMEM) + str = text->id.name + 2; + else + str = BKE_main_blendfile_path(bmain); - RNA_string_set(op->ptr, "filepath", str); - WM_event_add_fileselect(C, op); + RNA_string_set(op->ptr, "filepath", str); + WM_event_add_fileselect(C, op); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } void TEXT_OT_save_as(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Save As"; - ot->idname = "TEXT_OT_save_as"; - ot->description = "Save active text file with options"; + /* identifiers */ + ot->name = "Save As"; + ot->idname = "TEXT_OT_save_as"; + ot->description = "Save active text file with options"; - /* api callbacks */ - ot->exec = text_save_as_exec; - ot->invoke = text_save_as_invoke; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_save_as_exec; + ot->invoke = text_save_as_invoke; + ot->poll = text_edit_poll; - /* properties */ - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT, FILE_SPECIAL, FILE_SAVE, - WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); //XXX TODO, relative_path + /* properties */ + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_TEXT | FILE_TYPE_PYSCRIPT, + FILE_SPECIAL, + FILE_SAVE, + WM_FILESEL_FILEPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); //XXX TODO, relative_path } /******************* run script operator *********************/ static bool text_run_script_poll(bContext *C) { - return (CTX_data_edit_text(C) != NULL); + return (CTX_data_edit_text(C) != NULL); } static int text_run_script(bContext *C, ReportList *reports) { #ifdef WITH_PYTHON - Text *text = CTX_data_edit_text(C); - const bool is_live = (reports == NULL); - - /* only for comparison */ - void *curl_prev = text->curl; - int curc_prev = text->curc; - - if (BPY_execute_text(C, text, reports, !is_live)) { - if (is_live) { - /* for nice live updates */ - WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); - } - return OPERATOR_FINISHED; - } - - /* Don't report error messages while live editing */ - if (!is_live) { - /* 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 failed, check the message in the system console"); - - return OPERATOR_FINISHED; - } + Text *text = CTX_data_edit_text(C); + const bool is_live = (reports == NULL); + + /* only for comparison */ + void *curl_prev = text->curl; + int curc_prev = text->curc; + + if (BPY_execute_text(C, text, reports, !is_live)) { + if (is_live) { + /* for nice live updates */ + WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); + } + return OPERATOR_FINISHED; + } + + /* Don't report error messages while live editing */ + if (!is_live) { + /* 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 failed, check the message in the system console"); + + return OPERATOR_FINISHED; + } #else - (void)C; - (void)reports; + (void)C; + (void)reports; #endif /* !WITH_PYTHON */ - return OPERATOR_CANCELLED; + return OPERATOR_CANCELLED; } static int text_run_script_exec(bContext *C, wmOperator *op) { #ifndef WITH_PYTHON - (void)C; /* unused */ + (void)C; /* unused */ - BKE_report(op->reports, RPT_ERROR, "Python disabled in this build"); + BKE_report(op->reports, RPT_ERROR, "Python disabled in this build"); - return OPERATOR_CANCELLED; + return OPERATOR_CANCELLED; #else - return text_run_script(C, op->reports); + return text_run_script(C, op->reports); #endif } void TEXT_OT_run_script(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Run Script"; - ot->idname = "TEXT_OT_run_script"; - ot->description = "Run active script"; + /* identifiers */ + ot->name = "Run Script"; + ot->idname = "TEXT_OT_run_script"; + ot->description = "Run active script"; - /* api callbacks */ - ot->poll = text_run_script_poll; - ot->exec = text_run_script_exec; + /* api callbacks */ + ot->poll = text_run_script_poll; + ot->exec = text_run_script_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /******************* refresh pyconstraints operator *********************/ @@ -658,1087 +674,1136 @@ void TEXT_OT_run_script(wmOperatorType *ot) static int text_refresh_pyconstraints_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) { #ifdef WITH_PYTHON -#if 0 - Text *text = CTX_data_edit_text(C); - Object *ob; - bConstraint *con; - short update; - - /* check all pyconstraints */ - for (ob = CTX_data_main(C)->objects.first; ob; ob = ob->id.next) { - update = 0; - if (ob->type == OB_ARMATURE && ob->pose) { - bPoseChannel *pchan; - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - for (con = pchan->constraints.first; con; con = con->next) { - if (con->type == CONSTRAINT_TYPE_PYTHON) { - bPythonConstraint *data = con->data; - if (data->text == text) BPY_pyconstraint_update(ob, con); - update = 1; - - } - } - } - } - for (con = ob->constraints.first; con; con = con->next) { - if (con->type == CONSTRAINT_TYPE_PYTHON) { - bPythonConstraint *data = con->data; - if (data->text == text) BPY_pyconstraint_update(ob, con); - update = 1; - } - } - - if (update) { - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - } - } -#endif +# if 0 + Text *text = CTX_data_edit_text(C); + Object *ob; + bConstraint *con; + short update; + + /* check all pyconstraints */ + for (ob = CTX_data_main(C)->objects.first; ob; ob = ob->id.next) { + update = 0; + if (ob->type == OB_ARMATURE && ob->pose) { + bPoseChannel *pchan; + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + for (con = pchan->constraints.first; con; con = con->next) { + if (con->type == CONSTRAINT_TYPE_PYTHON) { + bPythonConstraint *data = con->data; + if (data->text == text) BPY_pyconstraint_update(ob, con); + update = 1; + + } + } + } + } + for (con = ob->constraints.first; con; con = con->next) { + if (con->type == CONSTRAINT_TYPE_PYTHON) { + bPythonConstraint *data = con->data; + if (data->text == text) BPY_pyconstraint_update(ob, con); + update = 1; + } + } + + if (update) { + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + } + } +# endif #endif - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_refresh_pyconstraints(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Refresh PyConstraints"; - ot->idname = "TEXT_OT_refresh_pyconstraints"; - ot->description = "Refresh all pyconstraints"; + /* identifiers */ + ot->name = "Refresh PyConstraints"; + ot->idname = "TEXT_OT_refresh_pyconstraints"; + ot->description = "Refresh all pyconstraints"; - /* api callbacks */ - ot->exec = text_refresh_pyconstraints_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_refresh_pyconstraints_exec; + ot->poll = text_edit_poll; } /******************* paste operator *********************/ static int text_paste_exec(bContext *C, wmOperator *op) { - const bool selection = RNA_boolean_get(op->ptr, "selection"); - Text *text = CTX_data_edit_text(C); - char *buf; - int buf_len; + const bool selection = RNA_boolean_get(op->ptr, "selection"); + Text *text = CTX_data_edit_text(C); + char *buf; + int buf_len; - buf = WM_clipboard_text_get(selection, &buf_len); + buf = WM_clipboard_text_get(selection, &buf_len); - if (!buf) - return OPERATOR_CANCELLED; + if (!buf) + return OPERATOR_CANCELLED; - text_drawcache_tag_update(CTX_wm_space_text(C), 0); + text_drawcache_tag_update(CTX_wm_space_text(C), 0); - TextUndoBuf *utxt = ED_text_undo_push_init(C); - txt_insert_buf(text, utxt, buf); - text_update_edited(text); + TextUndoBuf *utxt = ED_text_undo_push_init(C); + txt_insert_buf(text, utxt, buf); + text_update_edited(text); - MEM_freeN(buf); + MEM_freeN(buf); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + 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); + /* run the script while editing, evil but useful */ + if (CTX_wm_space_text(C)->live_edit) + text_run_script(C, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_paste(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Paste"; - ot->idname = "TEXT_OT_paste"; - ot->description = "Paste text from clipboard"; + /* identifiers */ + ot->name = "Paste"; + ot->idname = "TEXT_OT_paste"; + ot->description = "Paste text from clipboard"; - /* api callbacks */ - ot->exec = text_paste_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_paste_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* properties */ - RNA_def_boolean(ot->srna, "selection", 0, "Selection", "Paste text selected elsewhere rather than copied (X11 only)"); + /* properties */ + RNA_def_boolean(ot->srna, + "selection", + 0, + "Selection", + "Paste text selected elsewhere rather than copied (X11 only)"); } /**************** duplicate operator *******************/ 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); - TextUndoBuf *utxt = ED_text_undo_push_init(C); + TextUndoBuf *utxt = ED_text_undo_push_init(C); - txt_duplicate_line(text, utxt); + txt_duplicate_line(text, utxt); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + 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); - } + /* run the script while editing, evil but useful */ + if (CTX_wm_space_text(C)->live_edit) { + text_run_script(C, NULL); + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_duplicate_line(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Duplicate Line"; - ot->idname = "TEXT_OT_duplicate_line"; - ot->description = "Duplicate the current line"; + /* identifiers */ + ot->name = "Duplicate Line"; + ot->idname = "TEXT_OT_duplicate_line"; + ot->description = "Duplicate the current line"; - /* api callbacks */ - ot->exec = text_duplicate_line_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_duplicate_line_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /******************* copy operator *********************/ static void txt_copy_clipboard(Text *text) { - char *buf; + char *buf; - if (!txt_has_sel(text)) - return; + if (!txt_has_sel(text)) + return; - buf = txt_sel_to_buf(text); + buf = txt_sel_to_buf(text); - if (buf) { - WM_clipboard_text_set(buf, 0); - MEM_freeN(buf); - } + if (buf) { + WM_clipboard_text_set(buf, 0); + MEM_freeN(buf); + } } static int text_copy_exec(bContext *C, wmOperator *UNUSED(op)) { - Text *text = CTX_data_edit_text(C); + Text *text = CTX_data_edit_text(C); - txt_copy_clipboard(text); + txt_copy_clipboard(text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy"; - ot->idname = "TEXT_OT_copy"; - ot->description = "Copy selected text to clipboard"; + /* identifiers */ + ot->name = "Copy"; + ot->idname = "TEXT_OT_copy"; + ot->description = "Copy selected text to clipboard"; - /* api callbacks */ - ot->exec = text_copy_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_copy_exec; + ot->poll = text_edit_poll; } /******************* cut operator *********************/ static int text_cut_exec(bContext *C, wmOperator *UNUSED(op)) { - Text *text = CTX_data_edit_text(C); + Text *text = CTX_data_edit_text(C); - text_drawcache_tag_update(CTX_wm_space_text(C), 0); + text_drawcache_tag_update(CTX_wm_space_text(C), 0); - txt_copy_clipboard(text); + txt_copy_clipboard(text); - TextUndoBuf *utxt = ED_text_undo_push_init(C); - txt_delete_selected(text, utxt); + TextUndoBuf *utxt = ED_text_undo_push_init(C); + txt_delete_selected(text, utxt); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + 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); + /* run the script while editing, evil but useful */ + if (CTX_wm_space_text(C)->live_edit) + text_run_script(C, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_cut(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Cut"; - ot->idname = "TEXT_OT_cut"; - ot->description = "Cut selected text to clipboard"; + /* identifiers */ + ot->name = "Cut"; + ot->idname = "TEXT_OT_cut"; + ot->description = "Cut selected text to clipboard"; - /* api callbacks */ - ot->exec = text_cut_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_cut_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /******************* indent operator *********************/ static int text_indent_exec(bContext *C, wmOperator *UNUSED(op)) { - Text *text = CTX_data_edit_text(C); + Text *text = CTX_data_edit_text(C); - text_drawcache_tag_update(CTX_wm_space_text(C), 0); + text_drawcache_tag_update(CTX_wm_space_text(C), 0); - TextUndoBuf *utxt = ED_text_undo_push_init(C); + TextUndoBuf *utxt = ED_text_undo_push_init(C); - if (txt_has_sel(text)) { - txt_order_cursors(text, false); - txt_indent(text, utxt); - } - else { - txt_add_char(text, utxt, '\t'); - } + if (txt_has_sel(text)) { + txt_order_cursors(text, false); + txt_indent(text, utxt); + } + else { + txt_add_char(text, utxt, '\t'); + } - text_update_edited(text); + text_update_edited(text); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_indent(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Indent"; - ot->idname = "TEXT_OT_indent"; - ot->description = "Indent selected text"; + /* identifiers */ + ot->name = "Indent"; + ot->idname = "TEXT_OT_indent"; + ot->description = "Indent selected text"; - /* api callbacks */ - ot->exec = text_indent_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_indent_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /******************* unindent operator *********************/ static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op)) { - Text *text = CTX_data_edit_text(C); + Text *text = CTX_data_edit_text(C); - text_drawcache_tag_update(CTX_wm_space_text(C), 0); + text_drawcache_tag_update(CTX_wm_space_text(C), 0); - TextUndoBuf *utxt = ED_text_undo_push_init(C); + TextUndoBuf *utxt = ED_text_undo_push_init(C); - txt_order_cursors(text, false); - txt_unindent(text, utxt); + txt_order_cursors(text, false); + txt_unindent(text, utxt); - text_update_edited(text); + text_update_edited(text); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_unindent(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Unindent"; - ot->idname = "TEXT_OT_unindent"; - ot->description = "Unindent selected text"; + /* identifiers */ + ot->name = "Unindent"; + ot->idname = "TEXT_OT_unindent"; + ot->description = "Unindent selected text"; - /* api callbacks */ - ot->exec = text_unindent_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_unindent_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /******************* line break operator *********************/ static int text_line_break_exec(bContext *C, wmOperator *UNUSED(op)) { - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); - int a, curts; - int space = (text->flags & TXT_TABSTOSPACES) ? st->tabnumber : 1; + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); + int a, curts; + int space = (text->flags & TXT_TABSTOSPACES) ? st->tabnumber : 1; - text_drawcache_tag_update(st, 0); + text_drawcache_tag_update(st, 0); - // double check tabs/spaces before splitting the line - curts = txt_setcurr_tab_spaces(text, space); - TextUndoBuf *utxt = ED_text_undo_push_init(C); - txt_split_curline(text, utxt); + // double check tabs/spaces before splitting the line + curts = txt_setcurr_tab_spaces(text, space); + TextUndoBuf *utxt = ED_text_undo_push_init(C); + txt_split_curline(text, utxt); - for (a = 0; a < curts; a++) { - if (text->flags & TXT_TABSTOSPACES) { - txt_add_char(text, utxt, ' '); - } - else { - txt_add_char(text, utxt, '\t'); - } - } + for (a = 0; a < curts; a++) { + if (text->flags & TXT_TABSTOSPACES) { + txt_add_char(text, utxt, ' '); + } + else { + txt_add_char(text, utxt, '\t'); + } + } - if (text->curl) { - if (text->curl->prev) - text_update_line_edited(text->curl->prev); - text_update_line_edited(text->curl); - } + if (text->curl) { + if (text->curl->prev) + text_update_line_edited(text->curl->prev); + text_update_line_edited(text->curl); + } - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_line_break(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Line Break"; - ot->idname = "TEXT_OT_line_break"; - ot->description = "Insert line break at cursor position"; + /* identifiers */ + ot->name = "Line Break"; + ot->idname = "TEXT_OT_line_break"; + ot->description = "Insert line break at cursor position"; - /* api callbacks */ - ot->exec = text_line_break_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_line_break_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /******************* comment operator *********************/ static int text_comment_exec(bContext *C, wmOperator *UNUSED(op)) { - Text *text = CTX_data_edit_text(C); + Text *text = CTX_data_edit_text(C); - if (txt_has_sel(text)) { - text_drawcache_tag_update(CTX_wm_space_text(C), 0); + if (txt_has_sel(text)) { + text_drawcache_tag_update(CTX_wm_space_text(C), 0); - TextUndoBuf *utxt = ED_text_undo_push_init(C); + TextUndoBuf *utxt = ED_text_undo_push_init(C); - txt_order_cursors(text, false); - txt_comment(text, utxt); - text_update_edited(text); + txt_order_cursors(text, false); + txt_comment(text, utxt); + text_update_edited(text); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; - } + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + return OPERATOR_FINISHED; + } - return OPERATOR_CANCELLED; + return OPERATOR_CANCELLED; } void TEXT_OT_comment(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Comment"; - ot->idname = "TEXT_OT_comment"; - ot->description = "Convert selected text to comment"; + /* identifiers */ + ot->name = "Comment"; + ot->idname = "TEXT_OT_comment"; + ot->description = "Convert selected text to comment"; - /* api callbacks */ - ot->exec = text_comment_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_comment_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /******************* uncomment operator *********************/ static int text_uncomment_exec(bContext *C, wmOperator *UNUSED(op)) { - Text *text = CTX_data_edit_text(C); + Text *text = CTX_data_edit_text(C); - if (txt_has_sel(text)) { - text_drawcache_tag_update(CTX_wm_space_text(C), 0); + if (txt_has_sel(text)) { + text_drawcache_tag_update(CTX_wm_space_text(C), 0); - TextUndoBuf *utxt = ED_text_undo_push_init(C); + TextUndoBuf *utxt = ED_text_undo_push_init(C); - txt_order_cursors(text, false); - txt_uncomment(text, utxt); - text_update_edited(text); + txt_order_cursors(text, false); + txt_uncomment(text, utxt); + text_update_edited(text); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; - } + return OPERATOR_FINISHED; + } - return OPERATOR_CANCELLED; + return OPERATOR_CANCELLED; } void TEXT_OT_uncomment(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Uncomment"; - ot->idname = "TEXT_OT_uncomment"; - ot->description = "Convert selected comment to text"; + /* identifiers */ + ot->name = "Uncomment"; + ot->idname = "TEXT_OT_uncomment"; + ot->description = "Convert selected comment to text"; - /* api callbacks */ - ot->exec = text_uncomment_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_uncomment_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /******************* convert whitespace operator *********************/ enum { TO_SPACES, TO_TABS }; static const EnumPropertyItem whitespace_type_items[] = { - {TO_SPACES, "SPACES", 0, "To Spaces", NULL}, - {TO_TABS, "TABS", 0, "To Tabs", NULL}, - {0, NULL, 0, NULL, NULL}, + {TO_SPACES, "SPACES", 0, "To Spaces", NULL}, + {TO_TABS, "TABS", 0, "To Tabs", NULL}, + {0, NULL, 0, NULL, NULL}, }; static int text_convert_whitespace_exec(bContext *C, wmOperator *op) { - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); - TextLine *tmp; - FlattenString fs; - size_t a, j, max_len = 0; - int type = RNA_enum_get(op->ptr, "type"); - - /* first convert to all space, this make it a lot easier to convert to tabs - * because there is no mixtures of ' ' && '\t' */ - for (tmp = text->lines.first; tmp; tmp = tmp->next) { - char *new_line; - - BLI_assert(tmp->line); - - flatten_string(st, &fs, tmp->line); - new_line = BLI_strdup(fs.buf); - flatten_string_free(&fs); - - MEM_freeN(tmp->line); - if (tmp->format) - MEM_freeN(tmp->format); - - /* Put new_line in the tmp->line spot still need to try and set the curc correctly. */ - tmp->line = new_line; - tmp->len = strlen(new_line); - tmp->format = NULL; - if (tmp->len > max_len) { - max_len = tmp->len; - } - } - - if (type == TO_TABS) { - char *tmp_line = MEM_mallocN(sizeof(*tmp_line) * (max_len + 1), __func__); - - for (tmp = text->lines.first; tmp; tmp = tmp->next) { - const char *text_check_line = tmp->line; - const int text_check_line_len = tmp->len; - char *tmp_line_cur = tmp_line; - const size_t tab_len = st->tabnumber; - - BLI_assert(text_check_line); - - for (a = 0; a < text_check_line_len;) { - /* A tab can only start at a position multiple of tab_len... */ - if (!(a % tab_len) && (text_check_line[a] == ' ')) { - /* a + 0 we already know to be ' ' char... */ - for (j = 1; (j < tab_len) && (a + j < text_check_line_len) && (text_check_line[a + j] == ' '); j++); - - if (j == tab_len) { - /* We found a set of spaces that can be replaced by a tab... */ - if ((tmp_line_cur == tmp_line) && a != 0) { - /* Copy all 'valid' string already 'parsed'... */ - memcpy(tmp_line_cur, text_check_line, a); - tmp_line_cur += a; - } - *tmp_line_cur = '\t'; - tmp_line_cur++; - a += j; - } - else { - if (tmp_line_cur != tmp_line) { - memcpy(tmp_line_cur, &text_check_line[a], j); - tmp_line_cur += j; - } - a += j; - } - } - else { - size_t len = BLI_str_utf8_size_safe(&text_check_line[a]); - if (tmp_line_cur != tmp_line) { - memcpy(tmp_line_cur, &text_check_line[a], len); - tmp_line_cur += len; - } - a += len; - } - } - - if (tmp_line_cur != tmp_line) { - *tmp_line_cur = '\0'; + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); + TextLine *tmp; + FlattenString fs; + size_t a, j, max_len = 0; + int type = RNA_enum_get(op->ptr, "type"); + + /* first convert to all space, this make it a lot easier to convert to tabs + * because there is no mixtures of ' ' && '\t' */ + for (tmp = text->lines.first; tmp; tmp = tmp->next) { + char *new_line; + + BLI_assert(tmp->line); + + flatten_string(st, &fs, tmp->line); + new_line = BLI_strdup(fs.buf); + flatten_string_free(&fs); + + MEM_freeN(tmp->line); + if (tmp->format) + MEM_freeN(tmp->format); + + /* Put new_line in the tmp->line spot still need to try and set the curc correctly. */ + tmp->line = new_line; + tmp->len = strlen(new_line); + tmp->format = NULL; + if (tmp->len > max_len) { + max_len = tmp->len; + } + } + + if (type == TO_TABS) { + char *tmp_line = MEM_mallocN(sizeof(*tmp_line) * (max_len + 1), __func__); + + for (tmp = text->lines.first; tmp; tmp = tmp->next) { + const char *text_check_line = tmp->line; + const int text_check_line_len = tmp->len; + char *tmp_line_cur = tmp_line; + const size_t tab_len = st->tabnumber; + + BLI_assert(text_check_line); + + for (a = 0; a < text_check_line_len;) { + /* A tab can only start at a position multiple of tab_len... */ + if (!(a % tab_len) && (text_check_line[a] == ' ')) { + /* a + 0 we already know to be ' ' char... */ + for (j = 1; + (j < tab_len) && (a + j < text_check_line_len) && (text_check_line[a + j] == ' '); + j++) + ; + + if (j == tab_len) { + /* We found a set of spaces that can be replaced by a tab... */ + if ((tmp_line_cur == tmp_line) && a != 0) { + /* Copy all 'valid' string already 'parsed'... */ + memcpy(tmp_line_cur, text_check_line, a); + tmp_line_cur += a; + } + *tmp_line_cur = '\t'; + tmp_line_cur++; + a += j; + } + else { + if (tmp_line_cur != tmp_line) { + memcpy(tmp_line_cur, &text_check_line[a], j); + tmp_line_cur += j; + } + a += j; + } + } + else { + size_t len = BLI_str_utf8_size_safe(&text_check_line[a]); + if (tmp_line_cur != tmp_line) { + memcpy(tmp_line_cur, &text_check_line[a], len); + tmp_line_cur += len; + } + a += len; + } + } + + if (tmp_line_cur != tmp_line) { + *tmp_line_cur = '\0'; #ifndef NDEBUG - BLI_assert(tmp_line_cur - tmp_line <= max_len); + BLI_assert(tmp_line_cur - tmp_line <= max_len); - flatten_string(st, &fs, tmp_line); - BLI_assert(STREQ(fs.buf, tmp->line)); - flatten_string_free(&fs); + flatten_string(st, &fs, tmp_line); + BLI_assert(STREQ(fs.buf, tmp->line)); + flatten_string_free(&fs); #endif - MEM_freeN(tmp->line); - if (tmp->format) - MEM_freeN(tmp->format); + MEM_freeN(tmp->line); + if (tmp->format) + MEM_freeN(tmp->format); - /* Put new_line in the tmp->line spot - * still need to try and set the curc correctly. */ - tmp->line = BLI_strdup(tmp_line); - tmp->len = strlen(tmp_line); - tmp->format = NULL; - } - } + /* Put new_line in the tmp->line spot + * still need to try and set the curc correctly. */ + tmp->line = BLI_strdup(tmp_line); + tmp->len = strlen(tmp_line); + tmp->format = NULL; + } + } - MEM_freeN(tmp_line); - } + MEM_freeN(tmp_line); + } - text_update_edited(text); - text_update_cursor_moved(C); - text_drawcache_tag_update(st, 1); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_edited(text); + text_update_cursor_moved(C); + text_drawcache_tag_update(st, 1); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_convert_whitespace(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Convert Whitespace"; - ot->idname = "TEXT_OT_convert_whitespace"; - ot->description = "Convert whitespaces by type"; + /* identifiers */ + ot->name = "Convert Whitespace"; + ot->idname = "TEXT_OT_convert_whitespace"; + ot->description = "Convert whitespaces by type"; - /* api callbacks */ - ot->exec = text_convert_whitespace_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_convert_whitespace_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* properties */ - RNA_def_enum(ot->srna, "type", whitespace_type_items, TO_SPACES, "Type", "Type of whitespace to convert to"); + /* properties */ + RNA_def_enum(ot->srna, + "type", + whitespace_type_items, + TO_SPACES, + "Type", + "Type of whitespace to convert to"); } /******************* select all operator *********************/ static int text_select_all_exec(bContext *C, wmOperator *UNUSED(op)) { - Text *text = CTX_data_edit_text(C); + Text *text = CTX_data_edit_text(C); - txt_sel_all(text); + txt_sel_all(text); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_select_all(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select All"; - ot->idname = "TEXT_OT_select_all"; - ot->description = "Select all text"; + /* identifiers */ + ot->name = "Select All"; + ot->idname = "TEXT_OT_select_all"; + ot->description = "Select all text"; - /* api callbacks */ - ot->exec = text_select_all_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_select_all_exec; + ot->poll = text_edit_poll; } /******************* select line operator *********************/ static int text_select_line_exec(bContext *C, wmOperator *UNUSED(op)) { - Text *text = CTX_data_edit_text(C); + Text *text = CTX_data_edit_text(C); - txt_sel_line(text); + txt_sel_line(text); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_select_line(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Line"; - ot->idname = "TEXT_OT_select_line"; - ot->description = "Select text by line"; + /* identifiers */ + ot->name = "Select Line"; + ot->idname = "TEXT_OT_select_line"; + ot->description = "Select text by line"; - /* api callbacks */ - ot->exec = text_select_line_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_select_line_exec; + ot->poll = text_edit_poll; } /******************* select word operator *********************/ static int text_select_word_exec(bContext *C, wmOperator *UNUSED(op)) { - Text *text = CTX_data_edit_text(C); - /* don't advance cursor before stepping */ - const bool use_init_step = false; + Text *text = CTX_data_edit_text(C); + /* don't advance cursor before stepping */ + const bool use_init_step = false; - txt_jump_left(text, false, use_init_step); - txt_jump_right(text, true, use_init_step); + txt_jump_left(text, false, use_init_step); + txt_jump_right(text, true, use_init_step); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_select_word(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Word"; - ot->idname = "TEXT_OT_select_word"; - ot->description = "Select word under cursor"; + /* identifiers */ + ot->name = "Select Word"; + ot->idname = "TEXT_OT_select_word"; + ot->description = "Select word under cursor"; - /* api callbacks */ - ot->exec = text_select_word_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_select_word_exec; + ot->poll = text_edit_poll; } /********************* move lines operators ***********************/ static int move_lines_exec(bContext *C, wmOperator *op) { - Text *text = CTX_data_edit_text(C); - const int direction = RNA_enum_get(op->ptr, "direction"); + Text *text = CTX_data_edit_text(C); + const int direction = RNA_enum_get(op->ptr, "direction"); - TextUndoBuf *utxt = ED_text_undo_push_init(C); + TextUndoBuf *utxt = ED_text_undo_push_init(C); - txt_move_lines(text, utxt, direction); + txt_move_lines(text, utxt, direction); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + 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); + /* run the script while editing, evil but useful */ + if (CTX_wm_space_text(C)->live_edit) + text_run_script(C, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_move_lines(wmOperatorType *ot) { - static const EnumPropertyItem direction_items[] = { - {TXT_MOVE_LINE_UP, "UP", 0, "Up", ""}, - {TXT_MOVE_LINE_DOWN, "DOWN", 0, "Down", ""}, - {0, NULL, 0, NULL, NULL}, - }; + static const 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 = "Move Lines"; - ot->idname = "TEXT_OT_move_lines"; - ot->description = "Move the currently selected line(s) up/down"; + /* identifiers */ + ot->name = "Move Lines"; + ot->idname = "TEXT_OT_move_lines"; + ot->description = "Move the currently selected line(s) up/down"; - /* api callbacks */ - ot->exec = move_lines_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = move_lines_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* properties */ - RNA_def_enum(ot->srna, "direction", direction_items, 1, "Direction", ""); + /* properties */ + RNA_def_enum(ot->srna, "direction", direction_items, 1, "Direction", ""); } /************************ move operator ************************/ static const EnumPropertyItem move_type_items[] = { - {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""}, - {LINE_END, "LINE_END", 0, "Line End", ""}, - {FILE_TOP, "FILE_TOP", 0, "File Top", ""}, - {FILE_BOTTOM, "FILE_BOTTOM", 0, "File Bottom", ""}, - {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""}, - {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, - {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""}, - {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""}, - {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""}, - {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""}, - {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""}, - {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""}, - {0, NULL, 0, NULL, NULL}, + {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""}, + {LINE_END, "LINE_END", 0, "Line End", ""}, + {FILE_TOP, "FILE_TOP", 0, "File Top", ""}, + {FILE_BOTTOM, "FILE_BOTTOM", 0, "File Bottom", ""}, + {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""}, + {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, + {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""}, + {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""}, + {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""}, + {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""}, + {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""}, + {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""}, + {0, NULL, 0, NULL, NULL}, }; /* get cursor position in line by relative wrapped line and column positions */ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int rell, int relc) { - int i, j, start, end, max, chop, curs, loop, endj, found, selc; - char ch; - - max = wrap_width(st, ar); - - selc = start = endj = curs = found = 0; - end = max; - chop = loop = 1; - - for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe(linein->line + j)) { - int chars; - int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */ - - /* Mimic replacement of tabs */ - ch = linein->line[j]; - if (ch == '\t') { - chars = st->tabnumber - i % st->tabnumber; - ch = ' '; - } - else { - chars = 1; - } - - while (chars--) { - if (rell == 0 && i - start <= relc && i + columns - start > relc) { - /* current position could be wrapped to next line */ - /* this should be checked when end of current line would be reached */ - selc = j; - found = 1; - } - else if (i - end <= relc && i + columns - end > relc) { - curs = j; - } - if (i + columns - start > max) { - end = MIN2(end, i); - - if (found) { - /* exact cursor position was found, check if it's */ - /* still on needed line (hasn't been wrapped) */ - if (selc > endj && !chop) selc = endj; - loop = 0; - break; - } - - if (chop) endj = j; - - start = end; - end += max; - chop = 1; - rell--; - - if (rell == 0 && i + columns - start > relc) { - selc = curs; - loop = 0; - break; - } - } - else if (ch == '\0') { - if (!found) selc = linein->len; - loop = 0; - break; - } - else if (ch == ' ' || ch == '-') { - if (found) { - loop = 0; - break; - } - - if (rell == 0 && i + columns - start > relc) { - selc = curs; - loop = 0; - break; - } - end = i + 1; - endj = j; - chop = 0; - } - i += columns; - } - } - - return selc; -} - -static int cursor_skip_find_line(SpaceText *st, ARegion *ar, - int lines, TextLine **linep, int *charp, int *rell, int *relc) -{ - int offl, offc, visible_lines; - - wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc); - *relc = text_get_char_pos(st, (*linep)->line, *charp) + offc; - *rell = lines; - - /* handle current line */ - if (lines > 0) { - visible_lines = text_get_visible_lines(st, ar, (*linep)->line); - - if (*rell - visible_lines + offl >= 0) { - if (!(*linep)->next) { - if (offl < visible_lines - 1) { - *rell = visible_lines - 1; - return 1; - } - - *charp = (*linep)->len; - return 0; - } - - *rell -= visible_lines - offl; - *linep = (*linep)->next; - } - else { - *rell += offl; - return 1; - } - } - else { - if (*rell + offl <= 0) { - if (!(*linep)->prev) { - if (offl) { - *rell = 0; - return 1; - } - - *charp = 0; - return 0; - } - - *rell += offl; - *linep = (*linep)->prev; - } - else { - *rell += offl; - return 1; - } - } - - /* skip lines and find destination line and offsets */ - while (*linep) { - visible_lines = text_get_visible_lines(st, ar, (*linep)->line); - - if (lines < 0) { /* moving top */ - if (*rell + visible_lines >= 0) { - *rell += visible_lines; - break; - } - - if (!(*linep)->prev) { - *rell = 0; - break; - } - - *rell += visible_lines; - *linep = (*linep)->prev; - } - else { /* moving bottom */ - if (*rell - visible_lines < 0) break; - - if (!(*linep)->next) { - *rell = visible_lines - 1; - break; - } - - *rell -= visible_lines; - *linep = (*linep)->next; - } - } - - return 1; + int i, j, start, end, max, chop, curs, loop, endj, found, selc; + char ch; + + max = wrap_width(st, ar); + + selc = start = endj = curs = found = 0; + end = max; + chop = loop = 1; + + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe(linein->line + j)) { + int chars; + int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */ + + /* Mimic replacement of tabs */ + ch = linein->line[j]; + if (ch == '\t') { + chars = st->tabnumber - i % st->tabnumber; + ch = ' '; + } + else { + chars = 1; + } + + while (chars--) { + if (rell == 0 && i - start <= relc && i + columns - start > relc) { + /* current position could be wrapped to next line */ + /* this should be checked when end of current line would be reached */ + selc = j; + found = 1; + } + else if (i - end <= relc && i + columns - end > relc) { + curs = j; + } + if (i + columns - start > max) { + end = MIN2(end, i); + + if (found) { + /* exact cursor position was found, check if it's */ + /* still on needed line (hasn't been wrapped) */ + if (selc > endj && !chop) + selc = endj; + loop = 0; + break; + } + + if (chop) + endj = j; + + start = end; + end += max; + chop = 1; + rell--; + + if (rell == 0 && i + columns - start > relc) { + selc = curs; + loop = 0; + break; + } + } + else if (ch == '\0') { + if (!found) + selc = linein->len; + loop = 0; + break; + } + else if (ch == ' ' || ch == '-') { + if (found) { + loop = 0; + break; + } + + if (rell == 0 && i + columns - start > relc) { + selc = curs; + loop = 0; + break; + } + end = i + 1; + endj = j; + chop = 0; + } + i += columns; + } + } + + return selc; +} + +static int cursor_skip_find_line( + SpaceText *st, ARegion *ar, int lines, TextLine **linep, int *charp, int *rell, int *relc) +{ + int offl, offc, visible_lines; + + wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc); + *relc = text_get_char_pos(st, (*linep)->line, *charp) + offc; + *rell = lines; + + /* handle current line */ + if (lines > 0) { + visible_lines = text_get_visible_lines(st, ar, (*linep)->line); + + if (*rell - visible_lines + offl >= 0) { + if (!(*linep)->next) { + if (offl < visible_lines - 1) { + *rell = visible_lines - 1; + return 1; + } + + *charp = (*linep)->len; + return 0; + } + + *rell -= visible_lines - offl; + *linep = (*linep)->next; + } + else { + *rell += offl; + return 1; + } + } + else { + if (*rell + offl <= 0) { + if (!(*linep)->prev) { + if (offl) { + *rell = 0; + return 1; + } + + *charp = 0; + return 0; + } + + *rell += offl; + *linep = (*linep)->prev; + } + else { + *rell += offl; + return 1; + } + } + + /* skip lines and find destination line and offsets */ + while (*linep) { + visible_lines = text_get_visible_lines(st, ar, (*linep)->line); + + if (lines < 0) { /* moving top */ + if (*rell + visible_lines >= 0) { + *rell += visible_lines; + break; + } + + if (!(*linep)->prev) { + *rell = 0; + break; + } + + *rell += visible_lines; + *linep = (*linep)->prev; + } + else { /* moving bottom */ + if (*rell - visible_lines < 0) + break; + + if (!(*linep)->next) { + *rell = visible_lines - 1; + break; + } + + *rell -= visible_lines; + *linep = (*linep)->next; + } + } + + return 1; } static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, const bool sel) { - Text *text = st->text; - TextLine **linep; - int *charp; - 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; } - - oldc = *charp; - - max = wrap_width(st, ar); - - start = endj = 0; - end = max; - chop = loop = 1; - *charp = 0; - - for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { - int chars; - int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */ - - /* Mimic replacement of tabs */ - ch = (*linep)->line[j]; - if (ch == '\t') { - chars = st->tabnumber - i % st->tabnumber; - ch = ' '; - } - else { - chars = 1; - } - - while (chars--) { - if (i + columns - start > max) { - end = MIN2(end, i); - - *charp = endj; - - if (j >= oldc) { - if (ch == '\0') *charp = txt_utf8_column_to_offset((*linep)->line, start); - loop = 0; - break; - } - - if (chop) endj = j; - - start = end; - end += max; - chop = 1; - } - else if (ch == ' ' || ch == '-' || ch == '\0') { - if (j >= oldc) { - *charp = txt_utf8_column_to_offset((*linep)->line, start); - loop = 0; - break; - } - - end = i + 1; - endj = j + 1; - chop = 0; - } - i += columns; - } - } - - if (!sel) txt_pop_sel(text); + Text *text = st->text; + TextLine **linep; + int *charp; + 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; + } + + oldc = *charp; + + max = wrap_width(st, ar); + + start = endj = 0; + end = max; + chop = loop = 1; + *charp = 0; + + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { + int chars; + int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */ + + /* Mimic replacement of tabs */ + ch = (*linep)->line[j]; + if (ch == '\t') { + chars = st->tabnumber - i % st->tabnumber; + ch = ' '; + } + else { + chars = 1; + } + + while (chars--) { + if (i + columns - start > max) { + end = MIN2(end, i); + + *charp = endj; + + if (j >= oldc) { + if (ch == '\0') + *charp = txt_utf8_column_to_offset((*linep)->line, start); + loop = 0; + break; + } + + if (chop) + endj = j; + + start = end; + end += max; + chop = 1; + } + else if (ch == ' ' || ch == '-' || ch == '\0') { + if (j >= oldc) { + *charp = txt_utf8_column_to_offset((*linep)->line, start); + loop = 0; + break; + } + + end = i + 1; + endj = j + 1; + chop = 0; + } + i += columns; + } + } + + if (!sel) + txt_pop_sel(text); } static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, const bool sel) { - Text *text = st->text; - TextLine **linep; - int *charp; - 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; } - - oldc = *charp; - - max = wrap_width(st, ar); - - start = endj = 0; - end = max; - chop = loop = 1; - *charp = 0; - - for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { - int chars; - int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */ - - /* Mimic replacement of tabs */ - ch = (*linep)->line[j]; - if (ch == '\t') { - chars = st->tabnumber - i % st->tabnumber; - ch = ' '; - } - else { - chars = 1; - } - - while (chars--) { - if (i + columns - start > max) { - end = MIN2(end, i); - - if (chop) endj = BLI_str_prev_char_utf8((*linep)->line + j) - (*linep)->line; - - if (endj >= oldc) { - if (ch == '\0') *charp = (*linep)->len; - else *charp = endj; - loop = 0; - break; - } - - start = end; - end += max; - chop = 1; - } - else if (ch == '\0') { - *charp = (*linep)->len; - loop = 0; - break; - } - else if (ch == ' ' || ch == '-') { - end = i + 1; - endj = j; - chop = 0; - } - i += columns; - } - } - - if (!sel) txt_pop_sel(text); + Text *text = st->text; + TextLine **linep; + int *charp; + 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; + } + + oldc = *charp; + + max = wrap_width(st, ar); + + start = endj = 0; + end = max; + chop = loop = 1; + *charp = 0; + + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { + int chars; + int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */ + + /* Mimic replacement of tabs */ + ch = (*linep)->line[j]; + if (ch == '\t') { + chars = st->tabnumber - i % st->tabnumber; + ch = ' '; + } + else { + chars = 1; + } + + while (chars--) { + if (i + columns - start > max) { + end = MIN2(end, i); + + if (chop) + endj = BLI_str_prev_char_utf8((*linep)->line + j) - (*linep)->line; + + if (endj >= oldc) { + if (ch == '\0') + *charp = (*linep)->len; + else + *charp = endj; + loop = 0; + break; + } + + start = end; + end += max; + chop = 1; + } + else if (ch == '\0') { + *charp = (*linep)->len; + loop = 0; + break; + } + else if (ch == ' ' || ch == '-') { + end = i + 1; + endj = j; + chop = 0; + } + i += columns; + } + } + + if (!sel) + txt_pop_sel(text); } static void txt_wrap_move_up(SpaceText *st, ARegion *ar, const bool sel) { - Text *text = st->text; - TextLine **linep; - int *charp; - int offl, offc, col; - - text_update_character_width(st); - - 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); - } - else { - if ((*linep)->prev) { - int visible_lines; - - *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); - } - else { - *charp = 0; - } - } - - if (!sel) txt_pop_sel(text); + Text *text = st->text; + TextLine **linep; + int *charp; + int offl, offc, col; + + text_update_character_width(st); + + 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); + } + else { + if ((*linep)->prev) { + int visible_lines; + + *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); + } + else { + *charp = 0; + } + } + + if (!sel) + txt_pop_sel(text); } static void txt_wrap_move_down(SpaceText *st, ARegion *ar, const bool sel) { - Text *text = st->text; - TextLine **linep; - int *charp; - 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; } - - 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); - } - else { - if ((*linep)->next) { - *linep = (*linep)->next; - *charp = text_get_cursor_rel(st, ar, *linep, 0, col); - } - else { - *charp = (*linep)->len; - } - } - - if (!sel) txt_pop_sel(text); + Text *text = st->text; + TextLine **linep; + int *charp; + 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; + } + + 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); + } + else { + if ((*linep)->next) { + *linep = (*linep)->next; + *charp = text_get_cursor_rel(st, ar, *linep, 0, col); + } + else { + *charp = (*linep)->len; + } + } + + if (!sel) + txt_pop_sel(text); } /* Moves the cursor vertically by the specified number of lines. @@ -1749,1524 +1814,1602 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, const bool sel) */ static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, const bool sel) { - TextLine **linep; - int *charp; - - if (sel) { linep = &text->sell; charp = &text->selc; } - else { linep = &text->curl; charp = &text->curc; } - - if (st && ar && st->wordwrap) { - int rell, relc; - - /* find line and offsets inside it needed to set cursor position */ - if (cursor_skip_find_line(st, ar, lines, linep, charp, &rell, &relc)) - *charp = text_get_cursor_rel(st, ar, *linep, rell, relc); - } - else { - while (lines > 0 && (*linep)->next) { - *linep = (*linep)->next; - lines--; - } - while (lines < 0 && (*linep)->prev) { - *linep = (*linep)->prev; - lines++; - } - } - - if (*charp > (*linep)->len) *charp = (*linep)->len; - - if (!sel) txt_pop_sel(text); + TextLine **linep; + int *charp; + + if (sel) { + linep = &text->sell; + charp = &text->selc; + } + else { + linep = &text->curl; + charp = &text->curc; + } + + if (st && ar && st->wordwrap) { + int rell, relc; + + /* find line and offsets inside it needed to set cursor position */ + if (cursor_skip_find_line(st, ar, lines, linep, charp, &rell, &relc)) + *charp = text_get_cursor_rel(st, ar, *linep, rell, relc); + } + else { + while (lines > 0 && (*linep)->next) { + *linep = (*linep)->next; + lines--; + } + while (lines < 0 && (*linep)->prev) { + *linep = (*linep)->prev; + lines++; + } + } + + if (*charp > (*linep)->len) + *charp = (*linep)->len; + + if (!sel) + txt_pop_sel(text); } static int text_move_cursor(bContext *C, int type, bool select) { - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); - ARegion *ar = CTX_wm_region(C); - - /* ensure we have the right region, it's optional */ - if (ar && ar->regiontype != RGN_TYPE_WINDOW) - ar = NULL; - - switch (type) { - case LINE_BEGIN: - if (!select) { - txt_sel_clear(text); - } - if (st && st->wordwrap && ar) txt_wrap_move_bol(st, ar, select); - else txt_move_bol(text, select); - break; - - case LINE_END: - if (!select) { - txt_sel_clear(text); - } - if (st && st->wordwrap && ar) txt_wrap_move_eol(st, ar, select); - else txt_move_eol(text, select); - break; - - case FILE_TOP: - txt_move_bof(text, select); - break; - - case FILE_BOTTOM: - txt_move_eof(text, select); - break; - - case PREV_WORD: - if (txt_cursor_is_line_start(text)) { - txt_move_left(text, select); - } - txt_jump_left(text, select, true); - break; - - case NEXT_WORD: - if (txt_cursor_is_line_end(text)) { - txt_move_right(text, select); - } - txt_jump_right(text, select, true); - break; - - case PREV_CHAR: - if (txt_has_sel(text) && !select) { - txt_order_cursors(text, false); - txt_pop_sel(text); - } - else { - txt_move_left(text, select); - } - break; - - case NEXT_CHAR: - if (txt_has_sel(text) && !select) { - txt_order_cursors(text, true); - txt_pop_sel(text); - } - else { - txt_move_right(text, select); - } - break; - - case PREV_LINE: - if (st && st->wordwrap && ar) txt_wrap_move_up(st, ar, select); - else txt_move_up(text, select); - break; - - case NEXT_LINE: - if (st && st->wordwrap && ar) txt_wrap_move_down(st, ar, select); - else txt_move_down(text, select); - break; - - case PREV_PAGE: - if (st) cursor_skip(st, ar, st->text, -st->viewlines, select); - else cursor_skip(NULL, NULL, text, -10, select); - break; - - case NEXT_PAGE: - if (st) cursor_skip(st, ar, st->text, st->viewlines, select); - else cursor_skip(NULL, NULL, text, 10, select); - break; - } - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); - - return OPERATOR_FINISHED; + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); + ARegion *ar = CTX_wm_region(C); + + /* ensure we have the right region, it's optional */ + if (ar && ar->regiontype != RGN_TYPE_WINDOW) + ar = NULL; + + switch (type) { + case LINE_BEGIN: + if (!select) { + txt_sel_clear(text); + } + if (st && st->wordwrap && ar) + txt_wrap_move_bol(st, ar, select); + else + txt_move_bol(text, select); + break; + + case LINE_END: + if (!select) { + txt_sel_clear(text); + } + if (st && st->wordwrap && ar) + txt_wrap_move_eol(st, ar, select); + else + txt_move_eol(text, select); + break; + + case FILE_TOP: + txt_move_bof(text, select); + break; + + case FILE_BOTTOM: + txt_move_eof(text, select); + break; + + case PREV_WORD: + if (txt_cursor_is_line_start(text)) { + txt_move_left(text, select); + } + txt_jump_left(text, select, true); + break; + + case NEXT_WORD: + if (txt_cursor_is_line_end(text)) { + txt_move_right(text, select); + } + txt_jump_right(text, select, true); + break; + + case PREV_CHAR: + if (txt_has_sel(text) && !select) { + txt_order_cursors(text, false); + txt_pop_sel(text); + } + else { + txt_move_left(text, select); + } + break; + + case NEXT_CHAR: + if (txt_has_sel(text) && !select) { + txt_order_cursors(text, true); + txt_pop_sel(text); + } + else { + txt_move_right(text, select); + } + break; + + case PREV_LINE: + if (st && st->wordwrap && ar) + txt_wrap_move_up(st, ar, select); + else + txt_move_up(text, select); + break; + + case NEXT_LINE: + if (st && st->wordwrap && ar) + txt_wrap_move_down(st, ar, select); + else + txt_move_down(text, select); + break; + + case PREV_PAGE: + if (st) + cursor_skip(st, ar, st->text, -st->viewlines, select); + else + cursor_skip(NULL, NULL, text, -10, select); + break; + + case NEXT_PAGE: + if (st) + cursor_skip(st, ar, st->text, st->viewlines, select); + else + cursor_skip(NULL, NULL, text, 10, select); + break; + } + + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); + + return OPERATOR_FINISHED; } static int text_move_exec(bContext *C, wmOperator *op) { - int type = RNA_enum_get(op->ptr, "type"); + int type = RNA_enum_get(op->ptr, "type"); - return text_move_cursor(C, type, 0); + return text_move_cursor(C, type, 0); } void TEXT_OT_move(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Move Cursor"; - ot->idname = "TEXT_OT_move"; - ot->description = "Move cursor to position type"; + /* identifiers */ + ot->name = "Move Cursor"; + ot->idname = "TEXT_OT_move"; + ot->description = "Move cursor to position type"; - /* api callbacks */ - ot->exec = text_move_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_move_exec; + ot->poll = text_edit_poll; - /* properties */ - RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to"); + /* properties */ + RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to"); } /******************* move select operator ********************/ static int text_move_select_exec(bContext *C, wmOperator *op) { - int type = RNA_enum_get(op->ptr, "type"); + int type = RNA_enum_get(op->ptr, "type"); - return text_move_cursor(C, type, 1); + return text_move_cursor(C, type, 1); } void TEXT_OT_move_select(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Move Select"; - ot->idname = "TEXT_OT_move_select"; - ot->description = "Move the cursor while selecting"; + /* identifiers */ + ot->name = "Move Select"; + ot->idname = "TEXT_OT_move_select"; + ot->description = "Move the cursor while selecting"; - /* api callbacks */ - ot->exec = text_move_select_exec; - ot->poll = text_space_edit_poll; + /* api callbacks */ + ot->exec = text_move_select_exec; + ot->poll = text_space_edit_poll; - /* properties */ - RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to, to make a selection"); + /* properties */ + RNA_def_enum(ot->srna, + "type", + move_type_items, + LINE_BEGIN, + "Type", + "Where to move cursor to, to make a selection"); } /******************* jump operator *********************/ static int text_jump_exec(bContext *C, wmOperator *op) { - Text *text = CTX_data_edit_text(C); - int line = RNA_int_get(op->ptr, "line"); - short nlines = txt_get_span(text->lines.first, text->lines.last) + 1; + Text *text = CTX_data_edit_text(C); + int line = RNA_int_get(op->ptr, "line"); + short nlines = txt_get_span(text->lines.first, text->lines.last) + 1; - if (line < 1) - txt_move_toline(text, 1, 0); - else if (line > nlines) - txt_move_toline(text, nlines - 1, 0); - else - txt_move_toline(text, line - 1, 0); + if (line < 1) + txt_move_toline(text, 1, 0); + else if (line > nlines) + txt_move_toline(text, nlines - 1, 0); + else + txt_move_toline(text, line - 1, 0); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int text_jump_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - return WM_operator_props_dialog_popup(C, op, 200, 100); - + return WM_operator_props_dialog_popup(C, op, 200, 100); } void TEXT_OT_jump(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Jump"; - ot->idname = "TEXT_OT_jump"; - ot->description = "Jump cursor to line"; + /* identifiers */ + ot->name = "Jump"; + ot->idname = "TEXT_OT_jump"; + ot->description = "Jump cursor to line"; - /* api callbacks */ - ot->invoke = text_jump_invoke; - ot->exec = text_jump_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->invoke = text_jump_invoke; + ot->exec = text_jump_exec; + ot->poll = text_edit_poll; - /* properties */ - prop = RNA_def_int(ot->srna, "line", 1, 1, INT_MAX, "Line", "Line number to jump to", 1, 10000); - RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT); + /* properties */ + prop = RNA_def_int(ot->srna, "line", 1, 1, INT_MAX, "Line", "Line number to jump to", 1, 10000); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT); } /******************* delete operator **********************/ static const EnumPropertyItem delete_type_items[] = { - {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, - {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""}, - {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""}, - {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""}, - {0, NULL, 0, NULL, NULL}, + {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, + {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""}, + {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""}, + {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""}, + {0, NULL, 0, NULL, NULL}, }; static int text_delete_exec(bContext *C, wmOperator *op) { - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); - int type = RNA_enum_get(op->ptr, "type"); - - - text_drawcache_tag_update(st, 0); - - /* behavior could be changed here, - * but for now just don't jump words when we have a selection */ - if (txt_has_sel(text)) { - if (type == DEL_PREV_WORD) type = DEL_PREV_CHAR; - else if (type == DEL_NEXT_WORD) type = DEL_NEXT_CHAR; - } - - TextUndoBuf *utxt = ED_text_undo_push_init(C); - - if (type == DEL_PREV_WORD) { - if (txt_cursor_is_line_start(text)) { - txt_backspace_char(text, utxt); - } - txt_backspace_word(text, utxt); - } - else if (type == DEL_PREV_CHAR) { - - if (text->flags & TXT_TABSTOSPACES) { - if (!txt_has_sel(text) && !txt_cursor_is_line_start(text)) { - int tabsize = 0; - tabsize = txt_calc_tab_left(text->curl, text->curc); - if (tabsize) { - text->sell = text->curl; - text->selc = text->curc - tabsize; - txt_order_cursors(text, false); - } - } - } - - txt_backspace_char(text, utxt); - } - else if (type == DEL_NEXT_WORD) { - if (txt_cursor_is_line_end(text)) { - txt_delete_char(text, utxt); - } - txt_delete_word(text, utxt); - } - else if (type == DEL_NEXT_CHAR) { - - if (text->flags & TXT_TABSTOSPACES) { - if (!txt_has_sel(text) && !txt_cursor_is_line_end(text)) { - int tabsize = 0; - tabsize = txt_calc_tab_right(text->curl, text->curc); - if (tabsize) { - text->sell = text->curl; - text->selc = text->curc + tabsize; - txt_order_cursors(text, true); - } - } - } - - txt_delete_char(text, utxt); - } - - text_update_line_edited(text->curl); - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - /* run the script while editing, evil but useful */ - if (st->live_edit) - text_run_script(C, NULL); - - return OPERATOR_FINISHED; + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); + int type = RNA_enum_get(op->ptr, "type"); + + text_drawcache_tag_update(st, 0); + + /* behavior could be changed here, + * but for now just don't jump words when we have a selection */ + if (txt_has_sel(text)) { + if (type == DEL_PREV_WORD) + type = DEL_PREV_CHAR; + else if (type == DEL_NEXT_WORD) + type = DEL_NEXT_CHAR; + } + + TextUndoBuf *utxt = ED_text_undo_push_init(C); + + if (type == DEL_PREV_WORD) { + if (txt_cursor_is_line_start(text)) { + txt_backspace_char(text, utxt); + } + txt_backspace_word(text, utxt); + } + else if (type == DEL_PREV_CHAR) { + + if (text->flags & TXT_TABSTOSPACES) { + if (!txt_has_sel(text) && !txt_cursor_is_line_start(text)) { + int tabsize = 0; + tabsize = txt_calc_tab_left(text->curl, text->curc); + if (tabsize) { + text->sell = text->curl; + text->selc = text->curc - tabsize; + txt_order_cursors(text, false); + } + } + } + + txt_backspace_char(text, utxt); + } + else if (type == DEL_NEXT_WORD) { + if (txt_cursor_is_line_end(text)) { + txt_delete_char(text, utxt); + } + txt_delete_word(text, utxt); + } + else if (type == DEL_NEXT_CHAR) { + + if (text->flags & TXT_TABSTOSPACES) { + if (!txt_has_sel(text) && !txt_cursor_is_line_end(text)) { + int tabsize = 0; + tabsize = txt_calc_tab_right(text->curl, text->curc); + if (tabsize) { + text->sell = text->curl; + text->selc = text->curc + tabsize; + txt_order_cursors(text, true); + } + } + } + + txt_delete_char(text, utxt); + } + + text_update_line_edited(text->curl); + + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + + /* run the script while editing, evil but useful */ + if (st->live_edit) + text_run_script(C, NULL); + + return OPERATOR_FINISHED; } void TEXT_OT_delete(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Delete"; - ot->idname = "TEXT_OT_delete"; - ot->description = "Delete text by cursor position"; + /* identifiers */ + ot->name = "Delete"; + ot->idname = "TEXT_OT_delete"; + ot->description = "Delete text by cursor position"; - /* api callbacks */ - ot->exec = text_delete_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_delete_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* properties */ - PropertyRNA *prop; - prop = RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete"); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + /* properties */ + PropertyRNA *prop; + prop = RNA_def_enum(ot->srna, + "type", + delete_type_items, + DEL_NEXT_CHAR, + "Type", + "Which part of the text to delete"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /******************* toggle overwrite operator **********************/ static int text_toggle_overwrite_exec(bContext *C, wmOperator *UNUSED(op)) { - SpaceText *st = CTX_wm_space_text(C); + SpaceText *st = CTX_wm_space_text(C); - st->overwrite = !st->overwrite; + st->overwrite = !st->overwrite; - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_overwrite_toggle(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Toggle Overwrite"; - ot->idname = "TEXT_OT_overwrite_toggle"; - ot->description = "Toggle overwrite while typing"; + /* identifiers */ + ot->name = "Toggle Overwrite"; + ot->idname = "TEXT_OT_overwrite_toggle"; + ot->description = "Toggle overwrite while typing"; - /* api callbacks */ - ot->exec = text_toggle_overwrite_exec; - ot->poll = text_space_edit_poll; + /* api callbacks */ + ot->exec = text_toggle_overwrite_exec; + ot->poll = text_space_edit_poll; } /******************* scroll operator **********************/ static void txt_screen_clamp(SpaceText *st, ARegion *ar) { - if (st->top <= 0) { - st->top = 0; - } - else { - int last; - last = text_get_total_lines(st, ar); - last = last - (st->viewlines / 2); - if (last > 0 && st->top > last) { - st->top = last; - } - } + if (st->top <= 0) { + st->top = 0; + } + else { + int last; + last = text_get_total_lines(st, ar); + last = last - (st->viewlines / 2); + if (last > 0 && st->top > last) { + st->top = last; + } + } } /* Moves the view vertically by the specified number of lines */ static void txt_screen_skip(SpaceText *st, ARegion *ar, int lines) { - st->top += lines; - txt_screen_clamp(st, ar); + st->top += lines; + txt_screen_clamp(st, ar); } /* quick enum for tsc->zone (scroller handles) */ enum { - SCROLLHANDLE_BAR, - SCROLLHANDLE_MIN_OUTSIDE, - SCROLLHANDLE_MAX_OUTSIDE, + SCROLLHANDLE_BAR, + SCROLLHANDLE_MIN_OUTSIDE, + SCROLLHANDLE_MAX_OUTSIDE, }; typedef struct TextScroll { - int old[2]; - int delta[2]; + int old[2]; + int delta[2]; - int first; - int scrollbar; + int first; + int scrollbar; - int zone; + int zone; } TextScroll; static bool text_scroll_poll(bContext *C) { - /* it should be possible to still scroll linked texts to read them, - * even if they can't be edited... */ - return CTX_data_edit_text(C) != NULL; + /* it should be possible to still scroll linked texts to read them, + * even if they can't be edited... */ + return CTX_data_edit_text(C) != NULL; } static int text_scroll_exec(bContext *C, wmOperator *op) { - SpaceText *st = CTX_wm_space_text(C); - ARegion *ar = CTX_wm_region(C); + SpaceText *st = CTX_wm_space_text(C); + ARegion *ar = CTX_wm_region(C); - int lines = RNA_int_get(op->ptr, "lines"); + int lines = RNA_int_get(op->ptr, "lines"); - if (lines == 0) - return OPERATOR_CANCELLED; + if (lines == 0) + return OPERATOR_CANCELLED; - txt_screen_skip(st, ar, lines * U.wheellinescroll); + txt_screen_skip(st, ar, lines * U.wheellinescroll); - ED_area_tag_redraw(CTX_wm_area(C)); + ED_area_tag_redraw(CTX_wm_area(C)); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static void text_scroll_apply(bContext *C, wmOperator *op, const wmEvent *event) { - SpaceText *st = CTX_wm_space_text(C); - ARegion *ar = CTX_wm_region(C); - TextScroll *tsc = op->customdata; - int mval[2] = {event->x, event->y}; - int scroll_steps[2] = {0, 0}; - - text_update_character_width(st); - - /* compute mouse move distance */ - if (tsc->first) { - tsc->old[0] = mval[0]; - tsc->old[1] = mval[1]; - tsc->first = 0; - } - - if (event->type != MOUSEPAN) { - tsc->delta[0] = mval[0] - tsc->old[0]; - tsc->delta[1] = mval[1] - tsc->old[1]; - } - - /* accumulate scroll, in float values for events that give less than one - * line offset but taken together should still scroll */ - if (!tsc->scrollbar) { - st->scroll_accum[0] += -tsc->delta[0] / (float)st->cwidth; - st->scroll_accum[1] += tsc->delta[1] / (float)(st->lheight_dpi + TXT_LINE_SPACING); - } - else { - st->scroll_accum[1] += -tsc->delta[1] * st->pix_per_line; - } - - /* round to number of lines to scroll */ - scroll_steps[0] = (int)st->scroll_accum[0]; - scroll_steps[1] = (int)st->scroll_accum[1]; - - st->scroll_accum[0] -= scroll_steps[0]; - st->scroll_accum[1] -= scroll_steps[1]; - - /* perform vertical and/or horizontal scroll */ - if (scroll_steps[0] || scroll_steps[1]) { - txt_screen_skip(st, ar, scroll_steps[1]); - - if (st->wordwrap) { - st->left = 0; - } - else { - st->left += scroll_steps[0]; - if (st->left < 0) st->left = 0; - } - - ED_area_tag_redraw(CTX_wm_area(C)); - } - - tsc->old[0] = mval[0]; - tsc->old[1] = mval[1]; + SpaceText *st = CTX_wm_space_text(C); + ARegion *ar = CTX_wm_region(C); + TextScroll *tsc = op->customdata; + int mval[2] = {event->x, event->y}; + int scroll_steps[2] = {0, 0}; + + text_update_character_width(st); + + /* compute mouse move distance */ + if (tsc->first) { + tsc->old[0] = mval[0]; + tsc->old[1] = mval[1]; + tsc->first = 0; + } + + if (event->type != MOUSEPAN) { + tsc->delta[0] = mval[0] - tsc->old[0]; + tsc->delta[1] = mval[1] - tsc->old[1]; + } + + /* accumulate scroll, in float values for events that give less than one + * line offset but taken together should still scroll */ + if (!tsc->scrollbar) { + st->scroll_accum[0] += -tsc->delta[0] / (float)st->cwidth; + st->scroll_accum[1] += tsc->delta[1] / (float)(st->lheight_dpi + TXT_LINE_SPACING); + } + else { + st->scroll_accum[1] += -tsc->delta[1] * st->pix_per_line; + } + + /* round to number of lines to scroll */ + scroll_steps[0] = (int)st->scroll_accum[0]; + scroll_steps[1] = (int)st->scroll_accum[1]; + + st->scroll_accum[0] -= scroll_steps[0]; + st->scroll_accum[1] -= scroll_steps[1]; + + /* perform vertical and/or horizontal scroll */ + if (scroll_steps[0] || scroll_steps[1]) { + txt_screen_skip(st, ar, scroll_steps[1]); + + if (st->wordwrap) { + st->left = 0; + } + else { + st->left += scroll_steps[0]; + if (st->left < 0) + st->left = 0; + } + + ED_area_tag_redraw(CTX_wm_area(C)); + } + + tsc->old[0] = mval[0]; + tsc->old[1] = mval[1]; } static void scroll_exit(bContext *C, wmOperator *op) { - SpaceText *st = CTX_wm_space_text(C); + SpaceText *st = CTX_wm_space_text(C); - st->flags &= ~ST_SCROLL_SELECT; - MEM_freeN(op->customdata); + st->flags &= ~ST_SCROLL_SELECT; + MEM_freeN(op->customdata); } static int text_scroll_modal(bContext *C, wmOperator *op, const wmEvent *event) { - TextScroll *tsc = op->customdata; - SpaceText *st = CTX_wm_space_text(C); - ARegion *ar = CTX_wm_region(C); - - switch (event->type) { - case MOUSEMOVE: - if (tsc->zone == SCROLLHANDLE_BAR) - text_scroll_apply(C, op, event); - break; - case LEFTMOUSE: - case RIGHTMOUSE: - case MIDDLEMOUSE: - if (event->val == KM_RELEASE) { - if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) { - txt_screen_skip(st, ar, st->viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1)); - - ED_area_tag_redraw(CTX_wm_area(C)); - } - scroll_exit(C, op); - return OPERATOR_FINISHED; - } - } - - return OPERATOR_RUNNING_MODAL; + TextScroll *tsc = op->customdata; + SpaceText *st = CTX_wm_space_text(C); + ARegion *ar = CTX_wm_region(C); + + switch (event->type) { + case MOUSEMOVE: + if (tsc->zone == SCROLLHANDLE_BAR) + text_scroll_apply(C, op, event); + break; + case LEFTMOUSE: + case RIGHTMOUSE: + case MIDDLEMOUSE: + if (event->val == KM_RELEASE) { + if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) { + txt_screen_skip( + st, ar, st->viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1)); + + ED_area_tag_redraw(CTX_wm_area(C)); + } + scroll_exit(C, op); + return OPERATOR_FINISHED; + } + } + + return OPERATOR_RUNNING_MODAL; } static void text_scroll_cancel(bContext *C, wmOperator *op) { - scroll_exit(C, op); + scroll_exit(C, op); } static int text_scroll_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - SpaceText *st = CTX_wm_space_text(C); - TextScroll *tsc; + SpaceText *st = CTX_wm_space_text(C); + TextScroll *tsc; - if (RNA_struct_property_is_set(op->ptr, "lines")) - return text_scroll_exec(C, op); + if (RNA_struct_property_is_set(op->ptr, "lines")) + return text_scroll_exec(C, op); - tsc = MEM_callocN(sizeof(TextScroll), "TextScroll"); - tsc->first = 1; - tsc->zone = SCROLLHANDLE_BAR; - op->customdata = tsc; + tsc = MEM_callocN(sizeof(TextScroll), "TextScroll"); + tsc->first = 1; + tsc->zone = SCROLLHANDLE_BAR; + op->customdata = tsc; - st->flags |= ST_SCROLL_SELECT; + st->flags |= ST_SCROLL_SELECT; - if (event->type == MOUSEPAN) { - text_update_character_width(st); + if (event->type == MOUSEPAN) { + text_update_character_width(st); - tsc->old[0] = event->x; - 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_dpi / 4; - tsc->first = 0; - tsc->scrollbar = 0; - text_scroll_apply(C, op, event); - scroll_exit(C, op); - return OPERATOR_FINISHED; - } + tsc->old[0] = event->x; + 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_dpi / 4; + tsc->first = 0; + tsc->scrollbar = 0; + text_scroll_apply(C, op, event); + scroll_exit(C, op); + return OPERATOR_FINISHED; + } - WM_event_add_modal_handler(C, op); + WM_event_add_modal_handler(C, op); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } void TEXT_OT_scroll(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Scroll"; - /* don't really see the difference between this and - * scroll_bar. Both do basically the same thing (aside - * from keymaps).*/ - ot->idname = "TEXT_OT_scroll"; + /* identifiers */ + ot->name = "Scroll"; + /* don't really see the difference between this and + * scroll_bar. Both do basically the same thing (aside + * from keymaps).*/ + ot->idname = "TEXT_OT_scroll"; - /* api callbacks */ - ot->exec = text_scroll_exec; - ot->invoke = text_scroll_invoke; - ot->modal = text_scroll_modal; - ot->cancel = text_scroll_cancel; - ot->poll = text_scroll_poll; + /* api callbacks */ + ot->exec = text_scroll_exec; + ot->invoke = text_scroll_invoke; + ot->modal = text_scroll_modal; + ot->cancel = text_scroll_cancel; + ot->poll = text_scroll_poll; - /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_INTERNAL; - /* properties */ - RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100); + /* properties */ + RNA_def_int( + ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100); } /******************** scroll bar operator *******************/ static bool text_region_scroll_poll(bContext *C) { - /* same as text_region_edit_poll except it works on libdata too */ - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); - ARegion *ar = CTX_wm_region(C); + /* same as text_region_edit_poll except it works on libdata too */ + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); + ARegion *ar = CTX_wm_region(C); - if (!st || !text) - return 0; + if (!st || !text) + return 0; - if (!ar || ar->regiontype != RGN_TYPE_WINDOW) - return 0; + if (!ar || ar->regiontype != RGN_TYPE_WINDOW) + return 0; - return 1; + return 1; } static int text_scroll_bar_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - SpaceText *st = CTX_wm_space_text(C); - ARegion *ar = CTX_wm_region(C); - TextScroll *tsc; - const int *mval = event->mval; - int zone = -1; - - if (RNA_struct_property_is_set(op->ptr, "lines")) - return text_scroll_exec(C, op); - - /* verify we are in the right zone */ - if (mval[0] > st->txtbar.xmin && mval[0] < st->txtbar.xmax) { - if (mval[1] >= st->txtbar.ymin && mval[1] <= st->txtbar.ymax) { - /* mouse inside scroll handle */ - zone = SCROLLHANDLE_BAR; - } - else if (mval[1] > TXT_SCROLL_SPACE && mval[1] < ar->winy - TXT_SCROLL_SPACE) { - if (mval[1] < st->txtbar.ymin) zone = SCROLLHANDLE_MIN_OUTSIDE; - else zone = SCROLLHANDLE_MAX_OUTSIDE; - } - } - - if (zone == -1) { - /* we are outside slider - nothing to do */ - return OPERATOR_PASS_THROUGH; - } - - tsc = MEM_callocN(sizeof(TextScroll), "TextScroll"); - tsc->first = 1; - tsc->scrollbar = 1; - tsc->zone = zone; - op->customdata = tsc; - st->flags |= ST_SCROLL_SELECT; - - /* jump scroll, works in v2d but needs to be added here too :S */ - if (event->type == MIDDLEMOUSE) { - 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->first = 0; - tsc->zone = SCROLLHANDLE_BAR; - text_scroll_apply(C, op, event); - } - - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; + SpaceText *st = CTX_wm_space_text(C); + ARegion *ar = CTX_wm_region(C); + TextScroll *tsc; + const int *mval = event->mval; + int zone = -1; + + if (RNA_struct_property_is_set(op->ptr, "lines")) + return text_scroll_exec(C, op); + + /* verify we are in the right zone */ + if (mval[0] > st->txtbar.xmin && mval[0] < st->txtbar.xmax) { + if (mval[1] >= st->txtbar.ymin && mval[1] <= st->txtbar.ymax) { + /* mouse inside scroll handle */ + zone = SCROLLHANDLE_BAR; + } + else if (mval[1] > TXT_SCROLL_SPACE && mval[1] < ar->winy - TXT_SCROLL_SPACE) { + if (mval[1] < st->txtbar.ymin) + zone = SCROLLHANDLE_MIN_OUTSIDE; + else + zone = SCROLLHANDLE_MAX_OUTSIDE; + } + } + + if (zone == -1) { + /* we are outside slider - nothing to do */ + return OPERATOR_PASS_THROUGH; + } + + tsc = MEM_callocN(sizeof(TextScroll), "TextScroll"); + tsc->first = 1; + tsc->scrollbar = 1; + tsc->zone = zone; + op->customdata = tsc; + st->flags |= ST_SCROLL_SELECT; + + /* jump scroll, works in v2d but needs to be added here too :S */ + if (event->type == MIDDLEMOUSE) { + 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->first = 0; + tsc->zone = SCROLLHANDLE_BAR; + text_scroll_apply(C, op, event); + } + + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; } void TEXT_OT_scroll_bar(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Scrollbar"; - /* don't really see the difference between this and - * scroll. Both do basically the same thing (aside - * from keymaps).*/ - ot->idname = "TEXT_OT_scroll_bar"; + /* identifiers */ + ot->name = "Scrollbar"; + /* don't really see the difference between this and + * scroll. Both do basically the same thing (aside + * from keymaps).*/ + ot->idname = "TEXT_OT_scroll_bar"; - /* api callbacks */ - ot->invoke = text_scroll_bar_invoke; - ot->modal = text_scroll_modal; - ot->cancel = text_scroll_cancel; - ot->poll = text_region_scroll_poll; + /* api callbacks */ + ot->invoke = text_scroll_bar_invoke; + ot->modal = text_scroll_modal; + ot->cancel = text_scroll_cancel; + ot->poll = text_region_scroll_poll; - /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL; - /* properties */ - RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100); + /* properties */ + RNA_def_int( + ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100); } /******************* set selection operator **********************/ typedef struct SetSelection { - int selecting; - int selc, sell; - short old[2]; - wmTimer *timer; /* needed for scrolling when mouse at region bounds */ + int selecting; + int selc, sell; + short old[2]; + wmTimer *timer; /* needed for scrolling when mouse at region bounds */ } SetSelection; static int flatten_width(SpaceText *st, const char *str) { - int i, total = 0; + int i, total = 0; - for (i = 0; str[i]; i += BLI_str_utf8_size_safe(str + i)) { - if (str[i] == '\t') { - total += st->tabnumber - total % st->tabnumber; - } - else { - total += BLI_str_utf8_char_width_safe(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; + } + else { + total += BLI_str_utf8_char_width_safe(str + i); + } + } - return total; + return total; } static int flatten_column_to_offset(SpaceText *st, const char *str, int index) { - int i = 0, j = 0, col; + int i = 0, j = 0, col; - while (*(str + j)) { - if (str[j] == '\t') - col = st->tabnumber - i % st->tabnumber; - else - col = BLI_str_utf8_char_width_safe(str + j); + while (*(str + j)) { + if (str[j] == '\t') + col = st->tabnumber - i % st->tabnumber; + else + col = BLI_str_utf8_char_width_safe(str + j); - if (i + col > index) - break; + if (i + col > index) + break; - i += col; - j += BLI_str_utf8_size_safe(str + j); - } + i += col; + j += BLI_str_utf8_size_safe(str + j); + } - return j; + return j; } static TextLine *get_line_pos_wrapped(SpaceText *st, ARegion *ar, int *y) { - TextLine *linep = st->text->lines.first; - int i, lines; - - if (*y < -st->top) { - return NULL; /* We are beyond the first line... */ - } - - for (i = -st->top; i <= *y && linep; linep = linep->next, i += lines) { - lines = text_get_visible_lines(st, ar, linep->line); - - if (i + lines > *y) { - /* We found the line matching given vertical 'coordinate', - * now set y relative to this line's start. */ - *y -= i; - break; - } - } - return linep; -} - -static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, int y, const bool sel) -{ - Text *text = st->text; - int max = wrap_width(st, ar); /* column */ - int charp = -1; /* mem */ - bool found = false; /* flags */ - - /* Point to line matching given y position, if any. */ - TextLine *linep = get_line_pos_wrapped(st, ar, &y); - - if (linep) { - int i = 0, start = 0, end = max; /* column */ - int j, curs = 0, endj = 0; /* mem */ - bool chop = true; /* flags */ - char ch; - - for (j = 0 ; !found && ((ch = linep->line[j]) != '\0'); j += BLI_str_utf8_size_safe(linep->line + j)) { - int chars; - int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */ - - /* Mimic replacement of tabs */ - if (ch == '\t') { - chars = st->tabnumber - i % st->tabnumber; - ch = ' '; - } - else { - chars = 1; - } - - while (chars--) { - /* Gone too far, go back to last wrap point */ - if (y < 0) { - charp = endj; - y = 0; - found = true; - break; - /* Exactly at the cursor */ - } - else if (y == 0 && i - start <= x && i + columns - start > x) { - /* current position could be wrapped to next line */ - /* this should be checked when end of current line would be reached */ - charp = curs = j; - found = true; - /* Prepare curs for next wrap */ - } - else if (i - end <= x && i + columns - end > x) { - curs = j; - } - if (i + columns - start > max) { - end = MIN2(end, i); - - if (found) { - /* exact cursor position was found, check if it's still on needed line - * (hasn't been wrapped) */ - if (charp > endj && !chop && ch != '\0') - charp = endj; - break; - } - - if (chop) - endj = j; - start = end; - end += max; - - if (j < linep->len) - y--; - - chop = true; - if (y == 0 && i + columns - start > x) { - charp = curs; - found = true; - break; - } - } - else if (ch == ' ' || ch == '-' || ch == '\0') { - if (found) { - break; - } - - if (y == 0 && i + columns - start > x) { - charp = curs; - found = true; - break; - } - end = i + 1; - endj = j; - chop = false; - } - i += columns; - } - } - - BLI_assert(y == 0); - - if (!found) { - /* On correct line but didn't meet cursor, must be at end */ - charp = linep->len; - } - } - else if (y < 0) { /* Before start of text. */ - linep = st->text->lines.first; - charp = 0; - } - else { /* Beyond end of text */ - linep = st->text->lines.last; - charp = linep->len; - } - - BLI_assert(linep && charp != -1); - - if (sel) { - text->sell = linep; - text->selc = charp; - } - else { - text->curl = linep; - text->curc = charp; - } + TextLine *linep = st->text->lines.first; + int i, lines; + + if (*y < -st->top) { + return NULL; /* We are beyond the first line... */ + } + + for (i = -st->top; i <= *y && linep; linep = linep->next, i += lines) { + lines = text_get_visible_lines(st, ar, linep->line); + + if (i + lines > *y) { + /* We found the line matching given vertical 'coordinate', + * now set y relative to this line's start. */ + *y -= i; + break; + } + } + return linep; +} + +static void text_cursor_set_to_pos_wrapped( + SpaceText *st, ARegion *ar, int x, int y, const bool sel) +{ + Text *text = st->text; + int max = wrap_width(st, ar); /* column */ + int charp = -1; /* mem */ + bool found = false; /* flags */ + + /* Point to line matching given y position, if any. */ + TextLine *linep = get_line_pos_wrapped(st, ar, &y); + + if (linep) { + int i = 0, start = 0, end = max; /* column */ + int j, curs = 0, endj = 0; /* mem */ + bool chop = true; /* flags */ + char ch; + + for (j = 0; !found && ((ch = linep->line[j]) != '\0'); + j += BLI_str_utf8_size_safe(linep->line + j)) { + int chars; + int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */ + + /* Mimic replacement of tabs */ + if (ch == '\t') { + chars = st->tabnumber - i % st->tabnumber; + ch = ' '; + } + else { + chars = 1; + } + + while (chars--) { + /* Gone too far, go back to last wrap point */ + if (y < 0) { + charp = endj; + y = 0; + found = true; + break; + /* Exactly at the cursor */ + } + else if (y == 0 && i - start <= x && i + columns - start > x) { + /* current position could be wrapped to next line */ + /* this should be checked when end of current line would be reached */ + charp = curs = j; + found = true; + /* Prepare curs for next wrap */ + } + else if (i - end <= x && i + columns - end > x) { + curs = j; + } + if (i + columns - start > max) { + end = MIN2(end, i); + + if (found) { + /* exact cursor position was found, check if it's still on needed line + * (hasn't been wrapped) */ + if (charp > endj && !chop && ch != '\0') + charp = endj; + break; + } + + if (chop) + endj = j; + start = end; + end += max; + + if (j < linep->len) + y--; + + chop = true; + if (y == 0 && i + columns - start > x) { + charp = curs; + found = true; + break; + } + } + else if (ch == ' ' || ch == '-' || ch == '\0') { + if (found) { + break; + } + + if (y == 0 && i + columns - start > x) { + charp = curs; + found = true; + break; + } + end = i + 1; + endj = j; + chop = false; + } + i += columns; + } + } + + BLI_assert(y == 0); + + if (!found) { + /* On correct line but didn't meet cursor, must be at end */ + charp = linep->len; + } + } + else if (y < 0) { /* Before start of text. */ + linep = st->text->lines.first; + charp = 0; + } + else { /* Beyond end of text */ + linep = st->text->lines.last; + charp = linep->len; + } + + BLI_assert(linep && charp != -1); + + if (sel) { + text->sell = linep; + text->selc = charp; + } + else { + text->curl = linep; + text->curc = charp; + } } static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, const bool sel) { - Text *text = st->text; - text_update_character_width(st); - y = (ar->winy - 2 - y) / (st->lheight_dpi + TXT_LINE_SPACING); - - if (st->showlinenrs) x -= TXT_OFFSET + TEXTXLOC; - else x -= TXT_OFFSET; - - if (x < 0) x = 0; - x = text_pixel_x_to_column(st, x) + st->left; - - if (st->wordwrap) { - text_cursor_set_to_pos_wrapped(st, ar, x, y, sel); - } - else { - TextLine **linep; - int *charp; - int w; - - if (sel) { linep = &text->sell; charp = &text->selc; } - else { linep = &text->curl; charp = &text->curc; } - - y -= txt_get_span(text->lines.first, *linep) - st->top; - - if (y > 0) { - while (y-- != 0) { - if ((*linep)->next) *linep = (*linep)->next; - } - } - else if (y < 0) { - while (y++ != 0) { - if ((*linep)->prev) *linep = (*linep)->prev; - } - } - - - w = flatten_width(st, (*linep)->line); - if (x < w) *charp = flatten_column_to_offset(st, (*linep)->line, x); - else *charp = (*linep)->len; - } - if (!sel) txt_pop_sel(text); + Text *text = st->text; + text_update_character_width(st); + y = (ar->winy - 2 - y) / (st->lheight_dpi + TXT_LINE_SPACING); + + if (st->showlinenrs) + x -= TXT_OFFSET + TEXTXLOC; + else + x -= TXT_OFFSET; + + if (x < 0) + x = 0; + x = text_pixel_x_to_column(st, x) + st->left; + + if (st->wordwrap) { + text_cursor_set_to_pos_wrapped(st, ar, x, y, sel); + } + else { + TextLine **linep; + int *charp; + int w; + + if (sel) { + linep = &text->sell; + charp = &text->selc; + } + else { + linep = &text->curl; + charp = &text->curc; + } + + y -= txt_get_span(text->lines.first, *linep) - st->top; + + if (y > 0) { + while (y-- != 0) { + if ((*linep)->next) + *linep = (*linep)->next; + } + } + else if (y < 0) { + while (y++ != 0) { + if ((*linep)->prev) + *linep = (*linep)->prev; + } + } + + w = flatten_width(st, (*linep)->line); + if (x < w) + *charp = flatten_column_to_offset(st, (*linep)->line, x); + else + *charp = (*linep)->len; + } + if (!sel) + txt_pop_sel(text); } static void text_cursor_timer_ensure(bContext *C, SetSelection *ssel) { - if (ssel->timer == NULL) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); + if (ssel->timer == NULL) { + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); - ssel->timer = WM_event_add_timer(wm, win, TIMER, 0.02f); - } + ssel->timer = WM_event_add_timer(wm, win, TIMER, 0.02f); + } } static void text_cursor_timer_remove(bContext *C, SetSelection *ssel) { - if (ssel->timer) { - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); + if (ssel->timer) { + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); - WM_event_remove_timer(wm, win, ssel->timer); - } - ssel->timer = NULL; + WM_event_remove_timer(wm, win, ssel->timer); + } + ssel->timer = NULL; } - - static void text_cursor_set_apply(bContext *C, wmOperator *op, const wmEvent *event) { - SpaceText *st = CTX_wm_space_text(C); - ARegion *ar = CTX_wm_region(C); - SetSelection *ssel = op->customdata; - - if (event->mval[1] < 0 || event->mval[1] > ar->winy) { - text_cursor_timer_ensure(C, ssel); - - if (event->type == TIMER) { - text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1); - text_scroll_to_cursor(st, ar, false); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); - } - } - else if (!st->wordwrap && (event->mval[0] < 0 || event->mval[0] > ar->winx)) { - text_cursor_timer_ensure(C, ssel); - - if (event->type == TIMER) { - text_cursor_set_to_pos(st, ar, CLAMPIS(event->mval[0], 0, ar->winx), event->mval[1], 1); - text_scroll_to_cursor(st, ar, false); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); - } - } - else { - text_cursor_timer_remove(C, ssel); - - if (event->type != TIMER) { - text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1); - text_scroll_to_cursor(st, ar, false); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); - - ssel->old[0] = event->mval[0]; - ssel->old[1] = event->mval[1]; - } - } + SpaceText *st = CTX_wm_space_text(C); + ARegion *ar = CTX_wm_region(C); + SetSelection *ssel = op->customdata; + + if (event->mval[1] < 0 || event->mval[1] > ar->winy) { + text_cursor_timer_ensure(C, ssel); + + if (event->type == TIMER) { + text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1); + text_scroll_to_cursor(st, ar, false); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); + } + } + else if (!st->wordwrap && (event->mval[0] < 0 || event->mval[0] > ar->winx)) { + text_cursor_timer_ensure(C, ssel); + + if (event->type == TIMER) { + text_cursor_set_to_pos(st, ar, CLAMPIS(event->mval[0], 0, ar->winx), event->mval[1], 1); + text_scroll_to_cursor(st, ar, false); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); + } + } + else { + text_cursor_timer_remove(C, ssel); + + if (event->type != TIMER) { + text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1); + text_scroll_to_cursor(st, ar, false); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); + + ssel->old[0] = event->mval[0]; + ssel->old[1] = event->mval[1]; + } + } } 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; - char *buffer; + SpaceText *st = CTX_wm_space_text(C); + Text *text = st->text; + SetSelection *ssel = op->customdata; + char *buffer; - if (txt_has_sel(text)) { - buffer = txt_sel_to_buf(text); - WM_clipboard_text_set(buffer, 1); - MEM_freeN(buffer); - } + if (txt_has_sel(text)) { + buffer = txt_sel_to_buf(text); + WM_clipboard_text_set(buffer, 1); + MEM_freeN(buffer); + } - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); - text_cursor_timer_remove(C, ssel); - MEM_freeN(ssel); + text_cursor_timer_remove(C, ssel); + MEM_freeN(ssel); } static int text_set_selection_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - SpaceText *st = CTX_wm_space_text(C); - SetSelection *ssel; + SpaceText *st = CTX_wm_space_text(C); + SetSelection *ssel; - if (event->mval[0] >= st->txtbar.xmin) - return OPERATOR_PASS_THROUGH; + if (event->mval[0] >= st->txtbar.xmin) + return OPERATOR_PASS_THROUGH; - op->customdata = MEM_callocN(sizeof(SetSelection), "SetCursor"); - ssel = op->customdata; - ssel->selecting = RNA_boolean_get(op->ptr, "select"); + op->customdata = MEM_callocN(sizeof(SetSelection), "SetCursor"); + ssel = op->customdata; + ssel->selecting = RNA_boolean_get(op->ptr, "select"); - ssel->old[0] = event->mval[0]; - ssel->old[1] = event->mval[1]; + ssel->old[0] = event->mval[0]; + ssel->old[1] = event->mval[1]; - ssel->sell = txt_get_span(st->text->lines.first, st->text->sell); - ssel->selc = st->text->selc; + ssel->sell = txt_get_span(st->text->lines.first, st->text->sell); + ssel->selc = st->text->selc; - WM_event_add_modal_handler(C, op); + WM_event_add_modal_handler(C, op); - text_cursor_set_apply(C, op, event); + text_cursor_set_apply(C, op, event); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } static int text_set_selection_modal(bContext *C, wmOperator *op, const wmEvent *event) { - switch (event->type) { - case LEFTMOUSE: - case MIDDLEMOUSE: - case RIGHTMOUSE: - text_cursor_set_exit(C, op); - return OPERATOR_FINISHED; - case TIMER: - case MOUSEMOVE: - text_cursor_set_apply(C, op, event); - break; - } + switch (event->type) { + case LEFTMOUSE: + case MIDDLEMOUSE: + case RIGHTMOUSE: + text_cursor_set_exit(C, op); + return OPERATOR_FINISHED; + case TIMER: + case MOUSEMOVE: + text_cursor_set_apply(C, op, event); + break; + } - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } static void text_set_selection_cancel(bContext *C, wmOperator *op) { - text_cursor_set_exit(C, op); + text_cursor_set_exit(C, op); } void TEXT_OT_selection_set(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Selection"; - ot->idname = "TEXT_OT_selection_set"; - ot->description = "Set cursor selection"; + /* identifiers */ + ot->name = "Set Selection"; + ot->idname = "TEXT_OT_selection_set"; + ot->description = "Set cursor selection"; - /* api callbacks */ - ot->invoke = text_set_selection_invoke; - ot->modal = text_set_selection_modal; - ot->cancel = text_set_selection_cancel; - ot->poll = text_region_edit_poll; + /* api callbacks */ + ot->invoke = text_set_selection_invoke; + ot->modal = text_set_selection_modal; + ot->cancel = text_set_selection_cancel; + ot->poll = text_region_edit_poll; - /* properties */ - RNA_def_boolean(ot->srna, "select", 0, "Select", "Set selection end rather than cursor"); + /* properties */ + RNA_def_boolean(ot->srna, "select", 0, "Select", "Set selection end rather than cursor"); } /******************* set cursor operator **********************/ static int text_cursor_set_exec(bContext *C, wmOperator *op) { - SpaceText *st = CTX_wm_space_text(C); - ARegion *ar = CTX_wm_region(C); - int x = RNA_int_get(op->ptr, "x"); - int y = RNA_int_get(op->ptr, "y"); + SpaceText *st = CTX_wm_space_text(C); + ARegion *ar = CTX_wm_region(C); + int x = RNA_int_get(op->ptr, "x"); + int y = RNA_int_get(op->ptr, "y"); - text_cursor_set_to_pos(st, ar, x, y, 0); + text_cursor_set_to_pos(st, ar, x, y, 0); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); - return OPERATOR_PASS_THROUGH; + return OPERATOR_PASS_THROUGH; } static int text_cursor_set_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - SpaceText *st = CTX_wm_space_text(C); + SpaceText *st = CTX_wm_space_text(C); - if (event->mval[0] >= st->txtbar.xmin) - return OPERATOR_PASS_THROUGH; + if (event->mval[0] >= st->txtbar.xmin) + return OPERATOR_PASS_THROUGH; - RNA_int_set(op->ptr, "x", event->mval[0]); - RNA_int_set(op->ptr, "y", event->mval[1]); + RNA_int_set(op->ptr, "x", event->mval[0]); + RNA_int_set(op->ptr, "y", event->mval[1]); - return text_cursor_set_exec(C, op); + return text_cursor_set_exec(C, op); } void TEXT_OT_cursor_set(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Cursor"; - ot->idname = "TEXT_OT_cursor_set"; - ot->description = "Set cursor position"; + /* identifiers */ + ot->name = "Set Cursor"; + ot->idname = "TEXT_OT_cursor_set"; + ot->description = "Set cursor position"; - /* api callbacks */ - ot->invoke = text_cursor_set_invoke; - ot->exec = text_cursor_set_exec; - ot->poll = text_region_edit_poll; + /* api callbacks */ + ot->invoke = text_cursor_set_invoke; + ot->exec = text_cursor_set_exec; + ot->poll = text_region_edit_poll; - /* properties */ - RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); + /* properties */ + RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); } /******************* line number operator **********************/ static int text_line_number_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); - ARegion *ar = CTX_wm_region(C); - const int *mval = event->mval; - double time; - static int jump_to = 0; - static double last_jump = 0; + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); + ARegion *ar = CTX_wm_region(C); + const int *mval = event->mval; + double time; + static int jump_to = 0; + static double last_jump = 0; - text_update_character_width(st); + text_update_character_width(st); - if (!st->showlinenrs) - return OPERATOR_PASS_THROUGH; + if (!st->showlinenrs) + return OPERATOR_PASS_THROUGH; - if (!(mval[0] > 2 && mval[0] < (TXT_OFFSET + TEXTXLOC) && mval[1] > 2 && mval[1] < ar->winy - 2)) - return OPERATOR_PASS_THROUGH; + if (!(mval[0] > 2 && mval[0] < (TXT_OFFSET + TEXTXLOC) && mval[1] > 2 && mval[1] < ar->winy - 2)) + return OPERATOR_PASS_THROUGH; - if (!(event->ascii >= '0' && event->ascii <= '9')) - return OPERATOR_PASS_THROUGH; + if (!(event->ascii >= '0' && event->ascii <= '9')) + return OPERATOR_PASS_THROUGH; - time = PIL_check_seconds_timer(); - if (last_jump < time - 1) - jump_to = 0; + time = PIL_check_seconds_timer(); + if (last_jump < time - 1) + jump_to = 0; - jump_to *= 10; - jump_to += (int)(event->ascii - '0'); + jump_to *= 10; + jump_to += (int)(event->ascii - '0'); - txt_move_toline(text, jump_to - 1, 0); - last_jump = time; + txt_move_toline(text, jump_to - 1, 0); + last_jump = time; - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_line_number(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Line Number"; - ot->idname = "TEXT_OT_line_number"; - ot->description = "The current line number"; + /* identifiers */ + ot->name = "Line Number"; + ot->idname = "TEXT_OT_line_number"; + ot->description = "The current line number"; - /* api callbacks */ - ot->invoke = text_line_number_invoke; - ot->poll = text_region_edit_poll; + /* api callbacks */ + ot->invoke = text_line_number_invoke; + ot->poll = text_region_edit_poll; } /******************* insert operator **********************/ 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; - bool done = false; - size_t i = 0; - unsigned int code; + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); + char *str; + bool done = false; + size_t i = 0; + unsigned int code; - text_drawcache_tag_update(st, 0); + text_drawcache_tag_update(st, 0); - str = RNA_string_get_alloc(op->ptr, "text", NULL, 0); + str = RNA_string_get_alloc(op->ptr, "text", NULL, 0); - TextUndoBuf *utxt = ED_text_undo_push_init(C); + TextUndoBuf *utxt = ED_text_undo_push_init(C); - if (st && st->overwrite) { - while (str[i]) { - code = BLI_str_utf8_as_unicode_step(str, &i); - done |= txt_replace_char(text, utxt, code); - } - } - else { - while (str[i]) { - code = BLI_str_utf8_as_unicode_step(str, &i); - done |= txt_add_char(text, utxt, code); - } - } + if (st && st->overwrite) { + while (str[i]) { + code = BLI_str_utf8_as_unicode_step(str, &i); + done |= txt_replace_char(text, utxt, code); + } + } + else { + while (str[i]) { + code = BLI_str_utf8_as_unicode_step(str, &i); + done |= txt_add_char(text, utxt, code); + } + } - MEM_freeN(str); + MEM_freeN(str); - if (!done) - return OPERATOR_CANCELLED; + if (!done) + return OPERATOR_CANCELLED; - text_update_line_edited(text->curl); + text_update_line_edited(text->curl); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - int ret; - - // 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 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 { - char str[BLI_UTF8_MAX + 1]; - size_t len; - - if (event->utf8_buf[0]) { - len = BLI_str_utf8_size_safe(event->utf8_buf); - memcpy(str, event->utf8_buf, len); - } - else { - /* in theory, ghost can set value to extended ascii here */ - len = BLI_str_utf8_from_unicode(event->ascii, str); - } - str[len] = '\0'; - RNA_string_set(op->ptr, "text", str); - } - } - - ret = text_insert_exec(C, op); - - /* run the script while editing, evil but useful */ - if (ret == OPERATOR_FINISHED && CTX_wm_space_text(C)->live_edit) - text_run_script(C, NULL); - - return ret; + int ret; + + // 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 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 { + char str[BLI_UTF8_MAX + 1]; + size_t len; + + if (event->utf8_buf[0]) { + len = BLI_str_utf8_size_safe(event->utf8_buf); + memcpy(str, event->utf8_buf, len); + } + else { + /* in theory, ghost can set value to extended ascii here */ + len = BLI_str_utf8_from_unicode(event->ascii, str); + } + str[len] = '\0'; + RNA_string_set(op->ptr, "text", str); + } + } + + ret = text_insert_exec(C, op); + + /* run the script while editing, evil but useful */ + if (ret == OPERATOR_FINISHED && CTX_wm_space_text(C)->live_edit) + text_run_script(C, NULL); + + return ret; } void TEXT_OT_insert(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Insert"; - ot->idname = "TEXT_OT_insert"; - ot->description = "Insert text at cursor position"; + /* identifiers */ + ot->name = "Insert"; + ot->idname = "TEXT_OT_insert"; + ot->description = "Insert text at cursor position"; - /* api callbacks */ - ot->exec = text_insert_exec; - ot->invoke = text_insert_invoke; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_insert_exec; + ot->invoke = text_insert_invoke; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* properties */ - prop = RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + /* properties */ + prop = RNA_def_string( + ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /******************* find operator *********************/ /* mode */ -#define TEXT_FIND 0 -#define TEXT_REPLACE 1 +#define TEXT_FIND 0 +#define TEXT_REPLACE 1 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 *text = st->text; - int flags; - int found = 0; - char *tmp; - - if (!st->findstr[0]) - return OPERATOR_CANCELLED; - - flags = st->flags; - if (flags & ST_FIND_ALL) - flags &= ~ST_FIND_WRAP; - - /* Replace current */ - if (mode != TEXT_FIND && txt_has_sel(text)) { - tmp = txt_sel_to_buf(text); - - if (flags & ST_MATCH_CASE) found = STREQ(st->findstr, tmp); - else found = BLI_strcasecmp(st->findstr, tmp) == 0; - - if (found) { - if (mode == TEXT_REPLACE) { - TextUndoBuf *utxt = ED_text_undo_push_init(C); - txt_insert_buf(text, utxt, 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; - } - - /* 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->texts.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; + Main *bmain = CTX_data_main(C); + SpaceText *st = CTX_wm_space_text(C); + Text *text = st->text; + int flags; + int found = 0; + char *tmp; + + if (!st->findstr[0]) + return OPERATOR_CANCELLED; + + flags = st->flags; + if (flags & ST_FIND_ALL) + flags &= ~ST_FIND_WRAP; + + /* Replace current */ + if (mode != TEXT_FIND && txt_has_sel(text)) { + tmp = txt_sel_to_buf(text); + + if (flags & ST_MATCH_CASE) + found = STREQ(st->findstr, tmp); + else + found = BLI_strcasecmp(st->findstr, tmp) == 0; + + if (found) { + if (mode == TEXT_REPLACE) { + TextUndoBuf *utxt = ED_text_undo_push_init(C); + txt_insert_buf(text, utxt, 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; + } + + /* 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->texts.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; } static int text_find_exec(bContext *C, wmOperator *op) { - return text_find_and_replace(C, op, TEXT_FIND); + return text_find_and_replace(C, op, TEXT_FIND); } void TEXT_OT_find(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Find Next"; - ot->idname = "TEXT_OT_find"; - ot->description = "Find specified text"; + /* identifiers */ + ot->name = "Find Next"; + ot->idname = "TEXT_OT_find"; + ot->description = "Find specified text"; - /* api callbacks */ - ot->exec = text_find_exec; - ot->poll = text_space_edit_poll; + /* api callbacks */ + ot->exec = text_find_exec; + ot->poll = text_space_edit_poll; } /******************* replace operator *********************/ static int text_replace_exec(bContext *C, wmOperator *op) { - return text_find_and_replace(C, op, TEXT_REPLACE); + return text_find_and_replace(C, op, TEXT_REPLACE); } void TEXT_OT_replace(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Replace"; - ot->idname = "TEXT_OT_replace"; - ot->description = "Replace text with the specified text"; + /* identifiers */ + ot->name = "Replace"; + ot->idname = "TEXT_OT_replace"; + ot->description = "Replace text with the specified text"; - /* api callbacks */ - ot->exec = text_replace_exec; - ot->poll = text_space_edit_poll; + /* api callbacks */ + ot->exec = text_replace_exec; + ot->poll = text_space_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /******************* find set selected *********************/ static int text_find_set_selected_exec(bContext *C, wmOperator *op) { - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); - char *tmp; + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); + char *tmp; - tmp = txt_sel_to_buf(text); - BLI_strncpy(st->findstr, tmp, ST_MAX_FIND_STR); - MEM_freeN(tmp); + tmp = txt_sel_to_buf(text); + BLI_strncpy(st->findstr, tmp, ST_MAX_FIND_STR); + MEM_freeN(tmp); - if (!st->findstr[0]) - return OPERATOR_FINISHED; + if (!st->findstr[0]) + return OPERATOR_FINISHED; - return text_find_and_replace(C, op, TEXT_FIND); + return text_find_and_replace(C, op, TEXT_FIND); } void TEXT_OT_find_set_selected(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Find Set Selected"; - ot->idname = "TEXT_OT_find_set_selected"; - ot->description = "Find specified text and set as selected"; + /* identifiers */ + ot->name = "Find Set Selected"; + ot->idname = "TEXT_OT_find_set_selected"; + ot->description = "Find specified text and set as selected"; - /* api callbacks */ - ot->exec = text_find_set_selected_exec; - ot->poll = text_space_edit_poll; + /* api callbacks */ + ot->exec = text_find_set_selected_exec; + ot->poll = text_space_edit_poll; } /******************* replace set selected *********************/ static int text_replace_set_selected_exec(bContext *C, wmOperator *UNUSED(op)) { - SpaceText *st = CTX_wm_space_text(C); - Text *text = CTX_data_edit_text(C); - char *tmp; + SpaceText *st = CTX_wm_space_text(C); + Text *text = CTX_data_edit_text(C); + char *tmp; - tmp = txt_sel_to_buf(text); - BLI_strncpy(st->replacestr, tmp, ST_MAX_FIND_STR); - MEM_freeN(tmp); + tmp = txt_sel_to_buf(text); + BLI_strncpy(st->replacestr, tmp, ST_MAX_FIND_STR); + MEM_freeN(tmp); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void TEXT_OT_replace_set_selected(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Replace Set Selected"; - ot->idname = "TEXT_OT_replace_set_selected"; - ot->description = "Replace text with specified text and set as selected"; + /* identifiers */ + ot->name = "Replace Set Selected"; + ot->idname = "TEXT_OT_replace_set_selected"; + ot->description = "Replace text with specified text and set as selected"; - /* api callbacks */ - ot->exec = text_replace_set_selected_exec; - ot->poll = text_space_edit_poll; + /* api callbacks */ + ot->exec = text_replace_set_selected_exec; + ot->poll = text_space_edit_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; } /****************** resolve conflict operator ******************/ enum { RESOLVE_IGNORE, RESOLVE_RELOAD, RESOLVE_SAVE, RESOLVE_MAKE_INTERNAL }; static const EnumPropertyItem resolution_items[] = { - {RESOLVE_IGNORE, "IGNORE", 0, "Ignore", ""}, - {RESOLVE_RELOAD, "RELOAD", 0, "Reload", ""}, - {RESOLVE_SAVE, "SAVE", 0, "Save", ""}, - {RESOLVE_MAKE_INTERNAL, "MAKE_INTERNAL", 0, "Make Internal", ""}, - {0, NULL, 0, NULL, NULL}, + {RESOLVE_IGNORE, "IGNORE", 0, "Ignore", ""}, + {RESOLVE_RELOAD, "RELOAD", 0, "Reload", ""}, + {RESOLVE_SAVE, "SAVE", 0, "Save", ""}, + {RESOLVE_MAKE_INTERNAL, "MAKE_INTERNAL", 0, "Make Internal", ""}, + {0, NULL, 0, NULL, NULL}, }; static int text_resolve_conflict_exec(bContext *C, wmOperator *op) { - Text *text = CTX_data_edit_text(C); - int resolution = RNA_enum_get(op->ptr, "resolution"); + Text *text = CTX_data_edit_text(C); + int resolution = RNA_enum_get(op->ptr, "resolution"); - switch (resolution) { - case RESOLVE_RELOAD: - return text_reload_exec(C, op); - case RESOLVE_SAVE: - return text_save_exec(C, op); - case RESOLVE_MAKE_INTERNAL: - return text_make_internal_exec(C, op); - case RESOLVE_IGNORE: - BKE_text_file_modified_ignore(text); - return OPERATOR_FINISHED; - } + switch (resolution) { + case RESOLVE_RELOAD: + return text_reload_exec(C, op); + case RESOLVE_SAVE: + return text_save_exec(C, op); + case RESOLVE_MAKE_INTERNAL: + return text_make_internal_exec(C, op); + case RESOLVE_IGNORE: + BKE_text_file_modified_ignore(text); + return OPERATOR_FINISHED; + } - return OPERATOR_CANCELLED; + return OPERATOR_CANCELLED; } static int text_resolve_conflict_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Text *text = CTX_data_edit_text(C); - uiPopupMenu *pup; - uiLayout *layout; - - switch (BKE_text_file_modified_check(text)) { - case 1: - if (text->flags & TXT_ISDIRTY) { - /* modified locally and externally, ahhh. offer more possibilities. */ - pup = UI_popup_menu_begin(C, IFACE_("File Modified Outside and Inside Blender"), ICON_NONE); - layout = UI_popup_menu_layout(pup); - uiItemEnumO_ptr(layout, op->type, IFACE_("Reload from disk (ignore local changes)"), - 0, "resolution", RESOLVE_RELOAD); - uiItemEnumO_ptr(layout, op->type, IFACE_("Save to disk (ignore outside changes)"), - 0, "resolution", RESOLVE_SAVE); - uiItemEnumO_ptr(layout, op->type, IFACE_("Make text internal (separate copy)"), - 0, "resolution", RESOLVE_MAKE_INTERNAL); - UI_popup_menu_end(C, pup); - } - else { - pup = UI_popup_menu_begin(C, IFACE_("File Modified Outside Blender"), ICON_NONE); - layout = UI_popup_menu_layout(pup); - uiItemEnumO_ptr(layout, op->type, IFACE_("Reload from disk"), 0, "resolution", RESOLVE_RELOAD); - uiItemEnumO_ptr(layout, op->type, IFACE_("Make text internal (separate copy)"), - 0, "resolution", RESOLVE_MAKE_INTERNAL); - uiItemEnumO_ptr(layout, op->type, IFACE_("Ignore"), 0, "resolution", RESOLVE_IGNORE); - UI_popup_menu_end(C, pup); - } - break; - case 2: - pup = UI_popup_menu_begin(C, IFACE_("File Deleted Outside Blender"), ICON_NONE); - layout = UI_popup_menu_layout(pup); - uiItemEnumO_ptr(layout, op->type, IFACE_("Make text internal"), 0, "resolution", RESOLVE_MAKE_INTERNAL); - uiItemEnumO_ptr(layout, op->type, IFACE_("Recreate file"), 0, "resolution", RESOLVE_SAVE); - UI_popup_menu_end(C, pup); - break; - } - - return OPERATOR_INTERFACE; + Text *text = CTX_data_edit_text(C); + uiPopupMenu *pup; + uiLayout *layout; + + switch (BKE_text_file_modified_check(text)) { + case 1: + if (text->flags & TXT_ISDIRTY) { + /* modified locally and externally, ahhh. offer more possibilities. */ + pup = UI_popup_menu_begin( + C, IFACE_("File Modified Outside and Inside Blender"), ICON_NONE); + layout = UI_popup_menu_layout(pup); + uiItemEnumO_ptr(layout, + op->type, + IFACE_("Reload from disk (ignore local changes)"), + 0, + "resolution", + RESOLVE_RELOAD); + uiItemEnumO_ptr(layout, + op->type, + IFACE_("Save to disk (ignore outside changes)"), + 0, + "resolution", + RESOLVE_SAVE); + uiItemEnumO_ptr(layout, + op->type, + IFACE_("Make text internal (separate copy)"), + 0, + "resolution", + RESOLVE_MAKE_INTERNAL); + UI_popup_menu_end(C, pup); + } + else { + pup = UI_popup_menu_begin(C, IFACE_("File Modified Outside Blender"), ICON_NONE); + layout = UI_popup_menu_layout(pup); + uiItemEnumO_ptr( + layout, op->type, IFACE_("Reload from disk"), 0, "resolution", RESOLVE_RELOAD); + uiItemEnumO_ptr(layout, + op->type, + IFACE_("Make text internal (separate copy)"), + 0, + "resolution", + RESOLVE_MAKE_INTERNAL); + uiItemEnumO_ptr(layout, op->type, IFACE_("Ignore"), 0, "resolution", RESOLVE_IGNORE); + UI_popup_menu_end(C, pup); + } + break; + case 2: + pup = UI_popup_menu_begin(C, IFACE_("File Deleted Outside Blender"), ICON_NONE); + layout = UI_popup_menu_layout(pup); + uiItemEnumO_ptr( + layout, op->type, IFACE_("Make text internal"), 0, "resolution", RESOLVE_MAKE_INTERNAL); + uiItemEnumO_ptr(layout, op->type, IFACE_("Recreate file"), 0, "resolution", RESOLVE_SAVE); + UI_popup_menu_end(C, pup); + break; + } + + return OPERATOR_INTERFACE; } void TEXT_OT_resolve_conflict(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Resolve Conflict"; - ot->idname = "TEXT_OT_resolve_conflict"; - ot->description = "When external text is out of sync, resolve the conflict"; + /* identifiers */ + ot->name = "Resolve Conflict"; + ot->idname = "TEXT_OT_resolve_conflict"; + ot->description = "When external text is out of sync, resolve the conflict"; - /* api callbacks */ - ot->exec = text_resolve_conflict_exec; - ot->invoke = text_resolve_conflict_invoke; - ot->poll = text_save_poll; + /* api callbacks */ + ot->exec = text_resolve_conflict_exec; + ot->invoke = text_resolve_conflict_invoke; + ot->poll = text_save_poll; - /* properties */ - RNA_def_enum(ot->srna, "resolution", resolution_items, RESOLVE_IGNORE, "Resolution", "How to solve conflict due to differences in internal and external text"); + /* properties */ + RNA_def_enum(ot->srna, + "resolution", + resolution_items, + RESOLVE_IGNORE, + "Resolution", + "How to solve conflict due to differences in internal and external text"); } /********************** to 3d object operator *****************/ static int text_to_3d_object_exec(bContext *C, wmOperator *op) { - Text *text = CTX_data_edit_text(C); - const bool split_lines = RNA_boolean_get(op->ptr, "split_lines"); + Text *text = CTX_data_edit_text(C); + const bool split_lines = RNA_boolean_get(op->ptr, "split_lines"); - ED_text_to_object(C, text, split_lines); + ED_text_to_object(C, text, split_lines); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } 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"; + /* identifiers */ + ot->name = "To 3D Object"; + ot->idname = "TEXT_OT_to_3d_object"; + ot->description = "Create 3D text object from active text data-block"; - /* api callbacks */ - ot->exec = text_to_3d_object_exec; - ot->poll = text_edit_poll; + /* api callbacks */ + ot->exec = text_to_3d_object_exec; + ot->poll = text_edit_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* 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"); + /* properties */ + RNA_def_boolean( + ot->srna, "split_lines", 0, "Split Lines", "Create one object per line in the text"); } |