/*
   Copyleft (c)2002  by Danilo Segan <mm01142@alas.matf.bg.ac.yu>

   Permission to use, copy, modify, distribute and sell this software
   and its documentation for any purpose is hereby granted without fee,
   provided that the above copyright notice appear in all copies.
   Danilo Segan makes no representations about the suitability of this 
   software for any purpose.  It is provided "as is" without express or 
   implied warranty.
*/


/*
 * This comment is parsed by configure to create ctype.c,
 * so don't change it unless you know what you are doing.
 *
 * .configure. number_srpski=45
 * .configure. strxfrm_multiply_srpski=2
 */


#include <global.h>
#include <my_sys.h>
#include "m_string.h"
#include "m_ctype.h"
#include "t_ctype.h"
#include <stdio.h>

#define FILENAME "/usr/local/mysql/share/mysql/charsets/srpski.txt"
#define U_REDU (0)
#define GRESKA (-1)



/* Podatke cuvamo u uredjenom stablu
   takvom da su u levoj grani ,,manji'' karakteri, u desnoj ,,veci'', a direktno ispod 
   su nastavci na trenutno slovo
 */

typedef struct scvor cvor;
typedef cvor* pcvor;
typedef struct scvor{
    int slovo; // ili neki drugi 32-bitni tip
    int kljuc; // koristim svih 32-bita
    cvor *l,*d,*i;
} tcvor;

/* Ucitavamo najvise jednom iz fajla */
static int sr_ucitano=0;

/* Mapa nizova znakova na kljuceve */
pcvor Mapa=NULL;

/* Size of the key */
static int KeySize=0;

/* Nalazi cvor i pravi ako ne postoji */
pcvor Nadji(pcvor *kor, int slovo) {
    pcvor k; k=*kor;
    if (k==NULL) {
	k=(pcvor)malloc(sizeof(cvor));
	*kor=k;
	k->slovo=slovo;
	k->kljuc=slovo; // inicijalizacija, nebitno
	k->l=k->d=k->i=NULL;
	return k;
    }
    if (k->slovo > slovo) {
	return Nadji(&(k->l),slovo);
    }
    else if (k->slovo < slovo) {
	return Nadji(&(k->d),slovo);
    }
    else return k; // jednaki su, to je to
}

/* samo nalazi odgovarajuci */
pcvor nadji(pcvor k, int slovo) {
    if (k==NULL) return NULL;
    else if (k->slovo > slovo) return nadji(k->l,slovo);
    else if (k->slovo < slovo) return nadji(k->d,slovo);
    else return k;
}

/* Reads data from FILENAME */
int ucitaj_bazu() {
    FILE *in;
    char *s=NULL,c,*k;
    int slovo;
    int duz=1,t,podslovo;
    int poredi[4],unos,tr,vred[4];
    pcvor mesto;

    if (sr_ucitano==1) return U_REDU; // ako je vec ucitano, nema potrebe ponavljati
    
    in=fopen(FILENAME,"rb");
    if (in==NULL) return GRESKA-1;

    KeySize=unos=fscanf(in,"poredi:%d %d %d %d\n",&poredi[0],&poredi[1],&poredi[2],&poredi[3]);

    while (!feof(in)) {
        c=fgetc(in);
	if (c=='\n') {
	  // obrada linije
	    k=s;
	    mesto=Mapa; podslovo=0;
	    while (sscanf(k,"0x%x%n",&slovo,&t)>0) {
		if (podslovo==1)  mesto=Nadji(&(mesto->i),slovo);
		else mesto=Nadji(&mesto,slovo);
		if (Mapa==NULL) Mapa=mesto;
		k+=t;
		while ((k[0]==' ') || (k[0]=='\t') || (k[0]==',')) {
		    if ((k[0]==',') && (mesto!=NULL)) {
			podslovo=1;
		    }
		    k++; // ignorisi razmake i zareze
		}
	    }
	    if (k[0]=='=') {
		k++;
		sscanf(k,"%d,%d,%d,%d",&vred[0],&vred[1],&vred[2],&vred[3]);
		if (mesto!=NULL) {
		  mesto->kljuc=0;
		  tr=0; 
		  do {
		    mesto->kljuc=(mesto->kljuc<<8)+((poredi[tr]<0)?(0xfe - vred[-poredi[tr]-1]):vred[poredi[tr]-1]);
		  } while (++tr<unos);
		}
	    } // inace nije pravilna linija, idi na sledecu
	  // spremi za sledeci
	    duz=1;
	    if (s!=NULL) free(s);
	    s=NULL;
	} else {
	    duz++;
	    s=(char *)realloc(s,duz);
	    s[duz-2]=c;
	    s[duz-1]=0;
	}
    }
    sr_ucitano=1;
    fclose(in);
    return U_REDU;
}

