Index: tools/genlang =================================================================== --- tools/genlang (revision 22930) +++ tools/genlang (working copy) @@ -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 @@ -28,7 +29,7 @@ if(!$ARGV[0]) { print < +Usage: genlang [options] -p= Make the tool create a [prefix].c and [prefix].h file. @@ -167,6 +168,12 @@ $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 @@ open(LANG, "<$input") || die "Error: couldn't read language file named $input\n"; my @phrase; my $header = 1; +my $langoptions = 0; + while() { $line++; @@ -510,10 +519,16 @@ 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 next; @@ -661,7 +676,8 @@ 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) { Index: apps/language.c =================================================================== --- apps/language.c (revision 22930) +++ apps/language.c (working copy) @@ -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 @@ } } +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 @@ retcode = 3; } close(fd); + lang_options = (retcode ? 0 : lang_header[3]); return retcode; } Index: apps/language.h =================================================================== --- apps/language.h (revision 22929) +++ apps/language.h (working copy) @@ -30,4 +30,6 @@ /* 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 Index: apps/lang/hebrew.lang =================================================================== --- apps/lang/hebrew.lang (revision 22929) +++ apps/lang/hebrew.lang (working copy) @@ -20,6 +20,10 @@ # - Rani Hod # - Tomer Shalev # - Sasha Khamkov + + + rtl: 1 + id: LANG_SET_BOOL_YES desc: bool true representation Index: apps/lang/arabic.lang =================================================================== --- apps/lang/arabic.lang (revision 22929) +++ apps/lang/arabic.lang (working copy) @@ -17,6 +17,9 @@ # Arabic language file, translated by: # - Mohamed Tarek # - Raafat Akkad + + rtl: 1 + id: LANG_EQUALIZER_HARDWARE_BANDWIDTH_NARROW desc: deprecated Index: apps/gui/bitmap/list.c =================================================================== --- apps/gui/bitmap/list.c (revision 22929) +++ apps/gui/bitmap/list.c (working copy) @@ -40,6 +40,7 @@ #include "sound.h" #include "misc.h" #include "viewport.h" +#include "language.h" #define ICON_PADDING 1 @@ -61,11 +62,16 @@ | | | 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) { const int screen = display->screen_type; int style = STYLE_DEFAULT; + bool ltr = !lang_is_rtl(); + display->scroll_stop(&title_text[screen]); if (!list_display_title(list, screen)) return false; @@ -77,10 +83,12 @@ struct viewport title_icon = title_text[screen]; title_icon.width = get_icon_width(screen) + ICON_PADDING*2; - title_icon.x += ICON_PADDING; + title_icon.x = (ltr ? ICON_PADDING : + display->getwidth() - ICON_PADDING - get_icon_width(screen)); title_text[screen].width -= title_icon.width; - title_text[screen].x += title_icon.width; + if (ltr) + title_text[screen].x += title_icon.width; display->set_viewport(&title_icon); screen_put_icon(display, 0, 0, list->title_icon); @@ -109,7 +117,10 @@ unsigned char cur_line = 0; #endif int item_offset; - bool show_title; + bool show_title, ltr = !lang_is_rtl(); + bool scrollbar_across = (global_settings.scrollbar == + (ltr ? SCROLLBAR_RIGHT : SCROLLBAR_LEFT)); + line_height = font_get(parent->font)->height; display->set_viewport(parent); display->clear_viewport(); @@ -132,12 +143,12 @@ vp = list_text[screen]; vp.width = SCROLLBAR_WIDTH; list_text[screen].width -= SCROLLBAR_WIDTH; - if(global_settings.scrollbar == SCROLLBAR_LEFT) + if (!scrollbar_across) 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 (scrollbar_across) vp.x += list_text[screen].width; display->set_viewport(&vp); gui_scrollbar_draw(display, 0, 0, SCROLLBAR_WIDTH-1, @@ -149,7 +160,7 @@ else if (show_title) { /* shift everything right a bit... */ - if(global_settings.scrollbar == SCROLLBAR_LEFT) + if (!scrollbar_across) { list_text[screen].width -= SCROLLBAR_WIDTH; list_text[screen].x += SCROLLBAR_WIDTH; @@ -167,8 +178,10 @@ 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 (ltr) + list_text[screen].x += list_icons.width + ICON_PADDING; + else + list_icons.x += list_text[screen].width; } for (i=start; inb_items; i++) Index: apps/gui/icon.c =================================================================== --- apps/gui/icon.c (revision 22929) +++ apps/gui/icon.c (working copy) @@ -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 @@ #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); } Index: firmware/drivers/lcd-bitmap-common.c =================================================================== --- firmware/drivers/lcd-bitmap-common.c (revision 22929) +++ firmware/drivers/lcd-bitmap-common.c (working copy) @@ -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 @@ 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); }