/[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.2 - (show annotations) (download) (as text)
Fri May 6 13:43:51 2005 UTC (4 years, 6 months ago) by alaa
Branch: MAIN
Changes since 1.1: +146 -113 lines
File MIME type: text/x-php
updated to 4.6
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 *
9 * 04/04/2005 Ported to drupal 4.6 API by Amr Mostafa
10 */
11
12 setlocale(LC_ALL, "ar_EG.UTF-8");
13
14
15 /**
16 * Implementation of hook_help()
17 */
18 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 /**
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
42 /**
43 * Implementation of hook_filter()
44 */
45 function bidi_filter($op, $delta = 0, $format = -1, $text = "") {
46 switch ($op) {
47 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 case "settings":
54 return _bidi_filter_settings($text);
55 default:
56 return $text;
57 }
58 }
59
60 /**
61 * Determine text language (arabic or english).
62 * This function needs to be split into a single include file so it can be used on theme and other places.
63 *
64 * @param $text
65 * The text needs to be.
66 * @return
67 * right2left or left2right depending on the detected language.
68 */
69 function _get_dir($text) {
70 $text = strtolower($text);
71 $len = strlen($text);
72
73 $arabic = 0;
74 $english = 0;
75
76 // constants
77 $a = ord('a');
78 $z = ord('z');
79
80 // arabic UTF-8 letters have one of these values in the 1st byte
81 $ar1 = 0xd8;
82 $ar2 = 0xd9;
83
84 // this calculates the dominant language in the text, most bidi implementations just use the first letter (which may be more efficient)
85 for ($i = 0; $i < $len; ++$i) {
86 $bin = ord($text[$i]);
87
88 if ($bin == $ar1 || $bin == $ar2) {
89 ++$arabic;
90 ++$i;
91 }
92 else if ($bin >= $a && $bin <= $z) {
93 ++$english;
94 }
95 }
96
97 // should this return a bool instead?
98 if ($english || $arabic) {
99 if ($english > $arabic)
100 return ' class="left2right"';
101 else
102 return ' class="right2left"';
103 }
104 else {
105 return "";
106 }
107 }
108
109 /**
110 * Sets HTML text line directions (rtl or ltr) as needed.
111 *
112 * @param $text
113 * The HTML text needs to be processed.
114 *
115 * @return
116 * The processed result, with line directions are set using css
117 * classes "righ2left" and "left2right".
118 */
119 function _bidi_filter_process($text) {
120 $output = "";
121
122 $len = strlen($text);
123 $i = 0;
124
125 while ($i < $len) {
126 // find next tag
127 $e = strpos(substr($text, $i), "<");
128 if ($e === FALSE) {
129 break;
130 }
131
132 $output .= substr($text, $i, $e);
133
134 $i += $e;
135
136 // find end of next tag
137 $e = strcspn(substr($text, $i), "/> ");
138 $tag = substr($text, $i+1, $e-1);
139
140 $output .= substr($text, $i, $e);
141 $i += $e;
142
143 switch ($tag) {
144 // single tag entity
145 case "img":
146 case "br":
147 case "hr":
148 continue;
149 break;
150
151 //nested cases
152 case "ul":
153 case "ol":
154 case "dl":
155 case "div":
156 $e = 0;
157 // stack counter
158 $j = 1;
159
160 // if $j = 0 then stack is empty
161 while ($j > 0) {
162 $e += strpos(substr($text, $i+$e) , $tag);
163
164 // yeah I know I'm assuming certain sizes for tags, sue me
165 // new nested block
166 if ($text[$i+$e-1] == '<') {
167 ++$j;
168 }
169 // end of block
170 else if ($text[$i+$e-1] == '/') {
171 --$j;
172 }
173 // skip current tag
174 $e += 2;
175 }
176
177 $content = substr($text, $i+1, $e);
178 $output .= _get_dir(strip_tags($content));
179 $e += strlen($tag);
180 $output.= substr($text, $i, $e);
181 $i += $e;
182 break;
183
184 // block elements these get out attention
185 case "p":
186 case "blockquote":
187 case "pre":
188 case "h1":
189 case "h2":
190 case "h3":
191 case "h4":
192 case "h5":
193 case "h6":
194
195 // nested lists are proken better think of a fix
196 case "li":
197 $close_tag = "</".$tag.">";
198 // breaks on extra whitespaces, maybe I should use regexps instead
199 $e = strpos(substr($text, $i), $close_tag);
200 $content = substr($text, $i+1, $e-1);
201 // calculate directions
202 $output.= _get_dir(strip_tags($content));
203 $e += strlen($close_tag);
204 $output.= substr($text, $i, $e);
205 $i += $e;
206 break;
207
208 // non block tags we are not handeling
209 default:
210 $close_tag = "</".$tag.">";
211 $e = strpos(substr($text, $i), $close_tag) + strlen($close_tag);
212 $output.= substr($text, $i, $e);
213 $i += $e;
214 }
215 }
216
217 // any missing content
218 $output .= substr($text, $i);
219
220 return $output;
221 }
222
223 /**
224 * Filter settings.
225 *
226 * @return
227 * HTML form for filter settings.
228 */
229 function _bidi_filter_settings() {
230 return form_group(t("Bidi filter"), t("automatic bidi"));
231 }
232
233 ?>

  ViewVC Help
Powered by ViewVC 1.1.2