/[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 - (show 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 <?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 default:
54 return $text;
55 }
56 }
57
58 /**
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 function _get_dir($text) {
68 $text = strtolower($text);
69 $len = strlen($text);
70
71 $arabic = 0;
72 $english = 0;
73
74 // constants
75 $a = ord('a');
76 $z = ord('z');
77
78 // arabic UTF-8 letters have one of these values in the 1st byte
79 $ar1 = 0xd8;
80 $ar2 = 0xd9;
81
82 // 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
86 if ($bin == $ar1 || $bin == $ar2) {
87 ++$arabic;
88 ++$i;
89 }
90 else if ($bin >= $a && $bin <= $z) {
91 ++$english;
92 }
93 }
94
95 // should this return a bool instead?
96 if ($english || $arabic) {
97 if ($english > $arabic)
98 return ' dir="LTR" ';
99 else
100 return ' dir="RTL" ';
101 }
102 else {
103 return "";
104 }
105 }
106
107 /**
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 function _bidi_filter_process($text) {
118 $output = "";
119
120 $len = strlen($text);
121 $i = 0;
122
123 while ($i < $len) {
124 // find next tag
125 $e = strpos(substr($text, $i), "<");
126 if ($e === FALSE) {
127 break;
128 }
129
130 $output .= substr($text, $i, $e);
131
132 $i += $e;
133
134 // find end of next tag
135 $e = strcspn(substr($text, $i), "/> ");
136 $tag = substr($text, $i+1, $e-1);
137
138 $output .= substr($text, $i, $e);
139 $i += $e;
140
141 switch ($tag) {
142 // single tag entity
143 case "img":
144 case "br":
145 case "hr":
146 continue;
147 break;
148
149 //nested cases
150 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
182 // 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
193 // 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
206 // 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 }
214
215 // any missing content
216 $output .= substr($text, $i);
217
218 return $output;
219 }
220
221 ?>

  ViewVC Help
Powered by ViewVC 1.1.2