#define UCS_GRESKA     (-1)
#define UCS_NEPRAVILNO (-2)
#define UCS_NEPODRZAN  (-3)

typedef int ucs_t;

/* reads in UTF-8 character starting from s and returns it in int (ucs_t)
   s is also moved past the read character (so the next one can be read 
   sequentialy).
   Serious limit: allows at most 3-byte utf8-sequences (<0x10000, entire Unicode 2-byte range)
   Contains some basic checks for validity of characters:
    - valid first chars are 0x00--0x7F and 0xC0--0xEF (0xF0 implicates 4-byte sequence, see above)
    - valid secondary chars are in the range 0x80--0xBF
    - if there are ,,continuing'' chars missing, it will return UCS_NEPRAVILAN (UCS_INCORRECT)
    - different representations of same chars are allowed (as opposed to only shortest sequences
      allowed for a single char; eg. '/' can be written as 0x2f or 0xC0,0xAF or 0xE0,0x80,0xAF).
   If you would like to extend it to support a wider range of ISO-10646 set, add another
     ,,else if (t[0] < 0xF8) { broj=(ucs_t) (t[0]&0x7); ostalo=3; }''
   in front of final ,,else''. The variable ,,ostalo'' contains the number of remaining bytes,
   constant 0xF8 is upper limit for numbers (range is in binary 11110000--11110111, inclusive),
   and 0x7 is a bitmask to extract the 3 least significant bits.

   If there's something you don't understand, consult UTF-8 RFC (number?)
 */


/* prevodi prvi sledeci UTF-8 karakter iz stringa u UCS-4 karakter 
   i pomera pokazivac na sledeci karakter 
   UTF-8 dozvoljava da neki karakteri budu kodirani na vise nacina, a to se ovde
   tolerise, a ukoliko to predstavlja problem, programer mora obratiti paznju na 
   to (npr. '/' se moze zapisati kao UTF8 0x2f ili kao 0xC0,0xAF, 
   ili 0xE0,0x80,0xAF itd. pa se moze javiti problem pri proveri putanja i slicno)
   jedno resenje (najjednostavnije i najsigurnije) je izmeniti donju funkciju tako
   da ne prihvata nijednu kombinaciju osim najkrace, ali ovde nema potrebe za tim
 */

