/*
 *  KANJI Code conversion routines.
 *  (for ptex only)
 */

#include "kanji.h"

#define CS_TOKEN_FLAG  0x1FFFFFFF
#define CJK_CHAR_LIMIT  0x1000000
#define CJK_TOKEN_FLAG   0xFFFFFF
#define KCAT_KANJI     16
#define KCAT_HANGUL    19

/* m: for debug */
integer check_kanji P2C(integer, c,integer, m)
{
    if (c > CS_TOKEN_FLAG) return 0;
    if (is_internalUPTEX()) {
        if ((c & CJK_TOKEN_FLAG) < CJK_CHAR_LIMIT) {
	  if (XXHi(c)==0) return 1;
	  else if (XXHi(c)>=KCAT_KANJI && XXHi(c)<=KCAT_HANGUL) return 2;
	}
    } else {
        if ((XHi(c)==0) &&
	    iskanji1(Hi(c)) && iskanji2(Lo(c))) {
	  if (XXHi(c)==0) return 1;
	  else if (XXHi(c)>=KCAT_KANJI && XXHi(c)<=KCAT_HANGUL) return 2;
	}
    }
    if (0 <= c && c <= 255) return -1;  /* ascii without catcode */
    return 0;  /* ascii with catcode */
}

boolean is_kanji(integer c)
{
    return (iskanji1(Hi(c)) && iskanji2(Lo(c)));
}

boolean is_char_ascii(integer c)
{
    return (0 <= c && c < 0x100);
}

boolean is_wchar_ascii(integer c)
{
    return (!is_char_ascii(c) && !is_kanji(c));
}

boolean ismultiprn(integer c)
{
    int i, j;

    for (i=2; i<=4; i++) for (j=1; j<=i; j++) {
        if (ismultichr(i,j,c)) return true;
    }
    return false;
}

integer calc_pos(integer c)
{
    unsigned char c1, c2;

    if(c>=0 && c<=255) return(c);
    c1 = Hi(c);
    c2 = Lo(c);

    c1 = (c1 % 4) * 64;  /* c1 = 0, 64, 128, 192 */
    c2 = c2 % 64;        /* c2 = 0..63 */
    return(c1 + c2);     /* ret = 0..255 */
}

