diff options
Diffstat (limited to 'source/blender/editors/space_text/text_ops.c')
-rw-r--r-- | source/blender/editors/space_text/text_ops.c | 322 |
1 files changed, 184 insertions, 138 deletions
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); } } |