/[drupal]/contributions/sandbox/alaa/bidi.module
ViewVC logotype

Contents of /contributions/sandbox/alaa/bidi.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (hide annotations) (download) (as text)
Fri Aug 18 03:50:07 2006 UTC (3 years, 3 months ago) by alaa
Branch: MAIN
Changes since 1.2: +2 -14 lines
File MIME type: text/x-php
removed settings form
1 alaa 1.1 <?php // -*-php-*-
2     /*
3     * Original module by Alaa Abd El Fatah.
4     * Mohammed Sameer: My Modifications Copyright (c) 2004 Mohammed Sameer,
5     * under the GNU GPL v2 or later.
6     * Mohammed Sameer: 2004 10 30
7     * * Ported to drupal 4.5 API.
8 alaa 1.2 *
9     * 04/04/2005 Ported to drupal 4.6 API by Amr Mostafa
10 alaa 1.1 */
11    
12     setlocale(LC_ALL, "ar_EG.UTF-8");
13    
14 alaa 1.2
15     /**
16     * Implementation of hook_help()
17     */
18 alaa 1.1 function bidi_help($section) {
19     $output = "";
20    
21     switch ($section) {
22     case 'admin/modules#description':
23     $output = t("Automaticaly sets line direction");
24     break;
25     }
26    
27     return $output;
28     }
29    
30 alaa 1.2 /**
31     * Implementation of hook_filter_tips()
32     */
33     function bidi_filter_tips($delta, $format, $long = false) {
34     if ($long) {
35     return t("You may write mixed Arabic and English freely, line direction will be computed automaticaly");
36     }
37     else {
38     return t("You may write mixed Arabic and English freely, line direction will be computed automaticaly");
39     }
40     }
41 alaa 1.1
42 alaa 1.2 /**
43     * Implementation of hook_filter()
44     */
45 alaa 1.1 function bidi_filter($op, $delta = 0, $format = -1, $text = "") {
46     switch ($op) {
47 alaa 1.2 case 'list':
48     return array(0 => t('BiDi'));
49     case 'description':
50     return t("Bidi filter");
51     case "process":
52     return _bidi_filter_process($text);
53     default:
54     return $text;
55 alaa 1.1 }
56     }
57    
58 alaa 1.2 /**
59     * Determine text language (arabic or english).
60     * This function needs to be split into a single include file so it can be used on theme and other places.
61     *
62     * @param $text
63     * The text needs to be.
64     * @return
65     * right2left or left2right depending on the detected language.
66     */
67 alaa 1.1 function _get_dir($text) {
68     $text = strtolower($text);
69     $len = strlen($text);
70 alaa 1.2
71 alaa 1.1 $arabic = 0;
72     $english = 0;
73    
74 alaa 1.2 // constants
75 alaa 1.1 $a = ord('a');
76     $z = ord('z');
77    
78 alaa 1.2 // arabic UTF-8 letters have one of these values in the 1st byte
79 alaa 1.1 $ar1 = 0xd8;
80     $ar2 = 0xd9;
81 alaa 1.2
82 alaa 1.1 // this calculates the dominant language in the text, most bidi implementations just use the first letter (which may be more efficient)
83     for ($i = 0; $i < $len; ++$i) {
84     $bin = ord($text[$i]);
85 alaa 1.2
86 alaa 1.1 if ($bin == $ar1 || $bin == $ar2) {
87     ++$arabic;
88     ++$i;
89 alaa 1.2 }
90     else if ($bin >= $a && $bin <= $z) {
91 alaa 1.1 ++$english;
92     }
93     }
94 alaa 1.2
95     // should this return a bool instead?
96 alaa 1.1 if ($english || $arabic) {
97     if ($english > $arabic)
98 alaa 1.3 return ' dir="LTR" ';
99 alaa 1.1 else
100 alaa 1.3 return ' dir="RTL" ';
101 alaa 1.2 }
102     else {
103 alaa 1.1 return "";
104     }
105     }
106    
107 alaa 1.2 /**
108     * Sets HTML text line directions (rtl or ltr) as needed.
109     *
110     * @param $text
111     * The HTML text needs to be processed.
112     *
113     * @return
114     * The processed result, with line directions are set using css
115     * classes "righ2left" and "left2right".
116     */
117 alaa 1.1 function _bidi_filter_process($text) {
118     $output = "";
119 alaa 1.2
120 alaa 1.1 $len = strlen($text);
121     $i = 0;
122    
123     while ($i < $len) {
124 alaa 1.2 // find next tag
125 alaa 1.1 $e = strpos(substr($text, $i), "<");
126 alaa 1.2 if ($e === FALSE) {
127     break;
128     }
129 alaa 1.1
130 alaa 1.2 $output .= substr($text, $i, $e);
131 alaa 1.1
132     $i += $e;
133    
134 alaa 1.2 // find end of next tag
135     $e = strcspn(substr($text, $i), "/> ");
136 alaa 1.1 $tag = substr($text, $i+1, $e-1);
137 alaa 1.2
138     $output .= substr($text, $i, $e);
139 alaa 1.1 $i += $e;
140    
141     switch ($tag) {
142 alaa 1.2 // single tag entity
143     case "img":
144     case "br":
145     case "hr":
146     continue;
147     break;
148    
149 alaa 1.1 //nested cases
150 alaa 1.2 case "ul":
151     case "ol":
152     case "dl":
153     case "div":
154     $e = 0;
155     // stack counter
156     $j = 1;
157    
158     // if $j = 0 then stack is empty
159     while ($j > 0) {
160     $e += strpos(substr($text, $i+$e) , $tag);
161    
162     // yeah I know I'm assuming certain sizes for tags, sue me
163     // new nested block
164     if ($text[$i+$e-1] == '<') {
165     ++$j;
166     }
167     // end of block
168     else if ($text[$i+$e-1] == '/') {
169     --$j;
170     }
171     // skip current tag
172     $e += 2;
173     }
174    
175     $content = substr($text, $i+1, $e);
176     $output .= _get_dir(strip_tags($content));
177     $e += strlen($tag);
178     $output.= substr($text, $i, $e);
179     $i += $e;
180     break;
181 alaa 1.1
182 alaa 1.2 // block elements these get out attention
183     case "p":
184     case "blockquote":
185     case "pre":
186     case "h1":
187     case "h2":
188     case "h3":
189     case "h4":
190     case "h5":
191     case "h6":
192 alaa 1.1
193 alaa 1.2 // nested lists are proken better think of a fix
194     case "li":
195     $close_tag = "</".$tag.">";
196     // breaks on extra whitespaces, maybe I should use regexps instead
197     $e = strpos(substr($text, $i), $close_tag);
198     $content = substr($text, $i+1, $e-1);
199     // calculate directions
200     $output.= _get_dir(strip_tags($content));
201     $e += strlen($close_tag);
202     $output.= substr($text, $i, $e);
203     $i += $e;
204     break;
205 alaa 1.1
206 alaa 1.2 // non block tags we are not handeling
207     default:
208     $close_tag = "</".$tag.">";
209     $e = strpos(substr($text, $i), $close_tag) + strlen($close_tag);
210     $output.= substr($text, $i, $e);
211     $i += $e;
212     }
213 alaa 1.1 }
214 alaa 1.2
215     // any missing content
216 alaa 1.1 $output .= substr($text, $i);
217    
218 alaa 1.2 return $output;
219 alaa 1.1 }
220    
221     ?>

  ViewVC Help
Powered by ViewVC 1.1.2