ucs_t utfslovo(char **s) {
    ucs_t broj=0;
    int ostalo;
    unsigned char *t;

    if ((s==NULL) || (*s==NULL)) { return UCS_GRESKA; }       // pozeljno je proveriti da s nije NULL pre poziva
    t = (*s);
    
    if (t[0] < 0x80 ) { broj=(ucs_t) t[0]; ostalo=0; }    // ASCII karakteri u jednom bajtu
    else if (t[0] < 0xC0) { return UCS_NEPRAVILNO; }       // Karakteri od 0x80--0xBF su dozvoljeni samo kao nastavci, ovo je prema tome nepravilan karakter
    else if (t[0] < 0xE0) { broj= (ucs_t) (t[0] & 0x1F); ostalo=1; }
    else if (t[0] < 0xF0) { broj= (ucs_t) (t[0] & 0xF);  ostalo=2; }
    else { // ovi nisu podrzani, pomeri na kraj ovog karaktera i vrati 0xFFFD
	t++;
	while ((t[0]>=0x80) && (t[0]<0xC0)) t++;
	return UCS_NEPODRZAN;
    }
    // Ukoliko vec nije izasao treba proci sve bajtove koji su preostali 
    // dok god su oni ,,nastavci'', tj. MSB su im '10'
    t++;
    while ((ostalo>0) && (t[0]>=0x80) && (t[0]<0xC0)) {
	broj<<=6;
	ostalo--;
	broj |= (t[0] & 0x3F);
	t++;
    }
    *s=t;
    if (ostalo != 0) return UCS_NEPRAVILNO; // dosao je do kraja a nije ceo karakter procitao
    return broj; // a *s sada sadrzi pokazivac na sledeci karakter
}


int my_strnncoll_srpski(char *s1,int len1, char *s2, int len2) {
    ucs_t sl1,sl2;
    int k1,k2; // kljucevi 1 i 2
    pcvor mapa,podslovo,temp;
    char *s,*o1=s1,*o2=s2;   // pocetne pozicije prvog i drugog

    ucitaj_bazu();
    if ((s1==NULL) || (s2==NULL)) return 0;
    do {
      /* Cita prvi kljuc */
      sl1=utfslovo(&s1); s=s1;
      mapa=nadji(Mapa,sl1); podslovo=mapa;
      sl2=utfslovo(&s);

      if ((mapa!=NULL) && (mapa->i!=NULL)) {
	mapa=podslovo->i;
	while ((podslovo!=NULL) && (podslovo->i!=NULL) && ((temp=nadji(mapa,sl2))!=NULL)) {
	  podslovo=temp;
	  mapa=podslovo->i; 
	  s1=s;
	  sl2=utfslovo(&s);
	}
      }
      if (podslovo!=NULL) k1=podslovo->kljuc;
      else k1=sl1;
  
      /* Cita drugi kljuc */
      sl1=utfslovo(&s2); s=s2;
      mapa=nadji(Mapa,sl1); podslovo=mapa;
      sl2=utfslovo(&s);
      if ((mapa!=NULL) && (mapa->i!=NULL)) {
	mapa=mapa->i;
	while ((podslovo!=NULL) && (podslovo->i!=NULL) && ((temp=nadji(mapa,sl2))!=NULL)) {
	  podslovo=temp;
	  mapa=podslovo->i;
	  s2=s;
	  sl2=utfslovo(&s);
	}
      }
      if (podslovo!=NULL) k2=podslovo->kljuc;
      else k2=sl1;
      
      if (k1!=k2) return k1-k2;
    } while ((k1==k2) && ((int)(s1-o1)<len1) && ((int)(s2-o2)<len2));
    return k1-k2;
}


int my_strcoll_srpski(char *s1, char *s2) {
  return my_strnncoll_srpski(s1,strlen(s1),s2,strlen(s2));
}



uchar NEAR ctype_srpski[257] =
{
  0,				/* For standard library */
  32,32,32,32,32,32,32,32,32,40,40,40,40,40,32,32,
  32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
  72,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
  132,132,132,132,132,132,132,132,132,132,16,16,16,16,16,16,
  16,129,129,129,129,129,129,1,1,1,1,1,1,1,1,1,
  1,1,1,1,1,1,1,1,1,1,1,16,16,16,16,16,
  16,130,130,130,130,130,130,2,2,2,2,2,2,2,2,2,
  2,2,2,2,2,2,2,2,2,2,2,16,16,16,16,32,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};

