<!DOCTYPE bindings [
  <!ENTITY NS_WIDTH "http://suika.fam.cx/www/style/text/wrap#">
]>
<bindings xmlns="http://www.mozilla.org/xbl">
  <binding id="halfwidth">
    <implementation>
      <constructor type="application/x-javascript" xml:space="preserve">
        var targetNode = this;
        window.addEventListener ('load', function () {
          if (!targetNode.widthTransformed ()) {
            targetNode.setAttributeNS
                           ('&NS_WIDTH;', 'width:widthTransformed', '1');
            var resolver = document.createNSResolver (targetNode);
            var nodes = document.evaluate (
              'descendant::*/child::text () | child::text ()',
              targetNode, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null
            );
            var pattern = targetNode.WidthPattern;
            var table = targetNode.WidthTable;
            for (var i = 0; i &lt; nodes.snapshotLength; i++) {
              var node = nodes.snapshotItem (i);
              node.data = node.data.replace (pattern, function (m) {
                return table[m] || table['#fallback'] || m;
              });
            }
          }
        }, false);
      </constructor>
      <field name="WidthPattern">
        /[\u3001\u3002\u300C\u300D\u309B\u309C\u30A0-\u30FF]/g;
      </field>
      <field name="WidthTable">
        var a = {};
        a['\u3001'] = '\uFF64';       // IDEOGRAPHIC COMMA
        a['\u3002'] = '\uFF61';       // IDEOGRAPHIC FULL STOP
        a['\u300C'] = '\uFF62';       // open kagi-kakko
        a['\u300D'] = '\uFF63';       // close kagi-kakko
        a['\u3099'] = '\uFF9E';       // combining voiced sound mark
        a['\u309A'] = '\uFF9F';       // combining semi-voiced sound mark
        a['\u309B'] = '\uFF9E';       // KATAKANA-HIRAGANA VOICED SOUND MARK
        a['\u309C'] = '\uFF9F';       // semi-voiced sound mark
        a['\u30A0'] = '=';            // KATAKANA DOUBLE HYPHEN
        a['\u30A1'] = '\uFF67';       // KATAKANA SMALL LETTER A
        a['\u30A2'] = '\uFF71';       // KATAKANA LETTER A
        a['\u30A3'] = '\uFF68';
        a['\u30A4'] = '\uFF72';
        a['\u30A5'] = '\uFF69';
        a['\u30A6'] = '\uFF73';
        a['\u30A7'] = '\uFF6A';
        a['\u30A8'] = '\uFF74';
        a['\u30A9'] = '\uFF6B';
        a['\u30AA'] = '\uFF75';
        a['\u30AB'] = '\uFF76';        // KATAKANA LETTER KA
        a['\u30AC'] = '\uFF76\uFF9E';
        a['\u30AD'] = '\uFF77';      
        a['\u30AE'] = '\uFF77\uFF9E';
        a['\u30AF'] = '\uFF78';
        a['\u30B0'] = '\uFF78\uFF9E';
        a['\u30B1'] = '\uFF79';
        a['\u30B2'] = '\uFF79\uFF9E';
        a['\u30B3'] = '\uFF7A';
        a['\u30B4'] = '\uFF7A\uFF9E';
        a['\u30B5'] = '\uFF7B';        // KATAKANA LETTER SA
        a['\u30B6'] = '\uFF7B\uFF9E';
        a['\u30B7'] = '\uFF7C';
        a['\u30B8'] = '\uFF7C\uFF9E';
        a['\u30B9'] = '\uFF7D';
        a['\u30BA'] = '\uFF7D\uFF9E';
        a['\u30BB'] = '\uFF7E';
        a['\u30BC'] = '\uFF7E\uFF9E';
        a['\u30BD'] = '\uFF7F';
        a['\u30BE'] = '\uFF7F\uFF9E';
        a['\u30BF'] = '\uFF80';        // KATAKANA LETTER TA
        a['\u30C0'] = '\uFF80\uFF9E';
        a['\u30C1'] = '\uFF81';
        a['\u30C2'] = '\uFF81\uFF9E';
        a['\u30C3'] = '\uFF6F';        // KATAKANA SMALL LETTER TU
        a['\u30C4'] = '\uFF82';
        a['\u30C5'] = '\uFF82\uFF9E';
        a['\u30C6'] = '\uFF83';
        a['\u30C7'] = '\uFF83\uFF9E';
        a['\u30C8'] = '\uFF84';
        a['\u30C9'] = '\uFF84\uFF9E';
        a['\u30CA'] = '\uFF85';        // KATAKANA LETTER NA
        a['\u30CB'] = '\uFF86';
        a['\u30CC'] = '\uFF87';
        a['\u30CD'] = '\uFF88';
        a['\u30CE'] = '\uFF89';
        a['\u30CF'] = '\uFF8A';        // KATAKANA LETTER HA
        a['\u30D0'] = '\uFF8A\uFF9E';
        a['\u30D1'] = '\uFF8A\uFF9F';
        a['\u30D2'] = '\uFF8B';
        a['\u30D3'] = '\uFF8B\uFF9E';
        a['\u30D4'] = '\uFF8B\uFF9F';
        a['\u30D5'] = '\uFF8C';
        a['\u30D6'] = '\uFF8C\uFF9E';
        a['\u30D7'] = '\uFF8C\uFF9F';
        a['\u30D8'] = '\uFF8D';
        a['\u30D9'] = '\uFF8D\uFF9E';
        a['\u30DA'] = '\uFF8D\uFF9F';
        a['\u30DB'] = '\uFF8E';
        a['\u30DC'] = '\uFF8E\uFF9E';
        a['\u30DD'] = '\uFF8E\uFF9F';
        a['\u30DE'] = '\uFF8F';        // KATAKANA LETTER MA
        a['\u30DF'] = '\uFF90';
        a['\u30E0'] = '\uFF91';
        a['\u30E1'] = '\uFF92';
        a['\u30E2'] = '\uFF93';
        a['\u30E3'] = '\uFF6C';        // KATAKANA LETTER SMALL YA
        a['\u30E4'] = '\uFF94';        // KATAKANA LETTER YA
        a['\u30E5'] = '\uFF6D';
        a['\u30E6'] = '\uFF95';
        a['\u30E7'] = '\uFF6E';
        a['\u30E8'] = '\uFF96';
        a['\u30E9'] = '\uFF97';        // KATAKANA LETTER RA
        a['\u30EA'] = '\uFF98';
        a['\u30EB'] = '\uFF99';
        a['\u30EC'] = '\uFF9A';
        a['\u30ED'] = '\uFF9B';
        // U+30EE KATAKANA LETTER SMALL WA
        a['\u30EF'] = '\uFF9C';        // KATAKANA LETTER WA
        a['\u30F2'] = '\uFF66';        // KATAKANA LETTER WO
        a['\u30F3'] = '\uFF9D';        // KATAKANA LETTER N
        a['\u30F4'] = '\uFF73\uFF9E';  // vu
        // U+30F5 KATAKANA LETTER SMALL KA
        // U+30F6 KATAKANA LETTER SMALL KE
        a['\u30F7'] = '\uFF9C\uFF9E';  // va
        // U+30F8 vi
        // U+30F9 ve
        a['\u30FA'] = '\uFF9D\uFF9E';  // vo
        a['\u30FB'] = '\uFF65';        // KATAKANA MIDDLE DOT
        a['\u30FC'] = '\uFF70';        // KATAKANA-HIRAGANA PROLONGED SOUND MARK
        // U+30FD katakana ditto
        // U+30FE katakana ditto + voiced
        // U+30FF katakana koto
        a;
      </field>
      <method name="widthTransformed">
        <body>
            if (this.getAttributeNS ('&NS_WIDTH;', 'widthTransformed')) {
              return true;
            }
            var parents = new Array (this.parentNode);
            while (parents.length > 0) {
              var node = parents.shift ();
              if (node.nodeType == node.ELEMENT_NODE &amp;&amp;
                  node.getAttributeNS ('&NS_WIDTH;', 'widthTransformed')) {
                return true;
              } else if (node.parentNode) {
                parents.push (node.parentNode);
              }
            }
            return false;
        </body>
      </method>
    </implementation>
  </binding>
  <binding id="fullwidth" extends="#halfwidth">
    <implementation>
      <field name="WidthPattern">
        /[\u0020-\u007F]/g;
      </field>
      <field name="WidthTable">
        var a = {};
        a['\u0020'] = '\u3000';
        a['\u0021'] = '\uFF01';
        a['\u0022'] = '\uFF02';
        a['\u0023'] = '\uFF03';
        a['\u0024'] = '\uFF04';
        a['\u0025'] = '\uFF05';
        a['\u0026'] = '\uFF06';
        a['\u0027'] = '\uFF07';
        a['\u0028'] = '\uFF08';
        a['\u0029'] = '\uFF09';
        a['\u002A'] = '\uFF0A';
        a['\u002B'] = '\uFF0B';
        a['\u002C'] = '\uFF0C';
        a['\u002D'] = '\uFF0D';
        a['\u002E'] = '\uFF0E';
        a['\u002F'] = '\uFF0F';
        a['\u0030'] = '\uFF10';
        a['\u0031'] = '\uFF11';
        a['\u0032'] = '\uFF12';
        a['\u0033'] = '\uFF13';
        a['\u0034'] = '\uFF14';
        a['\u0035'] = '\uFF15';
        a['\u0036'] = '\uFF16';
        a['\u0037'] = '\uFF17';
        a['\u0038'] = '\uFF18';
        a['\u0039'] = '\uFF19';
        a['\u003A'] = '\uFF1A';
        a['\u003B'] = '\uFF1B';
        a['\u003C'] = '\uFF1C';
        a['\u003D'] = '\uFF1D';
        a['\u003E'] = '\uFF1E';
        a['\u003F'] = '\uFF1F';
        a['\u0040'] = '\uFF20';
        a['\u0041'] = '\uFF21';
        a['\u0042'] = '\uFF22';
        a['\u0043'] = '\uFF23';
        a['\u0044'] = '\uFF24';
        a['\u0045'] = '\uFF25';
        a['\u0046'] = '\uFF26';
        a['\u0047'] = '\uFF27';
        a['\u0048'] = '\uFF28';
        a['\u0049'] = '\uFF29';
        a['\u004A'] = '\uFF2A';
        a['\u004B'] = '\uFF2B';
        a['\u004C'] = '\uFF2C';
        a['\u004D'] = '\uFF2D';
        a['\u004E'] = '\uFF2E';
        a['\u004F'] = '\uFF2F';
        a['\u0050'] = '\uFF30';
        a['\u0051'] = '\uFF31';
        a['\u0052'] = '\uFF32';
        a['\u0053'] = '\uFF33';
        a['\u0054'] = '\uFF34';
        a['\u0055'] = '\uFF35';
        a['\u0056'] = '\uFF36';
        a['\u0057'] = '\uFF37';
        a['\u0058'] = '\uFF38';
        a['\u0059'] = '\uFF39';
        a['\u005A'] = '\uFF3A';
        a['\u005B'] = '\uFF3B';
        a['\u005C'] = '\uFF3C';
        a['\u005D'] = '\uFF3D';
        a['\u005E'] = '\uFF3E';
        a['\u005F'] = '\uFF3F';
        a['\u0060'] = '\uFF40';
        a['\u0061'] = '\uFF41';
        a['\u0062'] = '\uFF42';
        a['\u0063'] = '\uFF43';
        a['\u0064'] = '\uFF44';
        a['\u0065'] = '\uFF45';
        a['\u0066'] = '\uFF46';
        a['\u0067'] = '\uFF47';
        a['\u0068'] = '\uFF48';
        a['\u0069'] = '\uFF49';
        a['\u006A'] = '\uFF4A';
        a['\u006B'] = '\uFF4B';
        a['\u006C'] = '\uFF4C';
        a['\u006D'] = '\uFF4D';
        a['\u006E'] = '\uFF4E';
        a['\u006F'] = '\uFF4F';
        a['\u0070'] = '\uFF50';
        a['\u0071'] = '\uFF51';
        a['\u0072'] = '\uFF52';
        a['\u0073'] = '\uFF53';
        a['\u0074'] = '\uFF54';
        a['\u0075'] = '\uFF55';
        a['\u0076'] = '\uFF56';
        a['\u0077'] = '\uFF57';
        a['\u0078'] = '\uFF58';
        a['\u0079'] = '\uFF59';
        a['\u007A'] = '\uFF5A';
        a['\u007B'] = '\uFF5B';
        a['\u007C'] = '\uFF5C';
        a['\u007D'] = '\uFF5D';
        // U+007E TILDE
        a;
      </field>
    </implementation>
  </binding>
