//**************************************************************************
//*                     This file is part of the                           *
//*                      Mpxplay - audio player.                           *
//*                  The source code of Mpxplay is                         *
//*        (C) copyright 1998-2006 by PDSoft (Attila Padar)                *
//*                    http://mpxplay.cjb.net                              *
//*                  email: mpxplay@freemail.hu                            *
//**************************************************************************
//*  This program 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.                  *
//*  Please contact with the author (with me) if you want to use           *
//*  or modify this source.                                                *
//**************************************************************************
//function: string handling

#include <string.h>
#include "newfunc.h"

#ifdef __DOS__
extern unsigned int is_lfn_support,uselfn;
#endif

unsigned int pds_strcpy(char *dest,char *src)
{
 char *begin;
 if(!dest || !src)
  return 0;
 begin=src;
 do{
  *dest=*src;
  if(!src[0])
   break;
  dest++;src++;
 }while(1);
 return (src-begin); // returns the lenght of string, not the target pointer!
}

unsigned int pds_strmove(char *dest,char *src)
{
 unsigned int len,count;
 if(!dest || !src)
  return 0;
 if(dest<src)
  return pds_strcpy(dest,src);
 count=len=pds_strlen(src)+1;
 src+=len;
 dest+=len;
 do{
  src--;dest--;
  *dest=*src;
 }while(--count);
 return len; // returns the lenght of string
}

unsigned int pds_strncpy(char *dest,char *src,unsigned int maxlen)
{
 char *begin;
 if(!dest || !src || !maxlen)
  return 0;
 begin=src;
 do{
  *dest=*src;
  if(!src[0])
   break;
  dest++;src++;
 }while(--maxlen);
 return (src-begin); // returns the lenght of string, not the target pointer!
}

unsigned int pds_strcat(char *strp1,char *strp2)
{
 if(!strp1 || !strp2)
  return 0;
 return pds_strcpy(&strp1[pds_strlen(strp1)],strp2);
}

int pds_strcmp(char *strp1,char *strp2)
{
 char c1,c2;
 if(!strp1 || !strp2)
  return 1;
 do{
  c1=*strp1;
  c2=*strp2;
  if(c1!=c2)
   if(c1<c2)
    return -1;
   else
    return 1;
  strp1++;strp2++;
 }while(c1 && c2);
 return 0;
}

int pds_stricmp(char *strp1,char *strp2)
{
 char c1,c2;
 if(!strp1 || !strp1[0])
  if(strp2 && strp2[0])
   return -1;
  else
   return 0;
 if(!strp2 || !strp2[0])
  if(strp1 && strp1[0])
   return 1;
  else
   return 0;

 do{
  c1=*strp1++;
  c2=*strp2++;
  if(c1!=c2){
   if(c1>='a' && c1<='z')  // convert to uppercase
    c1-=32;                // c1-='a'-'A'
   if(c2>='a' && c2<='z')
    c2-=32;
   if(c1!=c2)
    if(c1<c2)
     return -1;
    else
     return 1;
  }
 }while(c1 && c2);
 return 0;
}

int pds_strricmp(char *str1,char *str2)
{
 char *pstr1=str1,*pstr2=str2;

 if(!str1 || !str2)
  return 1;
 while(pstr1[0]!=0)
  pstr1++;
 while(pstr1[0]==0 || pstr1[0]==32)
  pstr1--;
 if(pstr1<=str1)
  return 1;
 while(pstr2[0]!=0)
  pstr2++;
 while(pstr2[0]==0 || pstr2[0]==32)
  pstr2--;
 if(pstr2<=str2)
  return -1;
 while(pstr1>=str1 && pstr2>=str2){
  char c1=pstr1[0];
  char c2=pstr2[0];
  if(c1>='a' && c1<='z')  // convert to uppercase
   c1-=32;
  if(c2>='a' && c2<='z')
   c2-=32;
  if(c1!=c2){
   if(c1<c2)
    return -1;
   else
    return 1;
  }
  pstr1--;pstr2--;
 }
 return 0;
}

int pds_strlicmp(char *str1,char *str2)
{
 char c1,c2;
 if(!str1 || !str2)
  return 1;
 do{
  c1=*str1;
  c2=*str2;
  if(!c1 || !c2)
   break;
  if(c1!=c2){
   if(c1>='a' && c1<='z')  // convert to uppercase
    c1-=32;
   if(c2>='a' && c2<='z')
    c2-=32;
   if(c1!=c2){
    if(c1<c2)
     return -1;
    else
     return 1;
   }
  }
  str1++;str2++;
 }while(1);
 return 0;
}

