/[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 - (hide 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 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     case "settings":
54     return _bidi_filter_settings($text);
55     default:
56     return $text;
57 alaa 1.1 }
58     }
59    
60 alaa 1.2 /**
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 alaa 1.1 function _get_dir($text) {
70     $text = strtolower($text);
71     $len = strlen($text);
72 alaa 1.2
73 alaa 1.1 $arabic = 0;
74     $english = 0;
75    
76 alaa 1.2 // constants
77 alaa 1.1 $a = ord('a');
78     $z = ord('z');
79    
80 alaa 1.2 // arabic UTF-8 letters have one of these values in the 1st byte
81 alaa 1.1 $ar1 = 0xd8;
82     $ar2 = 0xd9;
83 alaa 1.2
84 alaa 1.1 // 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 alaa 1.2
88 alaa 1.1 if ($bin == $ar1 || $bin == $ar2) {
89     ++$arabic;
90     ++$i;
91 alaa 1.2 }
92     else if ($bin >= $a && $bin <= $z) {
93 alaa 1.1 ++$english;
94     }
95     }
96 alaa 1.2
97     // should this return a bool instead?
98 alaa 1.1 if ($english || $arabic) {
99     if ($english > $arabic)
100     return ' class="left2right"';
101     else
102     return ' class="right2left"';
103 alaa 1.2 }
104     else {
105 alaa 1.1 return "";
106     }
107     }
108    
109 alaa 1.2 /**
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 alaa 1.1 function _bidi_filter_process($text) {
120     $output = "";
121 alaa 1.2
122 alaa 1.1 $len = strlen($text);
123     $i = 0;
124    
125     while ($i < $len) {
126 alaa 1.2 // find next tag
127 alaa 1.1 $e = strpos(substr($text, $i), "<");
128 alaa 1.2 if ($e === FALSE) {
129     break;
130     }
131 alaa 1.1
132 alaa 1.2 $output .= substr($text, $i, $e);
133 alaa 1.1
134     $i += $e;
135    
136 alaa 1.2 // find end of next tag
137     $e = strcspn(substr($text, $i), "/> ");
138 alaa 1.1 $tag = substr($text, $i+1, $e-1);
139 alaa 1.2
140     $output .= substr($text, $i, $e);
141 alaa 1.1 $i += $e;
142    
143     switch ($tag) {
144 alaa 1.2 // single tag entity
145     case "img":
146     case "br":
147     case "hr":
148     continue;
149     break;
150    
151 alaa 1.1 //nested cases
152 alaa 1.2 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 alaa 1.1
184 alaa 1.2 // 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 alaa 1.1
195 alaa 1.2 // 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 alaa 1.1
208 alaa 1.2 // 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 alaa 1.1 }
216 alaa 1.2
217     // any missing content
218 alaa 1.1 $output .= substr($text, $i);
219    
220 alaa 1.2 return $output;
221 alaa 1.1 }
222    
223 alaa 1.2 /**
224     * Filter settings.
225     *
226     * @return
227     * HTML form for filter settings.
228     */
229 alaa 1.1 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