/* Ref. http://www.unicode.org/Public/UNIDATA/Blocks.txt */
static long ucs_range[]={
      0x0000, /* Basic Latin					0x00 */
      0x0080, /* Latin-1 Supplement				0x01 */
      0x0100, /* Latin Extended-A				0x02 */
      0x0180, /* Latin Extended-B				0x03 */
      0x0250, /* IPA Extensions					0x04 */
      0x02B0, /* Spacing Modifier Letters			0x05 */
      0x0300, /* Combining Diacritical Marks			0x06 */
      0x0370, /* Greek and Coptic				0x07 */
      0x0400, /* Cyrillic					0x08 */
      0x0500, /* Cyrillic Supplement				0x09 */
      0x0530, /* Armenian					0x0a */
      0x0590, /* Hebrew						0x0b */
      0x0600, /* Arabic						0x0c */
      0x0700, /* Syriac						0x0d */
      0x0750, /* Arabic Supplement				0x0e */
      0x0780, /* Thaana						0x0f */
      0x07C0, /* NKo						0x10 */
      0x0900, /* Devanagari					0x11 */
      0x0980, /* Bengali					0x12 */
      0x0A00, /* Gurmukhi					0x13 */
      0x0A80, /* Gujarati					0x14 */
      0x0B00, /* Oriya						0x15 */
      0x0B80, /* Tamil						0x16 */
      0x0C00, /* Telugu						0x17 */
      0x0C80, /* Kannada					0x18 */
      0x0D00, /* Malayalam					0x19 */
      0x0D80, /* Sinhala					0x1a */
      0x0E00, /* Thai						0x1b */
      0x0E80, /* Lao						0x1c */
      0x0F00, /* Tibetan					0x1d */
      0x1000, /* Myanmar					0x1e */
      0x10A0, /* Georgian					0x1f */
      0x1100, /* Hangul Jamo					0x20 */
      0x1200, /* Ethiopic					0x21 */
      0x1380, /* Ethiopic Supplement				0x22 */
      0x13A0, /* Cherokee					0x23 */
      0x1400, /* Unified Canadian Aboriginal Syllabics		0x24 */
      0x1680, /* Ogham						0x25 */
      0x16A0, /* Runic						0x26 */
      0x1700, /* Tagalog					0x27 */
      0x1720, /* Hanunoo					0x28 */
      0x1740, /* Buhid						0x29 */
      0x1760, /* Tagbanwa					0x2a */
      0x1780, /* Khmer						0x2b */
      0x1800, /* Mongolian					0x2c */
      0x1900, /* Limbu						0x2d */
      0x1950, /* Tai Le						0x2e */
      0x1980, /* New Tai Lue					0x2f */
      0x19E0, /* Khmer Symbols					0x30 */
      0x1A00, /* Buginese					0x31 */
      0x1B00, /* Balinese					0x32 */
      0x1D00, /* Phonetic Extensions				0x33 */
      0x1D80, /* Phonetic Extensions Supplement			0x34 */
      0x1DC0, /* Combining Diacritical Marks Supplement		0x35 */
      0x1E00, /* Latin Extended Additional			0x36 */
      0x1F00, /* Greek Extended					0x37 */
      0x2000, /* General Punctuation				0x38 */
      0x2070, /* Superscripts and Subscripts			0x39 */
      0x20A0, /* Currency Symbols				0x3a */
      0x20D0, /* Combining Diacritical Marks for Symbols	0x3b */
      0x2100, /* Letterlike Symbols				0x3c */
      0x2150, /* Number Forms					0x3d */
      0x2190, /* Arrows						0x3e */
      0x2200, /* Mathematical Operators				0x3f */
      0x2300, /* Miscellaneous Technical			0x40 */
      0x2400, /* Control Pictures				0x41 */
      0x2440, /* Optical Character Recognition			0x42 */
      0x2460, /* Enclosed Alphanumerics				0x43 */
      0x2500, /* Box Drawing					0x44 */
      0x2580, /* Block Elements					0x45 */
      0x25A0, /* Geometric Shapes				0x46 */
      0x2600, /* Miscellaneous Symbols				0x47 */
      0x2700, /* Dingbats					0x48 */
      0x27C0, /* Miscellaneous Mathematical Symbols-A		0x49 */
      0x27F0, /* Supplemental Arrows-A				0x4a */
      0x2800, /* Braille Patterns				0x4b */
      0x2900, /* Supplemental Arrows-B				0x4c */
      0x2980, /* Miscellaneous Mathematical Symbols-B		0x4d */
      0x2A00, /* Supplemental Mathematical Operators		0x4e */
      0x2B00, /* Miscellaneous Symbols and Arrows		0x4f */
      0x2C00, /* Glagolitic					0x50 */
      0x2C60, /* Latin Extended-C				0x51 */
      0x2C80, /* Coptic						0x52 */
      0x2D00, /* Georgian Supplement				0x53 */
      0x2D30, /* Tifinagh					0x54 */
      0x2D80, /* Ethiopic Extended				0x55 */
      0x2E00, /* Supplemental Punctuation			0x56 */
      0x2E80, /* CJK Radicals Supplement			0x57 */
      0x2F00, /* Kangxi Radicals				0x58 */
      0x2FF0, /* Ideographic Description Characters		0x59 */
      0x3000, /* CJK Symbols and Punctuation			0x5a */
      0x3040, /* Hiragana					0x5b */
      0x30A0, /* Katakana					0x5c */
      0x3100, /* Bopomofo					0x5d */
      0x3130, /* Hangul Compatibility Jamo			0x5e */
      0x3190, /* Kanbun						0x5f */
      0x31A0, /* Bopomofo Extended				0x60 */
      0x31C0, /* CJK Strokes					0x61 */
      0x31F0, /* Katakana Phonetic Extensions			0x62 */
      0x3200, /* Enclosed CJK Letters and Months		0x63 */
      0x3300, /* CJK Compatibility				0x64 */
      0x3400, /* CJK Unified Ideographs Extension A		0x65 */
      0x4DC0, /* Yijing Hexagram Symbols			0x66 */
      0x4E00, /* CJK Unified Ideographs				0x67 */
      0xA000, /* Yi Syllables					0x68 */
      0xA490, /* Yi Radicals					0x69 */
      0xA700, /* Modifier Tone Letters				0x6a */
      0xA720, /* Latin Extended-D				0x6b */
      0xA800, /* Syloti Nagri					0x6c */
      0xA840, /* Phags-pa					0x6d */
      0xAC00, /* Hangul Syllables				0x6e */
      0xD800, /* High Surrogates				0x6f */
      0xDB80, /* High Private Use Surrogates			0x70 */
      0xDC00, /* Low Surrogates					0x71 */
      0xE000, /* Private Use Area				0x72 */
      0xF900, /* CJK Compatibility Ideographs			0x73 */
      0xFB00, /* Alphabetic Presentation Forms			0x74 */
      0xFB50, /* Arabic Presentation Forms-A			0x75 */
      0xFE00, /* Variation Selectors				0x76 */
      0xFE10, /* Vertical Forms					0x77 */
      0xFE20, /* Combining Half Marks				0x78 */
      0xFE30, /* CJK Compatibility Forms			0x79 */
      0xFE50, /* Small Form Variants				0x7a */
      0xFE70, /* Arabic Presentation Forms-B			0x7b */
      0xFF00, /* Halfwidth and Fullwidth Forms			0x7c */
      0xFFF0, /* Specials                               	0x7d */
      0x10000, /* Linear B Syllabary				0x7e */
      0x10080, /* Linear B Ideograms				0x7f */
      0x10100, /* Aegean Numbers				0x80 */
      0x10140, /* Ancient Greek Numbers				0x81 */
      0x10300, /* Old Italic					0x82 */
      0x10330, /* Gothic					0x83 */
      0x10380, /* Ugaritic					0x84 */
      0x103A0, /* Old Persian					0x85 */
      0x10400, /* Deseret					0x86 */
      0x10450, /* Shavian					0x87 */
      0x10480, /* Osmanya					0x88 */
      0x10800, /* Cypriot Syllabary				0x89 */
      0x10900, /* Phoenician					0x8a */
      0x10A00, /* Kharoshthi					0x8b */
      0x12000, /* Cuneiform					0x8c */
      0x12400, /* Cuneiform Numbers and Punctuation		0x8d */
      0x1D000, /* Byzantine Musical Symbols			0x8e */
      0x1D100, /* Musical Symbols				0x8f */
      0x1D200, /* Ancient Greek Musical Notation		0x90 */
      0x1D300, /* Tai Xuan Jing Symbols				0x91 */
      0x1D360, /* Counting Rod Numerals				0x92 */
      0x1D400, /* Mathematical Alphanumeric Symbols		0x93 */
      0x20000, /* CJK Unified Ideographs Extension B		0x94 */
      0x2F800, /* CJK Compatibility Ideographs Supplement	0x95 */
      0x30000, /* reserved					0x96 */
      0x40000, /* reserved					0x97 */
      0x50000, /* reserved					0x98 */
      0x60000, /* reserved					0x99 */
      0x70000, /* reserved					0x9a */
      0x80000, /* reserved					0x9b */
      0x90000, /* reserved					0x9c */
      0xA0000, /* reserved					0x9d */
      0xB0000, /* reserved					0x9e */
      0xC0000, /* reserved					0x9f */
      0xD0000, /* reserved					0xa0 */
      0xE0000, /* Tags						0xa1 */
      0xE0100, /* Variation Selectors Supplement		0xa2 */
      0xF0000, /* Supplementary Private Use Area-A		0xa3 */
      0x100000, /* Supplementary Private Use Area-B		0xa4 */
  /* Value over 0x10FFFF is illegal under Unicode,
     They are for some special use.  *** experimental ***  */
      0x110000, /* Reserved					0xa5 */
      0x120000, /* Reserved					0xa6 */
      0x130000, /* Reserved					0xa7 */
      0x140000, /* Reserved					0xa8 */
      0x150000, /* Reserved					0xa9 */
      0x160000, /* Reserved					0xaa */
      0x170000, /* Reserved					0xab */
      0x180000, /* Reserved					0xac */
      0x190000, /* Reserved					0xad */
      0x1A0000, /* Reserved					0xae */
      0x1B0000, /* Reserved					0xaf */
      0x1C0000, /* Reserved					0xb0 */
      0x1D0000, /* Reserved					0xb1 */
      0x1E0000, /* Reserved					0xb2 */
      0x1F0000, /* Reserved					0xb3 */
      0x200000, /* Reserved					0xb4 */
      0x210000, /* Reserved					0xb5 */
      0x220000, /* Reserved					0xb6 */
      CJK_CHAR_LIMIT
};

#define NUCS_RANGE (sizeof(ucs_range)/sizeof(ucs_range[0]))

/* Return i, which satisfies a[i] <= x < a[i+1]. */
/* 'i' is serached between left <= i <= right. */
/* If no i satisfies such condition, return left-1. */
/* [Okumura et al.] An algorithm encyclopedia in Java, p.236. */
int binary_search P4C(long, x, long*, a, int, left, int, right)
{
    right++;
    while (left < right) {
        int mid = (left + right) / 2;
        if (a[mid] <= x ) left = mid + 1;
        else             right = mid;
    }
    return left - 1;
}

integer kcatcodekey(integer c)
{
    if (is_internalUPTEX()) {
        return binary_search((long)c, ucs_range, 0, NUCS_RANGE-1);
    } else {
        return Hi(toDVI(c));
    }
}

integer multilenbuffchar(integer c)
{
    c=toBUFF(c);
    if (BYTE1(c)) return 4;
    if (BYTE2(c)) return 3;
    if (BYTE3(c)) return 2;
    if (BYTE4(c)) return 1;
    return 0;
}