int pds_strncmp(char *strp1,char *strp2,unsigned int counter)
{
 char c1,c2;
 if(!strp1 || !strp2)
  return 1;
 if(!counter)
  return 0;
 do{
  c1=*strp1;
  c2=*strp2;
  if(c1!=c2)
   if(c1<c2)
    return -1;
   else
    return 1;
  strp1++;strp2++;
 }while(c1 && c2 && --counter);
 return 0;
}

int pds_strnicmp(char *strp1,char *strp2,unsigned int counter)
{
 char c1,c2;
 if(!strp1 || !strp2)
  return 1;
 if(!counter)
  return 0;
 do{
  c1=*strp1;
  c2=*strp2;
  if(c1!=c2){
   if(c1>='a' && c1<='z')
    c1-=32;
   if(c2>='a' && c2<='z')
    c2-=32;
   if(c1!=c2){
    if(c1<c2)
     return -1;
    else
     return 1;
   }
  }
  strp1++;strp2++;
 }while(c1 && c2 && --counter);
 return 0;
}

unsigned int pds_strlen(char *strp)
{
 char *beginp;
 if(!strp || !strp[0])
  return 0;
 beginp=strp;
 do{
  strp++;
 }while(*strp);
 return (unsigned int)(strp-beginp);
}

unsigned int pds_strlenc(char *strp,char seek)
{
 char *lastnotmatchp,*beginp;

 if(!strp || !strp[0])
  return 0;

 lastnotmatchp=NULL;
 beginp=strp;
 do{
  if(*strp!=seek)
   lastnotmatchp=strp;
  strp++;
 }while(*strp);

 if(!lastnotmatchp)
  return 0;
 return (unsigned int)(lastnotmatchp-beginp+1);
}

char *pds_strchr(char *strp,char seek)
{
 if(!strp || !strp[0])
  return NULL;
 do{
  if(*strp==seek)
   return strp;
  strp++;
 }while(*strp);
 return NULL;
}

char *pds_strrchr(char *strp,char seek)
{
 char *foundp=NULL,curr;

 if(!strp)
  return foundp;

 curr=*strp;
 if(!curr)
  return foundp;
 do{
  if(curr==seek)
   foundp=strp;
  strp++;
  curr=*strp;
 }while(curr);
 return foundp;
}

char *pds_strnchr(char *strp,char seek,unsigned int len)
{
 if(!strp || !strp[0] || !len)
  return NULL;
 do{
  if(*strp==seek)
   return strp;
  strp++;
 }while(*strp && --len);
 return NULL;
}

char *pds_strstr(char *s1,char *s2)
{
 if(s1 && s2 && s2[0]){
  char c20=*s2;
  do{
   char c1=*s1;
   if(!c1)
    break;
   if(c1==c20){        // search the first occurence
    char *s1p=s1,*s2p=s2;
    do{                 // compare the strings (part of s1 with s2)
     char c2=*(++s2p);
     if(!c2)
      return s1;
     c1=*(++s1p);
     if(!c1)
      return NULL;
     if(c1!=c2)
      break;
    }while(1);
   }
   s1++;
  }while(1);
 }
 return NULL;
}

char *pds_strstri(char *s1,char *s2)
{
 if(s1 && s2 && s2[0]){
  char c20=*s2;
  if(c20>='a' && c20<='z')  // convert to uppercase (first character of s2)
   c20-=32;
  do{
   char c1=*s1;
   if(!c1)
    break;
   if(c1>='a' && c1<='z')  // convert to uppercase (current char of s1)
    c1-=32;
   if(c1==c20){        // search the first occurence
    char *s1p=s1,*s2p=s2;
    do{                 // compare the strings (part of s1 with s2)
     char c2;
     s2p++;
     c2=*s2p;
     if(!c2)
      return s1;
     s1p++;
     c1=*s1p;
     if(!c1)
      return NULL;
     if(c1>='a' && c1<='z')  // convert to uppercase
      c1-=32;
     if(c2>='a' && c2<='z')  // convert to uppercase
      c2-=32;
     if(c1!=c2)
      break;
    }while(1);
   }
   s1++;
  }while(1);
 }
 return NULL;
}

