text viewer: reworks screen access logics and some bugs fix.
authoruchida <uchida@a1c6a512-1295-4272-9138-f99709370657>
Sat, 26 Jun 2010 09:14:53 +0000 (26 09:14 +0000)
committeruchida <uchida@a1c6a512-1295-4272-9138-f99709370657>
Sat, 26 Jun 2010 09:14:53 +0000 (26 09:14 +0000)
- screen access logics separte from tv_window. (new tv_display.[ch])
- using multi screen api.
- (bug fix) the head of the each line is not normally displayed when the alignment is RIGHT.
- (bug fix) unnecessary blank line is not displayed. (a part of FS#11400).
- (bug fix) the order by which callback functions were called was not correct. (FIFO->FILO)

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27138 a1c6a512-1295-4272-9138-f99709370657

apps/plugins/text_viewer/SOURCES
apps/plugins/text_viewer/tv_display.c [new file with mode: 0644]
apps/plugins/text_viewer/tv_display.h [new file with mode: 0644]
apps/plugins/text_viewer/tv_preferences.c
apps/plugins/text_viewer/tv_text_processor.c
apps/plugins/text_viewer/tv_window.c

index 7e45d1f..80fec09 100644 (file)
@@ -1,6 +1,7 @@
 text_viewer.c
 tv_action.c
 tv_bookmark.c
+tv_display.c
 tv_menu.c
 tv_pager.c
 tv_preferences.c
diff --git a/apps/plugins/text_viewer/tv_display.c b/apps/plugins/text_viewer/tv_display.c
new file mode 100644 (file)
index 0000000..78b5b4b
--- /dev/null
@@ -0,0 +1,344 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Yoshihisa Uchida
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "tv_display.h"
+#include "tv_preferences.h"
+
+/*
+ * display layout
+ *
+ * when is defined HAVE_LCD_BITMAP
+ * +-------------------------+
+ * |statusbar (1)            |
+ * +-------------------------+
+ * |filename  (2)            |
+ * +---+---------------------+
+ * |s  |                     |
+ * |c  |                     |
+ * |r  | draw area           |
+ * |o  |                     |
+ * |l  |                     |
+ * |l  |                     |
+ * |b  |                     |
+ * |a  |                     |
+ * |r  |                     |
+ * |(3)|                     |
+ * +---+---------------------+
+ * |   |scrollbar (4)        |
+ * +---+---------------------+
+ * |page (5)                 |
+ * +-------------------------+
+ * |statusbar (6)            |
+ * +-------------------------+
+ *
+ * (1) displays when rb->global_settings->statusbar == STATUSBAR_TOP
+ *              and  preferences->header_mode is HD_SBAR or HD_BOTH.
+ * (2) displays when preferences->header_mode is HD_PATH or HD_BOTH.
+ * (3) displays when preferences->vertical_scrollbar is SB_ON.
+ * (4) displays when preferences->horizontal_scrollbar is SB_ON.
+ * (5) displays when preferences->footer_mode is FT_PAGE or FT_BOTH.
+ * (6) displays when rb->global_settings->statusbar == STATUSBAR_BOTTOM
+ *              and  preferences->footer_mode is FT_SBAR or FT_BOTH.
+ *
+ *
+ * when isn't defined HAVE_LCD_BITMAP
+ * +---+---------------------+
+ * |   |                     |
+ * |(7)| draw area           |
+ * |   |                     |
+ * +---+---------------------+
+ * (7) bookmark
+ */
+
+#define TV_SCROLLBAR_WIDTH  rb->global_settings->scrollbar_width
+#define TV_SCROLLBAR_HEIGHT 4
+
+#ifndef HAVE_LCD_BITMAP
+#define TV_BOOKMARK_ICON 0xe101
+#endif
+
+struct tv_rect {
+    int x;
+    int y;
+    int w;
+    int h;
+};
+
+static struct viewport vp_info;
+static bool is_initialized_vp = false;
+
+#ifdef HAVE_LCD_BITMAP
+static int drawmode = DRMODE_SOLID;
+static int totalsize;
+static bool show_vertical_scrollbar;
+#endif
+
+static struct screen* display;
+
+/* layout */
+#ifdef HAVE_LCD_BITMAP
+static struct tv_rect header;
+static struct tv_rect footer;
+static struct tv_rect horizontal_scrollbar;
+static struct tv_rect vertical_scrollbar;
+#else
+static struct tv_rect bookmark;
+#endif
+static struct tv_rect drawarea;
+
+static int display_columns;
+static int display_rows;
+
+static int col_width;
+static int row_height;
+
+#ifdef HAVE_LCD_BITMAP
+
+void tv_show_header(void)
+{
+    unsigned header_mode = header_mode;
+
+    if (preferences->header_mode == HD_PATH || preferences->header_mode == HD_BOTH)
+        display->putsxy(header.x, header.y, preferences->file_name);
+}
+
+void tv_show_footer(const struct tv_screen_pos *pos)
+{
+    unsigned char buf[12];
+    unsigned footer_mode = preferences->footer_mode;
+
+    if (footer_mode == FT_PAGE || footer_mode == FT_BOTH)
+    {
+        if (pos->line == 0)
+            rb->snprintf(buf, sizeof(buf), "%d", pos->page + 1);
+        else
+            rb->snprintf(buf, sizeof(buf), "%d - %d", pos->page + 1, pos->page + 2);
+        display->putsxy(footer.x, footer.y, buf);
+    }
+}
+
+void tv_init_scrollbar(off_t total, bool show_scrollbar)
+{
+    totalsize = total;
+    show_vertical_scrollbar = show_scrollbar;
+}
+
+void tv_show_scrollbar(int window, int col, off_t cur_pos, int size)
+{
+    int items;
+    int min_shown;
+    int max_shown;
+
+    if (preferences->horizontal_scrollbar)
+    {
+        items     = preferences->windows * display_columns;
+        min_shown = window * display_columns + col;
+        max_shown = min_shown + display_columns;
+
+        rb->gui_scrollbar_draw(display,
+                               horizontal_scrollbar.x, horizontal_scrollbar.y,
+                               horizontal_scrollbar.w, TV_SCROLLBAR_HEIGHT,
+                               items, min_shown, max_shown, HORIZONTAL);
+    }
+
+    if (show_vertical_scrollbar)
+    {
+        items     = (int) totalsize;
+        min_shown = (int) cur_pos;
+        max_shown = min_shown + size;
+
+        rb->gui_scrollbar_draw(display,
+                               vertical_scrollbar.x, vertical_scrollbar.y,
+                               TV_SCROLLBAR_WIDTH-1, vertical_scrollbar.h,
+                               items, min_shown, max_shown, VERTICAL);
+    }
+}
+
+void tv_fillrect(int col, int row, int rows)
+{
+    display->fillrect(drawarea.x + col * col_width, drawarea.y + row * row_height,
+                      drawarea.w - col * col_width, rows * row_height);
+}
+
+void tv_set_drawmode(int mode)
+{
+    rb->lcd_set_drawmode(mode);
+}
+
+#endif
+
+void tv_draw_text(int row, const unsigned char *text, int offset)
+{
+    int xpos = -offset * col_width;
+    int text_width;
+
+    if (row < 0 || row >= display_rows)
+        return;
+
+    if (preferences->alignment == AL_RIGHT)
+    {
+        display->getstringsize(text, &text_width, NULL);
+        xpos += ((offset > 0)? drawarea.w * 2 : drawarea.w) - text_width;
+    }
+
+#ifdef HAVE_LCD_BITMAP
+    display->putsxy(drawarea.x + xpos, drawarea.y + row * row_height, text);
+#else
+    display->puts(drawarea.x + xpos, drawarea.y + row, text);
+#endif
+}
+
+#ifndef HAVE_LCD_BITMAP
+void tv_put_bookmark_icon(int row)
+{
+    display->putchar(bookmark.x, drawarea.y + row, TV_BOOKMARK_ICON);
+}
+#endif
+
+void tv_init_display(void)
+{
+    display = rb->screens[SCREEN_MAIN];
+    display->clear_viewport();
+}
+
+void tv_start_display(void)
+{
+    display->set_viewport(&vp_info);
+#ifdef HAVE_LCD_BITMAP
+    drawmode = rb->lcd_get_drawmode();
+#endif
+}
+
+void tv_end_display(void)
+{
+#ifdef HAVE_LCD_BITMAP
+    rb->lcd_set_drawmode(drawmode);
+#endif
+    display->set_viewport(NULL);
+}
+
+void tv_clear_display(void)
+{
+    display->clear_viewport();
+}
+
+void tv_update_display(void)
+{
+    display->update_viewport();
+}
+
+#ifdef HAVE_LCD_BITMAP
+void tv_set_layout(int col_w, bool show_scrollbar)
+#else
+void tv_set_layout(int col_w)
+#endif
+{
+#ifdef HAVE_LCD_BITMAP
+    int scrollbar_width  = (show_scrollbar)?                    TV_SCROLLBAR_WIDTH  : 0;
+    int scrollbar_height = (preferences->horizontal_scrollbar)? TV_SCROLLBAR_HEIGHT : 0;
+    unsigned header_mode = preferences->header_mode;
+    unsigned footer_mode = preferences->footer_mode;
+
+    row_height = preferences->font->height;
+
+    header.x = 0;
+    header.y = 0;
+    header.w = vp_info.width;
+    header.h = (header_mode == HD_PATH || header_mode == HD_BOTH)? row_height : 0;
+
+    footer.x = 0;
+    footer.w = vp_info.width;
+    footer.h = (footer_mode == FT_PAGE || footer_mode == FT_BOTH)? row_height : 0;
+    footer.y = vp_info.height - footer.h;
+
+    drawarea.x = scrollbar_width;
+    drawarea.y = header.y + header.h;
+    drawarea.w = vp_info.width - scrollbar_width;
+    drawarea.h = footer.y - drawarea.y - scrollbar_height;
+
+    horizontal_scrollbar.x = drawarea.x;
+    horizontal_scrollbar.y = footer.y - scrollbar_height;
+    horizontal_scrollbar.w = drawarea.w;
+    horizontal_scrollbar.h = scrollbar_height;
+
+    vertical_scrollbar.x = 0;
+    vertical_scrollbar.y = drawarea.y;
+    vertical_scrollbar.w = scrollbar_width;
+    vertical_scrollbar.h = drawarea.h;
+#else
+    row_height = 1;
+
+    bookmark.x = 0;
+    bookmark.y = 0;
+    bookmark.w = 1;
+    bookmark.h = vp_info.height;
+
+    drawarea.x = 1;
+    drawarea.y = 0;
+    drawarea.w = vp_info.width - 1;
+    drawarea.h = vp_info.height;
+#endif
+    col_width = col_w;
+
+    display_columns = drawarea.w / col_width;
+    display_rows    = drawarea.h / row_height;
+}
+
+void tv_get_drawarea_info(int *width, int *cols, int *rows)
+{
+    *width = drawarea.w;
+    *cols  = display_columns;
+    *rows  = display_rows;
+}
+
+void tv_change_viewport(void)
+{
+#ifdef HAVE_LCD_BITMAP
+    struct viewport vp;
+    bool show_statusbar = (preferences->header_mode == HD_SBAR ||
+                           preferences->header_mode == HD_BOTH ||
+                           preferences->footer_mode == FT_SBAR ||
+                           preferences->footer_mode == FT_BOTH);
+
+    if (is_initialized_vp)
+        tv_undo_viewport();
+    else
+        is_initialized_vp = true;
+
+    rb->viewportmanager_theme_enable(SCREEN_MAIN, show_statusbar, &vp);
+    vp_info = vp;
+    vp_info.flags &= ~VP_FLAG_ALIGNMENT_MASK;
+
+#else
+    if (!is_initialized_vp)
+    {
+        rb->viewport_set_defaults(&vp_info, SCREEN_MAIN);
+        is_initialized_vp = true;
+    }
+#endif
+}
+
+void tv_undo_viewport(void)
+{
+#ifdef HAVE_LCD_BITMAP
+    if (is_initialized_vp)
+        rb->viewportmanager_theme_undo(SCREEN_MAIN, false);
+#endif
+}
diff --git a/apps/plugins/text_viewer/tv_display.h b/apps/plugins/text_viewer/tv_display.h
new file mode 100644 (file)
index 0000000..005011c
--- /dev/null
@@ -0,0 +1,175 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Yoshihisa Uchida
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef PLUGIN_TEXT_VIEWER_DISPLAY_H
+#define PLUGIN_TEXT_VIEWER_DISPLAY_H
+
+#include "plugin.h"
+#include "tv_screen_pos.h"
+
+/* text viewer layout parts functions */
+#ifdef HAVE_LCD_BITMAP
+
+/* show headaer */
+void tv_show_header(void);
+
+/*
+ * show footer
+ *
+ * [In] pos
+ *       the current position
+ */
+void tv_show_footer(const struct tv_screen_pos *pos);
+
+/*
+ * initialize the scrollbar
+ *
+ * [In] total
+ *          total text size
+ *
+ * [In] show_scrollbar
+ *          true:  show the vertical scrollbar
+ *          false: does not show the vertical scrollbar
+ */
+void tv_init_scrollbar(off_t total, bool show_scrollbar);
+
+/*
+ * show horizontal/vertical scrollbar
+ *
+ * [In] window
+ *          the current window
+ *
+ * [In] col
+ *          the current column
+ *
+ * [In] cur_pos
+ *          the current text position
+ *
+ * [In] size
+ *          the size of text in displayed.
+ */
+void tv_show_scrollbar(int window, int col, off_t cur_pos, int size);
+
+#else
+
+/*
+ * put the bookmark icon
+ *
+ * [In] row
+ *          the row where the bookmark icon is put
+ */
+void tv_put_bookmark_icon(int row);
+
+#endif
+
+/* common display functons */
+
+/* initialized display functions */
+void tv_init_display(void);
+
+/* start the display processing  */
+void tv_start_display(void);
+
+/* end the display processing */
+void tv_end_display(void);
+
+/* clear the display */
+void tv_clear_display(void);
+
+/*update the display  */
+void tv_update_display(void);
+
+#ifdef HAVE_LCD_BITMAP
+
+/*
+ * set the drawmode
+ *
+ * [In] mode
+ *          new drawmode
+ */
+void tv_set_drawmode(int mode);
+
+/*
+ * draw the rectangle that paints out inside
+ *
+ * [In] col
+ *          the column of the upper left
+ *
+ * [In] row
+ *          the row of the upper left
+ *
+ * [In] row
+ *          draw rows
+ */
+void tv_fillrect(int col, int row, int rows);
+
+#endif
+
+/*
+ * draw the text
+ *
+ * [In] row
+ *          the row that displays the text
+ *
+ * [In] text
+ *          text
+ *
+ * [In] offset
+ *          display the text that is since offset columns
+ */
+void tv_draw_text(int row, const unsigned char *text, int offset);
+
+/* layout functions */
+#ifdef HAVE_LCD_BITMAP
+
+/*
+ * set the layout
+ *
+ * [In] col_w
+ *          width per column
+ *
+ * [In] show_scrollbar
+ *          true:  show the vertical scrollbar
+ *          false: does not show the vertical scrollbar
+ */
+void tv_set_layout(int col_w, bool show_scrollbar);
+
+#else
+
+/*
+ * set the layout
+ *
+ * [In] col_w
+ *          width per column
+ */
+void tv_set_layout(int col_w);
+
+#endif
+void tv_get_drawarea_info(int *width, int *cols, int *rows);
+
+/* viewport functions */
+
+/* change the viewport */
+void tv_change_viewport(void);
+
+/* undo the viewport */
+void tv_undo_viewport(void);
+
+#endif
index 30b5f5c..72cda9d 100644 (file)
@@ -62,7 +62,8 @@ static void tv_notify_change_preferences(const struct tv_preferences *oldp)
 #endif
         (rb->strcmp(oldp->file_name, preferences->file_name)))
     {
-        for (i = 0; i < listner_count; i++)
+        /* callback functions are called as FILO */
+        for (i = listner_count - 1; i >= 0; i--)
             listners[i](oldp);
     }
 }
