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:
authorSv. Lockal <lockalsash@gmail.com>2012-01-16 20:23:25 +0400
committerSv. Lockal <lockalsash@gmail.com>2012-01-16 20:23:25 +0400
commitc150d0084f0e1cf86f063d993b31d02fc3e9c71f (patch)
tree851acfa580b5c463e6df632a77e30d4a47ea1dc1 /source
parentae9582836e047b1da87f8178e34ad63ed0b9824e (diff)
patch [#29859] UTF-8 support for text editor.
This also fixes cursor movement in the beginning of line and adds do_versions block for converting text files with old extended ascii encoding into UTF-8.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_text.h55
-rw-r--r--source/blender/blenkernel/intern/text.c801
-rw-r--r--source/blender/blenloader/intern/readfile.c18
-rw-r--r--source/blender/editors/space_text/text_draw.c224
-rw-r--r--source/blender/editors/space_text/text_intern.h3
-rw-r--r--source/blender/editors/space_text/text_ops.c322
6 files changed, 869 insertions, 554 deletions
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index a951347d946..ffea8e0c8e2 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -46,6 +46,7 @@ void free_text (struct Text *text);
void txt_set_undostate (int u);
int txt_get_undostate (void);
struct Text* add_empty_text (const char *name);
+int txt_extended_ascii_as_utf8(char **str);
int reopen_text (struct Text *text);
struct Text* add_text (const char *file, const char *relpath);
struct Text* copy_text (struct Text *ta);
@@ -59,6 +60,8 @@ void txt_order_cursors (struct Text *text);
int txt_find_string (struct Text *text, const char *findstr, int wrap, int match_case);
int txt_has_sel (struct Text *text);
int txt_get_span (struct TextLine *from, struct TextLine *to);
+int txt_utf8_offset_to_index(char *str, int offset);
+int txt_utf8_index_to_offset(char *str, int index);
void txt_move_up (struct Text *text, short sel);
void txt_move_down (struct Text *text, short sel);
void txt_move_left (struct Text *text, short sel);
@@ -86,9 +89,9 @@ void txt_do_redo (struct Text *text);
void txt_split_curline (struct Text *text);
void txt_backspace_char (struct Text *text);
void txt_backspace_word (struct Text *text);
-int txt_add_char (struct Text *text, char add);
-int txt_add_raw_char (struct Text *text, char add);
-int txt_replace_char (struct Text *text, char add);
+int txt_add_char (struct Text *text, unsigned int add);
+int txt_add_raw_char (struct Text *text, unsigned int add);
+int txt_replace_char (struct Text *text, unsigned int add);
void txt_export_to_object(struct Text *text);
void txt_export_to_objects(struct Text *text);
void txt_unindent (struct Text *text);
@@ -127,34 +130,48 @@ int text_check_whitespace(char ch);
#define UNDO_SLEFT 005
#define UNDO_SRIGHT 006
#define UNDO_SUP 007
-#define UNDO_SDOWN 021
+#define UNDO_SDOWN 010
/* Complex movement (opcode is followed
* by 4 character line ID + a 2 character
* position ID and opcode (repeat)) */
-#define UNDO_CTO 022
-#define UNDO_STO 023
-
-/* Complex editing (opcode is followed
- * by 1 character ID and opcode (repeat)) */
-#define UNDO_INSERT 024
-#define UNDO_BS 025
-#define UNDO_DEL 026
+#define UNDO_CTO 011
+#define UNDO_STO 012
+
+/* Complex editing */
+/* 1 - opcode is followed by 1 byte for ascii character and opcode (repeat)) */
+/* 2 - opcode is followed by 2 bytes for utf-8 character and opcode (repeat)) */
+/* 3 - opcode is followed by 3 bytes for utf-8 character and opcode (repeat)) */
+/* 4 - opcode is followed by 4 bytes for unicode character and opcode (repeat)) */
+#define UNDO_INSERT_1 013
+#define UNDO_INSERT_2 014
+#define UNDO_INSERT_3 015
+#define UNDO_INSERT_4 016
+
+#define UNDO_BS_1 017
+#define UNDO_BS_2 020
+#define UNDO_BS_3 021
+#define UNDO_BS_4 022
+
+#define UNDO_DEL_1 023
+#define UNDO_DEL_2 024
+#define UNDO_DEL_3 025
+#define UNDO_DEL_4 026
/* Text block (opcode is followed
* by 4 character length ID + the text
* block itself + the 4 character length
* ID (repeat) and opcode (repeat)) */
-#define UNDO_DBLOCK 027 /* Delete block */
-#define UNDO_IBLOCK 030 /* Insert block */
+#define UNDO_DBLOCK 027 /* Delete block */
+#define UNDO_IBLOCK 030 /* Insert block */
/* Misc */
-#define UNDO_SWAP 031 /* Swap cursors */
+#define UNDO_SWAP 031 /* Swap cursors */
-#define UNDO_INDENT 032
-#define UNDO_UNINDENT 033
-#define UNDO_COMMENT 034
-#define UNDO_UNCOMMENT 035
+#define UNDO_INDENT 032
+#define UNDO_UNINDENT 033
+#define UNDO_COMMENT 034
+#define UNDO_UNCOMMENT 035
/* Marker flags */
#define TMARK_TEMP 0x01 /* Remove on non-editing events, don't save */
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 7e102bc9854..bc86a53c35e 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -33,6 +33,8 @@
#include <string.h> /* strstr */
#include <sys/types.h>
#include <sys/stat.h>
+#include <wchar.h>
+#include <wctype.h>
#include "MEM_guardedalloc.h"
@@ -215,8 +217,48 @@ Text *add_empty_text(const char *name)
return ta;
}
+/* this function replaces extended ascii characters */
+/* to a valid utf-8 sequences */
+int txt_extended_ascii_as_utf8(char **str)
+{
+ int bad_char, added= 0, i= 0;
+ int length = strlen(*str);
+
+ while ((*str)[i]) {
+ if((bad_char= BLI_utf8_invalid_byte(*str+i, length)) == -1)
+ break;
+
+ added++;
+ i+= bad_char + 1;
+ }
+
+ if (added != 0) {
+ char *newstr = MEM_mallocN(length+added+1, "text_line");
+ int mi = 0;
+ i= 0;
+
+ while ((*str)[i]) {
+ if((bad_char= BLI_utf8_invalid_byte((*str)+i, length)) == -1) {
+ memcpy(newstr+mi, (*str)+i, length - i + 1);
+ break;
+ }
+
+ memcpy(newstr+mi, (*str)+i, bad_char);
+
+ BLI_str_utf8_from_unicode((*str)[i+bad_char], newstr+mi+bad_char);
+ i+= bad_char+1;
+ mi+= bad_char+2;
+ }
+ newstr[length+added] = '\0';
+ MEM_freeN(*str);
+ *str = newstr;
+ }
+
+ return added;
+}
+
// this function removes any control characters from
-// a textline
+// a textline and fixes invalid utf-8 sequences
static void cleanup_textline(TextLine * tl)
{
@@ -229,6 +271,7 @@ static void cleanup_textline(TextLine * tl)
i--;
}
}
+ tl->len+= txt_extended_ascii_as_utf8(&tl->line);
}
int reopen_text(Text *text)
@@ -689,16 +732,10 @@ static void txt_make_dirty (Text *text)
}
/* 0:whitespace, 1:punct, 2:alphanumeric */
-static short txt_char_type (char ch)
-{
- if (ch <= ' ') return 0; /* 32 */
- if (ch <= '/') return 1; /* 47 */
- if (ch <= '9') return 2; /* 57 */
- if (ch <= '@') return 1; /* 64 */
- if (ch <= 'Z') return 2; /* 90 */
- if (ch == '_') return 2; /* 95, dont delimit '_' */
- if (ch <= '`') return 1; /* 96 */
- if (ch <= 'z') return 2; /* 122 */
+static short txt_char_type(unsigned int ch)
+{
+ if (iswspace(ch)) return 0;
+ if (iswalpha(ch) || iswdigit(ch)) return 2;
return 1;
}
@@ -731,9 +768,42 @@ static void txt_curs_first (Text *text, TextLine **linep, int *charp)
}
}
-/****************************/
+/*****************************/
/* Cursor movement functions */
-/****************************/
+/*****************************/
+
+int txt_utf8_offset_to_index(char *str, int offset)
+{
+ int index= 0, pos= 0;
+ while (pos != offset) {
+ pos += BLI_str_utf8_size(str + pos);
+ index++;
+ }
+ return index;
+}
+
+int txt_utf8_index_to_offset(char *str, int index)
+{
+ int offset= 0, pos= 0;
+ while (pos != index) {
+ offset += BLI_str_utf8_size(str + offset);
+ pos++;
+ }
+ return offset;
+}
+
+/* returns the real number of characters in string */
+/* not the same as BLI_strlen_utf8, which returns length for wide characters */
+static int txt_utf8_len(const char *src)
+{
+ int len;
+
+ for (len=0; *src; len++) {
+ src += BLI_str_utf8_size(src);
+ }
+
+ return len;
+}
void txt_move_up(Text *text, short sel)
{
@@ -747,13 +817,13 @@ void txt_move_up(Text *text, short sel)
old= *charp;
if((*linep)->prev) {
+ int index = txt_utf8_offset_to_index((*linep)->line, *charp);
*linep= (*linep)->prev;
- if (*charp > (*linep)->len) {
- *charp= (*linep)->len;
- if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->next), old, txt_get_span(text->lines.first, *linep), (unsigned short) *charp);
- } else {
- if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
- }
+ if (index > txt_utf8_len((*linep)->line)) *charp= (*linep)->len;
+ else *charp= txt_utf8_index_to_offset((*linep)->line, index);
+
+ if(!undoing)
+ txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP);
} else {
txt_move_bol(text, sel);
}
@@ -773,12 +843,13 @@ void txt_move_down(Text *text, short sel)
old= *charp;
if((*linep)->next) {
+ int index = txt_utf8_offset_to_index((*linep)->line, *charp);
*linep= (*linep)->next;
- if (*charp > (*linep)->len) {
- *charp= (*linep)->len;
- if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->prev), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp);
- } else
- if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
+ if (index > txt_utf8_len((*linep)->line)) *charp= (*linep)->len;
+ else *charp= txt_utf8_index_to_offset((*linep)->line, index);
+
+ if(!undoing)
+ txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN);
} else {
txt_move_eol(text, sel);
}
@@ -790,7 +861,7 @@ void txt_move_left(Text *text, short sel)
{
TextLine **linep;
int *charp, oundoing= undoing;
- int tabsize = 1, i=0;
+ int tabsize= 0, i= 0;
if (!text) return;
if(sel) txt_curs_sel(text, &linep, &charp);
@@ -799,32 +870,36 @@ void txt_move_left(Text *text, short sel)
undoing= 1;
- // do nice left only if there are only spaces
- // TXT_TABSIZE hardcoded in DNA_text_types.h
- if (text->flags & TXT_TABSTOSPACES) {
- tabsize = TXT_TABSIZE;
-
- if (*charp < tabsize)
- tabsize = *charp;
- else {
- for (i=0;i<(*charp);i++)
+ if (*charp== 0) {
+ if ((*linep)->prev) {
+ txt_move_up(text, sel);
+ *charp= (*linep)->len;
+ }
+ }
+ else {
+ // do nice left only if there are only spaces
+ // TXT_TABSIZE hardcoded in DNA_text_types.h
+ if (text->flags & TXT_TABSTOSPACES) {
+ tabsize= (*charp < TXT_TABSIZE) ? *charp : TXT_TABSIZE;
+
+ for (i=0; i<(*charp); i++)
if ((*linep)->line[i] != ' ') {
- tabsize = 1;
+ tabsize= 0;
break;
}
+
// if in the middle of the space-tab
- if ((*charp) % tabsize != 0)
- tabsize = ((*charp) % tabsize);
+ if (tabsize && (*charp) % TXT_TABSIZE != 0)
+ tabsize= ((*charp) % TXT_TABSIZE);
}
- }
-
- if (*charp== 0) {
- if ((*linep)->prev) {
- txt_move_up(text, sel);
- *charp= (*linep)->len;
+
+ if (tabsize)
+ (*charp)-= tabsize;
+ else {
+ const char *prev= BLI_str_prev_char_utf8((*linep)->line + *charp);
+ *charp= prev - (*linep)->line;
}
}
- else (*charp)-= tabsize;
undoing= oundoing;
if(!undoing) txt_undo_add_op(text, sel?UNDO_SLEFT:UNDO_CLEFT);
@@ -835,8 +910,7 @@ void txt_move_left(Text *text, short sel)
void txt_move_right(Text *text, short sel)
{
TextLine **linep;
- int *charp, oundoing= undoing;
- int tabsize=1, i=0;
+ int *charp, oundoing= undoing, do_tab= 0, i;
if (!text) return;
if(sel) txt_curs_sel(text, &linep, &charp);
@@ -845,32 +919,33 @@ void txt_move_right(Text *text, short sel)
undoing= 1;
- // do nice right only if there are only spaces
- // spaces hardcoded in DNA_text_types.h
- if (text->flags & TXT_TABSTOSPACES) {
- tabsize = TXT_TABSIZE;
-
- if ((*charp) + tabsize > (*linep)->len)
- tabsize = 1;
- else {
- for (i=0;i<(*charp) + tabsize - ((*charp) % tabsize);i++)
- if ((*linep)->line[i] != ' ') {
- tabsize = 1;
- break;
- }
- // if in the middle of the space-tab
- tabsize -= (*charp) % tabsize;
- }
- }
-
if (*charp== (*linep)->len) {
if ((*linep)->next) {
txt_move_down(text, sel);
*charp= 0;
}
- } else {
- (*charp)+=tabsize;
+ }
+ else {
+ // do nice right only if there are only spaces
+ // spaces hardcoded in DNA_text_types.h
+ if (text->flags & TXT_TABSTOSPACES && (*linep)->line[*charp]== ' ') {
+ do_tab= 1;
+ for (i=0; i<*charp; i++)
+ if ((*linep)->line[i]!= ' ') {
+ do_tab= 0;
+ break;
+ }
+ }
+
+ if (do_tab) {
+ int tabsize= (*charp) % TXT_TABSIZE + 1;
+ for (i=*charp+1; (*linep)->line[i]==' ' && tabsize<TXT_TABSIZE; i++)
+ tabsize++;
+ (*charp)= i;
+ }
+ else (*charp)+= BLI_str_utf8_size((*linep)->line + *charp);
}
+
undoing= oundoing;
if(!undoing) txt_undo_add_op(text, sel?UNDO_SRIGHT:UNDO_CRIGHT);
@@ -896,9 +971,12 @@ void txt_jump_left(Text *text, short sel)
count= 0;
for (i=0; i<3; i++) {
if (count < 2) {
- while (*charp>0 && txt_char_type((*linep)->line[*charp-1])==i) {
- txt_move_left(text, sel);
- count++;
+ while (*charp>0) {
+ char *sym= BLI_str_prev_char_utf8((*linep)->line + *charp);
+ if (txt_char_type(BLI_str_utf8_as_unicode(sym))==i) {
+ txt_move_left(text, sel);
+ count++;
+ } else break;
}
}
}
@@ -927,9 +1005,12 @@ void txt_jump_right(Text *text, short sel)
count= 0;
for (i=0; i<3; i++) {
if (count < 2) {
- while (*charp<(*linep)->len && txt_char_type((*linep)->line[*charp])==i) {
- txt_move_right(text, sel);
- count++;
+ while (*charp<(*linep)->len) {
+ char *sym= (*linep)->line + *charp;
+ if (txt_char_type(BLI_str_utf8_as_unicode(sym))==i) {
+ txt_move_right(text, sel);
+ count++;
+ } else break;
}
}
}
@@ -1014,6 +1095,7 @@ void txt_move_toline (Text *text, unsigned int line, short sel)
txt_move_to(text, line, 0, sel);
}
+/* Moves to a certain byte in a line, not a certain utf8-character! */
void txt_move_to (Text *text, unsigned int line, unsigned int ch, short sel)
{
TextLine **linep, *oldl;
@@ -1396,42 +1478,45 @@ static void txt_shift_markers(Text *text, int lineno, int count)
void txt_insert_buf(Text *text, const char *in_buffer)
{
- int i=0, l=0, j, u, len, lineno= -1, count= 0;
+ int l=0, u, len, lineno= -1, count= 0;
+ size_t i=0, j;
TextLine *add;
+ char *buffer;
if (!text) return;
if (!in_buffer) return;
txt_delete_sel(text);
- if(!undoing) txt_undo_add_block (text, UNDO_IBLOCK, in_buffer);
+ len= strlen(in_buffer);
+ buffer= BLI_strdupn(in_buffer, len);
+ len+= txt_extended_ascii_as_utf8(&buffer);
+
+ if(!undoing) txt_undo_add_block(text, UNDO_IBLOCK, buffer);
u= undoing;
undoing= 1;
/* Read the first line (or as close as possible */
- while (in_buffer[i] && in_buffer[i]!='\n') {
- txt_add_raw_char(text, in_buffer[i]);
- i++;
- }
+ while (buffer[i] && buffer[i]!='\n')
+ txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &i));
- if (in_buffer[i]=='\n') txt_split_curline(text);
- else { undoing = u; return; }
+ if (buffer[i]=='\n') txt_split_curline(text);
+ else { undoing = u; MEM_freeN(buffer); return; }
i++;
/* Read as many full lines as we can */
- len= strlen(in_buffer);
lineno= txt_get_span(text->lines.first, text->curl);
while (i<len) {
l=0;
- while (in_buffer[i] && in_buffer[i]!='\n') {
+ while (buffer[i] && buffer[i]!='\n') {
i++; l++;
}
- if(in_buffer[i]=='\n') {
- add= txt_new_linen(in_buffer +(i-l), l);
+ if(buffer[i]=='\n') {
+ add= txt_new_linen(buffer +(i-l), l);
BLI_insertlinkbefore(&text->lines, text->curl, add);
i++;
count++;
@@ -1441,21 +1526,19 @@ void txt_insert_buf(Text *text, const char *in_buffer)
count= 0;
}
- for (j= i-l; j<i && j<(int)strlen(in_buffer); j++) {
- txt_add_raw_char(text, in_buffer[j]);
- }
+ for (j= i-l; j<i && j<len; )
+ txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j));
break;
}
}
+
+ MEM_freeN(buffer);
if(count) {
txt_shift_markers(text, lineno, count);
- count= 0;
}
undoing= u;
-
- (void)count;
}
/******************/
@@ -1525,12 +1608,30 @@ void txt_print_undo(Text *text)
ops= "Selection ";
} else if (op==UNDO_CTO) {
ops= "Cursor ";
- } else if (op==UNDO_INSERT) {
- ops= "Insert";
- } else if (op==UNDO_BS) {
- ops= "Backspace";
- } else if (op==UNDO_DEL) {
- ops= "Delete";
+ } else if (op==UNDO_INSERT_1) {
+ ops= "Insert ascii ";
+ } else if (op==UNDO_INSERT_2) {
+ ops= "Insert 2 bytes ";
+ } else if (op==UNDO_INSERT_3) {
+ ops= "Insert 3 bytes ";
+ } else if (op==UNDO_INSERT_4) {
+ ops= "Insert unicode ";
+ } else if (op==UNDO_BS_1) {
+ ops= "Backspace for ascii ";
+ } else if (op==UNDO_BS_2) {
+ ops= "Backspace for 2 bytes ";
+ } else if (op==UNDO_BS_3) {
+ ops= "Backspace for 3 bytes ";
+ } else if (op==UNDO_BS_4) {
+ ops= "Backspace for unicode ";
+ } else if (op==UNDO_DEL_1) {
+ ops= "Delete ascii ";
+ } else if (op==UNDO_DEL_2) {
+ ops= "Delete 2 bytes ";
+ } else if (op==UNDO_DEL_3) {
+ ops= "Delete 3 bytes ";
+ } else if (op==UNDO_DEL_4) {
+ ops= "Delete unicode ";
} else if (op==UNDO_SWAP) {
ops= "Cursor swap";
} else if (op==UNDO_DBLOCK) {
@@ -1550,10 +1651,35 @@ void txt_print_undo(Text *text)
}
printf ("Op (%o) at %d = %s", op, i, ops);
- if (op==UNDO_INSERT || op==UNDO_BS || op==UNDO_DEL) {
- i++;
- printf (" - Char is %c", text->undo_buf[i]);
+ if (op >= UNDO_INSERT_1 && op <= UNDO_DEL_4) {
i++;
+ printf (" - Char is ");
+ switch (op) {
+ case UNDO_INSERT_1: case UNDO_BS_1: case UNDO_DEL_1:
+ printf ("%c", text->undo_buf[i]);
+ i++;
+ break;
+ case UNDO_INSERT_2: case UNDO_BS_2: case UNDO_DEL_2:
+ printf ("%c%c", text->undo_buf[i], text->undo_buf[i+1]);
+ i+=2;
+ break;
+ case UNDO_INSERT_3: case UNDO_BS_3: case UNDO_DEL_3:
+ printf ("%c%c%c", text->undo_buf[i], text->undo_buf[i+1], text->undo_buf[i+2]);
+ i+=3;
+ break;
+ case UNDO_INSERT_4: case UNDO_BS_4: case UNDO_DEL_4: {
+ unsigned int uc;
+ char c[BLI_UTF8_MAX+1];
+ size_t c_len;
+ uc= text->undo_buf[i]; i++;
+ uc= uc+(text->undo_buf[i]<<8); i++;
+ uc= uc+(text->undo_buf[i]<<16); i++;
+ uc= uc+(text->undo_buf[i]<<24); i++;
+ c_len= BLI_str_utf8_from_unicode(uc, c);
+ c[c_len]= '\0';
+ printf ("%s", c);
+ }
+ }
} else if (op==UNDO_STO || op==UNDO_CTO) {
i++;
@@ -1635,40 +1761,43 @@ static void txt_undo_add_op(Text *text, int op)
text->undo_buf[text->undo_pos+1]= 0;
}
+static void txt_undo_store_uint16(char *undo_buf, int *undo_pos, unsigned short value)
+{
+ undo_buf[*undo_pos]= (value)&0xff;
+ (*undo_pos)++;
+ undo_buf[*undo_pos]= (value>>8)&0xff;
+ (*undo_pos)++;
+}
+
+static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int value)
+{
+ undo_buf[*undo_pos]= (value)&0xff;
+ (*undo_pos)++;
+ undo_buf[*undo_pos]= (value>>8)&0xff;
+ (*undo_pos)++;
+ undo_buf[*undo_pos]= (value>>16)&0xff;
+ (*undo_pos)++;
+ undo_buf[*undo_pos]= (value>>24)&0xff;
+ (*undo_pos)++;
+}
+
static void txt_undo_add_block(Text *text, int op, const char *buf)
{
- int length;
-
- length= strlen(buf);
+ unsigned int length= strlen(buf);
if(!max_undo_test(text, length+11))
return;
text->undo_pos++;
text->undo_buf[text->undo_pos]= op;
-
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (length)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (length>>8)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (length>>16)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (length>>24)&0xff;
-
text->undo_pos++;
+
+ txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
+
strncpy(text->undo_buf+text->undo_pos, buf, length);
text->undo_pos+=length;
- text->undo_buf[text->undo_pos]= (length)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (length>>8)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (length>>16)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (length>>24)&0xff;
-
- text->undo_pos++;
+ txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
text->undo_buf[text->undo_pos]= op;
text->undo_buf[text->undo_pos+1]= 0;
@@ -1685,51 +1814,139 @@ void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fr
text->undo_buf[text->undo_pos]= op;
text->undo_pos++;
- text->undo_buf[text->undo_pos]= (fromc)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (fromc>>8)&0xff;
+
+ txt_undo_store_uint16(text->undo_buf, &text->undo_pos, fromc);
+ txt_undo_store_uint32(text->undo_buf, &text->undo_pos, froml);
+ txt_undo_store_uint16(text->undo_buf, &text->undo_pos, toc);
+ txt_undo_store_uint32(text->undo_buf, &text->undo_pos, tol);
+
+ text->undo_buf[text->undo_pos]= op;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (froml)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (froml>>8)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (froml>>16)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (froml>>24)&0xff;
+ text->undo_buf[text->undo_pos+1]= 0;
+}
+static void txt_undo_add_charop(Text *text, int op_start, unsigned int c)
+{
+ char utf8[BLI_UTF8_MAX];
+ size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8);
+
+ if(!max_undo_test(text, 3 + utf8_size))
+ return;
+
text->undo_pos++;
- text->undo_buf[text->undo_pos]= (toc)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (toc>>8)&0xff;
+
+ if (utf8_size < 4) {
+ text->undo_buf[text->undo_pos]= op_start + utf8_size - 1;
+ text->undo_pos++;
+
+ for (i = 0; i < utf8_size; i++) {
+ text->undo_buf[text->undo_pos]= utf8[i];
+ text->undo_pos++;
+ }
+
+ text->undo_buf[text->undo_pos]= op_start + utf8_size - 1;
+ } else {
+ text->undo_buf[text->undo_pos]= op_start + 3;
+ text->undo_pos++;
+ txt_undo_store_uint32(text->undo_buf, &text->undo_pos, c);
+ text->undo_buf[text->undo_pos]= op_start + 3;
+ }
+
+ text->undo_buf[text->undo_pos+1]= 0;
+}
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (tol)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (tol>>8)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (tol>>16)&0xff;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= (tol>>24)&0xff;
+static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos)
+{
+ unsigned short val;
+ val= undo_buf[*undo_pos]; (*undo_pos)--;
+ val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--;
+ return val;
+}
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= op;
+static unsigned int txt_undo_read_uint32(const char *undo_buf, int *undo_pos)
+{
+ unsigned int val;
+ val= undo_buf[*undo_pos]; (*undo_pos)--;
+ val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--;
+ val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--;
+ val= (val<<8)+undo_buf[*undo_pos]; (*undo_pos)--;
+ return val;
+}
- text->undo_buf[text->undo_pos+1]= 0;
+static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, short bytes)
+{
+ unsigned int unicode;
+ char utf8[BLI_UTF8_MAX+1];
+
+ switch (bytes) {
+ case 1: /* ascii */
+ unicode = undo_buf[*undo_pos]; (*undo_pos)--;
+ break;
+ case 2: /* 2-byte symbol */
+ utf8[2] = '\0';
+ utf8[1] = undo_buf[*undo_pos]; (*undo_pos)--;
+ utf8[0] = undo_buf[*undo_pos]; (*undo_pos)--;
+ unicode= BLI_str_utf8_as_unicode(utf8);
+ break;
+ case 3: /* 3-byte symbol */
+ utf8[3] = '\0';
+ utf8[2] = undo_buf[*undo_pos]; (*undo_pos)--;
+ utf8[1] = undo_buf[*undo_pos]; (*undo_pos)--;
+ utf8[0] = undo_buf[*undo_pos]; (*undo_pos)--;
+ unicode= BLI_str_utf8_as_unicode(utf8);
+ break;
+ case 4: /* 32-bit unicode symbol */
+ unicode= txt_undo_read_uint32(undo_buf, undo_pos);
+ }
+
+ return unicode;
}
-static void txt_undo_add_charop(Text *text, int op, char c)
+static unsigned short txt_redo_read_uint16(const char *undo_buf, int *undo_pos)
{
- if(!max_undo_test(text, 4))
- return;
+ unsigned short val;
+ val = undo_buf[*undo_pos]; (*undo_pos)++;
+ val = val+(undo_buf[*undo_pos]<<8); (*undo_pos)++;
+ return val;
+}
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= op;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= c;
- text->undo_pos++;
- text->undo_buf[text->undo_pos]= op;
- text->undo_buf[text->undo_pos+1]= 0;
+static unsigned int txt_redo_read_uint32(const char *undo_buf, int *undo_pos)
+{
+ unsigned int val;
+ val= undo_buf[*undo_pos]; (*undo_pos)++;
+ val= val+(undo_buf[*undo_pos]<<8); (*undo_pos)++;
+ val= val+(undo_buf[*undo_pos]<<16); (*undo_pos)++;
+ val= val+(undo_buf[*undo_pos]<<24); (*undo_pos)++;
+ return val;
+}
+
+static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, short bytes)
+{
+ unsigned int unicode;
+ char utf8[BLI_UTF8_MAX+1];
+
+ switch (bytes) {
+ case 1: /* ascii */
+ unicode = undo_buf[*undo_pos]; (*undo_pos)++;
+ break;
+ case 2: /* 2-byte symbol */
+ utf8[0] = undo_buf[*undo_pos]; (*undo_pos)++;
+ utf8[1] = undo_buf[*undo_pos]; (*undo_pos)++;
+ utf8[2] = '\0';
+ unicode= BLI_str_utf8_as_unicode(utf8);
+ break;
+ case 3: /* 3-byte symbol */
+ utf8[0] = undo_buf[*undo_pos]; (*undo_pos)++;
+ utf8[1] = undo_buf[*undo_pos]; (*undo_pos)++;
+ utf8[2] = undo_buf[*undo_pos]; (*undo_pos)++;
+ utf8[3] = '\0';
+ unicode= BLI_str_utf8_as_unicode(utf8);
+ break;
+ case 4: /* 32-bit unicode symbol */
+ unicode= txt_undo_read_uint32(undo_buf, undo_pos);
+ }
+
+ return unicode;
}
void txt_do_undo(Text *text)
@@ -1792,13 +2009,8 @@ void txt_do_undo(Text *text)
text->undo_pos--;
text->undo_pos--;
- linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
-
- charp= text->undo_buf[text->undo_pos]; text->undo_pos--;
- charp= (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
+ charp= txt_undo_read_uint16(text->undo_buf, &text->undo_pos);
if (op==UNDO_CTO) {
txt_move_toline(text, linep, 0);
@@ -1812,23 +2024,23 @@ void txt_do_undo(Text *text)
text->undo_pos--;
break;
- case UNDO_INSERT:
+ case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4:
txt_backspace_char(text);
- text->undo_pos--;
+ text->undo_pos-= op - UNDO_INSERT_1 + 1;
text->undo_pos--;
break;
- case UNDO_BS:
- txt_add_char(text, text->undo_buf[text->undo_pos]);
- text->undo_pos--;
+ case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4:
+ charp = op - UNDO_BS_1 + 1;
+ txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp));
text->undo_pos--;
- break;
-
- case UNDO_DEL:
- txt_add_char(text, text->undo_buf[text->undo_pos]);
+ break;
+
+ case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4:
+ charp = op - UNDO_DEL_1 + 1;
+ txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp));
txt_move_left(text, 0);
text->undo_pos--;
- text->undo_pos--;
break;
case UNDO_SWAP:
@@ -1836,10 +2048,7 @@ void txt_do_undo(Text *text)
break;
case UNDO_DBLOCK:
- linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
buf= MEM_mallocN(linep+1, "dblock buffer");
for (i=0; i < linep; i++){
@@ -1863,25 +2072,31 @@ void txt_do_undo(Text *text)
}
text->curc= holdc;
- linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ text->undo_pos--;
+ text->undo_pos--;
+ text->undo_pos--;
+ text->undo_pos--;
text->undo_pos--;
break;
case UNDO_IBLOCK:
- linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
-
+ linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
txt_delete_sel(text);
+
+ /* txt_backspace_char removes utf8-characters, not bytes */
+ buf= MEM_mallocN(linep+1, "iblock buffer");
+ for (i=0; i < linep; i++){
+ buf[(linep-1)-i]= text->undo_buf[text->undo_pos];
+ text->undo_pos--;
+ }
+ buf[i]= 0;
+ linep= txt_utf8_len(buf);
+ MEM_freeN(buf);
+
while (linep>0) {
txt_backspace_char(text);
- text->undo_pos--;
linep--;
}
@@ -1897,30 +2112,23 @@ void txt_do_undo(Text *text)
case UNDO_UNINDENT:
case UNDO_COMMENT:
case UNDO_UNCOMMENT:
- linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
//linep is now the end line of the selection
- charp = text->undo_buf[text->undo_pos]; text->undo_pos--;
- charp = (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos);
//charp is the last char selected or text->line->len
- //set the selcetion for this now
+
+ //set the selection for this now
text->selc = charp;
text->sell = text->lines.first;
for (i= 0; i < linep; i++) {
text->sell = text->sell->next;
}
- linep= text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
- linep = (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ linep= txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
//first line to be selected
- charp = text->undo_buf[text->undo_pos]; text->undo_pos--;
- charp = (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--;
+ charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos);
//first postion to be selected
text->curc = charp;
text->curl = text->lines.first;
@@ -2014,22 +2222,22 @@ void txt_do_redo(Text *text)
txt_move_down(text, 1);
break;
- case UNDO_INSERT:
- text->undo_pos++;
- txt_add_char(text, text->undo_buf[text->undo_pos]);
+ case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4:
text->undo_pos++;
+ charp = op - UNDO_INSERT_1 + 1;
+ txt_add_char(text, txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp));
break;
- case UNDO_BS:
+ case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4:
text->undo_pos++;
txt_backspace_char(text);
- text->undo_pos++;
+ text->undo_pos+= op - UNDO_BS_1 + 1;
break;
- case UNDO_DEL:
+ case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4:
text->undo_pos++;
txt_delete_char(text);
- text->undo_pos++;
+ text->undo_pos+= op - UNDO_DEL_1 + 1;
break;
case UNDO_SWAP:
@@ -2049,15 +2257,8 @@ void txt_do_redo(Text *text)
text->undo_pos++;
- charp= text->undo_buf[text->undo_pos];
- text->undo_pos++;
- charp= charp+(text->undo_buf[text->undo_pos]<<8);
-
- text->undo_pos++;
- linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+ charp= txt_redo_read_uint16(text->undo_buf, &text->undo_pos);
+ linep= txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
if (op==UNDO_CTO) {
txt_move_toline(text, linep, 0);
@@ -2072,12 +2273,9 @@ void txt_do_redo(Text *text)
case UNDO_DBLOCK:
text->undo_pos++;
- linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
-
+ linep= txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
txt_delete_sel(text);
+
text->undo_pos+=linep;
text->undo_pos++;
@@ -2089,10 +2287,7 @@ void txt_do_redo(Text *text)
case UNDO_IBLOCK:
text->undo_pos++;
- linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+ linep= txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
buf= MEM_mallocN(linep+1, "iblock buffer");
memcpy (buf, &text->undo_buf[text->undo_pos], linep);
@@ -2102,26 +2297,21 @@ void txt_do_redo(Text *text)
txt_insert_buf(text, buf);
MEM_freeN(buf);
- linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
- linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
- (void)linep;
-
+ text->undo_pos++;
+ text->undo_pos++;
+ text->undo_pos++;
+ text->undo_pos++;
break;
+
case UNDO_INDENT:
case UNDO_UNINDENT:
case UNDO_COMMENT:
case UNDO_UNCOMMENT:
text->undo_pos++;
- charp = text->undo_buf[text->undo_pos]; text->undo_pos++;
- charp = charp+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
+ charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos);
//charp is the first char selected or 0
- linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
- linep = linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
- linep = linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
- linep = linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+ linep= txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
//linep is now the first line of the selection
//set the selcetion for this now
text->curc = charp;
@@ -2130,13 +2320,10 @@ void txt_do_redo(Text *text)
text->curl = text->curl->next;
}
- charp = text->undo_buf[text->undo_pos]; text->undo_pos++;
- charp = charp+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
+ charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos);
//last postion to be selected
- linep= text->undo_buf[text->undo_pos]; text->undo_pos++;
- linep = linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++;
- linep = linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++;
- linep = linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++;
+
+ linep= txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
//Last line to be selected
text->selc = charp;
@@ -2203,8 +2390,7 @@ void txt_split_curline (Text *text)
left[text->curc]=0;
right= MEM_mallocN(text->curl->len - text->curc+1, "textline_string");
- if (text->curl->len - text->curc) memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc);
- right[text->curl->len - text->curc]=0;
+ memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc+1);
MEM_freeN(text->curl->line);
if (text->curl->format) MEM_freeN(text->curl->format);
@@ -2228,7 +2414,7 @@ void txt_split_curline (Text *text)
txt_clean_text(text);
txt_pop_sel(text);
- if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, '\n');
+ if(!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, '\n');
}
static void txt_delete_line (Text *text, TextLine *line)
@@ -2296,9 +2482,9 @@ static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb)
txt_clean_text(text);
}
-void txt_delete_char (Text *text)
+void txt_delete_char(Text *text)
{
- char c='\n';
+ unsigned int c='\n';
if (!text) return;
if (!text->curl) return;
@@ -2314,12 +2500,14 @@ void txt_delete_char (Text *text)
txt_pop_sel(text);
}
} else { /* Just deleting a char */
- int i= text->curc;
+ size_t c_len = 0;
+ TextMarker *mrk;
+ c= BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &c_len);
- TextMarker *mrk= txt_find_marker_region(text, text->curl, i-1, text->curl->len, 0, 0);
+ mrk= txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0);
if (mrk) {
int lineno= mrk->lineno;
- if (mrk->end==i) {
+ if (mrk->end==text->curc) {
if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) {
txt_clear_markers(text, mrk->group, TMARK_TEMP);
} else {
@@ -2328,18 +2516,15 @@ void txt_delete_char (Text *text)
return;
}
do {
- if (mrk->start>i) mrk->start--;
- mrk->end--;
+ if (mrk->start>text->curc) mrk->start-= c_len;
+ mrk->end-= c_len;
mrk= mrk->next;
} while (mrk && mrk->lineno==lineno);
}
- c= text->curl->line[i];
- while(i< text->curl->len) {
- text->curl->line[i]= text->curl->line[i+1];
- i++;
- }
- text->curl->len--;
+ memmove(text->curl->line+text->curc, text->curl->line+text->curc+c_len, text->curl->len-text->curc-c_len+1);
+
+ text->curl->len-= c_len;
txt_pop_sel(text);
}
@@ -2347,7 +2532,7 @@ void txt_delete_char (Text *text)
txt_make_dirty(text);
txt_clean_text(text);
- if(!undoing) txt_undo_add_charop(text, UNDO_DEL, c);
+ if(!undoing) txt_undo_add_charop(text, UNDO_DEL_1, c);
}
void txt_delete_word (Text *text)
@@ -2358,7 +2543,7 @@ void txt_delete_word (Text *text)
void txt_backspace_char (Text *text)
{
- char c='\n';
+ unsigned int c='\n';
if (!text) return;
if (!text->curl) return;
@@ -2378,12 +2563,15 @@ void txt_backspace_char (Text *text)
txt_pop_sel(text);
}
else { /* Just backspacing a char */
- int i= text->curc-1;
+ size_t c_len = 0;
+ TextMarker *mrk;
+ char *prev = BLI_str_prev_char_utf8(text->curl->line + text->curc);
+ c= BLI_str_utf8_as_unicode_and_size(prev, &c_len);
- TextMarker *mrk= txt_find_marker_region(text, text->curl, i, text->curl->len, 0, 0);
+ mrk= txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0);
if (mrk) {
int lineno= mrk->lineno;
- if (mrk->start==i+1) {
+ if (mrk->start==text->curc) {
if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) {
txt_clear_markers(text, mrk->group, TMARK_TEMP);
} else {
@@ -2392,19 +2580,16 @@ void txt_backspace_char (Text *text)
return;
}
do {
- if (mrk->start>i) mrk->start--;
- mrk->end--;
+ if (mrk->start>text->curc - c_len) mrk->start-= c_len;
+ mrk->end-= c_len;
mrk= mrk->next;
} while (mrk && mrk->lineno==lineno);
}
- c= text->curl->line[i];
- while(i< text->curl->len) {
- text->curl->line[i]= text->curl->line[i+1];
- i++;
- }
- text->curl->len--;
- text->curc--;
+ memcpy(text->curl->line + text->curc - c_len, text->curl->line + text->curc, text->curl->len-text->curc+1);
+
+ text->curl->len-= c_len;
+ text->curc-= c_len;
txt_pop_sel(text);
}
@@ -2412,7 +2597,7 @@ void txt_backspace_char (Text *text)
txt_make_dirty(text);
txt_clean_text(text);
- if(!undoing) txt_undo_add_charop(text, UNDO_BS, c);
+ if(!undoing) txt_undo_add_charop(text, UNDO_BS_1, c);
}
void txt_backspace_word (Text *text)
@@ -2436,11 +2621,12 @@ static void txt_convert_tab_to_spaces (Text *text)
txt_insert_buf(text, sb);
}
-static int txt_add_char_intern (Text *text, char add, int replace_tabs)
+static int txt_add_char_intern (Text *text, unsigned int add, int replace_tabs)
{
- int len, lineno;
- char *tmp;
+ int lineno;
+ char *tmp, ch[BLI_UTF8_MAX];
TextMarker *mrk;
+ size_t add_len;
if (!text) return 0;
if (!text->curl) return 0;
@@ -2458,43 +2644,42 @@ static int txt_add_char_intern (Text *text, char add, int replace_tabs)
txt_delete_sel(text);
+ add_len = BLI_str_utf8_from_unicode(add, ch);
mrk= txt_find_marker_region(text, text->curl, text->curc-1, text->curl->len, 0, 0);
if (mrk) {
lineno= mrk->lineno;
do {
- if (mrk->start>text->curc) mrk->start++;
- mrk->end++;
+ if (mrk->start>text->curc) mrk->start+= add_len;
+ mrk->end+= add_len;
mrk= mrk->next;
} while (mrk && mrk->lineno==lineno);
}
- tmp= MEM_mallocN(text->curl->len+2, "textline_string");
-
- if(text->curc) memcpy(tmp, text->curl->line, text->curc);
- tmp[text->curc]= add;
+ tmp= MEM_mallocN(text->curl->len+add_len+1, "textline_string");
- len= text->curl->len - text->curc;
- if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len);
- tmp[text->curl->len+1]=0;
+ memcpy(tmp, text->curl->line, text->curc);
+ memcpy(tmp+text->curc, ch, add_len);
+ memcpy(tmp+text->curc+add_len, text->curl->line+text->curc, text->curl->len-text->curc+1);
+
make_new_line(text->curl, tmp);
- text->curc++;
+ text->curc+= add_len;
txt_pop_sel(text);
txt_make_dirty(text);
txt_clean_text(text);
- if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, add);
+ if(!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add);
return 1;
}
-int txt_add_char (Text *text, char add)
+int txt_add_char (Text *text, unsigned int add)
{
return txt_add_char_intern(text, add, text->flags & TXT_TABSTOSPACES);
}
-int txt_add_raw_char (Text *text, char add)
+int txt_add_raw_char (Text *text, unsigned int add)
{
return txt_add_char_intern(text, add, 0);
}
@@ -2505,34 +2690,48 @@ void txt_delete_selected(Text *text)
txt_make_dirty(text);
}
-int txt_replace_char (Text *text, char add)
+int txt_replace_char (Text *text, unsigned int add)
{
- char del;
+ unsigned int del;
+ size_t del_size = 0, add_size;
+ char ch[BLI_UTF8_MAX];
if (!text) return 0;
if (!text->curl) return 0;
/* If text is selected or we're at the end of the line just use txt_add_char */
if (text->curc==text->curl->len || txt_has_sel(text) || add=='\n') {
- TextMarker *mrk;
int i= txt_add_char(text, add);
- mrk= txt_find_marker(text, text->curl, text->curc, 0, 0);
- if (mrk && mrk->end==text->curc) mrk->end--;
+ TextMarker *mrk= txt_find_marker(text, text->curl, text->curc, 0, 0);
+ if (mrk) BLI_freelinkN(&text->markers, mrk);
return i;
}
- del= text->curl->line[text->curc];
- text->curl->line[text->curc]= (unsigned char) add;
- text->curc++;
- txt_pop_sel(text);
+ del= BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size);
+ add_size= BLI_str_utf8_from_unicode(add, ch);
+ if (add_size > del_size) {
+ char *tmp= MEM_mallocN(text->curl->len+add_size-del_size+1, "textline_string");
+ memcpy(tmp, text->curl->line, text->curc);
+ memcpy(tmp+text->curc+add_size, text->curl->line+text->curc+del_size, text->curl->len-text->curc-del_size+1);
+ MEM_freeN(text->curl->line);
+ text->curl->line = tmp;
+ } else if (add_size < del_size) {
+ char *tmp= text->curl->line;
+ memmove(tmp+text->curc+add_size, tmp+text->curc+del_size, text->curl->len-text->curc-del_size+1);
+ }
+
+ memcpy(text->curl->line + text->curc, ch, add_size);
+ text->curc+= add_size;
+
+ txt_pop_sel(text);
txt_make_dirty(text);
txt_clean_text(text);
/* Should probably create a new op for this */
if(!undoing) {
- txt_undo_add_charop(text, UNDO_DEL, del);
- txt_undo_add_charop(text, UNDO_INSERT, add);
+ txt_undo_add_charop(text, UNDO_DEL_1, del);
+ txt_undo_add_charop(text, UNDO_INSERT_1, add);
}
return 1;
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 0c05655b8d7..1aa71732697 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -135,6 +135,7 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
+#include "BKE_text.h" // for txt_extended_ascii_as_utf8
#include "BKE_texture.h" // for open_plugin_tex
#include "BKE_tracking.h"
#include "BKE_utildefines.h" // SWITCH_INT DATA ENDB DNA1 O_BINARY GLOB USER TEST REND
@@ -12976,6 +12977,23 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* put compatibility code here until next subversion bump */
{
+ {
+ /* convert extended ascii to utf-8 for text editor */
+ Text *text;
+ for (text= main->text.first; text; text= text->id.next)
+ if(!(text->flags & TXT_ISEXT)) {
+ TextLine *tl;
+
+ for (tl= text->lines.first; tl; tl= tl->next) {
+ int added= txt_extended_ascii_as_utf8(&tl->line);
+ tl->len+= added;
+
+ /* reset cursor position if line was changed */
+ if (added && tl == text->curl)
+ text->curc = 0;
+ }
+ }
+ }
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 25b9c2f2864..8a78f236fea 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -72,7 +72,7 @@ static void text_font_end(SpaceText *UNUSED(st))
{
}
-static int text_font_draw(SpaceText *UNUSED(st), int x, int y, char *str)
+static int text_font_draw(SpaceText *UNUSED(st), int x, int y, const char *str)
{
BLF_position(mono, x, y, 0);
BLF_draw(mono, str, BLF_DRAW_STR_DUMMY_MAX);
@@ -92,19 +92,28 @@ static int text_font_draw_character(SpaceText *st, int x, int y, char c)
return st->cwidth;
}
-int text_font_width(SpaceText *UNUSED(st), const char *str)
+static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char *c)
{
- return BLF_width(mono, str);
+ char str[BLI_UTF8_MAX+1];
+ size_t len = BLI_str_utf8_size(c);
+ memcpy(str, c, len);
+ str[len]= '\0';
+
+ BLF_position(mono, x, y, 0);
+ BLF_draw(mono, str, len);
+
+ return st->cwidth;
}
/****************** flatten string **********************/
-static void flatten_string_append(FlattenString *fs, char c, int accum)
+static void flatten_string_append(FlattenString *fs, const char *c, int accum, int len)
{
- if(fs->pos>=fs->len && fs->pos>=sizeof(fs->fixedbuf)-1) {
+ int i;
+
+ if(fs->pos+len > fs->len) {
char *nbuf; int *naccum;
- if(fs->len) fs->len*= 2;
- else fs->len= sizeof(fs->fixedbuf) * 2;
+ fs->len*= 2;
nbuf= MEM_callocN(sizeof(*fs->buf)*fs->len, "fs->buf");
naccum= MEM_callocN(sizeof(*fs->accum)*fs->len, "fs->accum");
@@ -121,35 +130,45 @@ static void flatten_string_append(FlattenString *fs, char c, int accum)
fs->accum= naccum;
}
- fs->buf[fs->pos]= c;
- fs->accum[fs->pos]= accum;
-
- fs->pos++;
+ for (i = 0; i < len; i++)
+ {
+ fs->buf[fs->pos+i]= c[i];
+ fs->accum[fs->pos+i]= accum;
+ }
+
+ fs->pos+= len;
}
int flatten_string(SpaceText *st, FlattenString *fs, const char *in)
{
- int r = 0, i = 0;
+ int r, i, total = 0;
memset(fs, 0, sizeof(FlattenString));
fs->buf= fs->fixedbuf;
fs->accum= fs->fixedaccum;
-
- for(r=0, i=0; *in; r++, in++) {
- if(*in=='\t') {
- if(fs->pos && *(in-1)=='\t')
- i= st->tabnumber;
- else if(st->tabnumber > 0)
- i= st->tabnumber - (fs->pos%st->tabnumber);
+ fs->len = sizeof(fs->fixedbuf);
+ for(r = 0, i = 0; *in; r++) {
+ if(*in=='\t') {
+ i= st->tabnumber - (total%st->tabnumber);
+ total+= i;
+
while(i--)
- flatten_string_append(fs, ' ', r);
+ flatten_string_append(fs, " ", r, 1);
+
+ in++;
+ }
+ else {
+ size_t len= BLI_str_utf8_size(in);
+ flatten_string_append(fs, in, r, len);
+ in += len;
+ total++;
}
- else
- flatten_string_append(fs, *in, r);
}
+
+ flatten_string_append(fs, "\0", r, 1);
- return fs->pos;
+ return total;
}
void flatten_string_free(FlattenString *fs)
@@ -304,9 +323,8 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
}
else orig = 0xFF;
- flatten_string(st, &fs, line->line);
+ len = flatten_string(st, &fs, line->line);
str = fs.buf;
- len = strlen(str);
if(!text_check_format_len(line, len)) {
flatten_string_free(&fs);
return;
@@ -318,7 +336,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
if(*str == '\\') {
*fmt = prev; fmt++; str++;
if(*str == '\0') break;
- *fmt = prev; fmt++; str++;
+ *fmt = prev; fmt++; str += BLI_str_utf8_size(str);
continue;
}
/* Handle continuations */
@@ -339,14 +357,16 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
}
*fmt = 'l';
+ str += BLI_str_utf8_size(str) - 1;
}
/* Not in a string... */
else {
/* Deal with comments first */
- if(prev == '#' || *str == '#')
+ if(prev == '#' || *str == '#') {
*fmt = '#';
- /* Strings */
- else if(*str == '"' || *str == '\'') {
+ str += BLI_str_utf8_size(str) - 1;
+ } else if(*str == '"' || *str == '\'') {
+ /* Strings */
find = *str;
cont = (*str== '"') ? TXT_DBLQUOTSTR : TXT_SNGQUOTSTR;
if(*(str+1) == find && *(str+2) == find) {
@@ -371,14 +391,18 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
}
*fmt = 'n';
}
- else
+ else {
+ str += BLI_str_utf8_size(str) - 1;
*fmt = 'q';
+ }
/* Punctuation */
else if(text_check_delim(*str))
*fmt = '!';
/* Identifiers and other text (no previous ws. or delims. so text continues) */
- else if(prev == 'q')
+ else if(prev == 'q') {
+ str += BLI_str_utf8_size(str) - 1;
*fmt = 'q';
+ }
/* Not ws, a digit, punct, or continuing text. Must be new, check for special words */
else {
/* Special vars(v) or built-in keywords(b) */
@@ -395,8 +419,10 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
}
*fmt = prev;
}
- else
+ else {
+ str += BLI_str_utf8_size(str) - 1;
*fmt = 'q';
+ }
}
}
prev = *fmt;
@@ -408,14 +434,11 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next)
*fmt = '\0'; fmt++;
*fmt = cont;
- /* Debugging */
- //print_format(st, line);
-
/* If continuation has changed and we're allowed, process the next line */
if(cont!=orig && do_next && line->next) {
txt_format_line(st, line->next, do_next);
}
-
+
flatten_string_free(&fs);
}
@@ -539,13 +562,14 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *
}
max= wrap_width(st, ar);
+ cursin = txt_utf8_offset_to_index(linein->line, cursin);
while(linep) {
start= 0;
end= max;
chop= 1;
*offc= 0;
- for(i=0, j=0; linep->line[j]!='\0'; j++) {
+ for(i=0, j=0; linep->line[j]; j+=BLI_str_utf8_size(linep->line+j)) {
int chars;
/* Mimic replacement of tabs */
@@ -591,6 +615,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *
}
}
+/* cursin - mem, offc - view */
void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int *offl, int *offc)
{
int i, j, start, end, chars, max, chop;
@@ -607,8 +632,9 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi
end= max;
chop= 1;
*offc= 0;
+ cursin = txt_utf8_offset_to_index(linein->line, cursin);
- for(i=0, j=0; linein->line[j]!='\0'; j++) {
+ for(i=0, j=0; linein->line[j]; j += BLI_str_utf8_size(linein->line + j)) {
/* Mimic replacement of tabs */
ch= linein->line[j];
@@ -653,7 +679,7 @@ int text_get_char_pos(SpaceText *st, const char *line, int cur)
{
int a=0, i;
- for(i=0; i<cur && line[i]; i++) {
+ for(i=0; i<cur && line[i]; i += BLI_str_utf8_size(line + i)) {
if(line[i]=='\t')
a += st->tabnumber-a%st->tabnumber;
else
@@ -662,54 +688,65 @@ int text_get_char_pos(SpaceText *st, const char *line, int cur)
return a;
}
-static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char *format, int skip)
+static const char *txt_utf8_get_nth(const char *str, int n)
+{
+ int pos= 0;
+ while (str[pos] && n--) {
+ pos+= BLI_str_utf8_size(str + pos);
+ }
+ return str + pos;
+}
+
+static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w, const char *format, int skip)
{
FlattenString fs;
- int basex, i, a, len, start, end, max, lines;
+ int basex, i, a, start, end, max, lines; /* view */
+ int mi, ma, mstart, mend; /* mem */
- len= flatten_string(st, &fs, str);
+ flatten_string(st, &fs, str);
str= fs.buf;
max= w/st->cwidth;
if(max<8) max= 8;
basex= x;
-
lines= 1;
- start= 0;
- end= max;
- for(i=0; i<len; i++) {
+
+ start= 0; mstart= 0;
+ end= max; mend= txt_utf8_get_nth(str, max) - str;
+
+ for(i=0, mi=0; str[mi]; i++, mi+=BLI_str_utf8_size(str+mi)) {
if(i-start >= max) {
/* skip hidden part of line */
if(skip) {
skip--;
- start= end;
- end += max;
+ start= end; mstart= mend;
+ end += max; mend= txt_utf8_get_nth(str+mend, max) - str;
continue;
}
/* Draw the visible portion of text on the overshot line */
- for(a=start; a<end; a++) {
+ for(a=start, ma=mstart; a<end; a++, ma+=BLI_str_utf8_size(str+ma)) {
if(st->showsyntax && format) format_draw_color(format[a]);
- x += text_font_draw_character(st, x, y, str[a]);
+ x += text_font_draw_character_utf8(st, x, y, str + ma);
}
y -= st->lheight;
x= basex;
lines++;
- start= end;
- end += max;
+ start= end; mstart= mend;
+ end += max; mend= txt_utf8_get_nth(str+mend, max) - str;
if(y<=0) break;
}
- else if(str[i]==' ' || str[i]=='-') {
- end = i+1;
+ else if(str[mi]==' ' || str[mi]=='-') {
+ end = i+1; mend = mi+1;
}
}
/* Draw the remaining text */
- for(a=start; a<len && y > 0; a++) {
+ for(a=start, ma=mstart; str[ma] && y > 0; a++, ma+=BLI_str_utf8_size(str+ma)) {
if(st->showsyntax && format)
format_draw_color(format[a]);
- x += text_font_draw_character(st, x, y, str[a]);
+ x += text_font_draw_character_utf8(st, x, y, str+ma);
}
flatten_string_free(&fs);
@@ -717,45 +754,36 @@ static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char
return lines;
}
-static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, char *format)
+static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, const char *format)
{
FlattenString fs;
- int r=0, w= 0, amount;
- int *acc;
- char *in;
+ int *acc, r=0;
+ const char *in;
- w= flatten_string(st, &fs, str);
+ int w= flatten_string(st, &fs, str);
if(w < cshift) {
flatten_string_free(&fs);
return 0; /* String is shorter than shift */
}
- in= fs.buf+cshift;
+ in= txt_utf8_get_nth(fs.buf, cshift);
acc= fs.accum+cshift;
w= w-cshift;
if(draw) {
+ int amount = maxwidth ? MIN2(w, maxwidth) : w;
+
if(st->showsyntax && format) {
- int a;
+ int a, str_shift= 0;
format = format+cshift;
-
- amount = strlen(in);
- if(maxwidth)
- amount= MIN2(amount, maxwidth);
-
+
for(a = 0; a < amount; a++) {
format_draw_color(format[a]);
- x += text_font_draw_character(st, x, y, in[a]);
+ x += text_font_draw_character_utf8(st, x, y, in + str_shift);
+ str_shift += BLI_str_utf8_size(in + str_shift);
}
}
- else {
- amount = strlen(in);
- if(maxwidth)
- amount= MIN2(amount, maxwidth);
-
- in[amount]= 0;
- text_font_draw(st, x, y, in);
- }
+ else text_font_draw(st, x, y, in);
}
else {
while(w-- && *acc++ < maxwidth)
@@ -976,8 +1004,8 @@ int text_get_visible_lines(SpaceText *st, ARegion *ar, const char *str)
max= wrap_width(st, ar);
lines= 1;
start= 0;
- end= max;
- for(i= 0, j= 0; str[j] != '\0'; j++) {
+ end= max;
+ for(i= 0, j= 0; str[j]; j+=BLI_str_utf8_size(str+j)) {
/* Mimic replacement of tabs */
ch= str[j];
if(ch=='\t') {
@@ -1421,7 +1449,7 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar)
BLI_strncpy(str, item->name, SUGG_LIST_WIDTH);
- w = text_font_width(st, str);
+ w = BLF_width(mono, str);
if(item == sel) {
UI_ThemeColor(TH_SHADE2);
@@ -1496,8 +1524,6 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
glRecti(x-4, y, ar->winx, y-st->lheight), y-=st->lheight;
glRecti(x-4, y, x+toc*st->cwidth, y-st->lheight); y-=st->lheight;
-
- (void)y;
}
}
else {
@@ -1569,8 +1595,9 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
{
TextLine *startl, *endl, *linep;
Text *text = st->text;
- int b, c, startc, endc, find, stack;
- int viewc, viewl, offl, offc, x, y;
+ int b, fc, find, stack, viewc, viewl, offl, offc, x, y;
+ int startc, endc, c;
+
char ch;
// showsyntax must be on or else the format string will be null
@@ -1584,21 +1611,23 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
linep= startl;
c= startc;
+ fc= txt_utf8_offset_to_index(linep->line, startc);
endl= NULL;
endc= -1;
find= -b;
stack= 0;
/* Dont highlight backets if syntax HL is off or bracket in string or comment. */
- if(!linep->format || linep->format[c] == 'l' || linep->format[c] == '#')
+ if(!linep->format || linep->format[fc] == 'l' || linep->format[fc] == '#')
return;
if(b>0) {
/* opening bracket, search forward for close */
- c++;
+ fc++;
+ c+= BLI_str_utf8_size(linep->line+c);
while(linep) {
while(c<linep->len) {
- if(linep->format && linep->format[c] != 'l' && linep->format[c] != '#') {
+ if(linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') {
b= text_check_bracket(linep->line[c]);
if(b==find) {
if(stack==0) {
@@ -1612,19 +1641,22 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
stack++;
}
}
- c++;
+ fc++;
+ c+= BLI_str_utf8_size(linep->line+c);
}
if(endl) break;
linep= linep->next;
c= 0;
+ fc= 0;
}
}
else {
/* closing bracket, search backward for open */
- c--;
+ fc--;
+ if (c>0) c -= linep->line+c-BLI_str_prev_char_utf8(linep->line+c);
while(linep) {
- while(c>=0) {
- if(linep->format && linep->format[c] != 'l' && linep->format[c] != '#') {
+ while(fc>=0) {
+ if(linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') {
b= text_check_bracket(linep->line[c]);
if(b==find) {
if(stack==0) {
@@ -1638,11 +1670,17 @@ static void draw_brackets(SpaceText *st, ARegion *ar)
stack++;
}
}
- c--;
+ fc--;
+ if (c>0) c -= linep->line+c-BLI_str_prev_char_utf8(linep->line+c);
}
if(endl) break;
linep= linep->prev;
- if(linep) c= linep->len-1;
+ if(linep) {
+ if (linep->format) fc= strlen(linep->format)-1;
+ else fc= -1;
+ if (linep->len) c= BLI_str_prev_char_utf8(linep->line+linep->len)-linep->line;
+ else fc= -1;
+ }
}
}
diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h
index 62cd4fedf0e..043fb97547b 100644
--- a/source/blender/editors/space_text/text_intern.h
+++ b/source/blender/editors/space_text/text_intern.h
@@ -47,9 +47,6 @@ struct wmWindowManager;
/* text_draw.c */
void draw_text_main(struct SpaceText *st, struct ARegion *ar);
-int text_font_width_character(struct SpaceText *st);
-int text_font_width(struct SpaceText *st, const char *str);
-
void text_update_line_edited(struct TextLine *line);
void text_update_edited(struct Text *text);
void text_update_character_width(struct SpaceText *st);
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 19f0c9bba61..eab06474546 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -1420,7 +1420,7 @@ static int text_get_cursor_rel(SpaceText* st, ARegion *ar, TextLine *linein, int
end= max;
chop= loop= 1;
- for(i=0, j=0; loop; j++) {
+ for(i=0, j=0; loop; j+=BLI_str_utf8_size(linein->line+j)) {
int chars;
/* Mimic replacement of tabs */
ch= linein->line[j];
@@ -1595,7 +1595,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel)
chop= loop= 1;
*charp= 0;
- for(i=0, j=0; loop; j++) {
+ for(i=0, j=0; loop; j+=BLI_str_utf8_size((*linep)->line+j)) {
int chars;
/* Mimic replacement of tabs */
ch= (*linep)->line[j];
@@ -1610,7 +1610,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel)
*charp= endj;
if(j>=oldc) {
- if(ch=='\0') *charp= start;
+ if(ch=='\0') *charp= txt_utf8_index_to_offset((*linep)->line, start);
loop= 0;
break;
}
@@ -1623,7 +1623,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel)
}
else if(ch==' ' || ch=='-' || ch=='\0') {
if(j>=oldc) {
- *charp= start;
+ *charp= txt_utf8_index_to_offset((*linep)->line, start);
loop= 0;
break;
}
@@ -1663,7 +1663,7 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel)
chop= loop= 1;
*charp= 0;
- for(i=0, j=0; loop; j++) {
+ for(i=0, j=0; loop; j+=BLI_str_utf8_size((*linep)->line+j)) {
int chars;
/* Mimic replacement of tabs */
ch= (*linep)->line[j];
@@ -1675,7 +1675,7 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel)
while(chars--) {
if(i-start>=max) {
- if(chop) endj= j-1;
+ if(chop) endj= BLI_str_prev_char_utf8((*linep)->line+j)-(*linep)->line;
if(endj>=oldc) {
if(ch=='\0') *charp= (*linep)->len;
@@ -2364,148 +2364,183 @@ typedef struct SetSelection {
short old[2];
} SetSelection;
-static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int sel)
+static int flatten_len(SpaceText *st, const char *str)
{
- FlattenString fs;
- Text *text= st->text;
- TextLine **linep;
- int *charp;
- int w;
-
- text_update_character_width(st);
+ int i, total = 0;
- if(sel) { linep= &text->sell; charp= &text->selc; }
- else { linep= &text->curl; charp= &text->curc; }
+ for(i = 0; str[i]; i += BLI_str_utf8_size(str+i)) {
+ if(str[i]=='\t') {
+ total += st->tabnumber - total%st->tabnumber;
+ }
+ else total++;
+ }
- y= (ar->winy - 2 - y)/st->lheight;
-
- if(st->showlinenrs)
- x-= TXT_OFFSET+TEXTXLOC;
- else
- x-= TXT_OFFSET;
+ return total;
+}
- if(x<0) x= 0;
- x = (x/st->cwidth) + st->left;
+static int flatten_index_to_offset(SpaceText *st, const char *str, int index)
+{
+ int i, j;
+ for (i= 0, j= 0; i < index; j += BLI_str_utf8_size(str+j))
+ if(str[j]=='\t')
+ i += st->tabnumber - i%st->tabnumber;
+ else
+ i++;
- if(st->wordwrap) {
- int i, j, endj, curs, max, chop, start, end, loop, found;
- char ch;
-
- /* Point to first visible line */
- *linep= text->lines.first;
- i= st->top;
- while(i>0 && *linep) {
- int lines= text_get_visible_lines(st, ar, (*linep)->line);
+ return j;
+}
- if (i-lines<0) {
- y+= i;
- break;
- } else {
- *linep= (*linep)->next;
- i-= lines;
- }
+static TextLine *get_first_visible_line(SpaceText *st, ARegion *ar, int *y)
+{
+ TextLine *linep = st->text->lines.first;
+ int i;
+ for (i = st->top; i > 0 && linep; ) {
+ int lines = text_get_visible_lines(st, ar, linep->line);
+
+ if (i-lines < 0) {
+ *y += i;
+ break;
+ } else {
+ linep = linep->next;
+ i -= lines;
}
+ }
+ return linep;
+}
- max= wrap_width(st, ar);
-
- loop= 1;
- found= 0;
- while(loop && *linep) {
- start= 0;
- end= max;
- chop= 1;
- curs= 0;
- endj= 0;
- for(i=0, j=0; loop; 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--) {
- /* Gone too far, go back to last wrap point */
- if(y<0) {
- *charp= endj;
- loop= 0;
- break;
+static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, int y, int sel)
+{
+ Text *text = st->text;
+ int max = wrap_width(st, ar); /* view */
+ int charp; /* mem */
+ int loop = 1, found = 0; /* flags */
+ char ch;
+
+ /* Point to first visible line */
+ TextLine *linep = get_first_visible_line(st, ar, &y);
+
+ while(loop && linep) {
+ int i = 0, start = 0, end = max; /* view */
+ int j = 0, curs = 0, endj = 0; /* mem */
+ int chop = 1; /* flags */
+
+ for (; 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--) {
+ /* Gone too far, go back to last wrap point */
+ if (y < 0) {
+ charp = endj;
+ loop = 0;
+ break;
/* Exactly at the cursor */
- }
- else if(y==0 && i-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= 1;
+ }
+ else if (y == 0 && i-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 = 1;
/* Prepare curs for next wrap */
+ }
+ else if(i - end == x) {
+ 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 (charp > endj && !chop && ch!='\0') charp = endj;
+ loop = 0;
+ break;
}
- else if(i-end==x) {
- curs= j;
+
+ if(chop) endj = j;
+ start = end;
+ end += max;
+
+ if(j < linep->len)
+ y--;
+
+ chop = 1;
+ if (y == 0 && i-start >= x) {
+ charp = curs;
+ loop = 0;
+ break;
}
- if(i-start>=max) {
- 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;
- loop= 0;
- break;
- }
-
- if(chop) endj= j;
- start= end;
- end += max;
-
- if(j<(*linep)->len)
- y--;
-
- chop= 1;
- if(y==0 && i-start>=x) {
- *charp= curs;
- loop= 0;
- break;
- }
+ }
+ else if (ch == ' ' || ch == '-' || ch == '\0') {
+ if (found) {
+ loop = 0;
+ break;
}
- else if(ch==' ' || ch=='-' || ch=='\0') {
- if(found) {
- loop= 0;
- break;
- }
-
- if(y==0 && i-start>=x) {
- *charp= curs;
- loop= 0;
- break;
- }
- end = i+1;
- endj = j;
- chop= 0;
+
+ if(y == 0 && i-start >= x) {
+ charp = curs;
+ loop = 0;
+ break;
}
- i++;
+ end = i + 1;
+ endj = j;
+ chop = 0;
}
- if(ch=='\0') break;
+ i++;
}
- if(!loop || found) break;
+
+ if(ch == '\0') break;
+ }
+
+ if(!loop || found) break;
+
+ if(!linep->next) {
+ charp = linep->len;
+ break;
+ }
+
+ /* On correct line but didn't meet cursor, must be at end */
+ if (y == 0) {
+ charp = linep->len;
+ break;
+ }
+ linep = linep->next;
+
+ y--;
+ }
+
+ if(sel) { text->sell = linep; text->selc = charp; }
+ else { text->curl = linep; text->curc = charp; }
+}
- if(!(*linep)->next) {
- *charp= (*linep)->len;
- break;
- }
+static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int sel)
+{
+ Text *text= st->text;
+ text_update_character_width(st);
+ y= (ar->winy - 2 - y)/st->lheight;
- /* On correct line but didn't meet cursor, must be at end */
- if(y==0) {
- *charp= (*linep)->len;
- break;
- }
- *linep= (*linep)->next;
- y--;
- }
+ if(st->showlinenrs) x-= TXT_OFFSET+TEXTXLOC;
+ else x-= TXT_OFFSET;
+ if(x<0) x= 0;
+ x = (x/st->cwidth) + 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) {
@@ -2516,10 +2551,9 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int
}
- w= flatten_string(st, &fs, (*linep)->line);
- if(x<w) *charp= fs.accum[x];
+ w= flatten_len(st, (*linep)->line);
+ if(x<w) *charp= flatten_index_to_offset(st, (*linep)->line, x);
else *charp= (*linep)->len;
- flatten_string_free(&fs);
}
if(!sel) txt_pop_sel(text);
}
@@ -2762,19 +2796,23 @@ 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;
- int done = 0, i;
+ int done = 0;
+ size_t i = 0;
+ unsigned int code;
text_drawcache_tag_update(st, 0);
str= RNA_string_get_alloc(op->ptr, "text", NULL, 0);
if(st && st->overwrite) {
- for(i=0; str[i]; i++) {
- done |= txt_replace_char(text, str[i]);
+ while (str[i]) {
+ code = BLI_str_utf8_as_unicode_step(str, &i);
+ done |= txt_replace_char(text, code);
}
} else {
- for(i=0; str[i]; i++) {
- done |= txt_add_char(text, str[i]);
+ while (str[i]) {
+ code = BLI_str_utf8_as_unicode_step(str, &i);
+ done |= txt_add_char(text, code);
}
}
@@ -2802,9 +2840,17 @@ static int text_insert_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_PASS_THROUGH;
}
else {
- char str[2];
- str[0]= event->ascii;
- str[1]= '\0';
+ char str[BLI_UTF8_MAX+1];
+ size_t len;
+
+ if (event->utf8_buf[0]) {
+ len = BLI_str_utf8_size(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);
}
}