Fix T46293: Text Editor: Convert to spaces/to tabs was totally broken with non-ASCII strings.

Code was totally unaware of UTF8, also it was needlessly complicated...
This commit is contained in:
Bastien Montagne 2015-09-28 10:04:37 +02:00
parent 1a6d45527f
commit fc97204742
Notes: blender-bot 2023-02-14 08:35:53 +01:00
Referenced by issue #46304, Point density texture is ignored by blender internal
Referenced by issue #46293, text crash
1 changed files with 70 additions and 78 deletions

View File

@ -1054,108 +1054,100 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
Text *text = CTX_data_edit_text(C);
TextLine *tmp;
FlattenString fs;
size_t a, j;
char *new_line;
int extra, number; //unknown for now
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) {
const char *text_check_line = tmp->line;
const int text_check_line_len = tmp->len;
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 < text_check_line_len; 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);
char *new_line;
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);
flatten_string(st, &fs, tmp->line);
new_line = BLI_strdup(fs.buf);
flatten_string_free(&fs);
/* 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;
if (tmp->len > max_len) {
max_len = tmp->len;
}
}
if (type == TO_TABS) { // Converting to tabs
//start over from the beginning
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;
extra = 0;
for (a = 0; a < text_check_line_len; a++) {
number = 0;
for (j = 0; j < (size_t)st->tabnumber; j++) {
if ((a + j) <= text_check_line_len) { //check to make sure we are not pass the end of the line
if (text_check_line[a + j] != ' ') {
number = 1;
char *tmp_line_cur = tmp_line;
const size_t tab_len = st->tabnumber;
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;
}
}
if (!number) { //found all number of space to equal a tab
a = a + (st->tabnumber - 1);
extra = extra + 1;
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 (extra > 0) { //got tabs make malloc and do what you have to do
new_line = MEM_callocN(text_check_line_len - (((st->tabnumber * extra) - extra) - 1), "Converted_Line");
extra = 0; //reuse vars
for (a = 0; a < text_check_line_len; a++) {
number = 0;
for (j = 0; j < (size_t)st->tabnumber; j++) {
if ((a + j) <= text_check_line_len) { //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);
if (tmp_line_cur != tmp_line) {
*tmp_line_cur = '\0';
#ifndef NDEBUG
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);
#endif
/* 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 = BLI_strdup(tmp_line);
tmp->len = strlen(tmp_line);
tmp->format = NULL;
}
}
MEM_freeN(tmp_line);
}
text_update_edited(text);