/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2005 by Gadi Cohen * * Largely based on php_hebrev by Zeev Suraski * Heavily modified by Gadi Cohen aka Kinslayer * * 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 #include #include #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 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 (unsigned char *)""; tmp = (unsigned char *)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_count0) { 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; }