[Bf-blender-cvs] [b4c14faeaf6] master: Text editor: convert tabs to spaces on paste

Bruno Boaventura Scholl noreply at git.blender.org
Thu Apr 25 19:34:57 CEST 2019


Commit: b4c14faeaf6fb4e6a7b95a1eea1fa18fa94d03e2
Author: Bruno Boaventura Scholl
Date:   Thu Apr 25 19:25:58 2019 +0200
Branches: master
https://developer.blender.org/rBb4c14faeaf6fb4e6a7b95a1eea1fa18fa94d03e2

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

===================================================================

M	source/blender/editors/space_text/text_ops.c

===================================================================

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);



More information about the Bf-blender-cvs mailing list