diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c index 94870538d6..ff29397532 100644 --- a/apps/gui/bitmap/list.c +++ b/apps/gui/bitmap/list.c @@ -40,6 +40,7 @@ #include "sound.h" #include "misc.h" #include "viewport.h" +#include "language.h" #define ICON_PADDING 1 @@ -61,6 +62,9 @@ bool list_display_title(struct gui_synclist *list, enum screen_type screen); | | | items | I - icons | | | | ------------------ + + Note: This image is flipped horizontally when the language is a + right-to-left one (Hebrew, Arabic) */ static bool draw_title(struct screen *display, struct gui_synclist *list) { @@ -77,10 +81,17 @@ static bool draw_title(struct screen *display, struct gui_synclist *list) struct viewport title_icon = title_text[screen]; title_icon.width = get_icon_width(screen) + ICON_PADDING*2; - title_icon.x += ICON_PADDING; - + if (lang_is_rtl()) + { + title_icon.x = title_text[screen].width - ICON_PADDING - + get_icon_width(screen); + } + else + { + title_icon.x = ICON_PADDING; + title_text[screen].x += title_icon.width; + } title_text[screen].width -= title_icon.width; - title_text[screen].x += title_icon.width; display->set_viewport(&title_icon); screen_put_icon(display, 0, 0, list->title_icon); @@ -108,7 +119,7 @@ void list_draw(struct screen *display, struct gui_synclist *list) #ifdef HAVE_LCD_COLOR unsigned char cur_line = 0; #endif - int item_offset; + int item_offset, is_rtl = lang_is_rtl(); bool show_title; line_height = font_get(parent->font)->height; display->set_viewport(parent); @@ -132,12 +143,12 @@ void list_draw(struct screen *display, struct gui_synclist *list) vp = list_text[screen]; vp.width = SCROLLBAR_WIDTH; list_text[screen].width -= SCROLLBAR_WIDTH; - if(global_settings.scrollbar == SCROLLBAR_LEFT) + if (global_settings.scrollbar == SCROLLBAR_SHOW) list_text[screen].x += SCROLLBAR_WIDTH; vp.height = line_height * viewport_get_nb_lines(&list_text[screen]); vp.x = parent->x; - if(global_settings.scrollbar == SCROLLBAR_RIGHT) + if (global_settings.scrollbar == SCROLLBAR_SHOW_OPPOSITE) vp.x += list_text[screen].width; display->set_viewport(&vp); gui_scrollbar_draw(display, 0, 0, SCROLLBAR_WIDTH-1, @@ -149,7 +160,7 @@ void list_draw(struct screen *display, struct gui_synclist *list) else if (show_title) { /* shift everything right a bit... */ - if(global_settings.scrollbar == SCROLLBAR_LEFT) + if (global_settings.scrollbar == SCROLLBAR_SHOW) { list_text[screen].width -= SCROLLBAR_WIDTH; list_text[screen].x += SCROLLBAR_WIDTH; @@ -167,8 +178,10 @@ void list_draw(struct screen *display, struct gui_synclist *list) list_icons.width = icon_width * icon_count; list_text[screen].width -= list_icons.width + ICON_PADDING; - list_text[screen].x += - list_icons.width + ICON_PADDING; + if (is_rtl) + list_icons.x += list_text[screen].width; + else + list_text[screen].x += list_icons.width + ICON_PADDING; } for (i=start; inb_items; i++) diff --git a/apps/gui/icon.c b/apps/gui/icon.c index 53cfd87774..a473c82872 100644 --- a/apps/gui/icon.c +++ b/apps/gui/icon.c @@ -29,6 +29,7 @@ #include "settings.h" #include "bmp.h" #include "filetypes.h" +#include "language.h" #include "bitmaps/default_icons.h" #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) @@ -170,6 +171,8 @@ void screen_put_iconxy(struct screen * display, #endif draw_func = display->bitmap_part; + if (lang_is_rtl()) + xpos = display->getwidth() - xpos - width; draw_func(data, 0, height * icon, stride, xpos, ypos, width, height); } diff --git a/apps/lang/arabic.lang b/apps/lang/arabic.lang index c06af35560..73a98fe906 100644 --- a/apps/lang/arabic.lang +++ b/apps/lang/arabic.lang @@ -17,6 +17,9 @@ # Arabic language file, translated by: # - Mohamed Tarek # - Raafat Akkad + + rtl: 1 + id: LANG_EQUALIZER_HARDWARE_BANDWIDTH_NARROW desc: deprecated diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 8be7380225..d34b2e9b32 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -13075,3 +13075,54 @@ swcodec: "Release Time" + + id: LANG_HIDE + desc: in Settings -> General -> Display -> Status-/Scrollbar -> Scrollbar + user: core + + *: none + lcd_bitmap: "Hide" + + + *: none + lcd_bitmap: "Hide" + + + *: none + lcd_bitmap: "Hide" + + + + id: LANG_SHOW + desc: in Settings -> General -> Display -> Status-/Scrollbar -> Scrollbar + user: core + + *: none + lcd_bitmap: "Show" + + + *: none + lcd_bitmap: "Show" + + + *: none + lcd_bitmap: "Show" + + + + id: LANG_SHOW_OPPOSITE + desc: in Settings -> General -> Display -> Status-/Scrollbar -> Scrollbar + user: core + + *: none + lcd_bitmap: "Show Opposite" + + + *: none + lcd_bitmap: "Show Opposite" + + + *: none + lcd_bitmap: "Show Opposite" + + diff --git a/apps/lang/hebrew.lang b/apps/lang/hebrew.lang index 76deb4d007..449bbfe0a0 100644 --- a/apps/lang/hebrew.lang +++ b/apps/lang/hebrew.lang @@ -20,6 +20,10 @@ # - Rani Hod # - Tomer Shalev # - Sasha Khamkov + + + rtl: 1 + id: LANG_SET_BOOL_YES desc: bool true representation diff --git a/apps/language.c b/apps/language.c index bba1359616..0c6245f08c 100644 --- a/apps/language.c +++ b/apps/language.c @@ -34,9 +34,10 @@ /* These defines must match the initial bytes in the binary lang file */ /* See tools/genlang (TODO: Use common include for both) */ #define LANGUAGE_COOKIE 0x1a -#define LANGUAGE_VERSION 0x04 +#define LANGUAGE_VERSION 0x05 +#define LANGUAGE_FLAG_RTL 0x01 -#define HEADER_SIZE 3 +#define HEADER_SIZE 4 static unsigned char language_buffer[MAX_LANGUAGE_SIZE]; @@ -51,6 +52,13 @@ void lang_init(void) } } +static unsigned char lang_options = 0; + +int lang_is_rtl(void) +{ + return (lang_options & LANGUAGE_FLAG_RTL) != 0; +} + int lang_load(const char *filename) { int fsize; @@ -98,6 +106,7 @@ int lang_load(const char *filename) retcode = 3; } close(fd); + lang_options = (retcode ? 0 : lang_header[3]); return retcode; } diff --git a/apps/language.h b/apps/language.h index 06769a3dd9..c2a1b70e18 100644 --- a/apps/language.h +++ b/apps/language.h @@ -30,4 +30,6 @@ int lang_load(const char *filename); /* get the ID of an english string so it can be localised */ int lang_english_to_id(const char* english); +/* returns whether the loaded language is a right-to-left language */ +int lang_is_rtl(void); #endif diff --git a/apps/settings.h b/apps/settings.h index b208ee5872..b64fe37c74 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -158,7 +158,7 @@ enum { REPLAYGAIN_TRACK = 0, REPLAYGAIN_ALBUM, REPLAYGAIN_SHUFFLE, REPLAYGAIN_OF enum { SHOW_PATH_OFF = 0, SHOW_PATH_CURRENT, SHOW_PATH_FULL }; /* scrollbar visibility/position */ -enum { SCROLLBAR_OFF = 0, SCROLLBAR_LEFT, SCROLLBAR_RIGHT }; +enum { SCROLLBAR_HIDE = 0, SCROLLBAR_SHOW, SCROLLBAR_SHOW_OPPOSITE }; /* Alarm settings */ #ifdef HAVE_RTC_ALARM diff --git a/apps/settings_list.c b/apps/settings_list.c index 62a9351782..d76c2deb69 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -641,8 +641,9 @@ const struct settings_list settings[] = { ID2P(LANG_STATUSBAR_BOTTOM)), #endif CHOICE_SETTING(F_THEMESETTING|F_TEMPVAR, scrollbar, - LANG_SCROLL_BAR, SCROLLBAR_LEFT, "scrollbar","off,left,right", - NULL, 3, ID2P(LANG_OFF), ID2P(LANG_LEFT), ID2P(LANG_RIGHT)), + LANG_SCROLL_BAR, SCROLLBAR_SHOW, + "scrollbar","hide,show,show_opposite", NULL, 3, + ID2P(LANG_HIDE), ID2P(LANG_SHOW), ID2P(LANG_SHOW_OPPOSITE)), INT_SETTING(F_THEMESETTING, scrollbar_width, LANG_SCROLLBAR_WIDTH, 6, "scrollbar width",UNIT_INT, 3, MAX(LCD_WIDTH/10,25), 1, NULL, NULL, NULL), diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index c1efd9097e..8d3b88f8e1 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c @@ -27,6 +27,7 @@ * KIND, either express or implied. * ****************************************************************************/ +#include "language.h" #ifndef LCDFN /* Not compiling for remote - define macros for main LCD. */ #define LCDFN(fn) lcd_ ## fn @@ -170,11 +171,16 @@ void LCDFN(puts_style_offset)(int x, int y, const unsigned char *str, int style, int offset) { int xpos, ypos, w, h; + unsigned long chars_in_str; LCDFN(scroll_stop_line)(current_vp, y); if(!str || !str[0]) return; + + chars_in_str = utf8length((char *)str); LCDFN(getstringsize)(str, &w, &h); - xpos = x * w / utf8length((char *)str); + xpos = x * w / chars_in_str; + if (lang_is_rtl()) + xpos = current_vp->width - w - xpos; ypos = y * h; LCDFN(putsxyofs_style)(xpos, ypos, str, style, w, h, offset); } diff --git a/tools/genlang b/tools/genlang index d191a820a6..44dfcc6fdf 100755 --- a/tools/genlang +++ b/tools/genlang @@ -13,7 +13,8 @@ # See apps/language.c (TODO: Use common include for both) # Cookie and binary version for the binary lang file my $LANGUAGE_COOKIE = 0x1a; -my $LANGUAGE_VERSION = 0x04; +my $LANGUAGE_VERSION = 0x05; +my $LANGUAGE_FLAG_RTL = 0x01; # A note for future users and readers: The original v1 language system allowed # the build to create and use a different language than english built-in. We @@ -167,6 +168,12 @@ sub phrase { $phrase{$n}=$v; } +my %options; +sub options { + my ($full, $n, $v)=@_; + $options{$n}=$v; +} + sub parsetarget { my ($debug, $strref, $full, $n, $v)=@_; my $string; @@ -381,6 +388,8 @@ my $voiceid=0x8000; # counter for voice-only ID numbers open(LANG, "<$input") || die "Error: couldn't read language file named $input\n"; my @phrase; my $header = 1; +my $langoptions = 0; + while() { $line++; @@ -510,9 +519,15 @@ while() { print "### $idstr: The phrase is not used. Skipped\n"; } } - undef @phrase; - } # end of + elsif($part eq "/options") { + # closing the options + if ($options{'rtl'}) { + $langoptions |= $LANGUAGE_FLAG_RTL; + } + } # end of + + undef @phrase; # starts with a slash, this _ends_ this section $m = pop @m; # get back old value, the previous level's tag @@ -661,7 +676,8 @@ elsif($binary) { open(OUTF, ">$binary") or die "Error: Can't create $binary"; binmode OUTF; - printf OUTF ("%c%c%c", $LANGUAGE_COOKIE, $LANGUAGE_VERSION, $target_id); # magic lang file header + printf OUTF ("%c%c%c%c", $LANGUAGE_COOKIE, $LANGUAGE_VERSION, $target_id, + $langoptions); # magic lang file header # loop over the target phrases for $i (1 .. $idcount) {