uchar NEAR to_lower_srpski[]=
{
  '\000','\001','\002','\003','\004','\005','\006','\007',
  '\010','\011','\012','\013','\014','\015','\016','\017',
  '\020','\021','\022','\023','\024','\025','\026','\027',
  '\030','\031','\032','\033','\034','\035','\036','\037',
  ' ',	 '!',	'"',   '#',   '$',   '%',   '&',   '\'',
  '(',	 ')',	'*',   '+',   ',',   '-',   '.',   '/',
  '0',	 '1',	'2',   '3',   '4',   '5',   '6',   '7',
  '8',	 '9',	':',   ';',   '<',   '=',   '>',   '?',
  '@',	 'a',	'b',   'c',   'd',   'e',   'f',   'g',
  'h',	 'i',	'j',   'k',   'l',   'm',   'n',   'o',
  'p',	 'q',	'r',   's',   't',   'u',   'v',   'w',
  'x',	 'y',	'z',   '[',   '\\',  ']',   '^',   '_',
  '`',	 'a',	'b',   'c',   'd',   'e',   'f',   'g',
  'h',	 'i',	'j',   'k',   'l',   'm',   'n',   'o',
  'p',	 'q',	'r',   's',   't',   'u',   'v',   'w',
  'x',	 'y',	'z',   '{',   '|',   '}',   '~',   '\177',
  (uchar) '\200',(uchar) '\201',(uchar) '\202',(uchar) '\203',(uchar) '\204',(uchar) '\205',(uchar) '\206',(uchar) '\207',
  (uchar) '\210',(uchar) '\211',(uchar) '\212',(uchar) '\213',(uchar) '\214',(uchar) '\215',(uchar) '\216',(uchar) '\217',
  (uchar) '\220',(uchar) '\221',(uchar) '\222',(uchar) '\223',(uchar) '\224',(uchar) '\225',(uchar) '\226',(uchar) '\227',
  (uchar) '\230',(uchar) '\231',(uchar) '\232',(uchar) '\233',(uchar) '\234',(uchar) '\235',(uchar) '\236',(uchar) '\237',
  (uchar) '\240',(uchar) '\241',(uchar) '\242',(uchar) '\243',(uchar) '\244',(uchar) '\245',(uchar) '\246',(uchar) '\247',
  (uchar) '\250',(uchar) '\251',(uchar) '\252',(uchar) '\253',(uchar) '\254',(uchar) '\255',(uchar) '\256',(uchar) '\257',
  (uchar) '\260',(uchar) '\261',(uchar) '\262',(uchar) '\263',(uchar) '\264',(uchar) '\265',(uchar) '\266',(uchar) '\267',
  (uchar) '\270',(uchar) '\271',(uchar) '\272',(uchar) '\273',(uchar) '\274',(uchar) '\275',(uchar) '\276',(uchar) '\277',
  (uchar) '\300',(uchar) '\301',(uchar) '\302',(uchar) '\303',(uchar) '\304',(uchar) '\305',(uchar) '\306',(uchar) '\307',
  (uchar) '\310',(uchar) '\311',(uchar) '\312',(uchar) '\313',(uchar) '\314',(uchar) '\315',(uchar) '\316',(uchar) '\317',
  (uchar) '\320',(uchar) '\321',(uchar) '\322',(uchar) '\323',(uchar) '\324',(uchar) '\325',(uchar) '\326',(uchar) '\327',
  (uchar) '\330',(uchar) '\331',(uchar) '\332',(uchar) '\333',(uchar) '\334',(uchar) '\335',(uchar) '\336',(uchar) '\337',
  (uchar) '\340',(uchar) '\341',(uchar) '\342',(uchar) '\343',(uchar) '\344',(uchar) '\345',(uchar) '\346',(uchar) '\347',
  (uchar) '\350',(uchar) '\351',(uchar) '\352',(uchar) '\353',(uchar) '\354',(uchar) '\355',(uchar) '\356',(uchar) '\357',
  (uchar) '\360',(uchar) '\361',(uchar) '\362',(uchar) '\363',(uchar) '\364',(uchar) '\365',(uchar) '\366',(uchar) '\367',
  (uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};

uchar NEAR to_upper_srpski[]=
{
  '\000','\001','\002','\003','\004','\005','\006','\007',
  '\010','\011','\012','\013','\014','\015','\016','\017',
  '\020','\021','\022','\023','\024','\025','\026','\027',
  '\030','\031','\032','\033','\034','\035','\036','\037',
  ' ',	 '!',	'"',   '#',   '$',   '%',   '&',   '\'',
  '(',	 ')',	'*',   '+',   ',',   '-',   '.',   '/',
  '0',	 '1',	'2',   '3',   '4',   '5',   '6',   '7',
  '8',	 '9',	':',   ';',   '<',   '=',   '>',   '?',
  '@',	 'A',	'B',   'C',   'D',   'E',   'F',   'G',
  'H',	 'I',	'J',   'K',   'L',   'M',   'N',   'O',
  'P',	 'Q',	'R',   'S',   'T',   'U',   'V',   'W',
  'X',	 'Y',	'Z',   '[',   '\\',  ']',   '^',   '_',
  '`',	 'A',	'B',   'C',   'D',   'E',   'F',   'G',
  'H',	 'I',	'J',   'K',   'L',   'M',   'N',   'O',
  'P',	 'Q',	'R',   'S',   'T',   'U',   'V',   'W',
  'X',	 'Y',	'Z',   '{',   '|',   '}',   '~',   '\177',
  (uchar) '\200',(uchar) '\201',(uchar) '\202',(uchar) '\203',(uchar) '\204',(uchar) '\205',(uchar) '\206',(uchar) '\207',
  (uchar) '\210',(uchar) '\211',(uchar) '\212',(uchar) '\213',(uchar) '\214',(uchar) '\215',(uchar) '\216',(uchar) '\217',
  (uchar) '\220',(uchar) '\221',(uchar) '\222',(uchar) '\223',(uchar) '\224',(uchar) '\225',(uchar) '\226',(uchar) '\227',
  (uchar) '\230',(uchar) '\231',(uchar) '\232',(uchar) '\233',(uchar) '\234',(uchar) '\235',(uchar) '\236',(uchar) '\237',
  (uchar) '\240',(uchar) '\241',(uchar) '\242',(uchar) '\243',(uchar) '\244',(uchar) '\245',(uchar) '\246',(uchar) '\247',
  (uchar) '\250',(uchar) '\251',(uchar) '\252',(uchar) '\253',(uchar) '\254',(uchar) '\255',(uchar) '\256',(uchar) '\257',
  (uchar) '\260',(uchar) '\261',(uchar) '\262',(uchar) '\263',(uchar) '\264',(uchar) '\265',(uchar) '\266',(uchar) '\267',
  (uchar) '\270',(uchar) '\271',(uchar) '\272',(uchar) '\273',(uchar) '\274',(uchar) '\275',(uchar) '\276',(uchar) '\277',
  (uchar) '\300',(uchar) '\301',(uchar) '\302',(uchar) '\303',(uchar) '\304',(uchar) '\305',(uchar) '\306',(uchar) '\307',
  (uchar) '\310',(uchar) '\311',(uchar) '\312',(uchar) '\313',(uchar) '\314',(uchar) '\315',(uchar) '\316',(uchar) '\317',
  (uchar) '\320',(uchar) '\321',(uchar) '\322',(uchar) '\323',(uchar) '\324',(uchar) '\325',(uchar) '\326',(uchar) '\327',
  (uchar) '\330',(uchar) '\331',(uchar) '\332',(uchar) '\333',(uchar) '\334',(uchar) '\335',(uchar) '\336',(uchar) '\337',
  (uchar) '\340',(uchar) '\341',(uchar) '\342',(uchar) '\343',(uchar) '\344',(uchar) '\345',(uchar) '\346',(uchar) '\347',
  (uchar) '\350',(uchar) '\351',(uchar) '\352',(uchar) '\353',(uchar) '\354',(uchar) '\355',(uchar) '\356',(uchar) '\357',
  (uchar) '\360',(uchar) '\361',(uchar) '\362',(uchar) '\363',(uchar) '\364',(uchar) '\365',(uchar) '\366',(uchar) '\367',
  (uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};

uchar NEAR sort_order_srpski[]=
{
  '\000','\001','\002','\003','\004','\005','\006','\007',
  '\010','\011','\012','\013','\014','\015','\016','\017',
  '\020','\021','\022','\023','\024','\025','\026','\027',
  '\030','\031','\032','\033','\034','\035','\036','\037',
  ' ',	 '!',	'"',   '#',   '$',   '%',   '&',   '\'',
  '(',	 ')',	'*',   '+',   ',',   '-',   '.',   '/',
  '0',	 '1',	'2',   '3',   '4',   '5',   '6',   '7',
  '8',	 '9',	':',   ';',   '<',   '=',   '>',   '?',
  '@',	 'A',	'B',   'C',   'D',   'E',   'F',   'G',
  'H',	 'I',	'J',   'K',   'L',   'M',   'N',   'O',
  'P',	 'Q',	'R',   'S',   'T',   'U',   'V',   'W',
  'X',	 'Y',	'Z',   '\\',  ']',   '[',   '^',   '_',
  'E',	 'A',	'B',   'C',   'D',   'E',   'F',   'G',
  'H',	 'I',	'J',   'K',   'L',   'M',   'N',   'O',
  'P',	 'Q',	'R',   'S',   'T',   'U',   'V',   'W',
  'X',	 'Y',	'Z',   '{',   '|',   '}',   'Y',   '\177',
  (uchar) '\200',(uchar) '\201',(uchar) '\202',(uchar) '\203',(uchar) '\204',(uchar) '\205',(uchar) '\206',(uchar) '\207',
  (uchar) '\210',(uchar) '\211',(uchar) '\212',(uchar) '\213',(uchar) '\214',(uchar) '\215',(uchar) '\216',(uchar) '\217',
  (uchar) '\220',(uchar) '\221',(uchar) '\222',(uchar) '\223',(uchar) '\224',(uchar) '\225',(uchar) '\226',(uchar) '\227',
  (uchar) '\230',(uchar) '\231',(uchar) '\232',(uchar) '\233',(uchar) '\234',(uchar) '\235',(uchar) '\236',(uchar) '\237',
  (uchar) '\240',(uchar) '\241',(uchar) '\242',(uchar) '\243',(uchar) '\244',(uchar) '\245',(uchar) '\246',(uchar) '\247',
  (uchar) '\250',(uchar) '\251',(uchar) '\252',(uchar) '\253',(uchar) '\254',(uchar) '\255',(uchar) '\256',(uchar) '\257',
  (uchar) '\260',(uchar) '\261',(uchar) '\262',(uchar) '\263',(uchar) '\264',(uchar) '\265',(uchar) '\266',(uchar) '\267',
  (uchar) '\270',(uchar) '\271',(uchar) '\272',(uchar) '\273',(uchar) '\274',(uchar) '\275',(uchar) '\276',(uchar) '\277',
  (uchar) '\300',(uchar) '\301',(uchar) '\302',(uchar) '\303',(uchar) '\304',(uchar) '\305',(uchar) '\306',(uchar) '\307',
  (uchar) '\310',(uchar) '\311',(uchar) '\312',(uchar) '\313',(uchar) '\314',(uchar) '\315',(uchar) '\316',(uchar) '\317',
  (uchar) '\320',(uchar) '\321',(uchar) '\322',(uchar) '\323',(uchar) '\324',(uchar) '\325',(uchar) '\326',(uchar) '\327',
  (uchar) '\330',(uchar) '\331',(uchar) '\332',(uchar) '\333',(uchar) '\334',(uchar) '\335',(uchar) '\336',(uchar) '\337',
  (uchar) '\340',(uchar) '\341',(uchar) '\342',(uchar) '\343',(uchar) '\344',(uchar) '\345',(uchar) '\346',(uchar) '\347',
  (uchar) '\350',(uchar) '\351',(uchar) '\352',(uchar) '\353',(uchar) '\354',(uchar) '\355',(uchar) '\356',(uchar) '\357',
  (uchar) '\360',(uchar) '\361',(uchar) '\362',(uchar) '\363',(uchar) '\364',(uchar) '\365',(uchar) '\366',(uchar) '\367',
  (uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};


/* strnxfrm replacement
   Arg: Destination buffer, source string, dest length and source length
   Ret: Converted string size
*/

int my_strnxfrm_srpski(char * dest, const char * src, int len, int srclen) {
    ucs_t sl1,sl2;
    int k; // kljuc
    int t; // temorary counter
    pcvor mapa,podslovo,temp;
    const char *s,*s1,*odr=dest;

    ucitaj_bazu();

    if ((src==NULL) || (dest==NULL)) return 0;
    s1=src;
    while ((len>=KeySize) && ((int)(s1-src)<srclen)) {
      /* Cita kljuc */
      sl1=utfslovo((char **)&s1); s=s1;
      mapa=nadji(Mapa,sl1); podslovo=mapa;
      sl2=utfslovo((char **)&s);

      if ((mapa!=NULL) && (mapa->i!=NULL)) {
	mapa=podslovo->i;
	while ((podslovo!=NULL) && (podslovo->i!=NULL) && ((temp=nadji(mapa,sl2))!=NULL)) {
	  podslovo=temp;
	  mapa=podslovo->i; 
	  s1=s;
	  sl2=utfslovo((char **)&s);
	}
      }
      if (podslovo!=NULL) k=podslovo->kljuc;
      else k=sl1;
  
      /* ISPRAVITI: treba da radi bar za sve 4 duzine, a ovako radi kada je ,,poredi:x y'' */
      for (t=0;t<KeySize;t++) {
	dest[t]=((k>>((KeySize-t-1)*8))&0xff);
	if (dest[t]!=(char)0xff) dest[t]++;
      }
      dest+=KeySize;
      len-=KeySize;
    };
    return (int)(dest-odr);
}

int my_strxfrm_srpski(char * dest, const char * src, int len) {
  return my_strnxfrm_srpski(dest,src,len,strlen(src));
}



/* Doslovno prepisano iz ctype-tis620.c */      /* Copied verbatim from ctype-tis620.c */
/* Trenutno ne radi kao sto zelim, pa   */      /* It's not working as I want it to,   */
/* ce se morati menjati.                */      /* so changes will be neccessary.      */
/* We just copy this function from opt_range.cc. No need to convert to
   thai2sortable string. min_str and max_str will be use for comparison and
   converted there. */
#define max_sort_chr ((char) 255)
#define wild_one '_'
#define wild_many '%'


my_bool my_like_range_srpski(const char *ptr, uint ptr_length, pchar escape,
		       uint res_length, char *min_str, char *max_str,
		       uint *min_length, uint *max_length)
{
  const char *end=ptr+ptr_length;
  char *min_org=min_str;
  char *min_end=min_str+res_length;

  for (; ptr != end && min_str != min_end ; ptr++)
  {
    if (*ptr == escape && ptr+1 != end)
    {
      ptr++;					// Skipp escape
      *min_str++= *max_str++ = *ptr;
      continue;
    }
    if (*ptr == wild_one)			// '_' in SQL
    {
      *min_str++='\0';				// This should be min char
      *max_str++=max_sort_chr;
      continue;
    }
    if (*ptr == wild_many)			// '%' in SQL
    {
      *min_length= (uint) (min_str - min_org);
      *max_length=res_length;
      do {
	*min_str++ = ' ';			// Because if key compression
	*max_str++ = max_sort_chr;
      } while (min_str != min_end);
      return 0;
    }
    *min_str++= *max_str++ = *ptr;
  }
  *min_length= *max_length = (uint) (min_str - min_org);

  while (min_str != min_end)
    *min_str++ = *max_str++ = ' ';		// Because if key compression
  return 0;
}