index 1ddee62..edb2ad0 100644 (file)
@@ -512,7 +512,8 @@ int tv_create_formed_text(const unsigned char *src, ssize_t bufsize,
     tv_get_ucs(src, &ch);
     is_indent = (tv_isspace(ch) && !is_break_line);
 
-    if (is_indent && preferences->indent_spaces == 0 && (expand_extra_line = !expand_extra_line) == true)
+    if (is_indent && preferences->line_mode == LM_REFLOW && preferences->indent_spaces == 0
+                  && (expand_extra_line = !expand_extra_line) == true)
         return 0;
 
     for (i = 0; i < block_count; i++)
index 1bb47b1..df3951a 100644 (file)
  ****************************************************************************/
 #include "plugin.h"
 #include "tv_bookmark.h"
+#include "tv_display.h"
 #include "tv_preferences.h"
 #include "tv_screen_pos.h"
 #include "tv_text_reader.h"
 #include "tv_window.h"
 
-#define TV_SCROLLBAR_WIDTH  rb->global_settings->scrollbar_width
-#define TV_SCROLLBAR_HEIGHT 4
-
-#ifndef HAVE_LCD_BITMAP
-#define TV_BOOKMARK_ICON 0xe101
-#endif
-
-#ifdef HAVE_LCD_BITMAP
-static int header_height;
-static int footer_height;
-static bool need_vertical_scrollbar = false;
-#endif
-
-static int start_width;
-static int display_lines;
-
 static int window_width;
 static int window_columns;
+static int display_lines;
 static int col_width;
 
 static int cur_window;
@@ -100,96 +86,6 @@ static bool tv_check_header_and_footer(struct tv_preferences *new_prefs)
 
     return change_prefs;
 }
