From 9e4bd41e416a2d48284947e9ccc09844d3db93ee Mon Sep 17 00:00:00 2001 From: Tomer Shalev Date: Wed, 7 Apr 2010 17:22:16 +0000 Subject: Text viewer: Fix RTL languages and diacritic characters support git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25515 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/viewer.c | 169 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 115 insertions(+), 54 deletions(-) (limited to 'apps/plugins/viewer.c') diff --git a/apps/plugins/viewer.c b/apps/plugins/viewer.c index 80b279c638..8751b43e93 100644 --- a/apps/plugins/viewer.c +++ b/apps/plugins/viewer.c @@ -636,11 +636,14 @@ static int bookmark_count; static bool is_bom = false; /* calculate the width of a UCS character (zero width for diacritics) */ -static int glyph_width(int ch) +static int glyph_width(unsigned short ch) { if (ch == 0) ch = ' '; + if (rb->is_diacritic(ch, NULL)) + return 0; + #ifdef HAVE_LCD_BITMAP return rb->font_get_width(pf, ch); #else @@ -730,6 +733,10 @@ static int col = 0; static inline void advance_conters(unsigned short ch, int* k, int* width) { + /* diacritics do not count */ + if (rb->is_diacritic(ch, NULL)) + return; + *width += glyph_width(ch); (*k)++; } @@ -760,11 +767,18 @@ static unsigned char* crop_at_width(const unsigned char* p) static unsigned char* find_first_feed(const unsigned char* p, int size) { - int i; + int s = 0; + unsigned short ch; + const unsigned char *oldp = p; - for (i=0; i < size; i++) - if (p[i] == 0) - return (unsigned char*) p+i; + while(s <= size) + { + if (*p == 0) + return (unsigned char*)p; + oldp = p; + p = get_ucs(p, &ch); + s += (p - oldp); + } return NULL; } @@ -786,18 +800,21 @@ static unsigned char* find_last_space(const unsigned char* p, int size) k = (prefs.line_mode==JOIN) || (prefs.line_mode==REFLOW) ? 0:1; - if (!BUFFER_OOB(&p[size])) - for (j=k; j < ((int) sizeof(line_break)) - 1; j++) - if (p[size] == line_break[j]) - return (unsigned char*) p+size; + i = size; + if (!BUFFER_OOB(&p[i])) + for (j=k; j < ((int) sizeof(line_break)) - 1; j++) { + if (p[i] == line_break[j]) + return (unsigned char*) p+i; + } - for (i=size-1; i>=0; i--) - for (j=k; j < (int) sizeof(line_break); j++) - { - if (!((p[i] == '-') && (prefs.word_mode == WRAP))) + if (prefs.word_mode == WRAP) { + for (i=size-1; i>=0; i--) { + for (j=k; j < (int) sizeof(line_break) - 1; j++) { if (p[i] == line_break[j]) return (unsigned char*) p+i; + } } + } return NULL; } @@ -805,9 +822,9 @@ static unsigned char* find_last_space(const unsigned char* p, int size) static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_short) { const unsigned char *next_line = NULL; - int size, i, j, k, width, search_len, spaces, newlines; + int size, i, j, j_next, j_prev, k, width, search_len, spaces, newlines; bool first_chars; - unsigned char c; + unsigned short ch; if (is_short != NULL) *is_short = true; @@ -829,16 +846,25 @@ static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_sho or possibly set next_line at second hard return in a row. */ next_line = NULL; first_chars=true; - for (j=k=width=spaces=newlines=0; ; j++) { + j_next=j=k=width=spaces=newlines=0; + while (1) { + const unsigned char *p, *oldp; + + j_prev = j; + j = j_next; + if (BUFFER_OOB(cur_line+j)) return NULL; if (line_is_full(k, width)) { - size = search_len = j; + size = search_len = j_prev; break; } - c = cur_line[j]; - switch (c) { + oldp = p = &cur_line[j]; + p = get_ucs(p, &ch); + j_next = j + (p - oldp); + + switch (ch) { case ' ': if (prefs.line_mode == REFLOW) { if (newlines > 0) { @@ -909,14 +935,18 @@ static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_sho if (prefs.word_mode == WRAP) /* Find last space */ next_line = find_last_space(cur_line, size); - if (next_line == NULL) + if (next_line == NULL) { next_line = crop_at_width(cur_line); - else - if (prefs.word_mode == WRAP) - for (i=0; - i col) { - str = oldstr = line_begin; - k = col; - width = 0; - while( (width 0) { - k -= glyph_width(ch); - line_begin = oldstr; - } else { - width += glyph_width(ch); - } + if ((col != -1) && (line_width > col)) { + str = oldstr = line_begin; + k = col; + width = 0; + while( (width 0) { + k -= glyph_width(ch); + line_begin = oldstr; + } else { + width += glyph_width(ch); } - - if(prefs.view_mode==WIDE) - endptr = rb->iso_decode(line_begin, utf8_buffer, - prefs.encoding, oldstr-line_begin); - else - endptr = rb->iso_decode(line_begin, utf8_buffer, - prefs.encoding, line_end-line_begin); - *endptr = 0; } + + if(prefs.view_mode==WIDE) + endptr = rb->iso_decode(line_begin, utf8_buffer, + prefs.encoding, oldstr-line_begin); + else + endptr = rb->iso_decode(line_begin, utf8_buffer, + prefs.encoding, line_end-line_begin); + *endptr = 0; + } } + + /* display on screen the displayed part of the line */ if (col != -1 && line_width > col) { int dpage = (cline+i <= display_lines)?cpage:cpage+1; -- cgit v1.2.3