/blender-2.63a/source/blender/editors/space_text/text_ops.c
C | 3311 lines | 2349 code | 695 blank | 267 comment | 537 complexity | 765ffcbecfc5dca33ebc2eb8a9886fc7 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, BSD-3-Clause, LGPL-3.0, BSD-2-Clause, Apache-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- /*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
- /** \file blender/editors/space_text/text_ops.c
- * \ingroup sptext
- */
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h> /* ispunct */
- #include <sys/stat.h>
- #include <errno.h>
- #include "MEM_guardedalloc.h"
- #include "DNA_text_types.h"
- #include "DNA_userdef_types.h"
- #include "BLI_blenlib.h"
- #include "BLI_utildefines.h"
- #include "PIL_time.h"
- #include "BKE_context.h"
- #include "BKE_global.h"
- #include "BKE_library.h"
- #include "BKE_main.h"
- #include "BKE_report.h"
- #include "BKE_text.h"
- #include "WM_api.h"
- #include "WM_types.h"
- #include "ED_text.h"
- #include "ED_curve.h"
- #include "ED_screen.h"
- #include "UI_interface.h"
- #include "UI_resources.h"
- #include "RNA_access.h"
- #include "RNA_define.h"
- #ifdef WITH_PYTHON
- #include "BPY_extern.h"
- #endif
- #include "text_intern.h"
- /************************ poll ***************************/
- BLI_INLINE int text_pixel_x_to_index(SpaceText *st, const int x)
- {
- /* add half the char width so mouse cursor selection is inbetween letters */
- return (x + (st->cwidth / 2)) / st->cwidth;
- }
- static int text_new_poll(bContext *UNUSED(C))
- {
- return 1;
- }
- static int text_edit_poll(bContext *C)
- {
- Text *text = CTX_data_edit_text(C);
- if (!text)
- return 0;
- if (text->id.lib) {
- // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata");
- return 0;
- }
- return 1;
- }
- static int text_space_edit_poll(bContext *C)
- {
- SpaceText *st = CTX_wm_space_text(C);
- Text *text = CTX_data_edit_text(C);
- if (!st || !text)
- return 0;
- if (text->id.lib) {
- // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata");
- return 0;
- }
- return 1;
- }
- static int 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);
- if (!st || !text)
- return 0;
-
- if (!ar || ar->regiontype != RGN_TYPE_WINDOW)
- return 0;
- if (text->id.lib) {
- // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata");
- return 0;
- }
- return 1;
- }
- /********************** updates *********************/
- void text_update_line_edited(TextLine *line)
- {
- if (!line)
- return;
- /* 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;
- 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);
- Text *text;
- PointerRNA ptr, idptr;
- PropertyRNA *prop;
- text = add_empty_text("Text");
- /* hook into UI */
- uiIDContextProperty(C, &ptr, &prop);
- if (prop) {
- /* when creating new ID blocks, use is already 1, but RNA
- * pointer se also increases user, so this compensates it */
- /* doesnt always seem to happen... (ton) */
- if (text->id.us > 1)
- text->id.us--;
- 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->top = 0;
- text_drawcache_tag_update(st, 1);
- }
- WM_event_add_notifier(C, NC_TEXT | NA_ADDED, text);
- return OPERATOR_FINISHED;
- }
- void TEXT_OT_new(wmOperatorType *ot)
- {
- /* identifiers */
- ot->name = "Create Text Block";
- 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;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
- }
- /******************* open operator *********************/
- static void text_open_init(bContext *C, wmOperator *op)
- {
- PropertyPointerRNA *pprop;
- op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
- uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
- }
- static int text_open_cancel(bContext *UNUSED(C), wmOperator *op)
- {
- MEM_freeN(op->customdata);
- return OPERATOR_CANCELLED;
- }
- static int text_open_exec(bContext *C, wmOperator *op)
- {
- SpaceText *st = CTX_wm_space_text(C);
- Text *text;
- PropertyPointerRNA *pprop;
- PointerRNA idptr;
- char str[FILE_MAX];
- short internal = RNA_boolean_get(op->ptr, "internal");
- RNA_string_get(op->ptr, "filepath", str);
- text = add_text(str, G.main->name);
- if (!text) {
- if (op->customdata) MEM_freeN(op->customdata);
- return OPERATOR_CANCELLED;
- }
- if (!op->customdata)
- text_open_init(C, op);
- /* hook into UI */
- pprop = op->customdata;
- if (pprop->prop) {
- /* when creating new ID blocks, use is already 1, but RNA
- * pointer se also increases user, so this compensates it */
- text->id.us--;
- 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->top = 0;
- }
-
- if (internal) {
- if (text->name)
- MEM_freeN(text->name);
-
- text->name = NULL;
- }
- text_drawcache_tag_update(st, 1);
- WM_event_add_notifier(C, NC_TEXT | NA_ADDED, text);
- MEM_freeN(op->customdata);
- return OPERATOR_FINISHED;
- }
- static int text_open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
- {
- Text *text = CTX_data_edit_text(C);
- char *path = (text && text->name) ? text->name : G.main->name;
- 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);
- return OPERATOR_RUNNING_MODAL;
- }
- void TEXT_OT_open(wmOperatorType *ot)
- {
- /* identifiers */
- ot->name = "Open Text Block";
- 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;
- /* flags */
- ot->flag = OPTYPE_UNDO;
-
- /* properties */
- WM_operator_properties_filesel(ot, FOLDERFILE | TEXTFILE | PYSCRIPTFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); //XXX TODO, relative_path
- 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)
- {
- Text *text = CTX_data_edit_text(C);
- if (!reopen_text(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);
- #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);
- 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";
-
- /* api callbacks */
- ot->exec = text_reload_exec;
- ot->invoke = WM_operator_confirm;
- ot->poll = text_edit_poll;
- }
- /******************* delete operator *********************/
- static int 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;
- }
- 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);
- /* 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);
- }
- }
- unlink_text(bmain, text);
- free_libblock(&bmain->text, text);
- text_drawcache_tag_update(st, 1);
- WM_event_add_notifier(C, NC_TEXT | NA_REMOVED, NULL);
- 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";
-
- /* api callbacks */
- ot->exec = text_unlink_exec;
- ot->invoke = WM_operator_confirm;
- ot->poll = text_unlink_poll;
-
- /* 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->flags |= TXT_ISMEM | TXT_ISDIRTY;
- 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);
- 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";
- /* api callbacks */
- ot->exec = text_make_internal_exec;
- ot->poll = text_edit_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO;
- }
- /******************* save operator *********************/
- static int text_save_poll(bContext *C)
- {
- Text *text = CTX_data_edit_text(C);
- if (!text_edit_poll(C))
- return 0;
-
- return (text->name != NULL && !(text->flags & TXT_ISMEM));
- }
- static void txt_write_file(Text *text, ReportList *reports)
- {
- FILE *fp;
- TextLine *tmp;
- struct stat st;
- char filepath[FILE_MAX];
-
- BLI_strncpy(filepath, text->name, FILE_MAX);
- BLI_path_abs(filepath, G.main->name);
-
- fp = BLI_fopen(filepath, "w");
- if (fp == NULL) {
- BKE_reportf(reports, RPT_ERROR, "Unable to save \"%s\": %s", filepath, errno ? strerror(errno) : "Unknown error writing file");
- return;
- }
- tmp = text->lines.first;
- while (tmp) {
- if (tmp->next) fprintf(fp, "%s\n", tmp->line);
- else fprintf(fp, "%s", tmp->line);
-
- tmp = tmp->next;
- }
-
- fclose(fp);
- if (stat(filepath, &st) == 0) {
- text->mtime = st.st_mtime;
- }
- else {
- text->mtime = 0;
- BKE_reportf(reports, RPT_WARNING, "Unable to stat \"%s\": %s", filepath, errno ? strerror(errno) : "Unknown error starrng file");
- }
-
- if (text->flags & TXT_ISDIRTY)
- text->flags ^= TXT_ISDIRTY;
- }
- static int text_save_exec(bContext *C, wmOperator *op)
- {
- Text *text = CTX_data_edit_text(C);
- txt_write_file(text, op->reports);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- 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";
- /* 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)
- {
- Text *text = CTX_data_edit_text(C);
- char str[FILE_MAX];
- if (!text)
- return OPERATOR_CANCELLED;
- RNA_string_get(op->ptr, "filepath", str);
- if (text->name) MEM_freeN(text->name);
- text->name = BLI_strdup(str);
- text->flags &= ~TXT_ISMEM;
- txt_write_file(text, op->reports);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
- }
- static int text_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
- {
- Text *text = CTX_data_edit_text(C);
- char *str;
- 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 = G.main->name;
-
- RNA_string_set(op->ptr, "filepath", str);
- WM_event_add_fileselect(C, op);
- 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";
-
- /* 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, FOLDERFILE | TEXTFILE | PYSCRIPTFILE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); //XXX TODO, relative_path
- }
- /******************* run script operator *********************/
- static int text_run_script_poll(bContext *C)
- {
- 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 short is_live = (reports == NULL);
- /* only for comparison */
- void *curl_prev = text->curl;
- int curc_prev = text->curc;
- if (BPY_text_exec(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) {
- if (text->curl != curl_prev || curc_prev != text->curc) {
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- }
- BKE_report(reports, RPT_ERROR, "Python script fail, look in the console for now...");
- }
- #else
- (void)C;
- (void)reports;
- #endif /* !WITH_PYTHON */
- return OPERATOR_CANCELLED;
- }
- static int text_run_script_exec(bContext *C, wmOperator *op)
- {
- #ifndef WITH_PYTHON
- (void)C; /* unused */
- BKE_report(op->reports, RPT_ERROR, "Python disabled in this build");
- return OPERATOR_CANCELLED;
- #else
- 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";
-
- /* api callbacks */
- ot->poll = text_run_script_poll;
- ot->exec = text_run_script_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- }
- /******************* refresh pyconstraints operator *********************/
- 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)->object.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) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- }
- }
- #endif
- #endif
- 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";
-
- /* api callbacks */
- ot->exec = text_refresh_pyconstraints_exec;
- ot->poll = text_edit_poll;
- }
- /******************* paste operator *********************/
- static char *txt_copy_selected(Text *text)
- {
- TextLine *tmp, *linef, *linel;
- char *buf = NULL;
- int charf, charl, length = 0;
-
- if (!text) return NULL;
- if (!text->curl) return NULL;
- if (!text->sell) return NULL;
- if (!txt_has_sel(text)) return NULL;
- if (text->curl == text->sell) {
- linef = linel = text->curl;
-
- if (text->curc < text->selc) {
- charf = text->curc;
- charl = text->selc;
- }
- else {
- charf = text->selc;
- charl = text->curc;
- }
- }
- else if (txt_get_span(text->curl, text->sell) < 0) {
- linef = text->sell;
- linel = text->curl;
- charf = text->selc;
- charl = text->curc;
- }
- else {
- linef = text->curl;
- linel = text->sell;
-
- charf = text->curc;
- charl = text->selc;
- }
- if (linef == linel) {
- length = charl - charf;
- buf = MEM_callocN(length + 1, "cut buffera");
-
- BLI_strncpy(buf, linef->line + charf, length + 1);
- }
- else {
- length += linef->len - charf;
- length += charl;
- length++; /* For the '\n' */
-
- tmp = linef->next;
- while (tmp && tmp != linel) {
- length += tmp->len + 1;
- tmp = tmp->next;
- }
-
- buf = MEM_callocN(length + 1, "cut bufferb");
-
- strncpy(buf, linef->line + charf, linef->len - charf);
- length = linef->len - charf;
-
- buf[length++] = '\n';
-
- tmp = linef->next;
- while (tmp && tmp != linel) {
- strncpy(buf + length, tmp->line, tmp->len);
- length += tmp->len;
-
- buf[length++] = '\n';
-
- tmp = tmp->next;
- }
- strncpy(buf + length, linel->line, charl);
- length += charl;
-
- buf[length] = 0;
- }
- return buf;
- }
- static int text_paste_exec(bContext *C, wmOperator *op)
- {
- Text *text = CTX_data_edit_text(C);
- char *buf;
- int selection = RNA_boolean_get(op->ptr, "selection");
- buf = WM_clipboard_text_get(selection);
- if (!buf)
- return OPERATOR_CANCELLED;
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- txt_insert_buf(text, buf);
- text_update_edited(text);
- MEM_freeN(buf);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- /* run the script while editing, evil but useful */
- if (CTX_wm_space_text(C)->live_edit)
- text_run_script(C, NULL);
- return OPERATOR_FINISHED;
- }
- void TEXT_OT_paste(wmOperatorType *ot)
- {
- /* 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;
-
- /* properties */
- RNA_def_boolean(ot->srna, "selection", 0, "Selection", "Paste text selected elsewhere rather than copied (X11 only)");
- }
- /******************* copy operator *********************/
- static void txt_copy_clipboard(Text *text)
- {
- char *buf;
- buf = txt_copy_selected(text);
- 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);
- txt_copy_clipboard(text);
- 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";
- /* 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_drawcache_tag_update(CTX_wm_space_text(C), 0);
- txt_copy_clipboard(text);
- txt_delete_selected(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);
- 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";
-
- /* api callbacks */
- ot->exec = text_cut_exec;
- ot->poll = text_edit_poll;
- }
- /******************* indent operator *********************/
- static int text_indent_exec(bContext *C, wmOperator *UNUSED(op))
- {
- Text *text = CTX_data_edit_text(C);
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- if (txt_has_sel(text)) {
- txt_order_cursors(text);
- txt_indent(text);
- }
- else
- txt_add_char(text, '\t');
- text_update_edited(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
- }
- void TEXT_OT_indent(wmOperatorType *ot)
- {
- /* 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;
- }
- /******************* unindent operator *********************/
- static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op))
- {
- Text *text = CTX_data_edit_text(C);
- if (txt_has_sel(text)) {
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- txt_order_cursors(text);
- txt_unindent(text);
- text_update_edited(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
- }
- return OPERATOR_CANCELLED;
- }
- void TEXT_OT_unindent(wmOperatorType *ot)
- {
- /* 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;
- }
- /******************* 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;
- text_drawcache_tag_update(st, 0);
- // double check tabs/spaces before splitting the line
- curts = setcurr_tab_spaces(text, space);
- txt_split_curline(text);
- for (a = 0; a < curts; a++) {
- if (text->flags & TXT_TABSTOSPACES) {
- txt_add_char(text, ' ');
- }
- else {
- txt_add_char(text, '\t');
- }
- }
- 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);
- return OPERATOR_CANCELLED;
- }
- 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";
-
- /* api callbacks */
- ot->exec = text_line_break_exec;
- ot->poll = text_edit_poll;
- }
- /******************* comment operator *********************/
- static int text_comment_exec(bContext *C, wmOperator *UNUSED(op))
- {
- Text *text = CTX_data_edit_text(C);
- if (txt_has_sel(text)) {
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- txt_order_cursors(text);
- txt_comment(text);
- text_update_edited(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
- }
- 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";
-
- /* api callbacks */
- ot->exec = text_comment_exec;
- ot->poll = text_edit_poll;
- }
- /******************* uncomment operator *********************/
- static int text_uncomment_exec(bContext *C, wmOperator *UNUSED(op))
- {
- Text *text = CTX_data_edit_text(C);
- if (txt_has_sel(text)) {
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- txt_order_cursors(text);
- txt_uncomment(text);
- text_update_edited(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
- }
- 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";
-
- /* api callbacks */
- ot->exec = text_uncomment_exec;
- ot->poll = text_edit_poll;
- }
- /******************* convert whitespace operator *********************/
- enum { TO_SPACES, TO_TABS };
- static EnumPropertyItem whitespace_type_items[] = {
- {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;
- char *text_check_line, *new_line;
- int extra, number; //unknown for now
- int type = RNA_enum_get(op->ptr, "type");
-
- tmp = text->lines.first;
-
- //first convert to all space, this make it a lot easier to convert to tabs because there is no mixtures of ' ' && '\t'
- while (tmp) {
- text_check_line = tmp->line;
- number = flatten_string(st, &fs, text_check_line) + 1;
- flatten_string_free(&fs);
- new_line = MEM_callocN(number, "Converted_Line");
- j = 0;
- for (a = 0; a < strlen(text_check_line); a++) { //foreach char in line
- if (text_check_line[a] == '\t') { //checking for tabs
- //get the number of spaces this tabs is showing
- //i don't like doing it this way but will look into it later
- new_line[j] = '\0';
- number = flatten_string(st, &fs, new_line);
- flatten_string_free(&fs);
- new_line[j] = '\t';
- new_line[j + 1] = '\0';
- number = flatten_string(st, &fs, new_line) - number;
- flatten_string_free(&fs);
- for (extra = 0; extra < number; extra++) {
- new_line[j] = ' ';
- j++;
- }
- }
- else {
- new_line[j] = text_check_line[a];
- ++j;
- }
- }
- new_line[j] = '\0';
- // put new_line in the tmp->line spot still need to try and set the curc correctly
- if (tmp->line) MEM_freeN(tmp->line);
- if (tmp->format) MEM_freeN(tmp->format);
-
- tmp->line = new_line;
- tmp->len = strlen(new_line);
- tmp->format = NULL;
- tmp = tmp->next;
- }
-
- if (type == TO_TABS) { // Converting to tabs
- //start over from the beginning
- tmp = text->lines.first;
-
- while (tmp) {
- text_check_line = tmp->line;
- extra = 0;
- for (a = 0; a < strlen(text_check_line); a++) {
- number = 0;
- for (j = 0; j < (size_t)st->tabnumber; j++) {
- if ((a + j) <= strlen(text_check_line)) { //check to make sure we are not pass the end of the line
- if (text_check_line[a + j] != ' ') {
- number = 1;
- }
- }
- }
- if (!number) { //found all number of space to equal a tab
- a = a + (st->tabnumber - 1);
- extra = extra + 1;
- }
- }
-
- if (extra > 0) { //got tabs make malloc and do what you have to do
- new_line = MEM_callocN(strlen(text_check_line) - (((st->tabnumber * extra) - extra) - 1), "Converted_Line");
- extra = 0; //reuse vars
- for (a = 0; a < strlen(text_check_line); a++) {
- number = 0;
- for (j = 0; j < (size_t)st->tabnumber; j++) {
- if ((a + j) <= strlen(text_check_line)) { //check to make sure we are not pass the end of the line
- if (text_check_line[a + j] != ' ') {
- number = 1;
- }
- }
- }
- if (!number) { //found all number of space to equal a tab
- new_line[extra] = '\t';
- a = a + (st->tabnumber - 1);
- ++extra;
-
- }
- else { //not adding a tab
- new_line[extra] = text_check_line[a];
- ++extra;
- }
- }
- new_line[extra] = '\0';
- // put new_line in the tmp->line spot still need to try and set the curc correctly
- if (tmp->line) MEM_freeN(tmp->line);
- if (tmp->format) MEM_freeN(tmp->format);
-
- tmp->line = new_line;
- tmp->len = strlen(new_line);
- tmp->format = NULL;
- }
- tmp = tmp->next;
- }
- }
- 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;
- }
- void TEXT_OT_convert_whitespace(wmOperatorType *ot)
- {
- /* 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;
- /* 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);
- txt_sel_all(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- 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";
-
- /* 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);
- txt_sel_line(text);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- 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";
-
- /* 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);
- txt_jump_left(text, 0);
- txt_jump_right(text, 1);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- 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";
- /* api callbacks */
- ot->exec = text_select_word_exec;
- ot->poll = text_edit_poll;
- }
- /******************* previous marker operator *********************/
- static int text_previous_marker_exec(bContext *C, wmOperator *UNUSED(op))
- {
- Text *text = CTX_data_edit_text(C);
- TextMarker *mrk;
- int lineno;
- lineno = txt_get_span(text->lines.first, text->curl);
- mrk = text->markers.last;
- while (mrk && (mrk->lineno > lineno || (mrk->lineno == lineno && mrk->end > text->curc)))
- mrk = mrk->prev;
- if (!mrk) mrk = text->markers.last;
- if (mrk) {
- txt_move_to(text, mrk->lineno, mrk->start, 0);
- txt_move_to(text, mrk->lineno, mrk->end, 1);
- }
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
- }
- void TEXT_OT_previous_marker(wmOperatorType *ot)
- {
- /* identifiers */
- ot->name = "Previous Marker";
- ot->idname = "TEXT_OT_previous_marker";
- ot->description = "Move to previous marker";
-
- /* api callbacks */
- ot->exec = text_previous_marker_exec;
- ot->poll = text_edit_poll;
- }
- /******************* next marker operator *********************/
- static int text_next_marker_exec(bContext *C, wmOperator *UNUSED(op))
- {
- Text *text = CTX_data_edit_text(C);
- TextMarker *mrk;
- int lineno;
- lineno = txt_get_span(text->lines.first, text->curl);
- mrk = text->markers.first;
- while (mrk && (mrk->lineno < lineno || (mrk->lineno == lineno && mrk->start <= text->curc)))
- mrk = mrk->next;
- if (!mrk) mrk = text->markers.first;
- if (mrk) {
- txt_move_to(text, mrk->lineno, mrk->start, 0);
- txt_move_to(text, mrk->lineno, mrk->end, 1);
- }
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
- }
- void TEXT_OT_next_marker(wmOperatorType *ot)
- {
- /* identifiers */
- ot->name = "Next Marker";
- ot->idname = "TEXT_OT_next_marker";
- ot->description = "Move to next marker";
-
- /* api callbacks */
- ot->exec = text_next_marker_exec;
- ot->poll = text_edit_poll;
- }
- /******************* clear all markers operator *********************/
- static int text_clear_all_markers_exec(bContext *C, wmOperator *UNUSED(op))
- {
- Text *text = CTX_data_edit_text(C);
- txt_clear_markers(text, 0, 0);
- text_update_cursor_moved(C);
- WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
- return OPERATOR_FINISHED;
- }
- void TEXT_OT_markers_clear(wmOperatorType *ot)
- {
- /* identifiers */
- ot->name = "Clear All Markers";
- ot->idname = "TEXT_OT_markers_clear";
- ot->description = "Clear all markers";
-
- /* api callbacks */
- ot->exec = text_clear_all_markers_exec;
- ot->poll = text_edit_poll;
- }
- /************************ move operator ************************/
- static 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}};
- /* 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(linein->line + j)) {
- int chars;
- /* 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) {
- /* 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) {
- curs = j;
- }
- if (i - start >= max) {
- 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 - 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 - start >= relc) {
- selc = curs;
- loop = 0;
- break;
- }
- end = i + 1;
- endj = j;
- chop = 0;
- }
- i++;
- }
- }
- 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, short sel)
- {
- Text *text = st->text;
- TextLine **linep;
- int *charp;
- int oldl, 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;
- oldl = txt_get_span(text->lines.first, *linep);
- 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((*linep)->line + j)) {
- int chars;
- /* 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 - start >= max) {
- *charp = endj;
- if (j >= oldc) {
- if (ch == '\0') *charp = txt_utf8_index_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_index_to_offset((*linep)->line, start);
- loop = 0;
- break;
- }
- end = i + 1;
- endj = j + 1;
- chop = 0;
- }
- i++;
- }
- }
- if (!sel) txt_pop_sel(text);
- txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, oldl, *charp);
- }
- static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel)
- {
- Text *text = st->text;
- TextLine **linep;
- int *charp;
- int oldl, 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;
- oldl = txt_get_span(text->lines.first, *linep);
- 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((*linep)->line + j)) {
- int chars;
- /* 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 - start >= max) {
- 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++;
- }
- }
- if (!sel) txt_pop_sel(text);
- txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, oldl, *charp);
- }
- static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel)
- {
- Text *text = st->text;
- TextLine **linep;
- int *charp;
- int oldl, oldc, offl, offc, col, newl;
- text_update_character_width(st);
- if (sel) linep = &text->sell, charp = &text->selc;
- else linep = &text->curl, charp = &text->curc;
- /* store previous position */
- oldc = *charp;
- newl = oldl = txt_get_span(text->lines.first, *linep);
- wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc);
- col = text_get_char_pos(st, (*linep)->line, *charp) + offc;
- if (offl) {
- *charp = text_get_cursor_rel(st, ar, *linep, offl - 1, col);
- newl = BLI_findindex(&text->lines, linep);
- }
- else {
- if ((*linep)->prev) {
- 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);
- newl--;
- }
- else *charp = 0;
- }
- if (!sel) txt_pop_sel(text);
- txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, newl, *charp);
- }
- static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel)
- {
- Text *text = st->text;
- TextLine **linep;
- int *charp;
- int oldl, oldc, offl, offc, col, newl, visible_lines;
- text_update_character_width(st);
- if (sel) linep = &text->sell, charp = &text->selc;
- else linep = &text->curl, charp = &text->curc;
- /* store previous position */
- oldc = *charp;
- newl = oldl = txt_get_span(text->lines.first, *linep);
- wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc);
- col = text_get_char_pos(st, (*linep)->line, *charp) + offc;
- visible_lines = text_get_visible_lines(st, ar, (*linep)->line);
- if (offl < visible_lines - 1) {
- *charp = text_get_cursor_rel(st, ar, *linep, offl + 1, col);
- newl = BLI_findindex(&text->lines, linep);
- }
- else {
- if ((*linep)->next) {
- *linep = (*linep)->next;
- *charp = text_get_cursor_rel(st, ar, *linep, 0, col);
- newl++;
- }
- else *charp = (*linep)->len;
- }
- if (!sel) txt_pop_sel(text);
- txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, newl, *charp);
- }
- /* Moves the cursor vertically by the specified number of lines.
- * If the destination line is shorter than the current cursor position, the
- * cursor will be positioned at the end of this line.
- *
- * This is to replace screen_skip for PageUp/Down operations.
- */
- static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, int sel)
- {
- TextLine **linep;
- int oldl, oldc, *charp;
-
- if (sel) linep = &text->sell, charp = &text->selc;
- else linep = &text->curl, charp = &text->curc;
- oldl = txt_get_span(text->lines.first, *linep);
- oldc = *charp;
- if (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);
- txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, *linep), *charp);
- }
- static int text_move_cursor(bContext *C, int type, int select)
- {
- 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 (st && st->wordwrap && ar) txt_wrap_move_bol(st, ar, select);
- else txt_move_bol(text, select);
- break;
-
- case LINE_END:
- 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:
- txt_jump_left(text, select);
- break;
- case NEXT_WORD:
- txt_jump_right(text, select);
- break;
- case PREV_CHAR:
- txt_move_left(text, select);
- break;
- case NEXT_CHAR:
- 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");
- 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";
-
- /* 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");
- }
- /******************* move select operator ********************/
- static int text_move_select_exec(bContext *C, wmOperator *op)
- {
- int type = RNA_enum_get(op->ptr, "type");
- 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 = "Make selection from current cursor position to new cursor position type";
-
- /* 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");
- }
- /******************* 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;
- 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);
- return OPERATOR_FINISHED;
- }
- static int text_jump_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
- {
- return WM_operator_props_dialog_popup(C, op, 200, 100);
- }
- void TEXT_OT_jump(wmOperatorType *ot)
- {
- /* 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;
- /* properties */
- RNA_def_int(ot->srna, "line", 1, 1, INT_MAX, "Line", "Line number to jump to", 1, 10000);
- }
- /******************* delete operator **********************/
- static 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}};
- static int text_delete_exec(bContext *C, wmOperator *op)
- {
- Text *text = CTX_data_edit_text(C);
- int type = RNA_enum_get(op->ptr, "type");
- text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- if (type == DEL_PREV_WORD)
- txt_backspace_word(text);
- else if (type == DEL_PREV_CHAR)
- txt_backspace_char(text);
- else if (type == DEL_NEXT_WORD)
- txt_delete_word(text);
- else if (type == DEL_NEXT_CHAR)
- txt_delete_char(text);
- 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 (CTX_wm_space_text(C)->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";
-
- /* api callbacks */
- ot->exec = text_delete_exec;
- ot->poll = text_edit_poll;
- /* properties */
- RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete");
- }
- /******************* toggle overwrite operator **********************/
- static int text_toggle_overwrite_exec(bContext *C, wmOperator *UNUSED(op))
- {
- SpaceText *st = CTX_wm_space_text(C);
- st->overwrite = !st->overwrite;
- WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
- 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";
-
- /* api callbacks */
- ot->exec = text_toggle_overwrite_exec;
- ot->poll = text_space_edit_poll;
- }
- /******************* scroll operator **********************/
- /* Moves the view vertically by the specified number of lines */
- static void txt_screen_skip(SpaceText *st, ARegion *ar, int lines)
- {
- int last;
- st->top += lines;
- last = text_get_total_lines(st, ar);
- last = last - (st->viewlines / 2);
-
- if (st->top > last) st->top = last;
- if (st->top < 0) st->top = 0;
- }
- /* quick enum for tsc->zone (scroller handles) */
- enum {
- SCROLLHANDLE_BAR,
- SCROLLHANDLE_MIN_OUTSIDE,
- SCROLLHANDLE_MAX_OUTSIDE
- };
- typedef struct TextScroll {
- short old[2];
- short delta[2];
- int first;
- int scrollbar;
- int zone;
- } TextScroll;
- static int 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;
- }
- static int text_scroll_exec(bContext *C, wmOperator *op)
- {
- SpaceText *st = CTX_wm_space_text(C);
- ARegion *ar = CTX_wm_region(C);
- int lines = RNA_int_get(op->ptr, "lines");
- if (lines == 0)
- return OPERATOR_CANCELLED;
- txt_screen_skip(st, ar, lines * U.wheellinescroll);
- ED_area_tag_redraw(CTX_wm_area(C));
- return OPERATOR_FINISHED;
- }
- static void text_scroll_apply(bContext *C, wmOperator *op, 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};
- short txtdelta[2] = {0, 0};
- text_update_character_width(st);
- if (tsc->first) {
- tsc->old[0] = mval[0];
- tsc->old[1] = mval[1];
- tsc->first = 0;
- }
- ts…
Large files files are truncated, but you can click here to view the full file