-
-static void tv_show_header(void)
-{
-    unsigned header_mode = header_mode;
-    if (header_mode == HD_SBAR || header_mode == HD_BOTH)
-        rb->gui_syncstatusbar_draw(rb->statusbars, true);
-
-    if (header_mode == HD_PATH || header_mode == HD_BOTH)
-        rb->lcd_putsxy(0, header_height - preferences->font->height, preferences->file_name);
-}
-
-static void tv_show_footer(const struct tv_screen_pos *pos)
-{
-    unsigned char buf[12];
-    unsigned footer_mode = preferences->footer_mode;
-
-    if (footer_mode == FT_SBAR || footer_mode == FT_BOTH)
-        rb->gui_syncstatusbar_draw(rb->statusbars, true);
-
-    if (footer_mode == FT_PAGE || footer_mode == FT_BOTH)
-    {
-        if (pos->line == 0)
-            rb->snprintf(buf, sizeof(buf), "%d", pos->page + 1);
-        else
-            rb->snprintf(buf, sizeof(buf), "%d - %d", pos->page + 1, pos->page + 2);
-
-        rb->lcd_putsxy(0, LCD_HEIGHT - footer_height, buf);
-    }
-}
-
-static void tv_show_scrollbar(off_t cur_pos, int size)
-{
-    int items;
-    int min_shown;
-    int max_shown;
-    int sb_width;
-    int sb_height;
-
-    sb_height = LCD_HEIGHT - header_height - footer_height;
-    if (preferences->horizontal_scrollbar)
-    {
-        items     = preferences->windows * window_columns;
-        min_shown = cur_window * window_columns + cur_column;
-        max_shown = min_shown + window_columns;
-        sb_width  = (need_vertical_scrollbar)? TV_SCROLLBAR_WIDTH : 0;
-        sb_height -= TV_SCROLLBAR_HEIGHT;
-
-        rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN],
-                               sb_width,
-                               LCD_HEIGHT - footer_height - TV_SCROLLBAR_HEIGHT,
-                               LCD_WIDTH - sb_width, TV_SCROLLBAR_HEIGHT,
-                               items, min_shown, max_shown, HORIZONTAL);
-    }
-
-    if (need_vertical_scrollbar)
-    {
-        items     = (int) tv_get_total_text_size();
-        min_shown = (int) cur_pos;
-        max_shown = min_shown + size;
-
-        rb->gui_scrollbar_draw(rb->screens[SCREEN_MAIN], 0, header_height,
-                               TV_SCROLLBAR_WIDTH-1, sb_height,
-                               items, min_shown, max_shown, VERTICAL);
-    }
-}
-
-static int tv_calc_display_lines(void)
-{
-    int scrollbar_height = preferences->horizontal_scrollbar ? TV_SCROLLBAR_HEIGHT : 0;
-    unsigned header_mode = preferences->header_mode;
-    unsigned footer_mode = preferences->footer_mode;
-
-    header_height = (header_mode == HD_SBAR || header_mode == HD_BOTH)?
-                    STATUSBAR_HEIGHT : 0;
-
-    footer_height = (footer_mode == FT_SBAR || footer_mode == FT_BOTH)?
-                    STATUSBAR_HEIGHT : 0;
-
-    if (header_mode == HD_NONE || header_mode == HD_PATH ||
-        footer_mode == FT_NONE || footer_mode == FT_PAGE)
-        rb->gui_syncstatusbar_draw(rb->statusbars, false);
-
-    if (header_mode == HD_PATH || header_mode == HD_BOTH)
-        header_height += preferences->font->height;
-
-    if (footer_mode == FT_PAGE || footer_mode == FT_BOTH)
-        footer_height += preferences->font->height;
-
-    return (LCD_HEIGHT - header_height - footer_height - scrollbar_height) / preferences->font->height;
-}
 #endif
 
 static void tv_show_bookmarks(const struct tv_screen_pos *top_pos)
