diff options
author | Sv. Lockal <lockalsash@gmail.com> | 2012-01-16 20:23:25 +0400 |
---|---|---|
committer | Sv. Lockal <lockalsash@gmail.com> | 2012-01-16 20:23:25 +0400 |
commit | c150d0084f0e1cf86f063d993b31d02fc3e9c71f (patch) | |
tree | 851acfa580b5c463e6df632a77e30d4a47ea1dc1 /source/blender/blenkernel | |
parent | ae9582836e047b1da87f8178e34ad63ed0b9824e (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/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_text.h | 55 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/text.c | 801 |
2 files changed, 536 insertions, 320 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; } |