char *pds_strcutspc(char *strp)
{
 if(!strp)
  return NULL;
 while(strp[0] && (strp[0]==32))
  strp++;
 if(strp[0]){
  char *locstrp=strp;
  while(locstrp[1])
   locstrp++;
  while(locstrp[0]==32){
   locstrp[0]=0;
   locstrp--;
  }
  return strp;
 }
 return NULL;
}

// does str contains uppercase chars only?
unsigned int pds_chkstr_uppercase(char *str)
{
 if(!str || !str[0])
  return 0;
 do{
  char c=*str;
  if((c>='a') && (c<='z')) // found lowercase char
   return 0;
  if(c>=128) // found non-us char
   return 0;
  str++;
 }while(*str);
 return 1;
}

void pds_ltoa(int value,char *ltoastr)
{
 static unsigned int dekadlim[10]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
 unsigned int dekad;

 dekad=1;
 while(value>dekadlim[dekad] && dekad<10)
  dekad++;
 do{
  *ltoastr++=(value/dekadlim[dekad-1])%10+0x30;
 }while(--dekad);
 *ltoastr=0;
}

/*void pds_ltoa16(int value,char *ltoastr)
{
 static int dekadlim[9]={1,0x10,0x100,0x1000,0x10000,0x100000,0x1000000,0x10000000,0x100000000};
 int dekad;

 dekad=1;
 while(value>dekadlim[dekad] && dekad<9)
  dekad++;
 do{
  int number=(value/dekadlim[dekad-1])%16;
  if(number>9)
   ltoastr[0]=number-10+'A';
  else
   ltoastr[0]=number+'0';
  dekad--;
  ltoastr++;
 }while(dekad>0);
 ltoastr[0]=0;
}*/

long pds_atol(char *strp)
{
 long number=0,negative=0;

 if(!strp)
  return number;

 while(*strp==' ')
  strp++;

 if(*strp=='-'){
  negative=1;
  strp++;
 }else{
  if(*strp=='+')
   strp++;
 }

 do{
  if((strp[0]<'0') || (strp[0]>'9'))
   break;
  number=(number<<3)+(number<<1);     // number*=10;
  number+=(unsigned long)strp[0]-'0';
  strp++;
 }while(1);
 if(negative)
  number=-number;
 return number;
}

long pds_atol16(char *strp)
{
 unsigned long number=0;

 if(!strp)
  return number;

 while(*strp==' ')
  strp++;

 if(*((unsigned short *)strp)==(((unsigned short)'x'<<8)|(unsigned short)'0'))
  strp+=2;

 do{
  char c=*strp++;
  if(c>='0' && c<='9')
   c-='0';
  else
   if(c>='a' && c<='f')
    c-=('a'-10);
   else
    if(c>='A' && c<='F')
     c-=('A'-10);
    else
     break;

  number<<=4;     // number*=16;
  number+=(unsigned long)c;
 }while(1);

 return number;
}

//-----------------------------------------------------------------------
// some filename/path routine (string handling only, no DOS calls)
char *pds_getfilename_from_fullname(char *fullname)
{
 char *filenamep;
 filenamep=pds_strrchr(fullname,PDS_DIRECTORY_SEPARATOR_CHAR);
 if(filenamep)
  filenamep++;
 else{
  filenamep=fullname;
  if(filenamep[1]==':' && filenamep[2]) // if no filename, it gives back drive-name (ie: C:) ! (if exists) (required for playlist-editor/directory-browser and for some LCD items)
   filenamep+=2;
 }
 return filenamep;
}

void pds_getfilename_noext_from_fullname(char *strout,char *fullname)
{
 char *filename=pds_getfilename_from_fullname(fullname);
 char *extension=pds_strrchr(filename,'.');
 if(extension>filename){
  unsigned int len=extension-filename;
  pds_strncpy(strout,filename,len);
  strout[len]=0;
 }else
  pds_strcpy(strout,filename);
}

