summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugin.c5
-rw-r--r--apps/plugin.h6
-rw-r--r--apps/plugins/viewer.c169
3 files changed, 125 insertions, 55 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index c9f649b096..2f54c0d314 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -41,6 +41,7 @@
41#include "storage.h" 41#include "storage.h"
42#include "pcmbuf.h" 42#include "pcmbuf.h"
43#include "errno.h" 43#include "errno.h"
44#include "diacritic.h"
44 45
45#if CONFIG_CHARGING 46#if CONFIG_CHARGING
46#include "power.h" 47#include "power.h"
@@ -710,6 +711,10 @@ static const struct plugin_api rockbox_api = {
710 appsversion, 711 appsversion,
711 /* new stuff at the end, sort into place next time 712 /* new stuff at the end, sort into place next time
712 the API gets incompatible */ 713 the API gets incompatible */
714
715#ifdef HAVE_LCD_BITMAP
716 is_diacritic,
717#endif
713}; 718};
714 719
715int plugin_load(const char* plugin, const void* parameter) 720int plugin_load(const char* plugin, const void* parameter)
diff --git a/apps/plugin.h b/apps/plugin.h
index c3466bc457..464a581dab 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -135,7 +135,7 @@ void* plugin_get_buffer(size_t *buffer_size);
135#define PLUGIN_MAGIC 0x526F634B /* RocK */ 135#define PLUGIN_MAGIC 0x526F634B /* RocK */
136 136
137/* increase this every time the api struct changes */ 137/* increase this every time the api struct changes */
138#define PLUGIN_API_VERSION 182 138#define PLUGIN_API_VERSION 183
139 139
140/* update this to latest version if a change to the api struct breaks 140/* update this to latest version if a change to the api struct breaks
141 backwards compatibility (and please take the opportunity to sort in any 141 backwards compatibility (and please take the opportunity to sort in any
@@ -863,6 +863,10 @@ struct plugin_api {
863 const char *appsversion; 863 const char *appsversion;
864 /* new stuff at the end, sort into place next time 864 /* new stuff at the end, sort into place next time
865 the API gets incompatible */ 865 the API gets incompatible */
866
867#ifdef HAVE_LCD_BITMAP
868 int (*is_diacritic)(const unsigned short char_code, bool *is_rtl);
869#endif
866}; 870};
867 871
868/* plugin header */ 872/* plugin header */
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;
636static bool is_bom = false; 636static bool is_bom = false;
637 637
638/* calculate the width of a UCS character (zero width for diacritics) */ 638/* calculate the width of a UCS character (zero width for diacritics) */
639static int glyph_width(int ch) 639static int glyph_width(unsigned short ch)
640{ 640{
641 if (ch == 0) 641 if (ch == 0)
642 ch = ' '; 642 ch = ' ';
643 643
644 if (rb->is_diacritic(ch, NULL))
645 return 0;
646
644#ifdef HAVE_LCD_BITMAP 647#ifdef HAVE_LCD_BITMAP
645 return rb->font_get_width(pf, ch); 648 return rb->font_get_width(pf, ch);
646#else 649#else
@@ -730,6 +733,10 @@ static int col = 0;
730 733
731static inline void advance_conters(unsigned short ch, int* k, int* width) 734static inline void advance_conters(unsigned short ch, int* k, int* width)
732{ 735{
736 /* diacritics do not count */
737 if (rb->is_diacritic(ch, NULL))
738 return;
739
733 *width += glyph_width(ch); 740 *width += glyph_width(ch);
734 (*k)++; 741 (*k)++;
735} 742}
@@ -760,11 +767,18 @@ static unsigned char* crop_at_width(const unsigned char* p)
760 767
761static unsigned char* find_first_feed(const unsigned char* p, int size) 768static unsigned char* find_first_feed(const unsigned char* p, int size)
762{ 769{
763 int i; 770 int s = 0;
771 unsigned short ch;
772 const unsigned char *oldp = p;
764 773
765 for (i=0; i < size; i++) 774 while(s <= size)
766 if (p[i] == 0) 775 {
767 return (unsigned char*) p+i; 776 if (*p == 0)
777 return (unsigned char*)p;
778 oldp = p;
779 p = get_ucs(p, &ch);
780 s += (p - oldp);
781 }
768 782
769 return NULL; 783 return NULL;
770} 784}
@@ -786,18 +800,21 @@ static unsigned char* find_last_space(const unsigned char* p, int size)
786 800
787 k = (prefs.line_mode==JOIN) || (prefs.line_mode==REFLOW) ? 0:1; 801 k = (prefs.line_mode==JOIN) || (prefs.line_mode==REFLOW) ? 0:1;
788 802
789 if (!BUFFER_OOB(&p[size])) 803 i = size;
790 for (j=k; j < ((int) sizeof(line_break)) - 1; j++) 804 if (!BUFFER_OOB(&p[i]))
791 if (p[size] == line_break[j]) 805 for (j=k; j < ((int) sizeof(line_break)) - 1; j++) {
792 return (unsigned char*) p+size; 806 if (p[i] == line_break[j])
807 return (unsigned char*) p+i;
808 }
793 809
794 for (i=size-1; i>=0; i--) 810 if (prefs.word_mode == WRAP) {
795 for (j=k; j < (int) sizeof(line_break); j++) 811 for (i=size-1; i>=0; i--) {
796 { 812 for (j=k; j < (int) sizeof(line_break) - 1; j++) {
797 if (!((p[i] == '-') && (prefs.word_mode == WRAP)))
798 if (p[i] == line_break[j]) 813 if (p[i] == line_break[j])
799 return (unsigned char*) p+i; 814 return (unsigned char*) p+i;
815 }
800 } 816 }
817 }
801 818
802 return NULL; 819 return NULL;
803} 820}
@@ -805,9 +822,9 @@ static unsigned char* find_last_space(const unsigned char* p, int size)
805static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_short) 822static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_short)
806{ 823{
807 const unsigned char *next_line = NULL; 824 const unsigned char *next_line = NULL;
808 int size, i, j, k, width, search_len, spaces, newlines; 825 int size, i, j, j_next, j_prev, k, width, search_len, spaces, newlines;
809 bool first_chars; 826 bool first_chars;
810 unsigned char c; 827 unsigned short ch;
811 828
812 if (is_short != NULL) 829 if (is_short != NULL)
813 *is_short = true; 830 *is_short = true;
@@ -829,16 +846,25 @@ static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_sho
829 or possibly set next_line at second hard return in a row. */ 846 or possibly set next_line at second hard return in a row. */
830 next_line = NULL; 847 next_line = NULL;
831 first_chars=true; 848 first_chars=true;
832 for (j=k=width=spaces=newlines=0; ; j++) { 849 j_next=j=k=width=spaces=newlines=0;
850 while (1) {
851 const unsigned char *p, *oldp;
852
853 j_prev = j;
854 j = j_next;
855
833 if (BUFFER_OOB(cur_line+j)) 856 if (BUFFER_OOB(cur_line+j))
834 return NULL; 857 return NULL;
835 if (line_is_full(k, width)) { 858 if (line_is_full(k, width)) {
836 size = search_len = j; 859 size = search_len = j_prev;
837 break; 860 break;
838 } 861 }
839 862
840 c = cur_line[j]; 863 oldp = p = &cur_line[j];
841 switch (c) { 864 p = get_ucs(p, &ch);
865 j_next = j + (p - oldp);
866
867 switch (ch) {
842 case ' ': 868 case ' ':
843 if (prefs.line_mode == REFLOW) { 869 if (prefs.line_mode == REFLOW) {
844 if (newlines > 0) { 870 if (newlines > 0) {
@@ -909,14 +935,18 @@ static unsigned char* find_next_line(const unsigned char* cur_line, bool *is_sho
909 if (prefs.word_mode == WRAP) /* Find last space */ 935 if (prefs.word_mode == WRAP) /* Find last space */
910 next_line = find_last_space(cur_line, size); 936 next_line = find_last_space(cur_line, size);
911 937
912 if (next_line == NULL) 938 if (next_line == NULL) {
913 next_line = crop_at_width(cur_line); 939 next_line = crop_at_width(cur_line);
914 else 940 }
915 if (prefs.word_mode == WRAP) 941 else {
916 for (i=0; 942 if (prefs.word_mode == WRAP) {
917 i<WRAP_TRIM && isspace(next_line[0]) && !BUFFER_OOB(next_line); 943 for (i=0;i<WRAP_TRIM;i++) {
918 i++) 944 if (!(isspace(next_line[0]) && !BUFFER_OOB(next_line)))
945 break;
919 next_line++; 946 next_line++;
947 }
948 }
949 }
920 } 950 }
921 951
922 if (prefs.line_mode == EXPAND) 952 if (prefs.line_mode == EXPAND)
@@ -1230,18 +1260,26 @@ static void viewer_show_footer(void)
1230} 1260}
1231#endif 1261#endif
1232 1262
1263/* We draw a diacritic char over a non-diacritic one. Therefore, such chars are
1264 * not considered to occupy space, therefore buffers might have more than
1265 * max_columns characters. The DIACRITIC_FACTOR is the max ratio between all
1266 * characters and non-diacritic characters in the buffer
1267 */
1268#define DIACRITIC_FACTOR 2
1269
1233static void viewer_draw(int col) 1270static void viewer_draw(int col)
1234{ 1271{
1235 int i, j, k, line_len, line_width, spaces, left_col=0; 1272 int i, j, k, line_len, line_width, spaces, left_col=0;
1236 int width, extra_spaces, indent_spaces, spaces_per_word; 1273 int width, extra_spaces, indent_spaces, spaces_per_word, spaces_width;
1237 bool multiple_spacing, line_is_short; 1274 bool multiple_spacing, line_is_short;
1238 unsigned short ch; 1275 unsigned short ch;
1239 unsigned char *str, *oldstr; 1276 unsigned char *str, *oldstr;
1240 unsigned char *line_begin; 1277 unsigned char *line_begin;
1241 unsigned char *line_end; 1278 unsigned char *line_end;
1242 unsigned char c; 1279 unsigned char c;
1243 unsigned char scratch_buffer[max_columns + 1]; 1280 int max_chars = max_columns * DIACRITIC_FACTOR;
1244 unsigned char utf8_buffer[max_columns*4 + 1]; 1281 unsigned char scratch_buffer[max_chars + 1];
1282 unsigned char utf8_buffer[max_chars * 4 + 1];
1245 unsigned char *endptr; 1283 unsigned char *endptr;
1246 1284
1247 /* If col==-1 do all calculations but don't display */ 1285 /* If col==-1 do all calculations but don't display */
@@ -1287,11 +1325,33 @@ static void viewer_draw(int col)
1287 oldstr = str; 1325 oldstr = str;
1288 str = crop_at_width(str); 1326 str = crop_at_width(str);
1289 j++; 1327 j++;
1328 if (oldstr == str)
1329 {
1330 oldstr = line_end;
1331 break;
1332 }
1290 } 1333 }
1334 /* width of un-displayed part of the line */
1291 line_width = j*draw_columns; 1335 line_width = j*draw_columns;
1336 spaces_width = 0;
1292 while (oldstr < line_end) { 1337 while (oldstr < line_end) {
1293 oldstr = get_ucs(oldstr, &ch); 1338 oldstr = get_ucs(oldstr, &ch);
1294 line_width += glyph_width(ch); 1339 /* add width of displayed part of the line */
1340 if (ch)
1341 {
1342 int dw = glyph_width(ch);
1343
1344 /* avoid counting spaces at the end of the line */
1345 if (ch == ' ')
1346 {
1347 spaces_width += dw;
1348 }
1349 else
1350 {
1351 line_width += dw + spaces_width;
1352 spaces_width = 0;
1353 }
1354 }
1295 } 1355 }
1296 1356
1297 if (prefs.line_mode == JOIN) { 1357 if (prefs.line_mode == JOIN) {
@@ -1303,7 +1363,7 @@ static void viewer_draw(int col)
1303 line_len--; 1363 line_len--;
1304 } 1364 }
1305 for (j=k=spaces=0; j < line_len; j++) { 1365 for (j=k=spaces=0; j < line_len; j++) {
1306 if (k == max_columns) 1366 if (k == max_chars)
1307 break; 1367 break;
1308 1368
1309 c = line_begin[j]; 1369 c = line_begin[j];
@@ -1319,7 +1379,7 @@ static void viewer_draw(int col)
1319 while (spaces) { 1379 while (spaces) {
1320 spaces--; 1380 spaces--;
1321 scratch_buffer[k++] = ' '; 1381 scratch_buffer[k++] = ' ';
1322 if (k == max_columns - 1) 1382 if (k == max_chars - 1)
1323 break; 1383 break;
1324 } 1384 }
1325 scratch_buffer[k++] = c; 1385 scratch_buffer[k++] = c;
@@ -1388,7 +1448,7 @@ static void viewer_draw(int col)
1388 1448
1389 multiple_spacing = false; 1449 multiple_spacing = false;
1390 for (j=k=spaces=0; j < line_len; j++) { 1450 for (j=k=spaces=0; j < line_len; j++) {
1391 if (k == max_columns) 1451 if (k == max_chars)
1392 break; 1452 break;
1393 1453
1394 c = line_begin[j]; 1454 c = line_begin[j];
@@ -1420,31 +1480,32 @@ static void viewer_draw(int col)
1420 } 1480 }
1421 } 1481 }
1422 else { /* prefs.line_mode != JOIN && prefs.line_mode != REFLOW */ 1482 else { /* prefs.line_mode != JOIN && prefs.line_mode != REFLOW */
1423 if (col != -1) 1483 if ((col != -1) && (line_width > col)) {
1424 if (line_width > col) { 1484 str = oldstr = line_begin;
1425 str = oldstr = line_begin; 1485 k = col;
1426 k = col; 1486 width = 0;
1427 width = 0; 1487 while( (width<draw_columns) && (oldstr<line_end) )
1428 while( (width<draw_columns) && (oldstr<line_end) ) 1488 {
1429 { 1489 oldstr = get_ucs(oldstr, &ch);
1430 oldstr = get_ucs(oldstr, &ch); 1490 if (k > 0) {
1431 if (k > 0) { 1491 k -= glyph_width(ch);
1432 k -= glyph_width(ch); 1492 line_begin = oldstr;
1433 line_begin = oldstr; 1493 } else {
1434 } else { 1494 width += glyph_width(ch);
1435 width += glyph_width(ch);
1436 }
1437 } 1495 }
1438
1439 if(prefs.view_mode==WIDE)
1440 endptr = rb->iso_decode(line_begin, utf8_buffer,
1441 prefs.encoding, oldstr-line_begin);
1442 else
1443 endptr = rb->iso_decode(line_begin, utf8_buffer,
1444 prefs.encoding, line_end-line_begin);
1445 *endptr = 0;
1446 } 1496 }
1497
1498 if(prefs.view_mode==WIDE)
1499 endptr = rb->iso_decode(line_begin, utf8_buffer,
1500 prefs.encoding, oldstr-line_begin);
1501 else
1502 endptr = rb->iso_decode(line_begin, utf8_buffer,
1503 prefs.encoding, line_end-line_begin);
1504 *endptr = 0;
1505 }
1447 } 1506 }
1507
1508 /* display on screen the displayed part of the line */
1448 if (col != -1 && line_width > col) 1509 if (col != -1 && line_width > col)
1449 { 1510 {
1450 int dpage = (cline+i <= display_lines)?cpage:cpage+1; 1511 int dpage = (cline+i <= display_lines)?cpage:cpage+1;