Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorBruno Boaventura Scholl <brunobbs>2019-04-25 20:25:58 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-04-25 20:25:58 +0300
commitb4c14faeaf6fb4e6a7b95a1eea1fa18fa94d03e2 (patch)
tree297a04dfb67cf5b6d30788064531bbdf4627a629 /source
parent4d1128872ecfe5f5b0fb794d2562a26f8b3b76ad (diff)
Text editor: convert tabs to spaces on paste
If the Tabs as Spaces settings is enabled for the text block. This avoids issues with inconsistent indentation when pasting Python code from another source. Differential Revision: https://developer.blender.org/D4512
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/space_text/text_ops.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 4d904822360..1c7e7b13589 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -61,6 +61,83 @@
static void txt_screen_clamp(SpaceText *st, ARegion *ar);
+/************************ util ***************************/
+
+/**
+ * Tests if the given character represents a start of a new line or the
+ * indentation part of a line.
+ * \param c: The current character.
+ * \param r_last_state: A pointer to a flag representing the last state. The
+ * flag may be modified.
+ */
+static void test_line_start(char c, bool *r_last_state)
+{
+ if (c == '\n') {
+ *r_last_state = true;
+ }
+ else if (!ELEM(c, '\t', ' ')) {
+ *r_last_state = false;
+ }
+}
+
+/**
+ * This function converts the indentation tabs from a buffer to spaces.
+ * \param buf: A pointer to a cstring.
+ * \param tab_size: The size, in spaces, of the tab character.
+ */
+static char *buf_tabs_to_spaces(const char *in_buf, const int tab_size)
+{
+ /* Get the number of tab characters in buffer. */
+ bool line_start = true;
+ int num_tabs = 0;
+
+ for (int in_offset = 0; in_buf[in_offset]; in_offset++) {
+ /* Verify if is an indentation whitespace character. */
+ test_line_start(in_buf[in_offset], &line_start);
+
+ if (in_buf[in_offset] == '\t' && line_start) {
+ num_tabs++;
+ }
+ }
+
+ /* Allocate output before with extra space for expanded tabs. */
+ const int out_size = strlen(in_buf) + num_tabs * (tab_size - 1);
+ char *out_buf = MEM_mallocN(out_size * sizeof(char), __func__);
+
+ /* Fill output buffer. */
+ int spaces_until_tab = 0;
+ int out_offset = 0;
+ line_start = true;
+
+ for (int in_offset = 0; in_buf[in_offset]; in_offset++) {
+ /* Verify if is an indentation whitespace character. */
+ test_line_start(in_buf[in_offset], &line_start);
+
+ if (in_buf[in_offset] == '\t' && line_start) {
+ /* Calculate tab size so it fills until next indentation. */
+ int num_spaces = tab_size - (spaces_until_tab % tab_size);
+ spaces_until_tab = 0;
+
+ /* Write to buffer. */
+ memset(&out_buf[out_offset], ' ', num_spaces);
+ out_offset += num_spaces;
+ }
+ else {
+ if (in_buf[in_offset] == ' ') {
+ spaces_until_tab++;
+ }
+ else if (in_buf[in_offset] == '\n') {
+ spaces_until_tab = 0;
+ }
+
+ out_buf[out_offset++] = in_buf[in_offset];
+ }
+ }
+
+ out_buf[out_offset] = '\0';
+ return out_buf;
+}
+
/************************ poll ***************************/
BLI_INLINE int text_pixel_x_to_column(SpaceText *st, const int x)
@@ -764,6 +841,14 @@ static int text_paste_exec(bContext *C, wmOperator *op)
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
TextUndoBuf *utxt = ED_text_undo_push_init(C);
+
+ /* Convert clipboard content indentation to spaces if specified */
+ if (text->flags & TXT_TABSTOSPACES) {
+ char *new_buf = buf_tabs_to_spaces(buf, TXT_TABSIZE);
+ MEM_freeN(buf);
+ buf = new_buf;
+ }
+
txt_insert_buf(text, utxt, buf);
text_update_edited(text);