Imported version 0.2-1
[mstardict] / src / lib / ctype-mb.cpp
1 /* Copyright (C) 2000 MySQL AB
2
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2 of the License, or
6    (at your option) any later version.
7
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
16
17 #ifdef HAVE_CONFIG_H
18 #  include "config.h"
19 #endif
20
21 #include "my_global.h"
22 #include "m_ctype.h"
23 #include "m_string.h"
24
25 using namespace stardict_collation;
26
27 //#ifdef USE_MB
28 #if 0
29
30
31 void my_caseup_str_mb(CHARSET_INFO * cs, char *str)
32 {
33   register uint32 l;
34   register char *end=str+strlen(str); /* BAR TODO: remove strlen() call */
35   register uchar *map=cs->to_upper;
36   
37   while (*str)
38   {
39     if ((l=my_ismbchar(cs, str,end)))
40       str+=l;
41     else
42     { 
43       *str=(char) map[(uchar)*str];
44       str++;
45     }
46   }
47 }
48
49 void my_casedn_str_mb(CHARSET_INFO * cs, char *str)
50 {
51   register uint32 l;
52   register char *end=str+strlen(str);
53   register uchar *map=cs->to_lower;
54   
55   while (*str)
56   {
57     if ((l=my_ismbchar(cs, str,end)))
58       str+=l;
59     else
60     {
61       *str=(char) map[(uchar)*str];
62       str++;
63     }
64   }
65 }
66
67 uint my_caseup_mb(CHARSET_INFO * cs, char *src, uint srclen,
68                   char *dst __attribute__((unused)),
69                   uint dstlen __attribute__((unused)))
70 {
71   register uint32 l;
72   register char *srcend= src + srclen;
73   register uchar *map= cs->to_upper;
74
75   DBUG_ASSERT(src == dst && srclen == dstlen);
76   while (src < srcend)
77   {
78     if ((l=my_ismbchar(cs, src, srcend)))
79       src+= l;
80     else 
81     {
82       *src=(char) map[(uchar) *src];
83       src++;
84     }
85   }
86   return srclen;
87 }
88
89 uint my_casedn_mb(CHARSET_INFO * cs, char *src, uint srclen,
90                   char *dst __attribute__((unused)),
91                   uint dstlen __attribute__((unused)))
92 {
93   register uint32 l;
94   register char *srcend= src + srclen;
95   register uchar *map=cs->to_lower;
96
97   DBUG_ASSERT(src == dst && srclen == dstlen);  
98   while (src < srcend)
99   {
100     if ((l= my_ismbchar(cs, src, srcend)))
101       src+= l;
102     else
103     {
104       *src= (char) map[(uchar)*src];
105       src++;
106     }
107   }
108   return srclen;
109 }
110
111 int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t)
112 {
113   register uint32 l;
114   register const char *end=s+strlen(s);
115   register uchar *map=cs->to_upper;
116   
117   while (s<end)
118   {
119     if ((l=my_ismbchar(cs, s,end)))
120     {
121       while (l--)
122         if (*s++ != *t++) 
123           return 1;
124     }
125     else if (my_mbcharlen(cs, *t) > 1)
126       return 1;
127     else if (map[(uchar) *s++] != map[(uchar) *t++])
128       return 1;
129   }
130   return *t;
131 }
132
133
134 /*
135 ** Compare string against string with wildcard
136 **      0 if matched
137 **      -1 if not matched with wildcard
138 **       1 if matched with wildcard
139 */
140
141 #define INC_PTR(cs,A,B) A+=(my_ismbchar(cs,A,B) ? my_ismbchar(cs,A,B) : 1)
142
143 #define likeconv(s,A) (uchar) (s)->sort_order[(uchar) (A)]
144
145 int my_wildcmp_mb(CHARSET_INFO *cs,
146                   const char *str,const char *str_end,
147                   const char *wildstr,const char *wildend,
148                   int escape, int w_one, int w_many)
149 {
150   int result= -1;                               /* Not found, using wildcards */
151
152   while (wildstr != wildend)
153   {
154     while (*wildstr != w_many && *wildstr != w_one)
155     {
156       int l;
157       if (*wildstr == escape && wildstr+1 != wildend)
158         wildstr++;
159       if ((l = my_ismbchar(cs, wildstr, wildend)))
160       {
161           if (str+l > str_end || memcmp(str, wildstr, l) != 0)
162               return 1;
163           str += l;
164           wildstr += l;
165       }
166       else
167       if (str == str_end || likeconv(cs,*wildstr++) != likeconv(cs,*str++))
168         return(1);                              /* No match */
169       if (wildstr == wildend)
170         return (str != str_end);                /* Match if both are at end */
171       result=1;                                 /* Found an anchor char */
172     }
173     if (*wildstr == w_one)
174     {
175       do
176       {
177         if (str == str_end)                     /* Skip one char if possible */
178           return (result);
179         INC_PTR(cs,str,str_end);
180       } while (++wildstr < wildend && *wildstr == w_one);
181       if (wildstr == wildend)
182         break;
183     }
184     if (*wildstr == w_many)
185     {                                           /* Found w_many */
186       uchar cmp;
187       const char* mb = wildstr;
188       int mblen=0;
189       
190       wildstr++;
191       /* Remove any '%' and '_' from the wild search string */
192       for (; wildstr != wildend ; wildstr++)
193       {
194         if (*wildstr == w_many)
195           continue;
196         if (*wildstr == w_one)
197         {
198           if (str == str_end)
199             return (-1);
200           INC_PTR(cs,str,str_end);
201           continue;
202         }
203         break;                                  /* Not a wild character */
204       }
205       if (wildstr == wildend)
206         return(0);                              /* Ok if w_many is last */
207       if (str == str_end)
208         return -1;
209       
210       if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
211         cmp= *++wildstr;
212         
213       mb=wildstr;
214       mblen= my_ismbchar(cs, wildstr, wildend);
215       INC_PTR(cs,wildstr,wildend);              /* This is compared trough cmp */
216       cmp=likeconv(cs,cmp);   
217       do
218       {
219         for (;;)
220         {
221           if (str >= str_end)
222             return -1;
223           if (mblen)
224           {
225             if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
226             {
227               str += mblen;
228               break;
229             }
230           }
231           else if (!my_ismbchar(cs, str, str_end) &&
232                    likeconv(cs,*str) == cmp)
233           {
234             str++;
235             break;
236           }
237           INC_PTR(cs,str, str_end);
238         }
239         {
240           int tmp=my_wildcmp_mb(cs,str,str_end,wildstr,wildend,escape,w_one,
241                                 w_many);
242           if (tmp <= 0)
243             return (tmp);
244         }
245       } while (str != str_end && wildstr[0] != w_many);
246       return(-1);
247     }
248   }
249   return (str != str_end ? 1 : 0);
250 }
251
252
253 uint my_numchars_mb(CHARSET_INFO *cs __attribute__((unused)),
254                       const char *pos, const char *end)
255 {
256   register uint32 count=0;
257   while (pos < end) 
258   {
259     uint mblen;
260     pos+= (mblen= my_ismbchar(cs,pos,end)) ? mblen : 1;
261     count++;
262   }
263   return count;
264 }
265
266
267 uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)),
268                      const char *pos, const char *end, uint length)
269 {
270   const char *start= pos;
271   
272   while (length && pos < end)
273   {
274     uint mblen;
275     pos+= (mblen= my_ismbchar(cs, pos, end)) ? mblen : 1;
276     length--;
277   }
278   return (uint) (length ? end+2-start : pos-start);
279 }
280
281
282 uint my_well_formed_len_mb(CHARSET_INFO *cs, const char *b, const char *e,
283                            uint pos, int *error)
284 {
285   const char *b_start= b;
286   *error= 0;
287   while (pos)
288   {
289     my_wc_t wc;
290     int mblen;
291
292     if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) b, (uchar*) e)) <= 0)
293     {
294       *error= b < e ? 1 : 0;
295       break;
296     }
297     b+= mblen;
298     pos--;
299   }
300   return (uint) (b - b_start);
301 }
302
303
304
305 uint my_instr_mb(CHARSET_INFO *cs,
306                  const char *b, uint b_length, 
307                  const char *s, uint s_length,
308                  my_match_t *match, uint nmatch)
309 {
310   register const char *end, *b0;
311   int res= 0;
312   
313   if (s_length <= b_length)
314   {
315     if (!s_length)
316     {
317       if (nmatch)
318       {
319         match->beg= 0;
320         match->end= 0;
321         match->mblen= 0;
322       }
323       return 1;         /* Empty string is always found */
324     }
325     
326     b0= b;
327     end= b+b_length-s_length+1;
328     
329     while (b < end)
330     {
331       int mblen;
332       
333       if (!cs->coll->strnncoll(cs, (unsigned char*) b,   s_length, 
334                                    (unsigned char*) s, s_length, 0))
335       {
336         if (nmatch)
337         {
338           match[0].beg= 0;
339           match[0].end= (uint) (b-b0);
340           match[0].mblen= res;
341           if (nmatch > 1)
342           {
343             match[1].beg= match[0].end;
344             match[1].end= match[0].end+s_length;
345             match[1].mblen= 0;  /* Not computed */
346           }
347         }
348         return 2;
349       }
350       mblen= (mblen= my_ismbchar(cs, b, end)) ? mblen : 1;
351       b+= mblen;
352       b_length-= mblen;
353       res++;
354     }
355   }
356   return 0;
357 }
358 #endif
359
360 /* BINARY collations handlers for MB charsets */
361
362 static int my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
363                                 const uchar *s, uint slen,
364                                 const uchar *t, uint tlen,
365                                 my_bool t_is_prefix)
366 {
367   uint len=min(slen,tlen);
368   int cmp= memcmp(s,t,len);
369   return cmp ? cmp : (int) ((t_is_prefix ? len : slen) - tlen);
370 }
371
372 #if 0
373 /*
374   Compare two strings. 
375   
376   SYNOPSIS
377     my_strnncollsp_mb_bin()
378     cs                  Chararacter set
379     s                   String to compare
380     slen                Length of 's'
381     t                   String to compare
382     tlen                Length of 't'
383     diff_if_only_endspace_difference
384                         Set to 1 if the strings should be regarded as different
385                         if they only difference in end space
386
387   NOTE
388    This function is used for character strings with binary collations.
389    The shorter string is extended with end space to be as long as the longer
390    one.
391
392   RETURN
393     A negative number if s < t
394     A positive number if s > t
395     0 if strings are equal
396 */
397
398 static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
399                                  const uchar *a, uint a_length, 
400                                  const uchar *b, uint b_length,
401                                  my_bool diff_if_only_endspace_difference)
402 {
403   const uchar *end;
404   uint length;
405   int res;
406
407 #ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
408   diff_if_only_endspace_difference= 0;
409 #endif
410   
411   end= a + (length= min(a_length, b_length));
412   while (a < end)
413   {
414     if (*a++ != *b++)
415       return ((int) a[-1] - (int) b[-1]);
416   }
417   res= 0;
418   if (a_length != b_length)
419   {
420     int swap= 1;
421     if (diff_if_only_endspace_difference)
422       res= 1;                                   /* Assume 'a' is bigger */
423     /*
424       Check the next not space character of the longer key. If it's < ' ',
425       then it's smaller than the other key.
426     */
427     if (a_length < b_length)
428     {
429       /* put shorter key in s */
430       a_length= b_length;
431       a= b;
432       swap= -1;                                 /* swap sign of result */
433       res= -res;
434     }
435     for (end= a + a_length-length; a < end ; a++)
436     {
437       if (*a != ' ')
438         return (*a < ' ') ? -swap : swap;
439     }
440   }
441   return res;
442 }
443
444
445 static int my_strnxfrm_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
446                               uchar * dest, uint dstlen,
447                               const uchar *src, uint srclen)
448 {
449   if (dest != src)
450     memcpy(dest, src, min(dstlen, srclen));
451   if (dstlen > srclen)
452     bfill(dest + srclen, dstlen - srclen, ' ');
453   return dstlen;
454 }
455
456
457 static int my_strcasecmp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
458                       const char *s, const char *t)
459 {
460   return strcmp(s,t);
461 }
462
463 static void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
464                       const uchar *key, uint len,ulong *nr1, ulong *nr2)
465 {
466   const uchar *pos = key;
467   
468   key+= len;
469   
470   for (; pos < (uchar*) key ; pos++)
471   {
472     nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * 
473              ((uint)*pos)) + (nr1[0] << 8);
474     nr2[0]+=3;
475   }
476 }
477
478
479 /* 
480   Write max key: create a buffer with multibyte
481   representation of the max_sort_char character,
482   and copy it into max_str in a loop. 
483 */
484 static void pad_max_char(CHARSET_INFO *cs, char *str, char *end)
485 {
486   char buf[10];
487   char buflen= cs->cset->wc_mb(cs, cs->max_sort_char, (uchar*) buf,
488                                (uchar*) buf + sizeof(buf));
489   DBUG_ASSERT(buflen > 0);
490   do
491   {
492     if ((str + buflen) < end)
493     {
494       /* Enough space for the characer */
495       memcpy(str, buf, buflen);
496       str+= buflen;
497     }
498     else
499     {
500       /* 
501         There is no space for whole multibyte
502         character, then add trailing spaces.
503       */  
504       *str++= ' ';
505     }
506   } while (str < end);
507 }
508
509 /*
510 ** Calculate min_str and max_str that ranges a LIKE string.
511 ** Arguments:
512 ** ptr          Pointer to LIKE string.
513 ** ptr_length   Length of LIKE string.
514 ** escape       Escape character in LIKE.  (Normally '\').
515 **              All escape characters should be removed from min_str and max_str
516 ** res_length   Length of min_str and max_str.
517 ** min_str      Smallest case sensitive string that ranges LIKE.
518 **              Should be space padded to res_length.
519 ** max_str      Largest case sensitive string that ranges LIKE.
520 **              Normally padded with the biggest character sort value.
521 **
522 ** The function should return 0 if ok and 1 if the LIKE string can't be
523 ** optimized !
524 */
525
526 my_bool my_like_range_mb(CHARSET_INFO *cs,
527                          const char *ptr,uint ptr_length,
528                          pbool escape, pbool w_one, pbool w_many,
529                          uint res_length,
530                          char *min_str,char *max_str,
531                          uint *min_length,uint *max_length)
532 {
533   const char *end= ptr + ptr_length;
534   char *min_org= min_str;
535   char *min_end= min_str + res_length;
536   char *max_end= max_str + res_length;
537   uint charlen= res_length / cs->mbmaxlen;
538
539   for (; ptr != end && min_str != min_end && charlen > 0 ; ptr++, charlen--)
540   {
541     if (*ptr == escape && ptr+1 != end)
542     {
543       ptr++;                                    /* Skip escape */
544       *min_str++= *max_str++ = *ptr;
545       continue;
546     }
547     if (*ptr == w_one || *ptr == w_many)        /* '_' and '%' in SQL */
548     {
549       charlen= my_charpos(cs, min_org, min_str, res_length/cs->mbmaxlen);
550       
551       if (charlen < (uint) (min_str - min_org))
552         min_str= min_org + charlen;
553       
554       /*
555         Calculate length of keys:
556         'a\0\0... is the smallest possible string when we have space expand
557         a\ff\ff... is the biggest possible string
558       */
559       *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
560                     res_length);
561       *max_length= res_length;
562       /* Create min key  */
563       do
564       {
565         *min_str++= (char) cs->min_sort_char;
566       } while (min_str != min_end);
567       
568       /* 
569         Write max key: create a buffer with multibyte
570         representation of the max_sort_char character,
571         and copy it into max_str in a loop. 
572       */
573       *max_length= res_length;
574       pad_max_char(cs, max_str, max_end);
575       return 0;
576     }
577     *min_str++= *max_str++ = *ptr;
578   }
579
580   *min_length= *max_length = (uint) (min_str - min_org);
581   while (min_str != min_end)
582     *min_str++= *max_str++= ' ';           /* Because if key compression */
583   return 0;
584 }
585
586
587 static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
588                   const char *str,const char *str_end,
589                   const char *wildstr,const char *wildend,
590                   int escape, int w_one, int w_many)
591 {
592   int result= -1;                               /* Not found, using wildcards */
593
594   while (wildstr != wildend)
595   {
596     while (*wildstr != w_many && *wildstr != w_one)
597     {
598       int l;
599       if (*wildstr == escape && wildstr+1 != wildend)
600         wildstr++;
601       if ((l = my_ismbchar(cs, wildstr, wildend)))
602       {
603           if (str+l > str_end || memcmp(str, wildstr, l) != 0)
604               return 1;
605           str += l;
606           wildstr += l;
607       }
608       else
609       if (str == str_end || *wildstr++ != *str++)
610         return(1);                              /* No match */
611       if (wildstr == wildend)
612         return (str != str_end);                /* Match if both are at end */
613       result=1;                                 /* Found an anchor char */
614     }
615     if (*wildstr == w_one)
616     {
617       do
618       {
619         if (str == str_end)                     /* Skip one char if possible */
620           return (result);
621         INC_PTR(cs,str,str_end);
622       } while (++wildstr < wildend && *wildstr == w_one);
623       if (wildstr == wildend)
624         break;
625     }
626     if (*wildstr == w_many)
627     {                                           /* Found w_many */
628       uchar cmp;
629       const char* mb = wildstr;
630       int mblen=0;
631       
632       wildstr++;
633       /* Remove any '%' and '_' from the wild search string */
634       for (; wildstr != wildend ; wildstr++)
635       {
636         if (*wildstr == w_many)
637           continue;
638         if (*wildstr == w_one)
639         {
640           if (str == str_end)
641             return (-1);
642           INC_PTR(cs,str,str_end);
643           continue;
644         }
645         break;                                  /* Not a wild character */
646       }
647       if (wildstr == wildend)
648         return(0);                              /* Ok if w_many is last */
649       if (str == str_end)
650         return -1;
651       
652       if ((cmp= *wildstr) == escape && wildstr+1 != wildend)
653         cmp= *++wildstr;
654         
655       mb=wildstr;
656       mblen= my_ismbchar(cs, wildstr, wildend);
657       INC_PTR(cs,wildstr,wildend);              /* This is compared trough cmp */
658       do
659       {
660         for (;;)
661         {
662           if (str >= str_end)
663             return -1;
664           if (mblen)
665           {
666             if (str+mblen <= str_end && memcmp(str, mb, mblen) == 0)
667             {
668               str += mblen;
669               break;
670             }
671           }
672           else if (!my_ismbchar(cs, str, str_end) && *str == cmp)
673           {
674             str++;
675             break;
676           }
677           INC_PTR(cs,str, str_end);
678         }
679         {
680           int tmp=my_wildcmp_mb_bin(cs,str,str_end,wildstr,wildend,escape,w_one,w_many);
681           if (tmp <= 0)
682             return (tmp);
683         }
684       } while (str != str_end && wildstr[0] != w_many);
685       return(-1);
686     }
687   }
688   return (str != str_end ? 1 : 0);
689 }
690
691
692 /*
693   Data was produced from EastAsianWidth.txt 
694   using utt11-dump utility.
695 */
696 static char pg11[256]=
697 {
698 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
699 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
700 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,
701 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
702 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
703 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
704 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
705 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
706 };
707
708 static char pg23[256]=
709 {
710 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
711 0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
712 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
713 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
714 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
715 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
716 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
717 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
718 };
719
720 static char pg2E[256]=
721 {
722 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
723 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
724 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
725 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
726 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,
727 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
728 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
729 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0
730 };
731
732 static char pg2F[256]=
733 {
734 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
735 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
736 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
737 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
738 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
739 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
740 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
741 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0
742 };
743
744 static char pg30[256]=
745 {
746 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
747 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
748 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
749 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
750 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,
751 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
752 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
753 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
754 };
755
756 static char pg31[256]=
757 {
758 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
759 1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
760 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
761 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
762 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
763 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
764 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
765 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
766 };
767
768 static char pg32[256]=
769 {
770 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
771 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
772 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
773 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,
774 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
775 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
776 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
777 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
778 };
779
780 static char pg4D[256]=
781 {
782 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
783 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
784 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
785 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
786 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
787 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,
788 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
789 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
790 };
791
792 static char pg9F[256]=
793 {
794 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
795 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
796 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
797 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
798 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
799 1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
800 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
801 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
802 };
803
804 static char pgA4[256]=
805 {
806 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
807 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
808 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
809 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
810 1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
811 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
812 1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
813 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
814 };
815
816 static char pgD7[256]=
817 {
818 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
819 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
820 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
821 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
822 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
823 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
824 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
825 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
826 };
827
828 static char pgFA[256]=
829 {
830 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
831 1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
832 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
833 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
834 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
835 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
836 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
837 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
838 };
839
840 static char pgFE[256]=
841 {
842 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
843 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
844 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,
845 1,1,1,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
846 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
847 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
848 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
849 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
850 };
851
852 static char pgFF[256]=
853 {
854 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
855 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
856 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
857 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
858 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
859 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
860 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
861 1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
862 };
863
864 static struct {int page; char *p;} utr11_data[256]=
865 {
866 {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
867 {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
868 {0,NULL},{0,pg11},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
869 {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
870 {0,NULL},{0,NULL},{0,NULL},{0,pg23},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
871 {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,pg2E},{0,pg2F},
872 {0,pg30},{0,pg31},{0,pg32},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
873 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
874 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
875 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{0,pg4D},{1,NULL},{1,NULL},
876 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
877 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
878 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
879 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
880 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
881 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
882 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
883 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
884 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
885 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{0,pg9F},
886 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{0,pgA4},{0,NULL},{0,NULL},{0,NULL},
887 {0,NULL},{0,NULL},{0,NULL},{0,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
888 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
889 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
890 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
891 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},
892 {1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{1,NULL},{0,pgD7},
893 {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
894 {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
895 {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
896 {0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},{0,NULL},
897 {0,NULL},{1,NULL},{0,pgFA},{0,NULL},{0,NULL},{0,NULL},{0,pgFE},{0,pgFF}
898 };
899
900 uint my_numcells_mb(CHARSET_INFO *cs, const char *b, const char *e)
901 {
902   my_wc_t wc;
903   int clen= 0;
904   
905   while (b < e)
906   {
907     int mblen;
908     uint pg;
909     if ((mblen= cs->cset->mb_wc(cs, &wc, (uchar*) b, (uchar*) e)) <= 0)
910     {
911       mblen= 1; /* Let's think a wrong sequence takes 1 dysplay cell */
912       b++;
913       continue;
914     }
915     b+= mblen;
916     pg= (wc >> 8) & 0xFF;
917     clen+= utr11_data[pg].p ? utr11_data[pg].p[wc & 0xFF] : utr11_data[pg].page;
918     clen++;
919   }
920   return clen;
921 }
922
923
924 int my_mb_ctype_mb(CHARSET_INFO *cs, int *ctype,
925                    const unsigned char *s, const unsigned char *e)
926 {
927   my_wc_t wc;
928   int res= cs->cset->mb_wc(cs, &wc, s, e);
929   if (res <= 0)
930     *ctype= 0;
931   else
932     *ctype= my_uni_ctype[wc>>8].ctype ?
933             my_uni_ctype[wc>>8].ctype[wc&0xFF] :
934             my_uni_ctype[wc>>8].pctype;    
935   return res;
936 }
937 #endif
938
939
940 namespace stardict_collation {
941
942 MY_COLLATION_HANDLER my_collation_mb_bin_handler =
943 {
944     NULL,               /* init */
945     my_strnncoll_mb_bin,
946     //my_strnncollsp_mb_bin,
947     //my_strnxfrm_mb_bin,
948     //my_strnxfrmlen_simple,
949     //my_like_range_simple,
950     //my_wildcmp_mb_bin,
951     //my_strcasecmp_mb_bin,
952     //my_instr_mb,
953     //my_hash_sort_mb_bin,
954     //my_propagate_simple
955 };
956
957 }; //namespace
958