diff options
| author | Linus Nielsen Feltzing <linus@haxx.se> | 2005-08-08 19:23:28 +0000 |
|---|---|---|
| committer | Linus Nielsen Feltzing <linus@haxx.se> | 2005-08-08 19:23:28 +0000 |
| commit | 41a53d2c1c536d20823f357af887c9ff74991efd (patch) | |
| tree | 365987aa7fdada4786fc280b50319d0cb1bb2acb | |
| parent | 1874a33298f6b639893e4bc8e556fd71e2c068d3 (diff) | |
| download | rockbox-41a53d2c1c536d20823f357af887c9ff74991efd.zip rockbox-41a53d2c1c536d20823f357af887c9ff74991efd.tar.gz rockbox-41a53d2c1c536d20823f357af887c9ff74991efd.tar.bz2 rockbox-41a53d2c1c536d20823f357af887c9ff74991efd.tar.xz | |
Patch #783877 by Gadi Cohen updated by Naftali Goldstein - Bidirectional text support for Hebrew and Arabic
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7292 a1c6a512-1295-4272-9138-f99709370657
| -rw-r--r-- | apps/lang/english.lang | 6 | ||||
| -rw-r--r-- | apps/settings.c | 8 | ||||
| -rw-r--r-- | apps/settings.h | 1 | ||||
| -rw-r--r-- | apps/settings_menu.c | 14 | ||||
| -rw-r--r-- | docs/CREDITS | 2 | ||||
| -rw-r--r-- | firmware/SOURCES | 1 | ||||
| -rw-r--r-- | firmware/bidi.c | 184 | ||||
| -rw-r--r-- | firmware/drivers/lcd-h100.c | 4 | ||||
| -rw-r--r-- | firmware/drivers/lcd-recorder.c | 4 | ||||
| -rw-r--r-- | firmware/export/bidi.h | 23 |
10 files changed, 246 insertions, 1 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index f8c0c33..c50a126 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -3238,3 +3238,9 @@ desc: in browse_id3 eng: "<No gain>" voice "" new: + +id: LANG_BIDI_SUPPORT +desc: in settings_menu, option to enable reversal of hebrew/arabic text +eng: "BiDi Hebrew/Arabic" +voice "" +new: diff --git a/apps/settings.c b/apps/settings.c index d37e026..63e7a3b 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -40,6 +40,7 @@ #include "power.h" #include "backlight.h" #include "powermgmt.h" +#include "bidi.h" #include "status.h" #include "atoi.h" #include "screens.h" @@ -265,10 +266,14 @@ static const struct bit_entry rtc_bits[] = {1, S_O(remote_flip_display), false, "remote flip display", off_on }, #endif +#ifdef HAVE_LCD_BITMAP /* move to LCD next time we bump version */ + {1, S_O(bidi_support), false, "bidi hebrew/arabic", off_on }, +#endif + /* new stuff to be added here */ /* If values are just added to the end, no need to bump the version. */ - /* Current sum of bits: 268 (worst case, but w/o remote lcd) */ + /* Current sum of bits: 277 (worst case, but w/o remote lcd) */ /* Sum of all bit sizes must not grow beyond 288! */ }; @@ -820,6 +825,7 @@ void settings_apply(void) #endif #ifdef HAVE_LCD_BITMAP + set_bidi_support(global_settings.bidi_support); lcd_set_invert_display(global_settings.invert); lcd_set_flip(global_settings.flip_display); button_set_flip(global_settings.flip_display); diff --git a/apps/settings.h b/apps/settings.h index e0a61bf..ff12186 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -197,6 +197,7 @@ struct user_settings bool invert_cursor; /* invert the current file in dir browser and menu instead of using the default cursor */ bool flip_display; /* turn display (and button layout) by 180 degrees */ + bool bidi_support; /* reverse hebrew/arabic chars: 0=off, 1=on */ int poweroff; /* power off timer */ int backlight_timeout; /* backlight off timeout: 0-18 0=never, 1=always, diff --git a/apps/settings_menu.c b/apps/settings_menu.c index 50f1396..54267e9 100644 --- a/apps/settings_menu.c +++ b/apps/settings_menu.c @@ -38,6 +38,7 @@ #include "fat.h" /* For dotfile settings */ #include "sleeptimer.h" #include "powermgmt.h" +#include "bidi.h" #include "rtc.h" #include "ata.h" #include "tree.h" @@ -279,6 +280,18 @@ static bool invert_cursor(void) } /** + * Menu to reverse Hebrew and Arabic text according to BiDi algorythm + */ +static bool bidi_support(void) +{ + return set_bool_options( str(LANG_BIDI_SUPPORT), + &global_settings.bidi_support, + STR(LANG_SET_BOOL_YES), + STR(LANG_SET_BOOL_NO), + set_bidi_support); +} + +/** * Menu to configure the battery display on status bar */ static bool battery_display(void) @@ -1421,6 +1434,7 @@ static bool lcd_settings_menu(void) { ID2P(LANG_INVERT), invert }, { ID2P(LANG_FLIP_DISPLAY), flip_display }, { ID2P(LANG_INVERT_CURSOR), invert_cursor }, + { ID2P(LANG_BIDI_SUPPORT), bidi_support }, #endif }; diff --git a/docs/CREDITS b/docs/CREDITS index 4c8b32f..2e7e064 100644 --- a/docs/CREDITS +++ b/docs/CREDITS @@ -129,3 +129,5 @@ Ryan Jackson Per Holmäng Frederic Devernay José M. Fandiño +Gadi Cohen +Naftali Goldstein diff --git a/firmware/SOURCES b/firmware/SOURCES index be471fb..84f54e5 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -49,6 +49,7 @@ drivers/lcd-player-charset.c drivers/lcd-player.c #endif #ifdef HAVE_LCD_BITMAP +bidi.c #if LCD_DEPTH == 2 drivers/lcd-h100.c #elif LCD_DEPTH == 1 diff --git a/firmware/bidi.c b/firmware/bidi.c new file mode 100644 index 0000000..765d3da --- /dev/null +++ b/firmware/bidi.c @@ -0,0 +1,184 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Gadi Cohen + * + * Largely based on php_hebrev by Zeev Suraski <zeev@php.net> + * Heavily modified by Gadi Cohen aka Kinslayer <dragon@wastelands.net> + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "file.h" +#include "lcd.h" + +#define _HEB_BUFFER_LENGTH MAX_PATH + LCD_WIDTH/2 + 3 + 2 + 2 +#define _HEB_BLOCK_TYPE_ENG 1 +#define _HEB_BLOCK_TYPE_HEB 0 +#define _HEB_ORIENTATION_LTR 1 +#define _HEB_ORIENTATION_RTL 0 + +#define ischar(c) (((((unsigned char) c)>=193) && (((unsigned char) c)<=250)) ? 1 : 0) +#define _isblank(c) (((((unsigned char) c)==' ' || ((unsigned char) c)=='\t')) ? 1 : 0) +#define _isnewline(c) (((((unsigned char) c)=='\n' || ((unsigned char) c)=='\r')) ? 1 : 0) +#define XOR(a,b) ((a||b) && !(a&&b)) + +bool bidi_support_enabled = false; + +unsigned char *bidi_l2v(const unsigned char *str, int orientation) +{ + static unsigned char buf_heb_str[_HEB_BUFFER_LENGTH]; + static unsigned char buf_broken_str[_HEB_BUFFER_LENGTH]; + const unsigned char *tmp; + unsigned char *heb_str, *target, *opposite_target, *broken_str; + int block_start, block_end, block_type, block_length, i; + int block_ended; + long max_chars=0; + int begin, end, char_count, orig_begin; + + if (!str || !*str) + return ""; + + tmp = str; + block_start=block_end=0; + block_ended=0; + + heb_str = buf_heb_str; + if (orientation) { + target = heb_str; + opposite_target = heb_str + strlen(str); + } else { + target = heb_str + strlen(str); + opposite_target = heb_str; + *target = 0; + target--; + } + + block_length=0; + if (ischar(*tmp)) + block_type = _HEB_BLOCK_TYPE_HEB; + else + block_type = _HEB_BLOCK_TYPE_ENG; + + do { + while((XOR(ischar((int)*(tmp+1)),block_type) + || _isblank((int)*(tmp+1)) || ispunct((int)*(tmp+1)) + || (int)*(tmp+1)=='\n') + && block_end<(int)strlen(str)-1) { + tmp++; + block_end++; + block_length++; + } + + if (block_type != orientation) { + while ((_isblank((int)*tmp) || ispunct((int)*tmp)) + && *tmp!='/' && *tmp!='-' && block_end>block_start) { + tmp--; + block_end--; + } + } + + for (i=block_start; i<=block_end; i++) { + *target = (block_type == orientation) ? *(str+i) : *(str+block_end-i+block_start); + if (block_type!=orientation) { + switch (*target) { + case '(': + *target = ')'; + break; + case ')': + *target = '('; + break; + default: + break; + } + } + target += orientation ? 1 : -1; + } + block_type = !block_type; + block_start=block_end+1; + } while(block_end<(int)strlen(str)-1); + + broken_str = buf_broken_str; + begin=end=strlen(str)-1; + target = broken_str; + + while (1) { + char_count=0; + while ((!max_chars || char_count<max_chars) && begin>0) { + char_count++; + begin--; + if (begin<=0 || _isnewline(heb_str[begin])) { + while(begin>0 && _isnewline(heb_str[begin-1])) { + begin--; + char_count++; + } + break; + } + } + if (char_count==max_chars) { /* try to avoid breaking words */ + int new_char_count = char_count; + int new_begin = begin; + + while (new_char_count>0) { + if (_isblank(heb_str[new_begin]) || + _isnewline(heb_str[new_begin])) { + break; + } + new_begin++; + new_char_count--; + } + if (new_char_count>0) { + char_count=new_char_count; + begin=new_begin; + } + } + orig_begin=begin; + + if (_isblank(heb_str[begin])) { + heb_str[begin]='\n'; + } + + /* skip leading newlines */ + while (begin<=end && _isnewline(heb_str[begin])) { + begin++; + } + + /* copy content */ + for (i=begin; i<=end; i++) { + *target = heb_str[i]; + target++; + } + + for (i=orig_begin; i<=end && _isnewline(heb_str[i]); i++) { + *target = heb_str[i]; + target++; + } + begin=orig_begin; + + if (begin<=0) { + *target = 0; + break; + } + begin--; + end=begin; + } + return broken_str; +} + +void set_bidi_support(bool setting) +{ + bidi_support_enabled = setting; +} diff --git a/firmware/drivers/lcd-h100.c b/firmware/drivers/lcd-h100.c index 5bdb08a..bfdceed 100644 --- a/firmware/drivers/lcd-h100.c +++ b/firmware/drivers/lcd-h100.c @@ -28,6 +28,7 @@ #include "debug.h" #include "system.h" #include "font.h" +#include "bidi.h" /*** definitions ***/ @@ -992,6 +993,9 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) int ch; struct font* pf = font_get(curfont); + if (bidi_support_enabled) + str = bidi_l2v(str, 1); + while ((ch = *str++) != '\0' && x < LCD_WIDTH) { int width; diff --git a/firmware/drivers/lcd-recorder.c b/firmware/drivers/lcd-recorder.c index cdeb4f2..53640ce 100644 --- a/firmware/drivers/lcd-recorder.c +++ b/firmware/drivers/lcd-recorder.c @@ -28,6 +28,7 @@ #include "system.h" #include "font.h" #include "hwcompat.h" +#include "bidi.h" /*** definitions ***/ @@ -846,6 +847,9 @@ static void lcd_putsxyofs(int x, int y, int ofs, const unsigned char *str) int ch; struct font* pf = font_get(curfont); + if (bidi_support_enabled) + str = bidi_l2v(str, 1); + while ((ch = *str++) != '\0' && x < LCD_WIDTH) { int width; diff --git a/firmware/export/bidi.h b/firmware/export/bidi.h new file mode 100644 index 0000000..88e2eeb --- /dev/null +++ b/firmware/export/bidi.h @@ -0,0 +1,23 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Gadi Cohen + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef BIDI_H +extern unsigned char *bidi_l2v(const unsigned char *str, int orientation); +extern bool bidi_support_enabled; +extern void set_bidi_support(bool setting); +#endif |