gt:       return 0x1EBB; // small e with hook above
context: // $Id$
  /**
   * Copyright (C) 2002 Bas  Peters  (mail@bpeters.com)
   * Copyright (C) 2002 Yves Pratter (ypratter@club-internet.fr)
   *
   * This file is part of MARC4J
   *
   * MARC4J is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public 
   * License as published by the Free Software Foundation; either 
   * version 2.1 of the License, or (at your option) any later version.
   *
   * MARC4J is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public 
   * License along with MARC4J; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  package org.marc4j.converter.impl;
  
  import org.marc4j.converter.CharConverter;
  
  /**
   * <p>
   * A utility to convert UNIMARC data to UCS/Unicode.
   * </p>
   * 
   * @author Bas Peters
   * @author Yves Pratter
   * @version $Revision$
   */
  public class Iso5426ToUnicode extends CharConverter {
  
    /**
     * <p>
     * Converts UNIMARC (ISO 5426 charset) data to UCS/Unicode.
     * </p>
     * 
     * @param data - the UNIMARC data in an array of char
     * @return {@link String}- the UCS/Unicode data
     */
    public String convert(char data[]) {
      StringBuffer sb = new StringBuffer();
  
      for (int i = 0; i < data.length; i++) {
        char c = data[i];
        int len = data.length;
        if (isAscii(c))
          sb.append(c);
        else if (isCombining(c) && hasNext(i, len)) {
          char d = getCombiningChar(c * 256 + data[i + 1]);
          if (d != 0) {
            sb.append(d);
            i++;
          } else {
            sb.append(getChar(c));
          }
        } else
          sb.append(getChar(c));
      }
      return sb.toString();
    }
  
    private boolean hasNext(int pos, int len) {
      if (pos < (len - 1))
        return true;
      return false;
    }
  
    private boolean isAscii(int i) {
      if (i >= 0x00 && i <= 0x7F)
        return true;
      return false;
    }
  
    private boolean isCombining(int i) {
      //	if (i > 0xE0 && i < 0xFF)
      if (i >= 0xC0 && i <= 0xDF)
        return true;
      return false;
    }
  
    // Source : http://www.itscj.ipsj.or.jp/ISO-IR/053.pdf
    private char getChar(int i) {
      switch (i) {
      case 0xA1:
        return 0x00A1; // 2/1 inverted exclamation mark
      case 0xA2:
        return 0x201C; // 2/2 left low double quotation mark
      case 0xA3:
        return 0x00A3; // 2/3 pound sign
      case 0xA4:
        return 0x0024; // 2/4 dollar sign
      case 0xA5:
        return 0x00A5; // 2/5 yen sign
      case 0xA6:
        return 0x2020; // 2/6 single dagger
      case 0xA7:
        return 0x00A7; // 2/7 paragraph (section)
      case 0xA8:
        return 0x2032; // 2/8 prime
      case 0xA9:
        return 0x2018; // 2/9 left high single quotation mark
      case 0xAA:
        return 0x201C; // 2/10 left high double quotation mark
      case 0xAB:
        return 0x00AB; // 2/11 left angle quotation mark
      case 0xAC:
        return 0x266D; // 2/12 music flat
      case 0xAD:
        return 0x00A9; // 2/13 copyright sign
      case 0xAE:
        return 0x2117; // 2/14 sound recording copyright sign
      case 0xAF:
        return 0x00AE; // 2/15 trade mark sign
  
      case 0xB0:
        return 0x0639; // 3/0 ayn [ain]
      case 0xB1:
        return 0x0623; // 3/1 alif/hamzah [alef with hamza above]
      case 0xB2:
        return 0x2018; // 3/2 left low single quotation mark
      // 3/3 (this position shall not be used)
      // 3/4 (this position shall not be used)
      // 3/5 (this position shall not be used)
      case 0xB6:
        return 0x2021; // 3/6 double dagger
      case 0xB7:
        return 0x00B7; // 3/7 middle dot
      case 0xB8:
        return 0x2033; // 3/8 double prime
      case 0xB9:
        return 0x2019; // 3/9 right high single quotation mark
      case 0xBA:
        return 0x201D; // 3/10 right high double quotation mark
      case 0xBB:
        return 0x00BB; // 3/11 right angle quotation mark
      case 0xBC:
        return 0x266F; // 3/12 musical sharp
      case 0xBD:
        return 0x02B9; // 3/13 mjagkij znak
      case 0xBE:
        return 0x02BA; // 3/14 tverdyj znak
      case 0xBF:
        return 0x00BF; // 3/15 inverted question mark
  
      // 4/0 to 5/15 diacritic characters
  
      // 6/0 (this position shall not be used)
      case 0xE1:
        return 0x00C6; // 6/1 CAPITAL DIPHTHONG A WITH E
      case 0xE2:
        return 0x0110; // 6/2 CAPITAL LETTER D WITH STROKE
      // 6/3 (this position shall not be used)
      // 6/4 (this position shall not be used)
      // 6/5 (this position shall not be used)
      case 0xE6:
        return 0x0132; // 6/6 CAPITAL LETTER IJ
      // 6/7 (this position shall not be used)
      case 0xE8:
        return 0x0141; // 6/8 CAPITAL LETTER L WITH STROKE
      case 0xE9:
        return 0x00D8; // 6/9 CAPITAL LETTER O WITH SOLIDUS [oblique stroke]
      case 0xEA:
        return 0x0152; // 6/10 CAPITAL DIPHTONG OE
      // 6/11 (this position shall not be used)
      case 0xEC:
        return 0x00DE; // 6/12 CAPITAL LETTER THORN
      // 6/13 (this position shall not be used)
      // 6/14 (this position shall not be used)
      // 6/15 (this position shall not be used)
  
      // 7/0 (this position shall not be used)
      case 0xF1:
        return 0x00E6; // 7/1 small diphthong a with e
      // 7/4 (this position shall not be used)
      case 0xF5:
        return 0x0131; // 7/5 small letter i without dot
      case 0xF6:
        return 0x0133; // 7/6 small letter ij
      // 7/7 (this position shall not be used)
      case 0xF8:
        return 0x0142; // 7/8 small letter l with stroke
      case 0xF9:
        return 0x00F8; // 7/9 small letter o with solidus (oblique stroke)
      case 0xFA:
        return 0x0153; // 7/10 small diphtong oe
      case 0xFB:
        return 0x00DF; // 7/11 small letter sharp s
      case 0xFC:
        return 0x00FE; // 7/12 small letter thorn
      // 7/13 (this position shall not be used)
      // 7/14 (this position shall not be used)
      default:
        return (char) i;
      }
    }
  
    private char getCombiningChar(int i) {
      switch (i) {
      // 4/0 low rising tone mark
      case 0xC041:
        return 0x1EA2; // CAPITAL A WITH HOOK ABOVE
      case 0xC045:
        return 0x1EBA; // CAPITAL E WITH HOOK ABOVE
      case 0xC049:
        return 0x1EC8; // CAPITAL I WITH HOOK ABOVE
      case 0xC04F:
        return 0x1ECE; // CAPITAL O WITH HOOK ABOVE
      case 0xC055:
        return 0x1EE6; // CAPITAL U WITH HOOK ABOVE
      case 0xC059:
        return 0x1EF6; // CAPITAL Y WITH HOOK ABOVE
      case 0xC061:
        return 0x1EA3; // small a with hook above
      case 0xC065:
  