</bindings>
<!-- ***** BEGIN LICENSE BLOCK *****
   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
   -
   - The contents of this file are subject to the Mozilla Public License Version
   - 1.1 (the "License"); you may not use this file except in compliance with
   - the License. You may obtain a copy of the License at
   - <http://www.mozilla.org/MPL/>
   -
   - Software distributed under the License is distributed on an "AS IS" basis,
   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   - for the specific language governing rights and limitations under the
   - License.
   -
   - The Original Code is wrap.xbl code.
   -
   - The Initial Developer of the Original Code is Wakaba.
   - Portions created by the Initial Developer are Copyright (C) 2005
   - the Initial Developer. All Rights Reserved.
   -
   - Contributor(s):
   -   Wakaba <w@suika.fam.cx>
   -
   - Alternatively, the contents of this file may be used under the terms of
   - either the GNU General Public License Version 2 or later (the "GPL"), or
   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   - in which case the provisions of the GPL or the LGPL are applicable instead
   - of those above. If you wish to allow use of your version of this file only
   - under the terms of either the GPL or the LGPL, and not to allow others to
   - use your version of this file under the terms of the MPL, indicate your
   - decision by deleting the provisions above and replace them with the notice
   - and other provisions required by the LGPL or the GPL. If you do not delete
   - the provisions above, a recipient may use your version of this file under
   - the terms of any one of the MPL, the GPL or the LGPL.
   -
   - ***** END LICENSE BLOCK ***** -->