@@ -199,8 +95,9 @@ static void tv_show_bookmarks(const struct tv_screen_pos *top_pos)
     int line;
 
 #ifdef HAVE_LCD_BITMAP
-    rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
+    tv_set_drawmode(DRMODE_COMPLEMENT);
 #endif
+
     while (count--)
     {
         line = (bookmarks[count].page - top_pos->page) * display_lines
@@ -208,66 +105,51 @@ static void tv_show_bookmarks(const struct tv_screen_pos *top_pos)
         if (line >= 0 && line < display_lines)
         {
 #ifdef HAVE_LCD_BITMAP
-            rb->lcd_fillrect(start_width, header_height + line * preferences->font->height,
-                             window_width, preferences->font->height);
+            tv_fillrect(0, line, 1);
 #else
-            rb->lcd_putc(start_width - 1, line, TV_BOOKMARK_ICON);
+            tv_put_bookmark_icon(line);
 #endif
         }
     }
-#ifdef HAVE_LCD_BITMAP
-    rb->lcd_set_drawmode(DRMODE_SOLID);
-#endif
 }
 
 void tv_draw_window(void)
 {
     struct tv_screen_pos pos;
-    const unsigned char *line_buf;
+    const unsigned char *text_buf;
     int line;
-    int offset = cur_column * col_width;
     int size = 0;
-    int line_width;
-    int draw_width = (preferences->windows - cur_window) * LCD_WIDTH - offset;
-    int dx = start_width - offset;
 
     tv_copy_screen_pos(&pos);
-    rb->lcd_clear_display();
 
-    if (preferences->alignment == AL_LEFT)
-        tv_read_start(cur_window, (cur_column > 0));
-    else
-        tv_read_start(0, preferences->windows > 1);
+    tv_start_display();
+
+#ifdef HAVE_LCD_BITMAP
+    tv_set_drawmode(DRMODE_SOLID);
+#endif
+    tv_clear_display();
+
+    tv_read_start(cur_window, (cur_column > 0));
 
     for (line = 0; line < display_lines; line++)
     {
-        if (!tv_get_next_line(&line_buf))
+        if (!tv_get_next_line(&text_buf))
             break;
 
-        if (preferences->alignment == AL_RIGHT)
-        {
-            rb->lcd_getstringsize(line_buf, &line_width, NULL);
-            dx = draw_width - line_width;
-        }
-
-#ifdef HAVE_LCD_BITMAP
-        rb->lcd_putsxy(dx, header_height + line * preferences->font->height, line_buf);
-#else
-        rb->lcd_puts(dx, line, line_buf);
-#endif
+        tv_draw_text(line, text_buf, cur_column);
     }
 
     size = tv_read_end();
 
-    tv_show_bookmarks(&pos);
-
 #ifdef HAVE_LCD_BITMAP
-    tv_show_scrollbar(pos.file_pos, size);
+    tv_show_scrollbar(cur_window, cur_column, pos.file_pos, size);
     tv_show_header();
     tv_show_footer(&pos);
 #endif
+    tv_show_bookmarks(&pos);
 
-    rb->lcd_update();
+    tv_update_display();
+    tv_end_display();
 }
 
 bool tv_traverse_lines(void)
