summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/viewer.c200
1 files changed, 124 insertions, 76 deletions
diff --git a/apps/plugins/viewer.c b/apps/plugins/viewer.c
index 5678c5ef7d..83dab4137d 100644
--- a/apps/plugins/viewer.c
+++ b/apps/plugins/viewer.c
@@ -639,6 +639,13 @@ static int bookmark_count;
639 639
640static bool is_bom = false; 640static bool is_bom = false;
641 641
642/* We draw a diacritic char over a non-diacritic one. Therefore, such chars are
643 * not considered to occupy space, therefore buffers might have more than
644 * max_columns characters. The DIACRITIC_FACTOR is the max ratio between all
645 * characters and non-diacritic characters in the buffer
646 */
647#define DIACRITIC_FACTOR 2
648
642/* calculate the width of a UCS character (zero width for diacritics) */ 649/* calculate the width of a UCS character (zero width for diacritics) */
643static int glyph_width(unsigned short ch) 650static int glyph_width(unsigned short ch)
644{ 651{
@@ -659,12 +666,11 @@ static int glyph_width(unsigned short ch)
659static unsigned char* get_ucs(const unsigned char* str, unsigned short* ch) 666static unsigned char* get_ucs(const unsigned char* str, unsigned short* ch)
660{ 667{
661 unsigned char utf8_tmp[6]; 668 unsigned char utf8_tmp[6];
662 int count; 669 int count = 2;
663 670
664 if (prefs.encoding == UTF_8) 671 if (prefs.encoding == UTF_8)
665 return (unsigned char*)rb->utf8decode(str, ch); 672 return (unsigned char*)rb->utf8decode(str, ch);
666 673
667 count = BUFFER_OOB(str+2)? 1:2;
668 rb->iso_decode(str, utf8_tmp, prefs.encoding, count); 674 rb->iso_decode(str, utf8_tmp, prefs.encoding, count);
669 rb->utf8decode(utf8_tmp, ch); 675 rb->utf8decode(utf8_tmp, ch);
670 676
@@ -678,41 +684,78 @@ static unsigned char* get_ucs(const unsigned char* str, unsigned short* ch)
678 return (unsigned char*)str+1; 684 return (unsigned char*)str+1;
679} 685}
680 686
681/* decode UCS string into UTF-8 string */ 687/* decode iso string into UTF-8 string */
682static unsigned char *decode2utf8(const unsigned char *src, unsigned char *dst, 688static unsigned char *decode2utf8(const unsigned char *src, unsigned char *dst,
683 int skip_width, int disp_width) 689 int skip_width, int disp_width)
684{ 690{
691 unsigned short ucs[max_columns * DIACRITIC_FACTOR + 1];
685 unsigned short ch; 692 unsigned short ch;
686 const unsigned char *oldstr; 693 const unsigned char *oldstr;
687 const unsigned char *str = src; 694 const unsigned char *str = src;
688 unsigned char *utf8 = dst; 695 unsigned char *utf8 = dst;
689 int width = 0; 696 int chars = 0;
697 int idx = 0;
698 int width = max_width;
690 699
691 /* skip the skip_width */ 700 if (prefs.alignment == LEFT)
692 while (*str != '\0')
693 { 701 {
694 oldstr = str; 702 /* skip the skip_width */
695 str = get_ucs(oldstr, &ch); 703 if (skip_width > 0)
696 width += glyph_width(ch);
697 if (width > skip_width)
698 { 704 {
699 str = oldstr; 705 while (skip_width > 0 && *str != '\0')
700 break; 706 {
707 oldstr = str;
708 str = get_ucs(oldstr, &ch);
709 skip_width -= glyph_width(ch);
710 }
711 if (skip_width < 0)
712 str = oldstr;
701 } 713 }
702 }
703 714
704 /* decode until string end or disp_width reached */ 715 /* decode until string end or disp_width reached */
705 width = 0; 716 while(*str != '\0')
706 while(*str != '\0') 717 {
718 str = get_ucs(str, &ch);
719 disp_width -= glyph_width(ch);
720 if (disp_width < 0)
721 break;
722 utf8 = rb->utf8encode(ch, utf8);
723 }
724 }
725 else
707 { 726 {
708 str = get_ucs(str, &ch); 727 while (width > 0 && *str != '\0')
709 width += glyph_width(ch); 728 {
710 if (width > disp_width) 729 str = get_ucs(str, &ch);
711 break; 730 ucs[chars++] = ch;
731 }
732 ucs[chars] = 0;
733
734 skip_width = max_width - skip_width - disp_width;
735 if (skip_width > 0)
736 {
737 while (skip_width > 0 && chars-- > 0)
738 skip_width -= glyph_width(ucs[chars]);
739
740 if (skip_width < 0)
741 chars++;
742 }
743 else
744 {
745 idx = chars;
746 while (disp_width > 0 && idx-- > 0)
747 disp_width -= glyph_width(ucs[idx]);
748
749 if (disp_width < 0 || idx < 0)
750 idx++;
751 }
712 752
713 utf8 = rb->utf8encode(ch, utf8); 753 for ( ; idx < chars; idx++)
754 utf8 = rb->utf8encode(ucs[idx], utf8);
714 } 755 }
715 756
757 *utf8 = '\0';
758
716 /* return a pointer after the dst string ends */ 759 /* return a pointer after the dst string ends */
717 return utf8; 760 return utf8;
718} 761}
@@ -776,6 +819,9 @@ static unsigned char* find_first_feed(const unsigned char* p, int size)
776 int s = 0; 819 int s = 0;
777 unsigned short ch; 820 unsigned short ch;
778 const unsigned char *oldp = p; 821 const unsigned char *oldp = p;
822 const unsigned char *lbrkp = NULL;
823 int j;
824 int width = 0;
779 825
780 while(s <= size) 826 while(s <= size)
781 { 827 {
@@ -783,6 +829,23 @@ static unsigned char* find_first_feed(const unsigned char* p, int size)
783 return (unsigned char*)p; 829 return (unsigned char*)p;
784 oldp = p; 830 oldp = p;
785 p = get_ucs(p, &ch); 831 p = get_ucs(p, &ch);
832
833 if (prefs.word_mode == WRAP)
834 {
835 for (j = 0; j < ((int) sizeof(line_break)); j++)
836 {
837 if (ch == line_break[j])
838 {
839 lbrkp = p;
840 break;
841 }
842 }
843 }
844
845 width += glyph_width(ch);
846 if (width > max_width)
847 return (lbrkp == NULL)? (unsigned char*)oldp : (unsigned char*)lbrkp;
848
786 s += (p - oldp); 849 s += (p - oldp);
787 } 850 }
788 851
@@ -1266,17 +1329,10 @@ static void viewer_show_footer(void)
1266} 1329}
1267#endif 1330#endif
1268 1331
1269/* We draw a diacritic char over a non-diacritic one. Therefore, such chars are
1270 * not considered to occupy space, therefore buffers might have more than
1271 * max_columns characters. The DIACRITIC_FACTOR is the max ratio between all
1272 * characters and non-diacritic characters in the buffer
1273 */
1274#define DIACRITIC_FACTOR 2
1275
1276static void viewer_draw(int col) 1332static void viewer_draw(int col)
1277{ 1333{
1278 int i, j, k, line_len, line_width, spaces, left_col=0; 1334 int i, j, k, line_len, line_width, spaces, left_col=0;
1279 int width, extra_spaces, indent_spaces, spaces_per_word, spaces_width; 1335 int width, extra_spaces, indent_spaces, spaces_per_word, spaces_width, disp_width = 0;
1280 bool multiple_spacing, line_is_short; 1336 bool multiple_spacing, line_is_short;
1281 unsigned short ch; 1337 unsigned short ch;
1282 unsigned char *str, *oldstr; 1338 unsigned char *str, *oldstr;
@@ -1284,9 +1340,8 @@ static void viewer_draw(int col)
1284 unsigned char *line_end; 1340 unsigned char *line_end;
1285 unsigned char c; 1341 unsigned char c;
1286 int max_chars = max_columns * DIACRITIC_FACTOR; 1342 int max_chars = max_columns * DIACRITIC_FACTOR;
1287 unsigned char scratch_buffer[max_chars + 1]; 1343 unsigned char scratch_buffer[max_chars * 4 + 1];
1288 unsigned char utf8_buffer[max_chars * 4 + 1]; 1344 unsigned char utf8_buffer[max_chars * 4 + 1];
1289 unsigned char *endptr;
1290 1345
1291 /* If col==-1 do all calculations but don't display */ 1346 /* If col==-1 do all calculations but don't display */
1292 if (col != -1) { 1347 if (col != -1) {
@@ -1392,11 +1447,7 @@ static void viewer_draw(int col)
1392 break; 1447 break;
1393 } 1448 }
1394 } 1449 }
1395 if (col != -1) { 1450 scratch_buffer[k] = 0;
1396 scratch_buffer[k] = 0;
1397 endptr = decode2utf8(scratch_buffer, utf8_buffer, col, draw_columns);
1398 *endptr = 0;
1399 }
1400 } 1451 }
1401 else if (prefs.line_mode == REFLOW) { 1452 else if (prefs.line_mode == REFLOW) {
1402 if (line_begin[0] == 0) { 1453 if (line_begin[0] == 0) {
@@ -1414,12 +1465,17 @@ static void viewer_draw(int col)
1414 for (str = line_begin; str < line_end; ) { 1465 for (str = line_begin; str < line_end; ) {
1415 str = get_ucs(str, &ch); 1466 str = get_ucs(str, &ch);
1416 switch (ch) { 1467 switch (ch) {
1417 case ' ':
1418 case 0: 1468 case 0:
1419 if ((str == line_begin) && (prefs.word_mode==WRAP)) 1469 case ' ':
1420 /* special case: indent the paragraph, 1470 if (str == line_begin)
1421 * don't count spaces */ 1471 {
1422 indent_spaces = par_indent_spaces; 1472 if (prefs.word_mode == WRAP && prefs.alignment == LEFT)
1473 {
1474 /* special case: indent the paragraph,
1475 * don't count spaces */
1476 indent_spaces = par_indent_spaces;
1477 }
1478 }
1423 else if (!multiple_spacing) 1479 else if (!multiple_spacing)
1424 spaces++; 1480 spaces++;
1425 multiple_spacing = true; 1481 multiple_spacing = true;
@@ -1451,7 +1507,6 @@ static void viewer_draw(int col)
1451 spaces_per_word = 1; 1507 spaces_per_word = 1;
1452 extra_spaces = 0; 1508 extra_spaces = 0;
1453 } 1509 }
1454
1455 multiple_spacing = false; 1510 multiple_spacing = false;
1456 for (j=k=spaces=0; j < line_len; j++) { 1511 for (j=k=spaces=0; j < line_len; j++) {
1457 if (k == max_chars) 1512 if (k == max_chars)
@@ -1459,12 +1514,18 @@ static void viewer_draw(int col)
1459 1514
1460 c = line_begin[j]; 1515 c = line_begin[j];
1461 switch (c) { 1516 switch (c) {
1462 case ' ':
1463 case 0: 1517 case 0:
1464 if (j==0 && prefs.word_mode==WRAP) { /* indent paragraph */ 1518 if (j == line_len - 1)
1465 for (j=0; j<par_indent_spaces; j++) 1519 break;
1466 scratch_buffer[k++] = ' '; 1520 case ' ':
1467 j=0; 1521 if (j==0) {
1522 /* indent paragraph */
1523 if (prefs.word_mode == WRAP && prefs.alignment == LEFT)
1524 {
1525 for (j=0; j<par_indent_spaces; j++)
1526 scratch_buffer[k++] = ' ';
1527 j=0;
1528 }
1468 } 1529 }
1469 else if (!multiple_spacing) { 1530 else if (!multiple_spacing) {
1470 for (width = spaces<extra_spaces ? -1:0; width < spaces_per_word; width++) 1531 for (width = spaces<extra_spaces ? -1:0; width < spaces_per_word; width++)
@@ -1479,47 +1540,34 @@ static void viewer_draw(int col)
1479 break; 1540 break;
1480 } 1541 }
1481 } 1542 }
1482 if (col != -1) { 1543 while (scratch_buffer[k-1] == ' ')
1483 scratch_buffer[k] = 0; 1544 k--;
1484 endptr = decode2utf8(scratch_buffer, utf8_buffer, col, draw_columns); 1545 scratch_buffer[k] = 0;
1485 *endptr = 0;
1486 }
1487 } 1546 }
1488 else { /* prefs.line_mode != JOIN && prefs.line_mode != REFLOW */ 1547 else { /* prefs.line_mode != JOIN && prefs.line_mode != REFLOW */
1489 if ((col != -1) && (line_width > col)) { 1548 if (col != -1)
1490 str = oldstr = line_begin; 1549 {
1491 k = col; 1550 rb->memcpy(scratch_buffer, line_begin, line_len);
1492 width = 0; 1551 scratch_buffer[line_len] = '\0';
1493 while( (width<draw_columns) && (oldstr<line_end) )
1494 {
1495 oldstr = get_ucs(oldstr, &ch);
1496 if (k > 0) {
1497 k -= glyph_width(ch);
1498 line_begin = oldstr;
1499 } else {
1500 width += glyph_width(ch);
1501 }
1502 }
1503
1504 if(prefs.view_mode==WIDE)
1505 endptr = rb->iso_decode(line_begin, utf8_buffer,
1506 prefs.encoding, oldstr-line_begin);
1507 else
1508 endptr = rb->iso_decode(line_begin, utf8_buffer,
1509 prefs.encoding, line_end-line_begin);
1510 *endptr = 0;
1511 } 1552 }
1512 } 1553 }
1513 1554
1555 /* create displayed line */
1556 if (col != -1)
1557 {
1558 decode2utf8(scratch_buffer, utf8_buffer, col, draw_columns);
1559 rb->lcd_getstringsize(utf8_buffer, &disp_width, NULL);
1560 }
1561
1514 /* display on screen the displayed part of the line */ 1562 /* display on screen the displayed part of the line */
1515 if (col != -1 && line_width > col) 1563 if (col != -1)
1516 { 1564 {
1517 int dpage = (cline+i <= display_lines)?cpage:cpage+1; 1565 int dpage = (cline+i <= display_lines)?cpage:cpage+1;
1518 int dline = cline+i - ((cline+i <= display_lines)?0:display_lines); 1566 int dline = cline+i - ((cline+i <= display_lines)?0:display_lines);
1519 bool bflag = (viewer_find_bookmark(dpage, dline) >= 0); 1567 bool bflag = (viewer_find_bookmark(dpage, dline) >= 0);
1520#ifdef HAVE_LCD_BITMAP 1568#ifdef HAVE_LCD_BITMAP
1521 int dy = i * pf->height + header_height; 1569 int dy = i * pf->height + header_height;
1522 int dx = (prefs.alignment == LEFT) ? left_col : LCD_WIDTH - line_width; 1570 int dx = (prefs.alignment == LEFT)? left_col : LCD_WIDTH - disp_width;
1523#endif 1571#endif
1524 if (bflag) 1572 if (bflag)
1525#ifdef HAVE_LCD_BITMAP 1573#ifdef HAVE_LCD_BITMAP