summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-remote-2bit-vi.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/lcd-remote-2bit-vi.c')
-rw-r--r--firmware/drivers/lcd-remote-2bit-vi.c294
1 files changed, 202 insertions, 92 deletions
diff --git a/firmware/drivers/lcd-remote-2bit-vi.c b/firmware/drivers/lcd-remote-2bit-vi.c
index d5757f4dbb..9ab98c69aa 100644
--- a/firmware/drivers/lcd-remote-2bit-vi.c
+++ b/firmware/drivers/lcd-remote-2bit-vi.c
@@ -46,12 +46,48 @@ static const fb_remote_data patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
46static fb_remote_data* remote_backdrop = NULL; 46static fb_remote_data* remote_backdrop = NULL;
47static long remote_backdrop_offset IDATA_ATTR = 0; 47static long remote_backdrop_offset IDATA_ATTR = 0;
48 48
49static unsigned fg_pattern IDATA_ATTR = 0xFFFF; /* initially black */ 49static struct viewport default_vp =
50static unsigned bg_pattern IDATA_ATTR = 0x0000; /* initially white */ 50{
51static int drawmode = DRMODE_SOLID; 51 .x = 0,
52static int xmargin = 0; 52 .y = 0,
53static int ymargin = 0; 53 .width = LCD_REMOTE_WIDTH,
54static int curfont = FONT_SYSFIXED; 54 .height = LCD_REMOTE_HEIGHT,
55 .font = FONT_SYSFIXED,
56 .drawmode = DRMODE_SOLID,
57 .xmargin = 0,
58 .ymargin = 0,
59 .fg_pattern = LCD_REMOTE_DEFAULT_FG,
60 .bg_pattern = LCD_REMOTE_DEFAULT_BG
61};
62
63static unsigned fg_pattern IBSS_ATTR;
64static unsigned bg_pattern IBSS_ATTR;
65
66static struct viewport* current_vp IBSS_ATTR;;
67
68/*** Viewports ***/
69
70void lcd_remote_set_viewport(struct viewport* vp)
71{
72 if (vp == NULL)
73 current_vp = &default_vp;
74 else
75 current_vp = vp;
76
77 fg_pattern = patterns[current_vp->fg_pattern & 3];
78 bg_pattern = patterns[current_vp->bg_pattern & 3];
79}
80
81void lcd_remote_update_viewport(void)
82{
83 lcd_remote_update_rect(current_vp->x, current_vp->y,
84 current_vp->width, current_vp->height);
85}
86
87void lcd_remote_update_viewport_rect(int x, int y, int width, int height)
88{
89 lcd_remote_update_rect(current_vp->x + x, current_vp->y + y, width, height);
90}
55 91
56/*** parameter handling ***/ 92/*** parameter handling ***/
57unsigned lcd_remote_color_to_native(unsigned color) 93unsigned lcd_remote_color_to_native(unsigned color)
@@ -69,32 +105,34 @@ unsigned lcd_remote_color_to_native(unsigned color)
69 105
70void lcd_remote_set_drawmode(int mode) 106void lcd_remote_set_drawmode(int mode)
71{ 107{
72 drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); 108 current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID);
73} 109}
74 110
75int lcd_remote_get_drawmode(void) 111int lcd_remote_get_drawmode(void)
76{ 112{
77 return drawmode; 113 return current_vp->drawmode;
78} 114}
79 115
80void lcd_remote_set_foreground(unsigned brightness) 116void lcd_remote_set_foreground(unsigned brightness)
81{ 117{
118 current_vp->fg_pattern = brightness;
82 fg_pattern = patterns[brightness & 3]; 119 fg_pattern = patterns[brightness & 3];
83} 120}
84 121
85unsigned lcd_remote_get_foreground(void) 122unsigned lcd_remote_get_foreground(void)
86{ 123{
87 return (~fg_pattern >> 7) & 3; 124 return current_vp->fg_pattern;
88} 125}
89 126
90void lcd_remote_set_background(unsigned brightness) 127void lcd_remote_set_background(unsigned brightness)
91{ 128{
129 current_vp->bg_pattern = brightness;
92 bg_pattern = patterns[brightness & 3]; 130 bg_pattern = patterns[brightness & 3];
93} 131}
94 132
95unsigned lcd_remote_get_background(void) 133unsigned lcd_remote_get_background(void)
96{ 134{
97 return (~bg_pattern >> 7) & 3; 135 return current_vp->bg_pattern;
98} 136}
99 137
100void lcd_remote_set_drawinfo(int mode, unsigned fg_brightness, 138void lcd_remote_set_drawinfo(int mode, unsigned fg_brightness,
@@ -105,30 +143,40 @@ void lcd_remote_set_drawinfo(int mode, unsigned fg_brightness,
105 lcd_remote_set_background(bg_brightness); 143 lcd_remote_set_background(bg_brightness);
106} 144}
107 145
146int lcd_remote_getwidth(void)
147{
148 return current_vp->width;
149}
150
151int lcd_remote_getheight(void)
152{
153 return current_vp->height;
154}
155
108void lcd_remote_setmargins(int x, int y) 156void lcd_remote_setmargins(int x, int y)
109{ 157{
110 xmargin = x; 158 current_vp->xmargin = x;
111 ymargin = y; 159 current_vp->ymargin = y;
112} 160}
113 161
114int lcd_remote_getxmargin(void) 162int lcd_remote_getxmargin(void)
115{ 163{
116 return xmargin; 164 return current_vp->xmargin;
117} 165}
118 166
119int lcd_remote_getymargin(void) 167int lcd_remote_getymargin(void)
120{ 168{
121 return ymargin; 169 return current_vp->ymargin;
122} 170}
123 171
124void lcd_remote_setfont(int newfont) 172void lcd_remote_setfont(int newfont)
125{ 173{
126 curfont = newfont; 174 current_vp->font = newfont;
127} 175}
128 176
129int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h) 177int lcd_remote_getstringsize(const unsigned char *str, int *w, int *h)
130{ 178{
131 return font_getstringsize(str, w, h, curfont); 179 return font_getstringsize(str, w, h, current_vp->font);
132} 180}
133 181
134/*** low-level drawing functions ***/ 182/*** low-level drawing functions ***/
@@ -351,9 +399,9 @@ static inline void setblock(fb_remote_data *address, unsigned mask, unsigned bit
351/* Clear the whole display */ 399/* Clear the whole display */
352void lcd_remote_clear_display(void) 400void lcd_remote_clear_display(void)
353{ 401{
354 if (drawmode & DRMODE_INVERSEVID) 402 if (default_vp.drawmode & DRMODE_INVERSEVID)
355 { 403 {
356 memset(lcd_remote_framebuffer, fg_pattern, 404 memset(lcd_remote_framebuffer, patterns[default_vp.fg_pattern & 3],
357 sizeof lcd_remote_framebuffer); 405 sizeof lcd_remote_framebuffer);
358 } 406 }
359 else 407 else
@@ -362,18 +410,44 @@ void lcd_remote_clear_display(void)
362 memcpy(lcd_remote_framebuffer, remote_backdrop, 410 memcpy(lcd_remote_framebuffer, remote_backdrop,
363 sizeof lcd_remote_framebuffer); 411 sizeof lcd_remote_framebuffer);
364 else 412 else
365 memset(lcd_remote_framebuffer, bg_pattern, 413 memset(lcd_remote_framebuffer, patterns[default_vp.bg_pattern & 3],
366 sizeof lcd_remote_framebuffer); 414 sizeof lcd_remote_framebuffer);
367 } 415 }
368 416
369 lcd_remote_scroll_info.lines = 0; 417 lcd_remote_scroll_info.lines = 0;
370} 418}
371 419
420/* Clear the current viewport */
421void lcd_remote_clear_viewport(void)
422{
423 int lastmode;
424
425 if (current_vp == &default_vp)
426 {
427 lcd_remote_clear_display();
428 }
429 else
430 {
431 lastmode = current_vp->drawmode;
432
433 /* Invert the INVERSEVID bit and set basic mode to SOLID */
434 current_vp->drawmode = (~lastmode & DRMODE_INVERSEVID) |
435 DRMODE_SOLID;
436
437 lcd_remote_fillrect(0, 0, current_vp->width, current_vp->height);
438
439 current_vp->drawmode = lastmode;
440
441 lcd_remote_scroll_stop(current_vp);
442 }
443}
444
372/* Set a single pixel */ 445/* Set a single pixel */
373void lcd_remote_drawpixel(int x, int y) 446void lcd_remote_drawpixel(int x, int y)
374{ 447{
375 if (((unsigned)x < LCD_REMOTE_WIDTH) && ((unsigned)y < LCD_REMOTE_HEIGHT)) 448 if (((unsigned)x < (unsigned)current_vp->width) &&
376 lcd_remote_pixelfuncs[drawmode](x, y); 449 ((unsigned)y < (unsigned)current_vp->height))
450 lcd_remote_pixelfuncs[current_vp->drawmode](current_vp->x+x, current_vp->y+y);
377} 451}
378 452
379/* Draw a line */ 453/* Draw a line */
@@ -385,7 +459,7 @@ void lcd_remote_drawline(int x1, int y1, int x2, int y2)
385 int d, dinc1, dinc2; 459 int d, dinc1, dinc2;
386 int x, xinc1, xinc2; 460 int x, xinc1, xinc2;
387 int y, yinc1, yinc2; 461 int y, yinc1, yinc2;
388 lcd_remote_pixelfunc_type *pfunc = lcd_remote_pixelfuncs[drawmode]; 462 lcd_remote_pixelfunc_type *pfunc = lcd_remote_pixelfuncs[current_vp->drawmode];
389 463
390 deltax = abs(x2 - x1); 464 deltax = abs(x2 - x1);
391 deltay = abs(y2 - y1); 465 deltay = abs(y2 - y1);
@@ -429,8 +503,9 @@ void lcd_remote_drawline(int x1, int y1, int x2, int y2)
429 503
430 for (i = 0; i < numpixels; i++) 504 for (i = 0; i < numpixels; i++)
431 { 505 {
432 if (((unsigned)x < LCD_REMOTE_WIDTH) && ((unsigned)y < LCD_REMOTE_HEIGHT)) 506 if (((unsigned)x < (unsigned)current_vp->width) &&
433 pfunc(x, y); 507 ((unsigned)y < (unsigned)current_vp->height))
508 pfunc(current_vp->x + x, current_vp->y + y);
434 509
435 if (d < 0) 510 if (d < 0)
436 { 511 {
@@ -451,6 +526,7 @@ void lcd_remote_drawline(int x1, int y1, int x2, int y2)
451void lcd_remote_hline(int x1, int x2, int y) 526void lcd_remote_hline(int x1, int x2, int y)
452{ 527{
453 int x; 528 int x;
529 int width;
454 fb_remote_data *dst, *dst_end; 530 fb_remote_data *dst, *dst_end;
455 unsigned mask; 531 unsigned mask;
456 lcd_remote_blockfunc_type *bfunc; 532 lcd_remote_blockfunc_type *bfunc;
@@ -464,24 +540,30 @@ void lcd_remote_hline(int x1, int x2, int y)
464 } 540 }
465 541
466 /* nothing to draw? */ 542 /* nothing to draw? */
467 if (((unsigned)y >= LCD_REMOTE_HEIGHT) || (x1 >= LCD_REMOTE_WIDTH) 543 if (((unsigned)y >= (unsigned)current_vp->height) || (x1 >= current_vp->width)
468 || (x2 < 0)) 544 || (x2 < 0))
469 return; 545 return;
470 546
471 /* clipping */ 547 /* clipping */
472 if (x1 < 0) 548 if (x1 < 0)
473 x1 = 0; 549 x1 = 0;
474 if (x2 >= LCD_REMOTE_WIDTH) 550 if (x2 >= current_vp->width)
475 x2 = LCD_REMOTE_WIDTH-1; 551 x2 = current_vp->width-1;
476 552
477 bfunc = lcd_remote_blockfuncs[drawmode]; 553 width = x2 - x1 + 1;
554
555 /* adjust x1 and y to viewport */
556 x1 += current_vp->x;
557 y += current_vp->y;
558
559 bfunc = lcd_remote_blockfuncs[current_vp->drawmode];
478 dst = &lcd_remote_framebuffer[y>>3][x1]; 560 dst = &lcd_remote_framebuffer[y>>3][x1];
479 mask = 0x0101 << (y & 7); 561 mask = 0x0101 << (y & 7);
480 562
481 dst_end = dst + x2 - x1; 563 dst_end = dst + width;
482 do 564 do
483 bfunc(dst++, mask, 0xFFFFu); 565 bfunc(dst++, mask, 0xFFFFu);
484 while (dst <= dst_end); 566 while (dst < dst_end);
485} 567}
486 568
487/* Draw a vertical line (optimised) */ 569/* Draw a vertical line (optimised) */
@@ -501,17 +583,22 @@ void lcd_remote_vline(int x, int y1, int y2)
501 } 583 }
502 584
503 /* nothing to draw? */ 585 /* nothing to draw? */
504 if (((unsigned)x >= LCD_REMOTE_WIDTH) || (y1 >= LCD_REMOTE_HEIGHT) 586 if (((unsigned)x >= (unsigned)current_vp->width) || (y1 >= current_vp->height)
505 || (y2 < 0)) 587 || (y2 < 0))
506 return; 588 return;
507 589
508 /* clipping */ 590 /* clipping */
509 if (y1 < 0) 591 if (y1 < 0)
510 y1 = 0; 592 y1 = 0;
511 if (y2 >= LCD_REMOTE_HEIGHT) 593 if (y2 >= current_vp->height)
512 y2 = LCD_REMOTE_HEIGHT-1; 594 y2 = current_vp->height-1;
595
596 /* adjust for viewport */
597 y1 += current_vp->y;
598 y2 += current_vp->y;
599 x += current_vp->x;
513 600
514 bfunc = lcd_remote_blockfuncs[drawmode]; 601 bfunc = lcd_remote_blockfuncs[current_vp->drawmode];
515 dst = &lcd_remote_framebuffer[y1>>3][x]; 602 dst = &lcd_remote_framebuffer[y1>>3][x];
516 ny = y2 - (y1 & ~7); 603 ny = y2 - (y1 & ~7);
517 mask = (0xFFu << (y1 & 7)) & 0xFFu; 604 mask = (0xFFu << (y1 & 7)) & 0xFFu;
@@ -555,8 +642,8 @@ void lcd_remote_fillrect(int x, int y, int width, int height)
555 bool fillopt = false; 642 bool fillopt = false;
556 643
557 /* nothing to draw? */ 644 /* nothing to draw? */
558 if ((width <= 0) || (height <= 0) || (x >= LCD_REMOTE_WIDTH) 645 if ((width <= 0) || (height <= 0) || (x >= current_vp->width)
559 || (y >= LCD_REMOTE_HEIGHT) || (x + width <= 0) || (y + height <= 0)) 646 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
560 return; 647 return;
561 648
562 /* clipping */ 649 /* clipping */
@@ -570,14 +657,18 @@ void lcd_remote_fillrect(int x, int y, int width, int height)
570 height += y; 657 height += y;
571 y = 0; 658 y = 0;
572 } 659 }
573 if (x + width > LCD_REMOTE_WIDTH) 660 if (x + width > current_vp->width)
574 width = LCD_REMOTE_WIDTH - x; 661 width = current_vp->width - x;
575 if (y + height > LCD_REMOTE_HEIGHT) 662 if (y + height > current_vp->height)
576 height = LCD_REMOTE_HEIGHT - y; 663 height = current_vp->height - y;
577 664
578 if (drawmode & DRMODE_INVERSEVID) 665 /* adjust for viewport */
666 x += current_vp->x;
667 y += current_vp->y;
668
669 if (current_vp->drawmode & DRMODE_INVERSEVID)
579 { 670 {
580 if ((drawmode & DRMODE_BG) && !remote_backdrop) 671 if ((current_vp->drawmode & DRMODE_BG) && !remote_backdrop)
581 { 672 {
582 fillopt = true; 673 fillopt = true;
583 bits = bg_pattern; 674 bits = bg_pattern;
@@ -585,13 +676,13 @@ void lcd_remote_fillrect(int x, int y, int width, int height)
585 } 676 }
586 else 677 else
587 { 678 {
588 if (drawmode & DRMODE_FG) 679 if (current_vp->drawmode & DRMODE_FG)
589 { 680 {
590 fillopt = true; 681 fillopt = true;
591 bits = fg_pattern; 682 bits = fg_pattern;
592 } 683 }
593 } 684 }
594 bfunc = lcd_remote_blockfuncs[drawmode]; 685 bfunc = lcd_remote_blockfuncs[current_vp->drawmode];
595 dst = &lcd_remote_framebuffer[y>>3][x]; 686 dst = &lcd_remote_framebuffer[y>>3][x];
596 ny = height - 1 + (y & 7); 687 ny = height - 1 + (y & 7);
597 mask = (0xFFu << (y & 7)) & 0xFFu; 688 mask = (0xFFu << (y & 7)) & 0xFFu;
@@ -653,8 +744,8 @@ void lcd_remote_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
653 lcd_remote_blockfunc_type *bfunc; 744 lcd_remote_blockfunc_type *bfunc;
654 745
655 /* nothing to draw? */ 746 /* nothing to draw? */
656 if ((width <= 0) || (height <= 0) || (x >= LCD_REMOTE_WIDTH) 747 if ((width <= 0) || (height <= 0) || (x >= current_vp->width) ||
657 || (y >= LCD_REMOTE_HEIGHT) || (x + width <= 0) || (y + height <= 0)) 748 (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
658 return; 749 return;
659 750
660 /* clipping */ 751 /* clipping */
@@ -670,10 +761,14 @@ void lcd_remote_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
670 src_y -= y; 761 src_y -= y;
671 y = 0; 762 y = 0;
672 } 763 }
673 if (x + width > LCD_REMOTE_WIDTH) 764 if (x + width > current_vp->width)
674 width = LCD_REMOTE_WIDTH - x; 765 width = current_vp->width - x;
675 if (y + height > LCD_REMOTE_HEIGHT) 766 if (y + height > current_vp->height)
676 height = LCD_REMOTE_HEIGHT - y; 767 height = current_vp->height - y;
768
769 /* adjust for viewport */
770 x += current_vp->x;
771 y += current_vp->y;
677 772
678 src += stride * (src_y >> 3) + src_x; /* move starting point */ 773 src += stride * (src_y >> 3) + src_x; /* move starting point */
679 src_y &= 7; 774 src_y &= 7;
@@ -682,7 +777,7 @@ void lcd_remote_mono_bitmap_part(const unsigned char *src, int src_x, int src_y,
682 shift = y & 7; 777 shift = y & 7;
683 ny = height - 1 + shift + src_y; 778 ny = height - 1 + shift + src_y;
684 779
685 bfunc = lcd_remote_blockfuncs[drawmode]; 780 bfunc = lcd_remote_blockfuncs[current_vp->drawmode];
686 mask = 0xFFu << (shift + src_y); 781 mask = 0xFFu << (shift + src_y);
687 /* not byte-doubled here because shift+src_y can be > 7 */ 782 /* not byte-doubled here because shift+src_y can be > 7 */
688 mask_bottom = 0xFFu >> (~ny & 7); 783 mask_bottom = 0xFFu >> (~ny & 7);
@@ -793,8 +888,8 @@ void lcd_remote_bitmap_part(const fb_remote_data *src, int src_x, int src_y,
793 unsigned mask, mask_bottom; 888 unsigned mask, mask_bottom;
794 889
795 /* nothing to draw? */ 890 /* nothing to draw? */
796 if ((width <= 0) || (height <= 0) || (x >= LCD_REMOTE_WIDTH) 891 if ((width <= 0) || (height <= 0) || (x >= current_vp->width)
797 || (y >= LCD_REMOTE_HEIGHT) || (x + width <= 0) || (y + height <= 0)) 892 || (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0))
798 return; 893 return;
799 894
800 /* clipping */ 895 /* clipping */
@@ -810,10 +905,14 @@ void lcd_remote_bitmap_part(const fb_remote_data *src, int src_x, int src_y,
810 src_y -= y; 905 src_y -= y;
811 y = 0; 906 y = 0;
812 } 907 }
813 if (x + width > LCD_REMOTE_WIDTH) 908 if (x + width > current_vp->width)
814 width = LCD_REMOTE_WIDTH - x; 909 width = current_vp->width - x;
815 if (y + height > LCD_REMOTE_HEIGHT) 910 if (y + height > current_vp->height)
816 height = LCD_REMOTE_HEIGHT - y; 911 height = current_vp->height - y;
912
913 /* adjust for viewport */
914 x += current_vp->x;
915 y += current_vp->y;
817 916
818 src += stride * (src_y >> 3) + src_x; /* move starting point */ 917 src += stride * (src_y >> 3) + src_x; /* move starting point */
819 src_y &= 7; 918 src_y &= 7;
@@ -917,11 +1016,11 @@ void lcd_remote_putsxyofs(int x, int y, int ofs, const unsigned char *str)
917{ 1016{
918 unsigned short ch; 1017 unsigned short ch;
919 unsigned short *ucs; 1018 unsigned short *ucs;
920 struct font* pf = font_get(curfont); 1019 struct font* pf = font_get(current_vp->font);
921 1020
922 ucs = bidi_l2v(str, 1); 1021 ucs = bidi_l2v(str, 1);
923 1022
924 while ((ch = *ucs++) != 0 && x < LCD_REMOTE_WIDTH) 1023 while ((ch = *ucs++) != 0 && x < current_vp->width)
925 { 1024 {
926 int width; 1025 int width;
927 const unsigned char *bits; 1026 const unsigned char *bits;
@@ -975,24 +1074,24 @@ void lcd_remote_puts_style_offset(int x, int y, const unsigned char *str,
975 int style, int offset) 1074 int style, int offset)
976{ 1075{
977 int xpos,ypos,w,h,xrect; 1076 int xpos,ypos,w,h,xrect;
978 int lastmode = drawmode; 1077 int lastmode = current_vp->drawmode;
979 1078
980 /* make sure scrolling is turned off on the line we are updating */ 1079 /* make sure scrolling is turned off on the line we are updating */
981 lcd_remote_scroll_info.lines &= ~(1 << y); 1080 lcd_remote_scroll_stop_line(current_vp, y);
982 1081
983 if(!str || !str[0]) 1082 if(!str || !str[0])
984 return; 1083 return;
985 1084
986 lcd_remote_getstringsize(str, &w, &h); 1085 lcd_remote_getstringsize(str, &w, &h);
987 xpos = xmargin + x*w / utf8length((char *)str); 1086 xpos = current_vp->xmargin + x*w / utf8length((char *)str);
988 ypos = ymargin + y*h; 1087 ypos = current_vp->ymargin + y*h;
989 drawmode = (style & STYLE_INVERT) ? 1088 current_vp->drawmode = (style & STYLE_INVERT) ?
990 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; 1089 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
991 lcd_remote_putsxyofs(xpos, ypos, offset, str); 1090 lcd_remote_putsxyofs(xpos, ypos, offset, str);
992 drawmode ^= DRMODE_INVERSEVID; 1091 current_vp->drawmode ^= DRMODE_INVERSEVID;
993 xrect = xpos + MAX(w - offset, 0); 1092 xrect = xpos + MAX(w - offset, 0);
994 lcd_remote_fillrect(xrect, ypos, LCD_REMOTE_WIDTH - xrect, h); 1093 lcd_remote_fillrect(xrect, ypos, current_vp->width - xrect, h);
995 drawmode = lastmode; 1094 current_vp->drawmode = lastmode;
996} 1095}
997 1096
998/*** scrolling ***/ 1097/*** scrolling ***/
@@ -1017,9 +1116,15 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri
1017 struct scrollinfo* s; 1116 struct scrollinfo* s;
1018 int w, h; 1117 int w, h;
1019 1118
1020 if(y>=LCD_REMOTE_SCROLLABLE_LINES) return; 1119 if ((unsigned)y >= (unsigned)current_vp->height)
1120 return;
1021 1121
1022 s = &lcd_remote_scroll_info.scroll[y]; 1122 /* remove any previously scrolling line at the same location */
1123 lcd_remote_scroll_stop_line(current_vp, y);
1124
1125 if (lcd_remote_scroll_info.lines >= LCD_REMOTE_SCROLLABLE_LINES) return;
1126
1127 s = &lcd_remote_scroll_info.scroll[lcd_remote_scroll_info.lines];
1023 1128
1024 s->start_tick = current_tick + lcd_remote_scroll_info.delay; 1129 s->start_tick = current_tick + lcd_remote_scroll_info.delay;
1025 s->style = style; 1130 s->style = style;
@@ -1031,7 +1136,7 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri
1031 1136
1032 lcd_remote_getstringsize(string, &w, &h); 1137 lcd_remote_getstringsize(string, &w, &h);
1033 1138
1034 if (LCD_REMOTE_WIDTH - x * 8 - xmargin < w) { 1139 if (current_vp->width - x * 8 - current_vp->xmargin < w) {
1035 /* prepare scroll line */ 1140 /* prepare scroll line */
1036 char *end; 1141 char *end;
1037 1142
@@ -1044,7 +1149,7 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri
1044 /* scroll bidirectional or forward only depending on the string 1149 /* scroll bidirectional or forward only depending on the string
1045 width */ 1150 width */
1046 if ( lcd_remote_scroll_info.bidir_limit ) { 1151 if ( lcd_remote_scroll_info.bidir_limit ) {
1047 s->bidir = s->width < (LCD_REMOTE_WIDTH - xmargin) * 1152 s->bidir = s->width < (current_vp->width - current_vp->xmargin) *
1048 (100 + lcd_remote_scroll_info.bidir_limit) / 100; 1153 (100 + lcd_remote_scroll_info.bidir_limit) / 100;
1049 } 1154 }
1050 else 1155 else
@@ -1057,17 +1162,17 @@ void lcd_remote_puts_scroll_style_offset(int x, int y, const unsigned char *stri
1057 } 1162 }
1058 1163
1059 end = strchr(s->line, '\0'); 1164 end = strchr(s->line, '\0');
1060 strncpy(end, (char *)string, LCD_REMOTE_WIDTH/2); 1165 strncpy(end, (char *)string, current_vp->width/2);
1061 1166
1167 s->vp = current_vp;
1168 s->y = y;
1062 s->len = utf8length((char *)string); 1169 s->len = utf8length((char *)string);
1063 s->offset = offset; 1170 s->offset = offset;
1064 s->startx = xmargin + x * s->width / s->len;; 1171 s->startx = current_vp->xmargin + x * s->width / s->len;
1065 s->backward = false; 1172 s->backward = false;
1066 lcd_remote_scroll_info.lines |= (1<<y); 1173
1174 lcd_remote_scroll_info.lines++;
1067 } 1175 }
1068 else
1069 /* force a bit switch-off since it doesn't scroll */
1070 lcd_remote_scroll_info.lines &= ~(1<<y);
1071} 1176}
1072 1177
1073void lcd_remote_scroll_fn(void) 1178void lcd_remote_scroll_fn(void)
@@ -1077,26 +1182,25 @@ void lcd_remote_scroll_fn(void)
1077 int index; 1182 int index;
1078 int xpos, ypos; 1183 int xpos, ypos;
1079 int lastmode; 1184 int lastmode;
1185 struct viewport* old_vp = current_vp;
1080 1186
1081 for ( index = 0; index < LCD_REMOTE_SCROLLABLE_LINES; index++ ) { 1187 for ( index = 0; index < lcd_remote_scroll_info.lines; index++ ) {
1082 /* really scroll? */
1083 if ((lcd_remote_scroll_info.lines & (1 << index)) == 0)
1084 continue;
1085
1086 s = &lcd_remote_scroll_info.scroll[index]; 1188 s = &lcd_remote_scroll_info.scroll[index];
1087 1189
1088 /* check pause */ 1190 /* check pause */
1089 if (TIME_BEFORE(current_tick, s->start_tick)) 1191 if (TIME_BEFORE(current_tick, s->start_tick))
1090 continue; 1192 continue;
1091 1193
1194 lcd_remote_set_viewport(s->vp);
1195
1092 if (s->backward) 1196 if (s->backward)
1093 s->offset -= lcd_remote_scroll_info.step; 1197 s->offset -= lcd_remote_scroll_info.step;
1094 else 1198 else
1095 s->offset += lcd_remote_scroll_info.step; 1199 s->offset += lcd_remote_scroll_info.step;
1096 1200
1097 pf = font_get(curfont); 1201 pf = font_get(current_vp->font);
1098 xpos = s->startx; 1202 xpos = s->startx;
1099 ypos = ymargin + index * pf->height; 1203 ypos = current_vp->ymargin + s->y * pf->height;
1100 1204
1101 if (s->bidir) { /* scroll bidirectional */ 1205 if (s->bidir) { /* scroll bidirectional */
1102 if (s->offset <= 0) { 1206 if (s->offset <= 0) {
@@ -1105,9 +1209,9 @@ void lcd_remote_scroll_fn(void)
1105 s->backward = false; 1209 s->backward = false;
1106 s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; 1210 s->start_tick = current_tick + lcd_remote_scroll_info.delay*2;
1107 } 1211 }
1108 if (s->offset >= s->width - (LCD_REMOTE_WIDTH - xpos)) { 1212 if (s->offset >= s->width - (current_vp->width - xpos)) {
1109 /* at end of line */ 1213 /* at end of line */
1110 s->offset = s->width - (LCD_REMOTE_WIDTH - xpos); 1214 s->offset = s->width - (current_vp->width - xpos);
1111 s->backward = true; 1215 s->backward = true;
1112 s->start_tick = current_tick + lcd_remote_scroll_info.delay*2; 1216 s->start_tick = current_tick + lcd_remote_scroll_info.delay*2;
1113 } 1217 }
@@ -1118,18 +1222,24 @@ void lcd_remote_scroll_fn(void)
1118 s->offset %= s->width; 1222 s->offset %= s->width;
1119 } 1223 }
1120 1224
1121 lastmode = drawmode; 1225 lastmode = current_vp->drawmode;
1122 drawmode = (s->style&STYLE_INVERT) ? 1226 current_vp->drawmode = (s->style&STYLE_INVERT) ?
1123 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; 1227 (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID;
1124 lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line); 1228 lcd_remote_putsxyofs(xpos, ypos, s->offset, s->line);
1125 drawmode = lastmode; 1229 current_vp->drawmode = lastmode;
1126 lcd_remote_update_rect(xpos, ypos, LCD_REMOTE_WIDTH - xpos, pf->height); 1230 lcd_remote_update_viewport_rect(xpos, ypos,
1231 current_vp->width - xpos, pf->height);
1127 } 1232 }
1233
1234 lcd_remote_set_viewport(old_vp);
1128} 1235}
1129 1236
1130/* LCD init */ 1237/* LCD init */
1131void lcd_remote_init(void) 1238void lcd_remote_init(void)
1132{ 1239{
1240 /* Initialise the viewport */
1241 lcd_remote_set_viewport(NULL);
1242
1133#ifndef SIMULATOR 1243#ifndef SIMULATOR
1134 /* Call device specific init */ 1244 /* Call device specific init */
1135 lcd_remote_init_device(); 1245 lcd_remote_init_device();