From 7b707552be324d6eab1e16ba20df77e36e3f0dca Mon Sep 17 00:00:00 2001 From: uchida Date: Mon, 12 Apr 2010 12:02:05 +0000 Subject: [PATCH] viewer plugin: when the alignment is RIGHT, supports WIDE screen. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25605 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/viewer.c | 200 +++++++++++++++++++++++++++++++------------------- 1 file changed, 124 insertions(+), 76 deletions(-) diff --git a/apps/plugins/viewer.c b/apps/plugins/viewer.c index 5678c5ef7..83dab4137 100644 --- a/apps/plugins/viewer.c +++ b/apps/plugins/viewer.c @@ -639,6 +639,13 @@ static int bookmark_count; static bool is_bom = false; +/* We draw a diacritic char over a non-diacritic one. Therefore, such chars are + * not considered to occupy space, therefore buffers might have more than + * max_columns characters. The DIACRITIC_FACTOR is the max ratio between all + * characters and non-diacritic characters in the buffer + */ +#define DIACRITIC_FACTOR 2 + /* calculate the width of a UCS character (zero width for diacritics) */ static int glyph_width(unsigned short ch) { @@ -659,12 +666,11 @@ static int glyph_width(unsigned short ch) static unsigned char* get_ucs(const unsigned char* str, unsigned short* ch) { unsigned char utf8_tmp[6]; - int count; + int count = 2; if (prefs.encoding == UTF_8) return (unsigned char*)rb->utf8decode(str, ch); - count = BUFFER_OOB(str+2)? 1:2; rb->iso_decode(str, utf8_tmp, prefs.encoding, count); rb->utf8decode(utf8_tmp, ch); @@ -678,41 +684,78 @@ static unsigned char* get_ucs(const unsigned char* str, unsigned short* ch) return (unsigned char*)str+1; } -/* decode UCS string into UTF-8 string */ +/* decode iso string into UTF-8 string */ static unsigned char *decode2utf8(const unsigned char *src, unsigned char *dst, int skip_width, int disp_width) { + unsigned short ucs[max_columns * DIACRITIC_FACTOR + 1]; unsigned short ch; const unsigned char *oldstr; const unsigned char *str = src; unsigned char *utf8 = dst; - int width = 0; + int chars = 0; + int idx = 0; + int width = max_width; - /* skip the skip_width */ - while (*str != '\0') + if (prefs.alignment == LEFT) { - oldstr = str; - str = get_ucs(oldstr, &ch); - width += glyph_width(ch); - if (width > skip_width) + /* skip the skip_width */ + if (skip_width > 0) { - str = oldstr; - break; + while (skip_width > 0 && *str != '\0') + { + oldstr = str; + str = get_ucs(oldstr, &ch); + skip_width -= glyph_width(ch); + } + if (skip_width < 0) + str = oldstr; } - } - /* decode until string end or disp_width reached */ - width = 0; - while(*str != '\0') + /* decode until string end or disp_width reached */ + while(*str != '\0') + { + str = get_ucs(str, &ch); + disp_width -= glyph_width(ch); + if (disp_width < 0) + break; + utf8 = rb->utf8encode(ch, utf8); + } + } + else { - str = get_ucs(str, &ch); - width += glyph_width(ch); - if (width > disp_width) - break; + while (width > 0 && *str != '\0') + { + str = get_ucs(str, &ch); + ucs[chars++] = ch; + } + ucs[chars] = 0; + + skip_width = max_width - skip_width - disp_width; + if (skip_width > 0) + { + while (skip_width > 0 && chars-- > 0) + skip_width -= glyph_width(ucs[chars]); + + if (skip_width < 0) + chars++; + } + else + { + idx = chars; + while (disp_width > 0 && idx-- > 0) + disp_width -= glyph_width(ucs[idx]); + + if (disp_width < 0 || idx < 0) + idx++; + } - utf8 = rb->utf8encode(ch, utf8); + for ( ; idx < chars; idx++) + utf8 = rb->utf8encode(ucs[idx], utf8); } + *utf8 = '\0'; + /* return a pointer after the dst string ends */ return utf8; } @@ -776,6 +819,9 @@ static unsigned char* find_first_feed(const unsigned char* p, int size) int s = 0; unsigned short ch; const unsigned char *oldp = p; + const unsigned char *lbrkp = NULL; + int j; + int width = 0; while(s <= size) { @@ -783,6 +829,23 @@ static unsigned char* find_first_feed(const unsigned char* p, int size) return (unsigned char*)p; oldp = p; p = get_ucs(p, &ch); + + if (prefs.word_mode == WRAP) + { + for (j = 0; j < ((int) sizeof(line_break)); j++) + { + if (ch == line_break[j]) + { + lbrkp = p; + break; + } + } + } + + width += glyph_width(ch); + if (width > max_width) + return (lbrkp == NULL)? (unsigned char*)oldp : (unsigned char*)lbrkp; + s += (p - oldp); } @@ -1266,17 +1329,10 @@ static void viewer_show_footer(void) } #endif -/* We draw a diacritic char over a non-diacritic one. Therefore, such chars are - * not considered to occupy space, therefore buffers might have more than - * max_columns characters. The DIACRITIC_FACTOR is the max ratio between all - * characters and non-diacritic characters in the buffer - */ -#define DIACRITIC_FACTOR 2 - static void viewer_draw(int col) { int i, j, k, line_len, line_width, spaces, left_col=0; - int width, extra_spaces, indent_spaces, spaces_per_word, spaces_width; + int width, extra_spaces, indent_spaces, spaces_per_word, spaces_width, disp_width = 0; bool multiple_spacing, line_is_short; unsigned short ch; unsigned char *str, *oldstr; @@ -1284,9 +1340,8 @@ static void viewer_draw(int col) unsigned char *line_end; unsigned char c; int max_chars = max_columns * DIACRITIC_FACTOR; - unsigned char scratch_buffer[max_chars + 1]; + unsigned char scratch_buffer[max_chars * 4 + 1]; unsigned char utf8_buffer[max_chars * 4 + 1]; - unsigned char *endptr; /* If col==-1 do all calculations but don't display */ if (col != -1) { @@ -1392,11 +1447,7 @@ static void viewer_draw(int col) break; } } - if (col != -1) { - scratch_buffer[k] = 0; - endptr = decode2utf8(scratch_buffer, utf8_buffer, col, draw_columns); - *endptr = 0; - } + scratch_buffer[k] = 0; } else if (prefs.line_mode == REFLOW) { if (line_begin[0] == 0) { @@ -1414,12 +1465,17 @@ static void viewer_draw(int col) for (str = line_begin; str < line_end; ) { str = get_ucs(str, &ch); switch (ch) { - case ' ': case 0: - if ((str == line_begin) && (prefs.word_mode==WRAP)) - /* special case: indent the paragraph, - * don't count spaces */ - indent_spaces = par_indent_spaces; + case ' ': + if (str == line_begin) + { + if (prefs.word_mode == WRAP && prefs.alignment == LEFT) + { + /* special case: indent the paragraph, + * don't count spaces */ + indent_spaces = par_indent_spaces; + } + } else if (!multiple_spacing) spaces++; multiple_spacing = true; @@ -1451,7 +1507,6 @@ static void viewer_draw(int col) spaces_per_word = 1; extra_spaces = 0; } - multiple_spacing = false; for (j=k=spaces=0; j < line_len; j++) { if (k == max_chars) @@ -1459,12 +1514,18 @@ static void viewer_draw(int col) c = line_begin[j]; switch (c) { - case ' ': case 0: - if (j==0 && prefs.word_mode==WRAP) { /* indent paragraph */ - for (j=0; j 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 (col != -1) + { + rb->memcpy(scratch_buffer, line_begin, line_len); + scratch_buffer[line_len] = '\0'; } } + /* create displayed line */ + if (col != -1) + { + decode2utf8(scratch_buffer, utf8_buffer, col, draw_columns); + rb->lcd_getstringsize(utf8_buffer, &disp_width, NULL); + } + /* display on screen the displayed part of the line */ - if (col != -1 && line_width > col) + if (col != -1) { int dpage = (cline+i <= display_lines)?cpage:cpage+1; int dline = cline+i - ((cline+i <= display_lines)?0:display_lines); bool bflag = (viewer_find_bookmark(dpage, dline) >= 0); #ifdef HAVE_LCD_BITMAP int dy = i * pf->height + header_height; - int dx = (prefs.alignment == LEFT) ? left_col : LCD_WIDTH - line_width; + int dx = (prefs.alignment == LEFT)? left_col : LCD_WIDTH - disp_width; #endif if (bflag) #ifdef HAVE_LCD_BITMAP -- 2.11.4.GIT