@@ -290,10 +172,13 @@ bool tv_traverse_lines(void)
 
 static void tv_change_preferences(const struct tv_preferences *oldp)
 {
-#ifdef HAVE_LCD_BITMAP
+#ifndef HAVE_LCD_BITMAP
+    (void)oldp;
+#else
     static bool font_changing = false;
     const unsigned char *font_str;
     bool change_prefs = false;
+    bool need_vertical_scrollbar;
     struct tv_preferences new_prefs;
     tv_copy_preferences(&new_prefs);
 
@@ -317,14 +202,6 @@ static void tv_change_preferences(const struct tv_preferences *oldp)
     }
 
     font_changing = false;
-
-    /* calculates display lines */
-    display_lines = tv_calc_display_lines();
-#else
-    (void)oldp;
-
-    /* REAL fixed pitch :) all chars use up 1 cell */
-    display_lines = 2;
 #endif
 
 #ifdef HAVE_LCD_BITMAP
@@ -336,27 +213,36 @@ static void tv_change_preferences(const struct tv_preferences *oldp)
     if (cur_window >= preferences->windows)
         cur_window = 0;
 
-    window_width = LCD_WIDTH;
+    /* change viewport */
+    tv_change_viewport();
+
 #ifdef HAVE_LCD_BITMAP
     need_vertical_scrollbar = false;
