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

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

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

revision 1.1, Thu Mar 3 15:59:48 2005 UTC revision 1.2, Fri May 6 13:43:51 2005 UTC
# Line 5  Line 5 
5   *                  under the GNU GPL v2 or later.   *                  under the GNU GPL v2 or later.
6   * Mohammed Sameer: 2004 10 30   * Mohammed Sameer: 2004 10 30
7   *                  * Ported to drupal 4.5 API.   *                  * 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");  setlocale(LC_ALL, "ar_EG.UTF-8");
13    
14    
15    /**
16     * Implementation of hook_help()
17     */
18  function bidi_help($section) {  function bidi_help($section) {
19    $output = "";    $output = "";
20    
# Line 21  function bidi_help($section) { Line 27  function bidi_help($section) {
27    return $output;    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 = "") {  function bidi_filter($op, $delta = 0, $format = -1, $text = "") {
46    switch ($op) {    switch ($op) {
47    case 'list':      case 'list':
48      return array(0 => t('BiDi'));        return array(0 => t('BiDi'));
49      //    case "name":      case 'description':
50      //    return t("Bidi filter");        return t("Bidi filter");
51    case 'description':      case "process":
52      return t("Bidi filter");          return _bidi_filter_process($text);
53    case "process":      case "settings":
54        return _bidi_filter_process($text);          return _bidi_filter_settings($text);
55    case "settings":      default:
56        return _bidi_filter_settings($text);          return $text;
   default:  
       return $text;  
57    }    }
58  }  }
59    
60    /**
61  //get dir needs to be split into a single include file so it can be used on theme and other places   * 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) {  function _get_dir($text) {
70    $text = strtolower($text);    $text = strtolower($text);
71    $len = strlen($text);    $len = strlen($text);
72    
73    $arabic = 0;    $arabic = 0;
74    $english = 0;    $english = 0;
75    
76    //constants    // constants
77    $a = ord('a');    $a = ord('a');
78    $z = ord('z');    $z = ord('z');
79    
80    //arabic UTF-8 letters have one of these values in the 1st byte    // arabic UTF-8 letters have one of these values in the 1st byte
81    $ar1 = 0xd8;    $ar1 = 0xd8;
82    $ar2 = 0xd9;    $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)    // 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) {    for ($i = 0; $i < $len; ++$i) {
86      $bin = ord($text[$i]);      $bin = ord($text[$i]);
87    
88      if ($bin == $ar1 || $bin == $ar2) {      if ($bin == $ar1 || $bin == $ar2) {
89        ++$arabic;        ++$arabic;
90        ++$i;        ++$i;
91      } else if ($bin >= $a && $bin <= $z) {      }
92        else if ($bin >= $a && $bin <= $z) {
93        ++$english;        ++$english;
94      }      }
95    }    }
96    
97    //should this return a bool instead?    // should this return a bool instead?
98    if ($english || $arabic) {    if ($english || $arabic) {
99      if ($english > $arabic)      if ($english > $arabic)
100        return ' class="left2right"';        return ' class="left2right"';
101      else      else
102        return ' class="right2left"';        return ' class="right2left"';
103    } else {    }
104      else {
105      return "";      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) {  function _bidi_filter_process($text) {
120    $output = "";    $output = "";
121    
122    $len = strlen($text);    $len = strlen($text);
123    $i = 0;    $i = 0;
124    
   
125    while ($i < $len) {    while ($i < $len) {
126      //find next tag      // find next tag
127      $e = strpos(substr($text, $i), "<");      $e = strpos(substr($text, $i), "<");
128      if ($e === FALSE) break;      if ($e === FALSE) {
129          break;
130        }
131    
132      $output.=substr($text, $i, $e);      $output .= substr($text, $i, $e);
133    
134      $i += $e;      $i += $e;
135    
136      //find end of next tag      // find end of next tag
137      $e = strcspn(substr($text, $i), "/> ");      $e = strcspn(substr($text, $i), "/> ");
138      $tag = substr($text, $i+1, $e-1);      $tag = substr($text, $i+1, $e-1);
   
     $output.=substr($text, $i, $e);  
     $i += $e;  
139    
140        $output .= substr($text, $i, $e);
141        $i += $e;
142    
143      switch ($tag) {      switch ($tag) {
144        //single tag entity        // single tag entity
145      case "img":        case "img":
146      case "br":        case "br":
147      case "hr":        case "hr":
148        continue;          continue;
149        break;          break;
150    
151        //nested cases        //nested cases
152      case "ul":        case "ul":
153      case "ol":        case "ol":
154      case "dl":        case "dl":
155      case "div":        case "div":
156        $e = 0;          $e = 0;
157        $j = 1; //stack counter          // stack counter
158            $j = 1;
159        // if $j = 0 then stack is empty  
160        while ($j > 0) {          // if $j = 0 then stack is empty
161          $e += strpos(substr($text, $i+$e) , $tag);          while ($j > 0) {
162              $e += strpos(substr($text, $i+$e) , $tag);
163          //yeah I know I'm assuming certain sizes for tags, sue me  
164          if ($text[$i+$e-1] == '<') { //new nested block            // yeah I know I'm assuming certain sizes for tags, sue me
165            ++$j;            // new nested block
166          } else if ($text[$i+$e-1] == '/') { //end of block            if ($text[$i+$e-1] == '<') {
167            --$j;              ++$j;
168          }            }
169          $e += 2; //skip current tag            // end of block
170        }            else if ($text[$i+$e-1] == '/') {
171        $content = substr($text, $i+1, $e);              --$j;
172        $output.=_get_dir(strip_tags($content));            }
173        $e += strlen($tag);            // skip current tag
174        $output.= substr($text, $i, $e);            $e += 2;
175        $i += $e;          }
176        break;  
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        //block elements these get out attention        case "p":
186      case "p":        case "blockquote":
187      case "blockquote":        case "pre":
188      case "pre":        case "h1":
189      case "h1":        case "h2":
190      case "h2":        case "h3":
191      case "h3":        case "h4":
192      case "h4":        case "h5":
193      case "h5":        case "h6":
     case "h6":  
   
       //nested lists are proken better think of a fix  
     case "li":  
       $close_tag = "</".$tag.">";  
       //breaks on extra whitespaces, maybe I should use regexps instead  
       $e = strpos(substr($text, $i), $close_tag);  
       $content = substr($text, $i+1, $e-1);  
       //calculate directions  
       $output.= _get_dir(strip_tags($content));  
       $e += strlen($close_tag);  
       $output.= substr($text, $i, $e);  
       $i += $e;  
194    
195        break;        // 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        // non block tags we are not handeling
209      default:        default:
210        $close_tag = "</".$tag.">";          $close_tag = "</".$tag.">";
211        $e = strpos(substr($text, $i), $close_tag) + strlen($close_tag);          $e = strpos(substr($text, $i), $close_tag) + strlen($close_tag);
212        $output.= substr($text, $i, $e);          $output.= substr($text, $i, $e);
213        $i += $e;          $i += $e;
214      }        }
   
215    }    }
   
   //any missing content  
   $output .= substr($text, $i);  
216    
217      // any missing content
218      $output .= substr($text, $i);
219    
220    return $output;    return $output;
221  }  }
222    
223    /**
224     * Filter settings.
225     *
226     * @return
227     *   HTML form for filter settings.
228     */
229  function _bidi_filter_settings() {  function _bidi_filter_settings() {
230    return form_group(t("Bidi filter"), t("automatic bidi"));    return form_group(t("Bidi filter"), t("automatic bidi"));
231  }  }
232    
 function bidi_filter_tips() {  
   if ($long)  
     {  
   
     }  
   else {  
   return t("You may write mixed Arabic and English freely, line direction will be computed automaticaly");  
     }  
 }  
   
233  ?>  ?>

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

  ViewVC Help
Powered by ViewVC 1.1.2