char *pds_getpath_from_fullname(char *path,char *fullname)
{
 char *filenamep;
 pds_strcpy(path,fullname);
 filenamep=pds_strrchr(path,PDS_DIRECTORY_SEPARATOR_CHAR);
 if(filenamep){
  if(path[1]==':' && filenamep==(path+2)) // c:\\filename.xxx
   filenamep[1]=0;
  else
   filenamep[0]=0;                        // c:\\subdir\\filename.xxx
  filenamep++;
 }else{
  filenamep=pds_strchr(path,':');
  if(filenamep)
   *(++filenamep)=0;
  else{
   filenamep=path;
   *path=0;
  }
 }
 filenamep=fullname+(filenamep-path);
 return filenamep;
}

int pds_getdrivenum_from_path(char *path)
{
 // a=0 b=1 c=2 ...
 if(path[1]==':'){
  char d=path[0];
  if(d>='a' && d<='z')
   return (d-'a');
  if(d>='A' && d<='Z')
   return (d-'A');
 }
 return -1;
}

unsigned int pds_fullpath_check(char *path)
{
 char drive;
 if(!path || !path[0])
  return 0;
 if(path[1]!=':' && path[2]!=PDS_DIRECTORY_SEPARATOR_CHAR)
  return 0;

 drive=path[0];
 if(!(drive>='a' && drive<='z') && !(drive>='A' && drive<='Z'))
  return 0;
 if(strstr(path,".."))
  return 0;
 return 1;
}

unsigned int pds_filename_cmp_mask(char *fullname,char *mask)
{
 unsigned int match;
 char *fn,*fe,*mn,*me;

 if(!fullname || !fullname[0] || !mask || !mask[0])
  return 0;
 if(pds_strcmp(mask,"*.*")==0 || pds_strcmp(mask,"*.?*")==0)
  return 1;

 fn=pds_getfilename_from_fullname(fullname);
 if(!fn)
  return 0;
 fe=pds_strrchr(fn,'.');
 if(fe)
  fe++;

 mn=mask;
 me=pds_strrchr(mn,'.');
 if(me)
  me++;

 match=1;
 while(fn[0] && (!fe || (fn<fe))){ // check filename (without extension)
  //fprintf(stdout,"fn:%c mn:%c\n",fn[0],mn[0]);
  if(!mn[0] || (me && mn>=me)){
   match=0;
   break;
  }
  if(mn[0]=='*')  // ie: track*
   break;
  if(mn[0]!='?'){
   char cf,cm;
   cf=fn[0];
   if(cf>='a' && cf<='z')
    cf-='a'-'A';
   cm=mn[0];
   if(cm>='a' && cm<='z')
    cm-='a'-'A';
   if(cf!=cm){
    match=0;
    break;
   }
  }
  fn++;mn++;
 }

 if(match && fe && me){ // check extension
  //fprintf(stdout,"fe:%c me:%c\n",fe[0],me[0]);
  while(fe[0]){
   if(!me[0]){
    match=0;
    break;
   }
   if(me[0]=='*')
    break;
   if(me[0]!='?'){
    char cf,cm;
    cf=fe[0];
    if(cf>='a' && cf<='z')
     cf-='a'-'A';
    cm=me[0];
    if(cm>='a' && cm<='z')
     cm-='a'-'A';
    if(cf!=cm){
     match=0;
     break;
    }
   }
   fe++;me++;
  }
 }

 return match;
}

//limit short pathes\filenames to 8.3
void pds_sfn_limit(char *fn)
{
#ifdef __DOS__
 char *nextdir,*fn_save;
 if((is_lfn_support && uselfn) || !fn || !fn[0])
  return;
 fn_save=fn;
 do{
  char *ext;
  unsigned int alen,flen,elen;
  nextdir=pds_strchr(fn,PDS_DIRECTORY_SEPARATOR_CHAR);
  if(nextdir)
   alen=nextdir-fn;
  else
   alen=pds_strlen(fn);
  ext=pds_strnchr(fn,'.',alen);
  if(ext){
   flen=ext-fn;
   elen=alen-flen-1;
  }else{
   flen=alen;
   elen=0;
  }
  if(elen>3){
   if(nextdir)
    pds_strcpy(&ext[4],nextdir);
   else
    ext[4]=0;
  }
  if(flen>8){
   if(ext)
    pds_strcpy(&fn[8],ext);
   else if(nextdir)
    pds_strcpy(&fn[8],nextdir);
   else
    fn[8]=0;
  }
  fn=nextdir+1;
 }while(nextdir);
 strupr(fn_save);
#endif
}