-    start_width = 0;
+    tv_set_layout(col_width, need_vertical_scrollbar);
+    tv_get_drawarea_info(&window_width, &window_columns, &display_lines);
     tv_seek_top();
     tv_set_read_conditions(preferences->windows, window_width);
     if (tv_traverse_lines() && preferences->vertical_scrollbar)
     {
         need_vertical_scrollbar = true;
-        start_width = TV_SCROLLBAR_WIDTH;
+        tv_set_layout(col_width, need_vertical_scrollbar);
+        tv_get_drawarea_info(&window_width, &window_columns, &display_lines);
     }
     tv_seek_top();
 #else
-    start_width = 1;
+    tv_set_layout(col_width);
+    tv_get_drawarea_info(&window_width, &window_columns, &display_lines);
 #endif
-    window_width -= start_width;
-    window_columns = window_width / col_width;
 
+    window_columns = window_width / col_width;
     cur_column = 0;
 
     tv_set_read_conditions(preferences->windows, window_width);
+
+    tv_init_display();
+#ifdef HAVE_LCD_BITMAP
+    tv_init_scrollbar(tv_get_total_text_size(), need_vertical_scrollbar);
+#endif
 }
 
 bool tv_init_window(unsigned char **buf, size_t *size)
@@ -375,6 +261,9 @@ void tv_finalize_window(void)
     {
         tv_set_font(rb->global_settings->font_file);
     }
+
+    /* undo viewport */
+    tv_undo_viewport();
 #endif
 }