/*
	WARNING: This file was generated by dkct.
	Changes you make here will be lost if dkct is run again!
	You should modify the original source and run dkct on it.
	Original source: dk3str.ctr
*/

/*
Copyright (C) 2011-2013, Dirk Krause

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above opyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.
* Neither the name of the author nor the names of contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**	@file dk3str.c The dk3str module.
*/


#line 2197 "dk3str.ctr"

#include "dk3all.h"






#line 2203 "dk3str.ctr"


/*
	8-bit characters
	----------------
*/

/**	The set of whitespace characters.
*/
static char const dk3str_c8_def_whsp[] = { " \t\r\n" };

/**	The current directory.
*/
static char const dk3str_c8_dot[] = { "." };

/**	The parent directory.
*/
static char const dk3str_c8_dot_dot[] = { ".." };

/**	File name separator.
*/
static char const dk3str_c8_fnsep[] = {
#if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
"\\"
#else
"/"
#endif
};


/**	Keywords to set boolean values.
*/
static char const * const dk3str_c8_bool_kw[] = {
  "0",
  "n$o",
  "of$f",
  "f$alse",
  "-",
  "+",
  "1",
  "y$es",
  "on",
  "ok",
  "t$rue",
  NULL
};

/**	Index of first "true" entry in \a dk3str_c8_bool_kw.
*/
#define	INDEX_OF_FIRST_BOOLEAN_TRUE 5


#if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
/**	File name separator character.
*/
#define	FNS_C8		'\\'
/**	Not the file name separator character.
*/
#define	NO_FNS_C8	'/'
#else
/**	File name separator character.
*/
#define	FNS_C8		'/'
/**	Not the file name separator character.
*/
#define	NO_FNS_C8	'\\'
#endif



char *
dk3str_c8_get_suffix(char const *s)
{
  char *back = NULL;
  char const *ptr;
  if(s) {
    ptr = s;
    while(*ptr) {
      if(*ptr == '.') {
        back = (char *)ptr;
      } else {
	if(*ptr == FNS_C8) {
	  back = NULL;
	}
      }
      ptr++;
    }
  }
  return back;
}



/**	Get string length.
*/
#define	STRLEN(s)	dk3str_c8_len_fb(s)

#if 0
#if DK3_HAVE_STRLEN
#ifdef __cplusplus
#define STRLEN(s) dk3str_c8_len_fb(s)
#else
#define STRLEN(s) strlen(s)
#endif
#else
#define STRLEN(s) dk3str_c8_len_fb(s)
#endif
#endif


/**	Compare two strings.
*/
#define	STRCMP(a,b)	dk3str_c8_cmp_fb(a,b)

#if 0
#if DK3_HAVE_STRCMP
#ifdef __cplusplus
#define STRCMP(a,b) dk3str_c8_cmp_fb(a,b)
#else
#define STRCMP(a,b) strcmp(a,b)
#endif
#else
#define STRCMP(a,b) dk3str_c8_cmp_fb(a,b)
#endif
#endif


/**	Compare two strings, use only a given number of characters.
*/
#define	STRNCMP(a,b,n)	dk3str_c8_ncmp(a,b,n)

#if 0
#if DK3_HAVE_STRNCMP
#ifdef __cplusplus
#define STRNCMP(a,b,n) dk3str_c8_ncmp(a,b,n)
#else
#define STRNCMP(a,b,n) strncmp(a,b,n)
#endif
#else
#define STRNCMP(a,b,n) dk3str_c8_ncmp(a,b,n)
#endif
#endif


/**	Case-insensitive string comparison.
*/
#define	STRICMP(a,b)	dk3str_c8_casecmp_fb(a,b)

#if 0
#if DK3_HAVE_STRCASECMP
#ifdef __cplusplus
#define STRICMP(a,b) dk3str_c8_casecmp_fb(a,b)
#else
#define STRICMP(a,b) strcasecmp(a,b)
#endif
#else
#if DK3_HAVE_STRICMP
#ifdef __cplusplus
#define STRICMP(a,b) dk3str_c8_casecmp_fb(a,b)
#else
#define STRICMP(a,b) stricmp(a,b)
#endif
#else
#define STRICMP(a,b) dk3str_c8_casecmp_fb(a,b)
#endif
#endif
#endif



/**	Copy string.
*/
#define	STRCPY(a,b)	dk3str_c8_cpy_fb(a,b)

#if 0
#if DK3_HAVE_STRCPY
#ifdef __cplusplus
#define STRCPY(a,b) dk3str_c8_cpy_fb(a,b)
#else
#define STRCPY(a,b) strcpy(a,b)
#endif
#else
#define STRCPY(a,b) dk3str_c8_cpy_fb(a,b)
#endif
#endif


/**	Concatenate two strings.
*/
#define	STRCAT(d,s)	dk3str_c8_cat_fb(d,s)

#if 0
#if DK3_HAVE_STRCAT
#ifdef __cplusplus
#define STRCAT(d,s) dk3str_c8_cat_fb(d,s)
#else
#define STRCAT(d,s) strcat(d,s)
#endif
#else
#define STRCAT(d,s) dk3str_c8_cat_fb(d,s)
#endif
#endif


/**	Find character in a string.
*/
#define	STRCHR(s,c)	dk3str_c8_chr_fb(s,c)

#if 0
#if DK3_HAVE_STRCHR
#ifdef __cplusplus
#define STRCHR(s,c) dk3str_c8_chr_fb(s,c)
#else
#define STRCHR(s,c) strchr(s,c)
#endif
#else
#define STRCHR(s,c) dk3str_c8_chr_fb(s,c)
#endif
#endif


/**	Find rightmost position of character in a string.
*/
#define STRRCHR(s,c)	dk3str_c8_rchr_fb(s,c)

#if 0
#if DK3_HAVE_STRRCHR
#ifdef __cplusplus
#define STRRCHR(s,c) dk3str_c8_rchr_fb(s,c)
#else
#define STRRCHR(s,c) strrchr(s,c)
#endif
#else
#define STRRCHR(s,c) dk3str_c8_rchr_fb(s,c)
#endif
#endif


char
dk3str_c8_tolower(char c)
{
  char back;		/* Function result. */
  back = c;
  if((back >= 'A') && (back <= 'Z')) {
    back = 'a' + (back - 'A');
  }
  return back;
}



char
dk3str_c8_toupper(char c)
{
  char back;		/* Function result. */
  back = c;
  if((back >= 'a') && (back <= 'z')) {
    back = 'A' + (back - 'a');
  }
  return back;
}



char *
dk3str_c8_chr_fb(char const *s, char c)
{
  register char *back;		/* Function result. */
  register char const *ptr;	/* Pointer to traverse s. */
  register char chr;		/* Register copy of c. */
  back = NULL; ptr = s; chr = c;
  while((*ptr) && (back == NULL)) {
    if(*ptr == chr) { back = (char *)ptr; } else { ptr++; }
  }
  return back;
}



char *
dk3str_c8_chr(char const *s, char c)
{
  char *back = NULL;		/* Function result. */
  if(s) {
    back = STRCHR(s,c);
  }
  return back;
}



char *
dk3str_c8_rchr_fb(char const *s, char c)
{
  register char *back;		/* Function result. */
  register char const *ptr;	/* Pointer to traverse s. */
  register char chr;		/* Register copy of c. */
  back = NULL; ptr = s; chr = c;
  while(*ptr) {
    if(*ptr == chr) { back = (char *)ptr; }
    ptr++;
  }
  return back;
}



char *
dk3str_c8_rchr(char const *s, char c)
{
  char *back = NULL;		/* Function result. */
  if(s) {
    back = STRRCHR(s,c);
  }
  return back;
}



size_t
dk3str_c8_len_fb(char const *s)
{
  register size_t back;		/* Function result. */
  register char const *ptr;	/* Pointer to traverse s. */
  back = 0; ptr = s;
  while(*(ptr++)) back++;
  return back;
}



size_t
dk3str_c8_len(char const *s)
{
  size_t back = 0;		/* Function result. */
  if(s) {
    back = STRLEN(s);
  }
  return back;
}



char *
dk3str_c8_dup_app(char const *s, dk3_app_t *app)
{
  char		*back = NULL;	/* Function result. */
  size_t	l;		/* String length. */
  if(s) {
    l = STRLEN(s) ;
    l++;
    if(l) {
      if(app) { back = (char *)dk3mem_malloc_app(l, app); }
      else { back = (char *)dk3mem_malloc(l); }
      if(back) {
	STRCPY(back,s) ;
      }
    } else {
      if(app) {
        /* String too long! */
	dk3app_log_i1(app, DK3_LL_ERROR, 108);
      }
    }
  }
  return back;
}



int
dk3str_c8_cmp_fb(char const *s1, char const *s2)
{
  register int back;		/* Function result. */
  register char const *p1;	/* Pointer to traverse s1. */
  register char const *p2;	/* Pointer to traverse s2. */
  register int  cc;		/* Flag: Can continue. */
  back = 0; p1 = s1; p2 = s2; cc = 1;
  while((cc) && (back == 0)) {
    if(*p1 > *p2) {
      back = 1;
    } else {
      if(*p1 < *p2) {
        back = -1;
      } else {
        if((*p1) && (*p2)) {
	  p1++; p2++;
	} else {
	  cc = 0;
	}
      }
    }
  }
  return back;
}



int
dk3str_c8_cmp(char const *s1, char const *s2)
{
  int back = 0;		/* Function result. */
  if(s1) {
    if(s2) {
#if DK3_HAVE_STRCMP
      back = strcmp(s1, s2);
      if(back >  1) back =  1;
      if(back < -1) back = -1;
#else
      back = dk3str_c8_cmp_fb(s1, s2);
#endif
    } else {
      back = 1;
    }
  } else {
    if(s2) {
      back = -1;
    }
  }
  return back;
}



int
dk3str_c8_ncmp_fb(char const *s1, char const *s2, size_t n)
{
  register int back;		/* Function result. */
  register char const *p1;	/* Pointer to traverse s1. */
  register char const *p2;	/* Pointer to traverse s2. */
  register size_t max;		/* Register copy of n. */
  register size_t used;		/* Number of chars already used. */
  back = 0; p1 = s1; p2 = s2; max = n; used = 0;
  while((used < max) && (back == 0)) {
    if(*p1 > *p2) {
      back = 1;
    } else {
      if(*p1 < *p2) {
        back = -1;
      } else {
        if((*p1) && (*p2)) {
	  p1++; p2++; used++;
	} else {
	  used = max;
	}
      }
    }
  }
  return back;
}



int
dk3str_c8_ncmp(char const *s1, char const *s2, size_t n)
{
  int back = 0;
  if(s1) {
    if(s2) {
      if(n) {
#if DK3_HAVE_STRNCMP
	back = strncmp(s1, s2, n);
	if(back >  1) back =  1;
	if(back < -1) back = -1;
#else
	back = dk3str_c8_ncmp_fb(s1, s2, n);
#endif
      }
    } else back = 1;
  } else {
    if(s2) back = -1;
  }
  return back;
}



int
dk3str_c8_casecmp_fb(char const *s1, char const *s2)
{
  register int back;		/* Function result. */
  register char const *p1;	/* Pointer to traverse s1. */
  register char const *p2;	/* Pointer to traverse s2. */
  register char c1;		/* Current character from s1. */
  register char c2;		/* Current character from s2. */
  register int cc;		/* Flag: Can continue. */
  back = 0; p1 = s1; p2 = s2; cc = 1;
  while((cc) && (back == 0)) {
    c1 = *p1; c2 = *p2;
    if((c1 >= 'A') && (c1 <= 'Z')) { c1 = 'a' + (c1 - 'A'); }
    if((c2 >= 'A') && (c2 <= 'Z')) { c2 = 'a' + (c2 - 'A'); }
    if(c1 > c2) {
      back = 1;
    } else {
      if(c1 < c2) {
        back = -1;
      } else {
        if((c1) && (c2)) {
	  p1++; p2++;
	} else {
	  cc = 0;
	}
      }
    }
  }
  return back;
}



int
dk3str_c8_casecmp(char const *s1, char const *s2)
{
  int back = 0;			/* Function result. */
  if(s1) {
    if(s2) {
#if DK3_ON_WINDOWS
      back = _stricmp(s1, s2);
      if(back >  1) back =  1;
      if(back < -1) back = -1;
#else
#if DK3_HAVE_STRCASECMP
      back = strcasecmp(s1, s2);
      if(back >  1) back =  1;
      if(back < -1) back = -1;
#else
#if DK3_HAVE_STRICMP
      back = stricmp(s1, s2);
      if(back >  1) back =  1;
      if(back < -1) back = -1;
#else
      back = dk3str_c8_casecmp_fb(s1, s2);
#endif
#endif
#endif
    } else back = 1;
  } else {
    if(s2) back = -1;
  }
  return back;
}



void
dk3str_c8_cpy_fb(char *d, char const *s)
{
  register char *dp;		/* Destination buffer pointer. */
  register char const *sp;	/* Source buffer pointer. */
  register char x;
  dp = d; sp = s;
  while(*sp) { x = *(sp++); *(dp++) = x; }
  *dp = '\0';
}



void
dk3str_c8_cpy(char *d, char const *s)
{
  if((d) && (s)) {
    STRCPY(d,s);
  }
}



void
dk3str_c8_ncpy_fb(char *d, char const *s, size_t n)
{
  register char *dp;		/* Destination buffer pointer. */
  register char const *sp;	/* Source buffer pointer. */
  register size_t max;		/* Register copy of n. */
  register size_t used;		/* Number of characters already copied. */
  register char	  x;
  dp = d; sp = s; max = n; used = 0;
  while((*sp) && (used < max)) { x = *(sp++); *(dp++) = x;  used++; }
  if(used < max) { *dp = '\0'; }
  else		 { d[max - 1] = '\0'; }
}



void
dk3str_c8_ncpy(char *d, char const *s, size_t n)
{
  if((d) && (s) && (n)) {
#if DK3_HAVE_STRNCPY
    strncpy(d, s, n);
    d[n - 1] = '\0';
#else
    dk3str_c8_ncpy_fb(d, s, n);
#endif
  }
}



void
dk3str_c8_cat_fb(char *d, char const *s)
{
  register char *dp;		/* Destination buffer pointer. */
  register char const *sp;	/* Source buffer pointer. */
  register char x;
  dp = d; sp = s;
  while(*dp) dp++;
  while(*sp) { x = *(sp++); *(dp++) = x; }
  *dp = '\0';
}



void
dk3str_c8_cat(char *d, char const *s)
{
  if((d) && (s)) {
    STRCAT(d,s);
  }
}



int
dk3str_c8_array_index(char const * const *a, char const *s, int c)
{
  int back = -1;		/* Function result. */
  int ci;			/* Current array index for test. */
  char const * const *ap;	/* Pointer to traverse array a. */
  if((a) && (s)) {
    ap = a; ci = 0;
    while((*ap) && (back == -1)) {
      if(c) {
        if(dk3str_c8_cmp(*ap, s) == 0) back = ci;
      } else {
        if(dk3str_c8_casecmp(*ap, s) == 0) back = ci;
      }
      if(back == -1) { ap++; ci++; }
    }
  }
  return back;
}



char *
dk3str_c8_start(char const *str, char const *whsp)
{
  char *back = NULL;	/* Function result. */
  char const *ptr;	/* Pointer to traverse str. */
  char const *wh;	/* Whitespaces set. */
  

#line 2853 "dk3str.ctr"
  if(str) {
    wh = (whsp ? whsp : dk3str_c8_def_whsp);
    ptr = str;
    while((*ptr) && (!(back))) {
      if(dk3str_c8_chr(wh,*ptr)) {
	ptr++;
      } else {
	back = (char *)ptr;
      }
    }
  } 

#line 2864 "dk3str.ctr"
  return back;
}



void
dk3str_c8_chomp(char *str, char const *whsp)
{
  char const *wh;	/* Whitespaces set to use. */
  char *ptr;		/* Pointer to traverse str. */
  char *x;		/* Start position of final space sequence. */
  

#line 2876 "dk3str.ctr"
  if(str) {
    wh = (whsp ? whsp : dk3str_c8_def_whsp);
    x = NULL; ptr = str;
    while(*ptr) {
      if(dk3str_c8_chr(wh, *ptr)) {
	if(!(x)) { x = ptr; }
      } else {
	x = NULL;
      }
      ptr++;
    }
    if(x) { *x = '\0'; }
  }
  

#line 2890 "dk3str.ctr"
}



void
dk3str_c8_delnl(char *str)
{
  char *ptr;
  if(str) {
    ptr = str;
    while(*ptr) {
      if(*ptr == 0x0D) {
        if(ptr[1] == 0x0A) {
	  *ptr = '\0';
	} else {
	  ptr++;
	}
      } else {
        if(*ptr == 0x0A) {
	  *ptr = '\0';
	} else {
	  ptr++;
	}
      }
    }
  }
}



char    *
dk3str_c8_next(char *str, char const *whsp)
{
  char *back = NULL;		/* Function result. */
  char *ptr = NULL;		/* Pointer to traverse str. */
  char const *wh = NULL;	/* Whitespaces set to use. */
  int state = 0;		/* Current processing state. */
  

#line 2928 "dk3str.ctr"
  if(str) {
    ptr = str;
    wh = (whsp ? whsp : dk3str_c8_def_whsp);
    state = 0;
    while((state < 2) && (*ptr)) {
      if(dk3str_c8_chr(wh, *ptr)) {
	if(state == 1) {
	  state = 2;
	  *(ptr++) = '\0';
	  back = dk3str_c8_start(ptr, wh);
	} else {
	  ptr++;
	}
      } else {
	state = 1;
	ptr++;
      }
    }
  } 

#line 2947 "dk3str.ctr"
  return back;
}



int
dk3str_c8_is_abbr(char const *line,char const *pattern,char spec,int cs)
{
  int back = 0;			/* Function result. */
  char cl;			/* Current character from line. */
  char cp;			/* Current character from pattern. */
  char const *lptr = NULL;	/* Pointer to traverse line. */
  char const *pptr = NULL;	/* Pointer to traverse pattern. */
  int afterspec = 0;		/* Flag: cs was already found in the pattern. */
  int cc = 0;			/* Flag: Can continue. */
  

#line 2963 "dk3str.ctr"
  if((line) && (pattern)) {
    lptr = line; pptr = pattern; afterspec = 0; cc = 1;
    while(cc) {
      if(*pptr) {
        if((!afterspec) && (*pptr == spec)) {
	  afterspec = 1; pptr++;
	} else {
	  if(*lptr) {
	    cl = *lptr; cp = *pptr;
	    if(!cs) {
	      cl = dk3str_c8_toupper(cl);
	      cp = dk3str_c8_toupper(cp);
	    }
	    if(cl == cp) {
	      lptr++; pptr++;
	    } else {
	      cc = 0; back = 0;
	    }
	  } else {
	    cc = 0;
	    if(afterspec) back = 1;
	  }
	}
      } else {
        cc = 0;
	if(!(*lptr)) {
	  back = 1;
	}
      }
    }
  }
  

#line 2995 "dk3str.ctr"
  return back;
}



int
dk3str_c8_array_abbr(char const * const *ar, char const *str, char sp, int cs)
{
  int back = -1;		/* Function result. */
  char const * const *ptr;	/* Pointer to traverse array ar. */
  int i;			/* Current index of ptr in ar. */
  

#line 3007 "dk3str.ctr"
  if((ar) && (str)) {
    i = 0; ptr = ar;
    while((*ptr) && (back == -1)) {
      

#line 3011 "dk3str.ctr"
      if(dk3str_c8_is_abbr(str, *ptr, sp, cs)) {
        back = i;
      }
      if(back == -1) {
	ptr++; i++;
      }
      

#line 3018 "dk3str.ctr"
    }
  } 

#line 3020 "dk3str.ctr"
  return back;
}




int
dk3str_c8_is_bool(char const *str)
{
  int back = 0;	/* Function result. */
  

#line 3031 "dk3str.ctr"
  if(str) {
    if(dk3str_c8_array_abbr(dk3str_c8_bool_kw,str,'$',0) >= 0) {
      back = 1;
    }
  } 

#line 3036 "dk3str.ctr"
  return back;
}



int
dk3str_c8_is_on(char const *str)
{
  int back = 0;	/* Function result. */
  

#line 3046 "dk3str.ctr"
  if(str) {
    if(dk3str_c8_array_abbr(dk3str_c8_bool_kw,str,'$',0) >= INDEX_OF_FIRST_BOOLEAN_TRUE) {
      back = 1;
    }
  } 

#line 3051 "dk3str.ctr"
  return back;
}



size_t
dk3str_c8_explode(char **array, size_t sz, char *str, char const *whsp)
{
  size_t	back = 0;	/* Function result. */
  char const	*wh = NULL;	/* White spaces set to use. */
  char		*current = NULL; /* Current text word to process. */
  char		*next = NULL;	/* Remaining text after processing the word. */
  char		**ptr = NULL;	/* Pointer to current array element. */
  size_t 	i = 0;		/* Number of remaining usable array elements. */
  if((array) && (sz > 1) && (str)) {
    wh = (whsp ? whsp : dk3str_c8_def_whsp);
    ptr = array; i = sz;
    while(i--) { *(ptr++) = NULL; }
    ptr = array; i = 0;
    current = dk3str_c8_start(str, wh);
    while((current) && (i < (sz - 1))) {
      next = dk3str_c8_next(current,wh);
      *(ptr++) = current; i++; back++;
      current = next;
    }
  }
  return back;
}



void
dk3str_c8_normalize(char *l, char const *w, char s)
{
  char		*parts[256];	/* All the text words. */
  char		*dp = NULL;	/* Destination pointer. */
  char		*sp = NULL;	/* Source pointer. */
  size_t	np = 0;		/* Number of parts used. */
  size_t	i = 0;		/* Current word to process. */
  if(l) {
    np = dk3str_c8_explode(parts, 255, l, w);
    if(np > 0) {
      dp = l;
      for(i = 0; i < np; i++) {
        sp = parts[i];
	if(i) { *(dp++) = s; }
	while(*sp) { *(dp++) = *(sp++); }
      }
      *dp = '\0';
    }
  }
}


void
dk3str_c8_correct_filename(char *n)
{
  register char *p;
  p = n;
  while(*p) { if(*p == NO_FNS_C8) { *p = FNS_C8; } p++; }
}



int
dk3str_c8_is_abs_path(char const *n)
{
  int back = 0;
  if(n) {
    if(*n == FNS_C8) {
      back = 1;
    } else {
#if DK3_ON_WINDOWS
      if(((*n >= 'A') && (*n <= 'Z')) || ((*n >= 'a') && (*n <= 'z'))) {
        if(n[1] == ':') {
	  if(n[2] == FNS_C8) {
	    back = 1;
	  }
	}
      }
#endif
    }
  }
  return back;
}


int
dk3str_c8_append_path_app(char *d, size_t sz, char const *n, dk3_app_t *app)
{
  int back = 0;			/* Function result. */
  char myn[DK3_MAX_PATH];	/* My editable copy of n. */
  char *p1 = NULL;		/* Current name part. */
  char *p2 = NULL;		/* Remaining text. */
  char *p3 = NULL;		/* Used to delete one part from path. */
  if((d) && (sz) && (n)) {
    if(dk3str_c8_is_abs_path(n)) {	/* Absolute path, copy. */
      if(STRLEN(n) < sz) {
        STRCPY(d,n);
	back = 1;
      } else {
        if(app) {
	  /* ERROR: Name n too long! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 109);
	}
      }
    } else {				/* Relative path, append. */
      if(STRLEN(n) < sizeof(myn)) {
        back = 1;
        STRCPY(myn,n);
	p1 = myn;
	while((p1) && (back)) {
	  p2 = STRCHR(p1,FNS_C8);
	  if(p2) { *(p2++) = '\0'; }
	  if(STRCMP(dk3str_c8_dot,p1)) {
	    if(STRCMP(dk3str_c8_dot_dot,p1)) {	/* Add another part. */
	      if((STRLEN(d) + STRLEN(dk3str_c8_fnsep) + STRLEN(p1)) < sz) {
	        STRCAT(d,dk3str_c8_fnsep);
		STRCAT(d,p1);
	      } else {
	        if(app) {
		  /* ERROR: Result too long for destination buffer! */
		  dk3app_log_i1(app, DK3_LL_ERROR, 38);
		}
	      }
	    } else {			/* Remove last part. */
	      p3 = STRRCHR(d,FNS_C8);
	      if(p3) {
	        *p3 = '\0';
	      } else {
	        if(app) {
		  /* ERROR: Too many ".." entries! */
#if DK3_CHAR_SIZE == 1
		  dk3app_log_i3(app, DK3_LL_ERROR, 110, 111, n);
#else
		  dk3app_log_i1(app, DK3_LL_ERROR, 126);
#endif
		}
	      }
	    }
	  }
	  p1 = p2;
	}
      } else {
        if(app) {
	  /* ERROR: Name n too long! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 109);
	}
      }
    }
  }
  return back;
}


/*
	16-bit characters
	-----------------
*/

/**	Default white spaces set.
*/
static dk3_c16_t const c16_def_whsp[] = {
  0x0020U, 0x0009U, 0x000AU, 0x000DU, 0U
};

/**	The dot for the current directory.
*/
static dk3_c16_t const c16_dot[] = {
  0x002EU, 0U
};

/**	The dot dot for the parent directory.
*/
static dk3_c16_t const c16_dot_dot[] = {
  0x002EU, 0x002EU, 0U
};

/**	File name separator (slash or backslash).
*/
static dk3_c16_t const c16_fnsep[] = {
#if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
0x005CU,
#else
0x002FU,
#endif
0U
};

#if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
/**	File name separator for 16-bit character strings.
*/
#define	FNS_C16		0x005CU
/**	Not the file name separator for 16-bit character strings.
*/
#define NO_FNS_C16	0x002FU
#else
/**	File name separator for 16-bit character strings.
*/
#define FNS_C16		0x002FU
/**	Not the file name separator for 16-bit character strings.
*/
#define NO_FNS_C16	0x005CU
#endif



dk3_c16_t *
dk3str_c16_get_suffix(dk3_c16_t const *s)
{
  dk3_c16_t *back = NULL;
  dk3_c16_t const *ptr;

  if(s) {
    ptr = s;
    while(*ptr) {
      if(*ptr == 0x002EU) {
        back = (dk3_c16_t *)ptr;
      } else {
        if(*ptr == FNS_C16) {
	  back = NULL;
	}
      }
      ptr++;
    }
  }
  return back;
}



/**	String length of 16-bit character string.
*/
#define	C16LEN(s)	dk3str_c16_len_fb(s)

#if 0
#if ((DK3_HAVE_WCSLEN) || DK3_ON_WINDOWS) && (DK3_SIZEOF_WCHAR_T == 2)
#define C16LEN(s) wcslen(s)
#else
#if (DK3_HAVE__WCSLEN) && (DK3_SIZEOF_WCHAR_T == 2)
#define C16LEN(s) _wcslen(s)
#else
#define C16LEN(s) dk3str_c16_len_fb(s)
#endif
#endif
#endif


/**	Compare two 16-bit character strings.
*/
#define	C16CMP(a,b)	dk3str_c16_cmp_fb(a,b)

#if 0
#if ((DK3_HAVE_WCSCMP) || DK3_ON_WINDOWS) && (DK3_SIZEOF_WCHAR_T == 2)
#define C16CMP(a,b)	wcscmp(a,b)
#else
#if (DK3_HAVE__WCSCMP) && (DK3_SIZEOF_WCHAR_T == 2)
#define C16CMP(a,b)	_wcscmp(a,b)
#else
#define	C16CMP(a,b)	dk3str_c16_cmp_fb(a,b)
#endif
#endif
#endif


/**	Compare two 16-bit character strings, restricted number of characters.
*/
#define	C16NCMP(a,b,n)	dk3str_c16_ncmp_fb(a,b,n)

#if 0
#if ((DK3_HAVE_WCSNCMP) || DK3_ON_WINDOWS) && (DK3_SIZEOF_WCHAR_T == 2)
#define	C16NCMP(a,b,n)	wcsncmp(a,b,n)
#else
#if (DK3_HAVE__WCSNCMP) && (DK3_SIZEOF_WCHAR_T == 2)
#define	C16NCMP(a,b,n)	_wcsncmp(a,b,n)
#else
#define	C16NCMP(a,b,n)	dk3str_c16_ncmp_fb(a,b,n)
#endif
#endif
#endif


/**	Case-insensitive comparison of 16-bit character strings.
*/
#define	C16ICMP(a,b)	dk3str_c16_casecmp_fb(a,b)

#if 0
#if (DK3_HAVE_WCSICMP) && (DK3_SIZEOF_WCHAR_T == 2)
#define	C16ICMP(a,b)	wcsicmp(a,b)
#else
#if (DK3_HAVE__WCSICMP) && (DK3_SIZEOF_WCHAR_T == 2)
#define	C16ICMP(a,b)	_wcsicmp(a,b)
#else
#define	C16ICMP(a,b)	dk3str_c16_casecmp_fb(a,b)
#endif
#endif
#endif


/**	Copy 16-bit character string.
*/
#define	C16CPY(d,s)	dk3str_c16_cpy_fb(d,s)

#if 0
#if ((DK3_HAVE_WCSCPY) || DK3_ON_WINDOWS) && (DK3_SIZEOF_WCHAR_T == 2)
#define	C16CPY(d,s)	wcscpy(d,s)
#else
#if (DK3_HAVE__WCSCPY) && (DK3_SIZEOF_WCHAR_T == 2)
#define	C16CPY(d,s)	_wcscpy(d,s)
#else
#define	C16CPY(d,s)	dk3str_c16_cpy_fb(d,s)
#endif
#endif
#endif


/**	Copy 16-bit character string, length restricted.
*/
#define	C16NCPY(d,s,n)	dk3str_c16_ncpy_fb(d,s,n)

#if 0
#if ((DK3_HAVE_WCSNCPY) || DK3_ON_WINDOWS) && (DK3_SIZEOF_WCHAR_T == 2)
#define	C16NCPY(d,s,n)	wcsncpy(d,s,n)
#else
#if (DK3_HAVE__WCSNCPY) && (DK3_SIZEOF_WCHAR_T == 2)
#define	C16NCPY(d,s,n)	_wcsncpy(d,s,n)
#else
#define	C16NCPY(d,s,n)	dk3str_c16_ncpy_fb(d,s,n)
#endif
#endif
#endif


/**	Concatenate 16-bit character strings.
*/
#define	C16CAT(d,s)	dk3str_c16_cat_fb(d,s)

#if 0
#if ((DK3_HAVE_WCSCAT) || DK3_ON_WINDOWS) && (DK3_SIZEOF_WCHAR_T == 2)
#define	C16CAT(d,s)	wcscat(d,s)
#else
#if (DK3_HAVE__WCSCAT) && (DK3_SIZEOF_WCHAR_T == 2)
#define	C16CAT(d,s)	_wcscat(d,s)
#else
#define	C16CAT(d,s)	dk3str_c16_cat_fb(d,s)
#endif
#endif
#endif


/**	Find position of character in 16-bit character string.
*/
#define	C16CHR(s,c)	dk3str_c16_chr_fb(s,c)

#if 0
#if ((DK3_HAVE_WCSCHR) || DK3_ON_WINDOWS) && (DK3_SIZEOF_WCHAR_T == 2)
#define C16CHR(s,c) wcschr(s,c)
#else
#if (DK3_HAVE__WCSCHR) && (DK3_SIZEOF_WCHAR_T == 2)
#define C16CHR(s,c) _wcschr(s,c)
#else
#define C16CHR(s,c) dk3str_c16_chr_fb(s,c)
#endif
#endif
#endif


/**	Find rightmost position of character in 16-bit character string.
*/
#define	C16RCHR(s,c)	dk3str_c16_rchr_fb(s,c)

#if 0
#if ((DK3_HAVE_WCSRCHR) || DK3_ON_WINDOWS) && (DK3_SIZEOF_WCHAR_T == 2)
#define C16RCHR(s,c) wcsrchr(s,c)
#else
#if (DK3_HAVE__WCSRCHR) && (DK3_SIZEOF_WCHAR_T == 2)
#define C16RCHR(s,c) _wcsrchr(s,c)
#else
#define C16RCHR(s,c) dk3str_c16_rchr_fb(s,c)
#endif
#endif
#endif



dk3_c16_t
dk3str_c16_tolower(dk3_c16_t c)
{
  dk3_c16_t back;
  back = c;
  if((back >= 0x0041U) && (back <= 0x005AU)) {
    back = 0x0061U + (back - 0x0041U);
  }
  return back;
}



dk3_c16_t
dk3str_c16_toupper(dk3_c16_t c)
{
  dk3_c16_t back;
  back = c;
  if((back >= 0x0061U) && (back <= 0x007AU)) {
    back = 0x0041U + (back - 0x0061U);
  }
  return back;
}



dk3_c16_t *
dk3str_c16_chr_fb(dk3_c16_t const *s, dk3_c16_t c)
{
  register dk3_c16_t *back;
  register dk3_c16_t const *ptr;	/* Traverse source string. */
  register dk3_c16_t chr;		/* Character to search for. */
  back = NULL; ptr = s; chr = c;
  while((*ptr) && (back == NULL)) {
    if(*ptr == chr) { back = (dk3_c16_t *)ptr; } else { ptr++; }
  }
  return back;
}



dk3_c16_t *
dk3str_c16_chr(dk3_c16_t const *s, dk3_c16_t c)
{
  dk3_c16_t *back = NULL;
  if(s) {
    back = C16CHR(s,c) ;
  }
  return back;
}



dk3_c16_t *
dk3str_c16_rchr_fb(dk3_c16_t const *s, dk3_c16_t c)
{
  register dk3_c16_t *back;
  register dk3_c16_t const *ptr;	/* Traverse the string. */
  register dk3_c16_t chr;		/* Character to search for. */
  back = NULL; ptr = s; chr = c;
  while(*ptr) {
    if(*ptr == chr) { back = (dk3_c16_t *)ptr; }
    ptr++;
  }
  return back;
}



dk3_c16_t *
dk3str_c16_rchr(dk3_c16_t const *s, dk3_c16_t c)
{
  dk3_c16_t *back = NULL;
  if(s) {
    back = C16RCHR(s,c) ;
  }
  return back;
}



size_t
dk3str_c16_len_fb(dk3_c16_t const *s)
{
  register size_t back;
  register dk3_c16_t const *ptr;	/* Traverse string. */
  back = 0; ptr = s;
  while(*(ptr++)) back++;
  return back;
}



size_t
dk3str_c16_len(dk3_c16_t const *s)
{
  size_t back = 0;
  if(s) {
    back = C16LEN(s) ;
  }
  return back;
}



int
dk3str_c16_cmp_fb(dk3_c16_t const *s1, dk3_c16_t const *s2)
{
  register int back;
  register dk3_c16_t const *p1;	/* Traverse left string. */
  register dk3_c16_t const *p2;	/* Traverse right string. */
  register int cc;		/* Flag: Can continue. */

  back = 0; p1 = s1; p2 = s2; cc = 1;
  while((cc) && (back == 0)) {
    if(*p1 > *p2) {
      back = 1;
    } else {
      if(*p1 < *p2) {
        back = -1;
      } else {
        if((*p1) && (*p2)) {
	  p1++; p2++;
	} else {
	  cc = 0;
	}
      }
    }
  }
  return back;
}



int
dk3str_c16_cmp(dk3_c16_t const *s1, dk3_c16_t const *s2)
{
  int back = 0;
  if(s1) {
    if(s2) {
      back = C16CMP(s1,s2) ;
      if(back >  1) back =  1;
      if(back < -1) back = -1;
    } else back = 1;
  } else {
    if(s2) back = -1;
  }
  return back;
}



int
dk3str_c16_ncmp_fb(dk3_c16_t const *s1, dk3_c16_t const *s2, size_t n)
{
  register int back;
  register dk3_c16_t const *p1;	/* Traverse left string. */
  register dk3_c16_t const *p2;	/* Traverse right string. */
  register size_t max;		/* Maximum number of characters to compare. */
  register size_t used;		/* Number of characters already compared. */

  back = 0; p1 = s1; p2 = s2; max = n; used = 0;
  while((used < max) && (back == 0)) {
    if(*p1 > *p2) {
      back = 1;
    } else {
      if(*p1 < *p2) {
        back = -1;
      } else {
        if((*p1) && (*p2)) {
	  p1++; p2++; used++;
	} else {
	  used = max;
	}
      }
    }
  }
  return back;
}



int
dk3str_c16_ncmp(dk3_c16_t const *s1, dk3_c16_t const *s2, size_t n)
{
  int back = 0;
  if(s1) {
    if(s2) {
      back = C16NCMP(s1,s2,n) ;
      if(back >  1) back =  1;
      if(back < -1) back = -1;
    } else back = 1;
  } else {
    if(s2) back = -1;
  }
  return back;
}



int
dk3str_c16_casecmp_fb(dk3_c16_t const *s1, dk3_c16_t const *s2)
{
  register int back;
  register dk3_c16_t const *p1;	/* Traverse left string. */
  register dk3_c16_t const *p2;	/* Traverse right string. */
  register dk3_c16_t c1;	/* Left character. */
  register dk3_c16_t c2;	/* Right character. */
  register int cc;		/* Flag: Can continue. */
  

#line 3646 "dk3str.ctr"
  back = 0; p1 = s1; p2 = s2; cc = 1;
  while((cc) && (back == 0)) {
    c1 = *p1; c2 = *p2;
    if((c1 >= 0x0041U) && (c1 <= 0x005AU)) { c1 = 0x0061U + (c1 - 0x0041U); }
    if((c2 >= 0x0041U) && (c2 <= 0x005AU)) { c2 = 0x0061U + (c2 - 0x0041U); }
    if(c1 > c2) {
      back = 1;
    } else {
      if(c1 < c2) {
        back = -1;
      } else {
        if((c1) && (c2)) {
	  p1++; p2++;
	} else {
	  cc = 0;
	}
      }
    }
  } 

#line 3665 "dk3str.ctr"
  return back;
}



int
dk3str_c16_casecmp(dk3_c16_t const *s1, dk3_c16_t const *s2)
{
  int back = 0;
  if(s1) {
    if(s2) {
      back = C16ICMP(s1,s2);
      if(back >  1) back =  1;
      if(back < -1) back = -1;
    } else back = 1;
  } else {
    if(s2) back = -1;
  }
  return back;
}



void
dk3str_c16_cpy_fb(dk3_c16_t *d, dk3_c16_t const *s)
{
  register dk3_c16_t *dp;	/* Destination pointer. */
  register dk3_c16_t const *sp;	/* Source pointer. */
  register dk3_c16_t x;		/* Current character. */

  dp = d; sp = s;
  while(*sp) { x = *(sp++); *(dp++) = x; }
  *dp = 0U;
}



void
dk3str_c16_cpy(dk3_c16_t *d, dk3_c16_t const *s)
{
  if((d) && (s)) {
    C16CPY(d,s) ;
  }
}



void
dk3str_c16_ncpy_fb(dk3_c16_t *d, dk3_c16_t const *s, size_t n)
{
  register dk3_c16_t *dp;	/* Destionation pointer. */
  register dk3_c16_t const *sp;	/* Source pointer. */
  register dk3_c16_t x;		/* Current character. */
  register size_t max;		/* Maximum number of characters to copy. */
  register size_t used;		/* Characters already copied. */

  dp = d; sp = s; max = n; used = 0;
  while((*sp) && (used < max)) { x = *(sp++); *(dp++) = x; used++; }
  if(used < max) { *dp = 0U; }
  else { d[max - 1] = 0U; }
}



void
dk3str_c16_ncpy(dk3_c16_t *d, dk3_c16_t const *s, size_t n)
{
  if((d) && (s) && (n)) {
    C16NCPY(d,s,n) ;
    d[n - 1] = 0U;
  }
}



void
dk3str_c16_cat_fb(dk3_c16_t *d, dk3_c16_t const *s)
{
  register dk3_c16_t *dp;	/* Destination pointer. */
  register dk3_c16_t const *sp;	/* Source pointer. */
  register dk3_c16_t x;		/* Current character. */
  dp = d; sp = s;
  while(*dp) dp++;
  while(*sp) { x = *(sp++); *(dp++) = x;  }
  *dp = 0U;
}



void
dk3str_c16_cat(dk3_c16_t *d, dk3_c16_t const *s)
{
  if((d) && (s)) {
    C16CAT(d,s) ;
  }
}



dk3_c16_t *
dk3str_c16_dup_app(dk3_c16_t const *s, dk3_app_t *app)
{
  dk3_c16_t	*back = NULL;
  size_t	l = 0;		/* String length, including delimiter. */
  if(s) {
    l = C16LEN(s) ;
    l++;
    if(l) {
      if(app) { back = (dk3_c16_t *)dk3mem_alloc_app(sizeof(dk3_c16_t),l,app); }
      else { back = (dk3_c16_t *)dk3mem_alloc(sizeof(dk3_c16_t),l); }
      if(back) {
        C16CPY(back,s) ;
      }
    } else {
      if(app) {
        /* ERROR: String too long! */
	dk3app_log_i1(app, DK3_LL_ERROR, 108);
      }
    }
  }
  return back;
}



int
dk3str_c16_array_index(dk3_c16_t const * const *a, dk3_c16_t const *s, int c)
{
  int back = -1;
  int ci;			/* Current index. */
  dk3_c16_t const * const *ap;	/* Pointer into array. */
  if((a) && (s)) {
    ap = a; ci = 0;
    while((*ap) && (back == -1)) {
      if(c) {
        if(dk3str_c16_cmp(*ap, s) == 0) back = ci;
      } else {
        if(dk3str_c16_casecmp(*ap, s) == 0) back = ci;
      }
      if(back == -1) { ap++; ci++; }
    }
  }
  return back;
}



dk3_c16_t *
dk3str_c16_start(dk3_c16_t const *str, dk3_c16_t const *whsp)
{
  dk3_c16_t *back = NULL;
  dk3_c16_t const *ptr;		/* Pointer into string. */
  dk3_c16_t const *wh;		/* Whitespaces set. */

  if(str) {
    wh = (whsp ? whsp : c16_def_whsp);
    ptr = str;
    while((*ptr) && (!(back))) {
      if(dk3str_c16_chr(wh, *ptr)) {
        ptr++;
      } else {
        back = (dk3_c16_t *)ptr;
      }
    }
  }
  return back;
}



void
dk3str_c16_chomp(dk3_c16_t *str, dk3_c16_t const *whsp)
{
  dk3_c16_t const *wh;	/* Whitespaces set. */
  dk3_c16_t *ptr;	/* Pointer into string. */
  dk3_c16_t *x;		/* Test pointer for whitespaces set. */

  if(str) {
    wh = (whsp ? whsp : c16_def_whsp);
    x = NULL; ptr = str;
    while(*ptr) {
      if(dk3str_c16_chr(wh, *ptr)) {
        if(!(x)) x = ptr;
      } else {
        x = NULL;
      }
      ptr++;
    }
    if(x) { *x = 0U; }
  }
}



void
dk3str_c16_delnl(dk3_c16_t *str)
{
  dk3_c16_t *ptr;
  if(str) {
    ptr = str;
    while(*ptr) {
      if(*ptr == 0x000DU) {
        if(ptr[1] == 0x000AU) {
	  *ptr = (dk3_c16_t)0U;
	} else {
	  ptr++;
	}
      } else {
        if(*ptr == 0x000AU) {
	  *ptr = (dk3_c16_t)0U;
	} else {
	  ptr++;
	}
      }
    }
  }
}



dk3_c16_t *
dk3str_c16_next(dk3_c16_t *str, dk3_c16_t const *whsp)
{
  dk3_c16_t *back = NULL;
  dk3_c16_t *ptr;		/* Pointer into string. */
  dk3_c16_t const *wh;		/* Whitespaces set. */
  int state;			/* Current state. */

  if(str) {
    ptr = str;
    wh = (whsp ? whsp : c16_def_whsp);
    state = 0;
    while((state < 2) && (*ptr)) {
      if(dk3str_c16_chr(wh, *ptr)) {
        if(state == 1) {
	  state = 2;
	  *(ptr++) = 0U;
	  back = dk3str_c16_start(ptr, wh);
	} else {
	  ptr++;
	}
      } else {
        state = 1; ptr++;
      }
    }
  }
  return back;
}



int
dk3str_c16_is_abbr(dk3_c16_t const *line, dk3_c16_t const *pattern, dk3_c16_t spec, int cs)
{
  int back = 0;
  dk3_c16_t cl;			/* Current character from line. */
  dk3_c16_t cp;			/* Current character from pattern. */
  dk3_c16_t const *lptr;	/* Input text to check. */
  dk3_c16_t const *pptr;	/* Pattern. */
  int afterspec;		/* Flag: Abbreviation inidicator found. */
  int cc;			/* Flag: Can continue. */

  if((line) && (pattern)) {
    lptr = line; pptr = pattern; afterspec = 0; cc = 1;
    while(cc) {
      if(*pptr) {
        if((!afterspec) && (*pptr == spec)) {
	  afterspec = 1; pptr++;
	} else {
	  if(*lptr) {
	    cl = *lptr; cp = *pptr;
	    if(!cs) {
	      cl = dk3str_c16_toupper(cl);
	      cp = dk3str_c16_toupper(cp);
	    }
	    if(cl == cp) {
	      lptr++; pptr++;
	    } else {
	      cc = 0; back = 0;
	    }
	  } else {
	    cc = 0;
	    if(afterspec) back = 1;
	  }
	}
      } else {
        cc = 0;
	if(!(*lptr)) {
	  back = 1;
	}
      }
    }
  }
  return back;
}



int
dk3str_c16_array_abbr(dk3_c16_t const * const *arr, dk3_c16_t const *str, dk3_c16_t sp, int cs)
{
  int back = -1;
  dk3_c16_t const * const *ptr;	/* Pointer into array. */
  int i;			/* Current index. */
  

#line 3970 "dk3str.ctr"
  if((arr) && (str)) {	

#line 3971 "dk3str.ctr"
    i = 0; ptr = arr;
    while((*ptr) && (back == -1)) {			

#line 3973 "dk3str.ctr"
#if DK3_CHAR_SIZE > 1
      

#line 3975 "dk3str.ctr"
#else
      

#line 3977 "dk3str.ctr"
#endif
      if(dk3str_c16_is_abbr(str, *ptr, sp, cs)) {	

#line 3979 "dk3str.ctr"
        back = i;
      } else {						

#line 3981 "dk3str.ctr"
      }
      if(back == -1) {
        ptr++; i++;
      }							

#line 3985 "dk3str.ctr"
    }				

#line 3986 "dk3str.ctr"
  } 

#line 3987 "dk3str.ctr"
  return back;
}



int
dk3str_c16_to_c8_simple_app(
  char *d, size_t sz, dk3_c16_t const *s, dk3_app_t *app
)
{
  int back = 0;
  dk3_c16_t const *ptr;	/* Source pointer. */
  dk3_c16_t c;		/* Source character. */
  unsigned char uc;	/* Destination character. */
  char *dptr;		/* Destination pointer. */

  if((d) && (sz) && (s)) {
    if(dk3str_c16_len(s) < sz) {
      back = 1; ptr = s; dptr = d;
      while((c = *ptr)) {
        if(c < 0x0100U) {
	  uc = (unsigned char)c;
	  *(dptr++) = (char)uc;
	} else {
	  if((back == 1) && (app)) {
	    /* ERROR: Illegal character(s) in source string! */
	    dk3app_log_i1(app, DK3_LL_ERROR, 112);
	  }
	  back = 0;
	}
        ptr++;
      }
      *dptr = '\0';
    } else {
      d[0] = '\0';
      if(app) {
        /* ERROR: Source string too long! */ 
	dk3app_log_i1(app, DK3_LL_ERROR, 108);
      }
    }
  }
  return back;
}



int
dk3str_c16_is_bool(dk3_c16_t const *str)
{
  int back = 0;
  char	mytest[256];	/* 8-bit version of the str text. */
  if(str) {
    if(dk3str_c16_to_c8_simple(mytest, sizeof(mytest), str)) {
      back = dk3str_c8_is_bool(mytest);
    }
  }
  return back;
}



int
dk3str_c16_is_on(dk3_c16_t const *str)
{
  int back = 0;
  char	mytest[256];	/* 8-bit version of the str text. */
  if(str) {
    if(dk3str_c16_to_c8_simple(mytest, sizeof(mytest), str)) {
      back = dk3str_c8_is_on(mytest);
    }
  }
  return back;
}


size_t
dk3str_c16_explode(dk3_c16_t **array, size_t sz, dk3_c16_t *str, dk3_c16_t const *whsp)
{
  size_t		back = 0;
  dk3_c16_t const	*wh = NULL;	/* Whitespaces set. */
  dk3_c16_t		*current = NULL;	/* Start of current word. */
  dk3_c16_t		*next = NULL;	/* Start of next word after current. */
  dk3_c16_t		**ptr = NULL;	/* Pointer into array. */
  size_t		i = 0;		/* Number of words found. */

  if((array) && (sz > 1) && (str)) {
    wh = (whsp ? whsp : c16_def_whsp);
    ptr = array; i = sz;
    while(i--) { *(ptr++) = NULL; }
    ptr = array; i = 0;
    current = dk3str_c16_start(str, wh);
    while((current) && (i < (sz - 1))) {
      next = dk3str_c16_next(current, wh);
      *(ptr++) = current; i++; back++;
      current = next;
    }
  }
  return back;
}


void
dk3str_c16_normalize(dk3_c16_t *l, dk3_c16_t const *w, char s)
{
  dk3_c16_t		*parts[256];	/* Pointers to the words. */
  dk3_c16_t		*dp = NULL;	/* Destination pointer. */
  dk3_c16_t		*sp = NULL;	/* Source pointer. */
  size_t		np = 0;		/* Number of parts. */
  size_t		i = 0;		/* Index of current part. */

  if(l) {
    np = dk3str_c16_explode(parts, 255, l, w);
    if(np > 0) {
      dp = l;
      for(i = 0; i < np; i++) {
        sp = parts[i];
	if(i) { *(dp++) = s; }
	while(*sp) { *(sp++) = *(dp++); }
      }
      *dp = 0U;
    }
  }
}



void
dk3str_c16_correct_filename(dk3_c16_t *n)
{
  register dk3_c16_t *p;
  p = n;
  while(*p) { if(*p == NO_FNS_C16) { *p = FNS_C16; } p++;}
}



int
dk3str_c16_is_abs_path(dk3_c16_t const *n)
{
  int back = 0;
  if(n) {
    if(*n == FNS_C16) {
      back = 1;
    } else {
#if DK3_ON_WINDOWS
      if(((*n >= 0x0061U) && (*n <= 0x007AU))
         || ((*n >= 0x0041U) && (*n <= 0x005AU)))
      {
        if(n[1] == 0x003AU) {
	  if(n[2] == FNS_C16) {
	    back = 1;
	  }
	}
      }
#endif
    }
  }
  return back;
}



int
dk3str_c16_append_path_app(dk3_c16_t *d, size_t sz, dk3_c16_t const *n, dk3_app_t *app)
{
  int back = 0;
  dk3_c16_t	myn[DK3_MAX_PATH];
  dk3_c16_t	*p1 = NULL;		/* Path component to process. */
  dk3_c16_t	*p2 = NULL;		/* Remainder of path. */
  dk3_c16_t	*p3 = NULL;		/* Last path component to remove. */

  if((d) && (sz) && (n)) {
    if(dk3str_c16_is_abs_path(n)) {
      if(C16LEN(n) < sz) {
        C16CPY(d,n) ;
	back = 1;
      } else {
        if(app) {
	  /* ERROR: Name n too long! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 109);
	}
      }
    } else {
      if(C16LEN(n) < DK3_SIZEOF(myn,dk3_c16_t)) {
        back = 1;
	C16CPY(myn,n) ;
	p1 = myn;
	while((p1) && (back)) {
	  p2 = C16CHR(p1, FNS_C16);
	  if(p2) { *(p2++) = 0U; }
	  if(C16CMP(c16_dot,p1)) {
	    if(C16CMP(c16_dot_dot,p1)) {
	      if((C16LEN(d) + C16LEN(c16_fnsep) + C16LEN(p1)) < sz) {
	        C16CAT(d,c16_fnsep);
		C16CAT(d,p1);
	      } else {
	        if(app) {
		  /* ERROR: Result too long for destination buffer! */
		  dk3app_log_i1(app, DK3_LL_ERROR, 38);
		}
	      }
	    } else {
	      p3 = C16RCHR(d,FNS_C16);
	      if(p3) {
	        *p3 = 0U;
	      } else {
	        if(app) {
		  /* ERROR: Too many ".." entries! */
#if DK3_CHAR_SIZE == 2
		  dk3app_log_i3(app, DK3_LL_ERROR, 110, 111, n);
#else
		  dk3app_log_i1(app, DK3_LL_ERROR, 126);
#endif
		}
	      }
	    }
	  }
	  p1 = p2;
	}
      } else {
        if(app) {
	  /* ERROR: Name n too long! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 109);
	}
      }
    }
  }
  return back;
}



/*
	32-bit characters
	-----------------
*/

/**	Default whitespaces set.
*/
static dk3_c32_t const c32_def_whsp[] = {
  0x00000020UL, 0x00000009UL, 0x0000000AUL, 0x0000000DUL, 0UL
};

/**	The dot is the current directory.
*/
static dk3_c32_t const c32_dot[] = {
  0x0000002EUL, 0UL
};

/**	The dot dot is the parent directory.
*/
static dk3_c32_t const c32_dot_dot[] = {
  0x0000002EUL, 0x0000002EUL, 0UL
};

/**	File name separator (slash or backslash).
*/
static dk3_c32_t const c32_fnsep[] = {
#if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
0x0000005CUL,
#else
0x0000002FUL,
#endif
0U
};

#if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
/**	File name separator for 32-bit character strings.
*/
#define	FNS_C32		0x0000005CUL
/**	Not a file name separator for 32-bit character strings.
*/
#define NO_FNS_C32	0x0000002FUL
#else
/**	File name separator for 32-bit character strings.
*/
#define FNS_C32		0x0000002FUL
/**	Not a file name separator for 32-bit character strings.
*/
#define NO_FNS_C32	0x0000005CUL
#endif



dk3_c32_t *
dk3str_c32_get_suffix(dk3_c32_t const *s)
{
  dk3_c32_t *back = NULL;
  dk3_c32_t const *ptr;
  if(s) {
    ptr = s;
    while(*ptr) {
      if(*ptr == 0x0000002EUL) {
        back = (dk3_c32_t *)ptr;
      } else {
        if(*ptr == FNS_C32) {
	  back = NULL;
	}
      }
      ptr++;
    }
  }
  return back;
}


/**	Get length of 32-bit character string.
*/
#define	C32LEN(s)	dk3str_c32_len_fb(s)

#if 0
#if (DK3_HAVE_WCSLEN) && (DK3_SIZEOF_WCHAR_T == 4)
#define C32LEN(s) wcslen(s)
#else
#if (DK3_HAVE__WCSLEN) && (DK3_SIZEOF_WCHAR_T == 4)
#define C32LEN(s) _wcslen(s)
#else
#define C32LEN(s) dk3str_c32_len_fb(s)
#endif
#endif
#endif


/**	Compare 32-bit character strings.
*/
#define	C32CMP(a,b)	dk3str_c32_cmp_fb(a,b)

#if 0
#if (DK3_HAVE_WCSCMP) && (DK3_SIZEOF_WCHAR_T == 4)
#define C32CMP(a,b)	wcscmp(a,b)
#else
#if (DK3_HAVE__WCSCMP) && (DK3_SIZEOF_WCHAR_T == 4)
#define C32CMP(a,b)	_wcscmp(a,b)
#else
#define	C32CMP(a,b)	dk3str_c32_cmp_fb(a,b)
#endif
#endif
#endif


/**	Compare 32-bit character strings, restricted length.
*/
#define	C32NCMP(a,b,n)	dk3str_c32_ncmp_fb(a,b,n)

#if 0
#if (DK3_HAVE_WCSNCMP) && (DK3_SIZEOF_WCHAR_T == 4)
#define	C32NCMP(a,b,n)	wcsncmp(a,b,n)
#else
#if (DK3_HAVE__WCSNCMP) && (DK3_SIZEOF_WCHAR_T == 4)
#define	C32NCMP(a,b,n)	_wcsncmp(a,b,n)
#else
#define	C32NCMP(a,b,n)	dk3str_c32_ncmp_fb(a,b,n)
#endif
#endif
#endif


/**	Case-insensitive comparison of 32-bit character strings.
*/
#define	C32ICMP(a,b)	dk3str_c32_casecmp_fb(a,b)

#if 0
#if (DK3_HAVE_WCSICMP) && (DK3_SIZEOF_WCHAR_T == 4)
#define	C32ICMP(a,b)	wcsicmp(a,b)
#else
#if (DK3_HAVE__WCSICMP) && (DK3_SIZEOF_WCHAR_T == 4)
#define	C32ICMP(a,b)	_wcsicmp(a,b)
#else
#define	C32ICMP(a,b)	dk3str_c32_casecmp_fb(a,b)
#endif
#endif
#endif


/**	Copy 32-bit character string.
*/
#define	C32CPY(d,s)	dk3str_c32_cpy_fb(d,s)

#if 0
#if (DK3_HAVE_WCSCPY) && (DK3_SIZEOF_WCHAR_T == 4)
#define	C32CPY(d,s)	wcscpy(d,s)
#else
#if (DK3_HAVE__WCSCPY) && (DK3_SIZEOF_WCHAR_T == 4)
#define	C32CPY(d,s)	_wcscpy(d,s)
#else
#define	C32CPY(d,s)	dk3str_c32_cpy_fb(d,s)
#endif
#endif
#endif


/**	Copy 32-bit character string, restricted length.
*/
#define	C32NCPY(d,s,n)	dk3str_c32_ncpy_fb(d,s,n)

#if 0
#if (DK3_HAVE_WCSNCPY) && (DK3_SIZEOF_WCHAR_T == 4)
#define	C32NCPY(d,s,n)	wcsncpy(d,s,n)
#else
#if (DK3_HAVE__WCSNCPY) && (DK3_SIZEOF_WCHAR_T == 4)
#define	C32NCPY(d,s,n)	_wcsncpy(d,s,n)
#else
#define	C32NCPY(d,s,n)	dk3str_c32_ncpy_fb(d,s,n)
#endif
#endif
#endif


/**	Concatenate 32-bit character strings.
*/
#define	C32CAT(d,s)	dk3str_c32_cat_fb(d,s)

#if 0
#if (DK3_HAVE_WCSCAT) && (DK3_SIZEOF_WCHAR_T == 4)
#define	C32CAT(d,s)	wcscat(d,s)
#else
#if (DK3_HAVE__WCSCAT) && (DK3_SIZEOF_WCHAR_T == 4)
#define	C32CAT(d,s)	_wcscat(d,s)
#else
#define	C32CAT(d,s)	dk3str_c32_cat_fb(d,s)
#endif
#endif
#endif


/**	Find position of character in 32-bit character string.
*/
#define	C32CHR(s,c)	dk3str_c32_chr_fb(s,c)

#if 0
#if (DK3_HAVE_WCSCHR) && (DK3_SIZEOF_WCHAR_T == 4)
#define C32CHR(s,c) wcschr(s,c)
#else
#if (DK3_HAVE__WCSCHR) && (DK3_SIZEOF_WCHAR_T == 4)
#define C32CHR(s,c) _wcschr(s,c)
#else
#define C32CHR(s,c) dk3str_c32_chr_fb(s,c)
#endif
#endif
#endif



/**	Find right-most position of character in 32-bit character string.
*/
#define	C32RCHR(s,c)	dk3str_c32_rchr_fb(s,c)

#if 0
#if (DK3_HAVE_WCSRCHR) && (DK3_SIZEOF_WCHAR_T == 4)
#define C32RCHR(s,c) wcsrchr(s,c)
#else
#if (DK3_HAVE__WCSRCHR) && (DK3_SIZEOF_WCHAR_T == 4)
#define C32RCHR(s,c) _wcsrchr(s,c)
#else
#define C32RCHR(s,c) dk3str_c32_rchr_fb(s,c)
#endif
#endif
#endif



dk3_c32_t
dk3str_c32_tolower(dk3_c32_t c)
{
  dk3_c32_t back;
  back = c;
  if((back >= (dk3_c32_t)0x00000041UL) && (back <= (dk3_c32_t)0x0000005AUL)) {
    back = (dk3_c32_t)0x00000061UL + (back - (dk3_c32_t)0x00000041UL);
  }
  return back;
}



dk3_c32_t
dk3str_c32_toupper(dk3_c32_t c)
{
  dk3_c32_t back;
  back = c;
  if((back >= (dk3_c32_t)0x00000061UL) && (back <= (dk3_c32_t)0x0000007AUL)) {
    back = (dk3_c32_t)0x00000041UL + (back - (dk3_c32_t)0x00000061UL);
  }
  return back;
}



dk3_c32_t *
dk3str_c32_chr_fb(dk3_c32_t const *s, dk3_c32_t c)
{
  register dk3_c32_t *back;
  register dk3_c32_t const *ptr;	/* Traverse source string. */
  register dk3_c32_t chr;		/* Character to find. */

  back = NULL; ptr = s; chr = c;
  while((*ptr) && (back == NULL)) {
    if(*ptr == chr) { back = (dk3_c32_t *)ptr; } else { ptr++; }
  }
  return back;
}



dk3_c32_t *
dk3str_c32_chr(dk3_c32_t const *s, dk3_c32_t c)
{
  dk3_c32_t *back = NULL;
  if(s) {
    back = C32CHR(s,c) ;
  }
  return back;
}



dk3_c32_t *
dk3str_c32_rchr_fb(dk3_c32_t const *s, dk3_c32_t c)
{
  register dk3_c32_t *back;
  register dk3_c32_t const *ptr;	/* Traverse source string. */
  register dk3_c32_t chr;		/* Character to search for. */

  back = NULL; ptr = s; chr = c;
  while(*ptr) {
    if(*ptr == chr) { back = (dk3_c32_t *)ptr; }
    ptr++;
  }
  return back;
}



dk3_c32_t *
dk3str_c32_rchr(dk3_c32_t const *s, dk3_c32_t c)
{
  dk3_c32_t *back = NULL;
  if(s) {
    back = C32RCHR(s,c) ;
  }
  return back;
}



size_t
dk3str_c32_len_fb(dk3_c32_t const *s)
{
  register size_t back;
  register dk3_c32_t const *ptr;	/* Traverse source string. */

  back = 0; ptr = s;
  while(*(ptr++)) back++;
  return back;
}



size_t
dk3str_c32_len(dk3_c32_t const *s)
{
  size_t back = 0;
  if(s) {
    back = C32LEN(s) ;
  }
  return back;
}



int
dk3str_c32_cmp_fb(dk3_c32_t const *s1, dk3_c32_t const *s2)
{
  register int back;
  register dk3_c32_t const *p1;	/* Traverse left string. */
  register dk3_c32_t const *p2;	/* Traverse right string. */
  register int cc;		/* Flag: Can continue. */

  back = 0; p1 = s1; p2 = s2; cc = 1;
  while((cc) && (back == 0)) {
    if(*p1 > *p2) {
      back = 1;
    } else {
      if(*p1 < *p2) {
        back = -1;
      } else {
        if((*p1) && (*p2)) {
	  p1++; p2++;
	} else {
	  cc = 0;
	}
      }
    }
  }
  return back;
}



int
dk3str_c32_cmp(dk3_c32_t const *s1, dk3_c32_t const *s2)
{
  int back = 0;
  if(s1) {
    if(s2) {
      back = C32CMP(s1,s2) ;
      if(back >  1) back =  1;
      if(back < -1) back = -1;
    } else back = 1;
  } else {
    if(s2) back = -1;
  }
  return back;
}



int
dk3str_c32_ncmp_fb(dk3_c32_t const *s1, dk3_c32_t const *s2, size_t n)
{
  register int back;
  register dk3_c32_t const *p1;	/* Traverse left string. */
  register dk3_c32_t const *p2;	/* Traverse right string. */
  register size_t max;		/* Maximum number of characters to compare. */
  register size_t used;		/* Number of characters used. */

  back = 0; p1 = s1; p2 = s2; max = n; used = 0;
  while((used < max) && (back == 0)) {
    if(*p1 > *p2) {
      back = 1;
    } else {
      if(*p1 < *p2) {
        back = -1;
      } else {
        if((*p1) && (*p2)) {
	  p1++; p2++; used++;
	} else {
	  used = max;
	}
      }
    }
  }
  return back;
}



int
dk3str_c32_ncmp(dk3_c32_t const *s1, dk3_c32_t const *s2, size_t n)
{
  int back = 0;
  if(s1) {
    if(s2) {
      back = C32NCMP(s1,s2,n) ;
      if(back >  1) back =  1;
      if(back < -1) back = -1;
    } else back = 1;
  } else {
    if(s2) back = -1;
  }
  return back;
}



int
dk3str_c32_casecmp_fb(dk3_c32_t const *s1, dk3_c32_t const *s2)
{
  register int back;
  register dk3_c32_t const *p1;	/* Traverse left string. */
  register dk3_c32_t const *p2;	/* Traverse right string. */
  register dk3_c32_t c1;	/* Left character. */
  register dk3_c32_t c2;	/* Right character. */
  register int cc;		/* Flag: Can continue. */

  back = 0; p1 = s1; p2 = s2; cc = 1;
  while((cc) && (back == 0)) {
    c1 = *p1; c2 = *p2;
    if((c1 >= (dk3_c32_t)0x00000041UL) && (c1 <= (dk3_c32_t)0x0000005AUL)) {
      c1 = 0x00000061UL + (c1 - 0x00000041UL);
    }
    if((c2 >= (dk3_c32_t)0x00000041UL) && (c2 <= (dk3_c32_t)0x0000005AUL)) {
      c2 = 0x00000061UL + (c2 - 0x00000041UL);
    }
    if(c1 > c2) {
      back = 1;
    } else {
      if(c1 < c2) {
        back = -1;
      } else {
        if((c1) && (c2)) {
	  p1++; p2++;
	} else {
	  cc = 0;
	}
      }
    }
  }
  return back;
}



int
dk3str_c32_casecmp(dk3_c32_t const *s1, dk3_c32_t const *s2)
{
  int back = 0;
  if(s1) {
    if(s2) {
      back = C32ICMP(s1,s2) ;
      if(back >  1) back =  1;
      if(back < -1) back = -1;
    } else back = 1;
  } else {
    if(s2) back = -1;
  }
  return back;
}


void
dk3str_c32_cpy_fb(dk3_c32_t *d, dk3_c32_t const *s)
{
  register dk3_c32_t *dp;	/* Destination pointer. */
  register dk3_c32_t const *sp;	/* Source pointer. */
  register dk3_c32_t x;		/* Current character. */
  dp = d; sp = s;
  while(*sp) { x = *(sp++); *(dp++) = x; }
  *dp = 0UL;
}



void
dk3str_c32_cpy(dk3_c32_t *d, dk3_c32_t const *s)
{
  if((d) && (s)) {
    C32CPY(d,s) ;
  }
}


void
dk3str_c32_ncpy_fb(dk3_c32_t *d, dk3_c32_t const *s, size_t n)
{
  register dk3_c32_t *dp;	/* Destination pointer. */
  register dk3_c32_t const *sp;	/* Source pointer. */
  register dk3_c32_t x;		/* Current character. */
  register size_t max;		/* Maximum number of characters to copy. */
  register size_t used;		/* Number of characters copied. */

  dp = d; sp = s; max = n; used = 0;
  while((*sp) && (used < max)) { x = *(sp++); *(dp++) = x; used++; }
  if(used < max) { *dp = 0UL; }
  else { d[max - 1] = 0UL; }
}



void
dk3str_c32_ncpy(dk3_c32_t *d, dk3_c32_t const *s, size_t n)
{
  if((d) && (s) && (n)) {
    C32NCPY(d,s,n) ;
    d[n - 1] = 0UL;
  }
}



void
dk3str_c32_cat_fb(dk3_c32_t *d, dk3_c32_t const *s)
{
  register dk3_c32_t *dp;	/* Destination pointer. */
  register dk3_c32_t const *sp;	/* Source pointer. */
  register dk3_c32_t x;		/* Current character. */

  dp = d; sp = s;
  while(*dp) dp++;
  while(*sp) { x = *(sp++); *(dp++) = x; }
  *dp = 0UL;
}



void
dk3str_c32_cat(dk3_c32_t *d, dk3_c32_t const *s)
{
  if((d) && (s)) {
    C32CAT(d,s) ;
  }
}



dk3_c32_t *
dk3str_c32_dup_app(dk3_c32_t const *s, dk3_app_t *app)
{
  dk3_c32_t	*back = NULL;
  size_t	l = 0;		/* String length including delimiter. */
  if(s) {
    l = C32LEN(s) ;
    l++;
    if(l) {
      if(app) { back = (dk3_c32_t *)dk3mem_alloc_app(sizeof(dk3_c32_t),l,app); }
      else { back = (dk3_c32_t *)dk3mem_alloc(sizeof(dk3_c32_t),l); }
      if(back) {
        C32CPY(back,s) ;
      }
    } else {
      if(app) {
        /* ERROR: String too long! */
	dk3app_log_i1(app, DK3_LL_ERROR, 108);
      }
    }
  }
  return back;
}



int
dk3str_c32_array_index(dk3_c32_t const * const *a, dk3_c32_t const *s, int c)
{
  int back = -1;
  int ci;			/* Current index. */
  dk3_c32_t const * const *ap;	/* Pointer into array. */

  if((a) && (s)) {
    ap = a; ci = 0;
    while((*ap) && (back == -1)) {
      if(c) {
        if(dk3str_c32_cmp(*ap, s) == 0) back = ci;
      } else {
        if(dk3str_c32_casecmp(*ap, s) == 0) back = ci;
      }
      if(back == -1) { ap++; ci++; }
    }
  }
  return back;
}



dk3_c32_t *
dk3str_c32_start(dk3_c32_t const *str, dk3_c32_t const *whsp)
{
  dk3_c32_t *back = NULL;
  dk3_c32_t const *ptr = NULL;	/* Current character. */
  dk3_c32_t const *wh = NULL;	/* Whitespaces set. */
  

#line 4837 "dk3str.ctr"
  if(str) {
    wh = (whsp ? whsp : c32_def_whsp);
    ptr = str;
    while((*ptr) && (!(back))) {
      if(dk3str_c32_chr(wh, *ptr)) {
        ptr++;
      } else {
        back = (dk3_c32_t *)ptr;
      }
    }
  } 

#line 4848 "dk3str.ctr"
  return back;
}



void
dk3str_c32_chomp(dk3_c32_t *str, dk3_c32_t const *whsp)
{
  dk3_c32_t const *wh = NULL;	/* Whitespaces set. */
  dk3_c32_t *ptr = NULL;	/* Pointer into string. */
  dk3_c32_t *x = NULL;		/* For whitespace-set test. */

  if(str) {
    wh = (whsp ? whsp : c32_def_whsp);
    x = NULL; ptr = str;
    while(*ptr) {
      if(dk3str_c32_chr(wh, *ptr)) {
        if(!(x)) x = ptr;
      } else {
        x = NULL;
      }
      ptr++;
    }
    if(x) { *x = 0UL; }
  }
}



void
dk3str_c32_delnl(dk3_c32_t *str)
{
  dk3_c32_t	*ptr;
  if(str) {
    ptr = str;
    while(*ptr) {
      if(*ptr == 0x0000000DUL) {
        if(ptr[1] == 0x0000000AUL) {
	  *ptr = (dk3_c32_t)0UL;
	} else {
	  ptr++;
	}
      } else {
        if(*ptr == 0x0000000AUL) {
	  *ptr = (dk3_c32_t)0UL;
	} else {
	  ptr++;
	}
      }
    }
  }
}




dk3_c32_t *
dk3str_c32_next(dk3_c32_t *str, dk3_c32_t const *whsp)
{
  dk3_c32_t *back = NULL;
  dk3_c32_t *ptr = NULL;	/* Pointer into string. */
  dk3_c32_t const *wh = NULL;	/* Whitespaces. */
  int state = 0;		/* Current processing state. */
  

#line 4912 "dk3str.ctr"
  if(str) {
    ptr = str;
    wh = (whsp ? whsp : c32_def_whsp);
    state = 0;
    while((state < 2) && (*ptr)) {
      if(dk3str_c32_chr(wh, *ptr)) {	

#line 4918 "dk3str.ctr"
        if(state == 1) {
	  state = 2;
	  *(ptr++) = 0UL;
	  back = dk3str_c32_start(ptr, wh);
	} else {
	  ptr++;
	}
      } else {
        state = 1; ptr++;
      }
    }
  } 

#line 4930 "dk3str.ctr"
  return back;
}


int
dk3str_c32_is_abbr(dk3_c32_t const *line, dk3_c32_t const *pattern, dk3_c32_t spec, int cs)
{
  int back = 0;
  dk3_c32_t cl = 0UL;		/* Text character. */
  dk3_c32_t cp = 0UL;		/* Pattern character. */
  dk3_c32_t const *lptr = NULL;	/* Pointer into text. */
  dk3_c32_t const *pptr = NULL;	/* Pointer into pattern. */
  int afterspec = 0;		/* Flag: Abbreviation indicator was found. */
  int cc = 0;			/* Flag: Can continue. */

  if((line) && (pattern)) {
    lptr = line; pptr = pattern; afterspec = 0; cc = 1;
    while(cc) {
      if(*pptr) {
        if((!afterspec) && (*pptr == spec)) {
	  afterspec = 1; pptr++;
	} else {
	  if(*lptr) {
	    cl = *lptr; cp = *pptr;
	    if(!cs) {
	      cl = dk3str_c32_toupper(cl);
	      cp = dk3str_c32_toupper(cp);
	    }
	    if(cl == cp) {
	      lptr++; pptr++;
	    } else {
	      cc = 0; back = 0;
	    }
	  } else {
	    cc = 0;
	    if(afterspec) back = 1;
	  }
	}
      } else {
        cc = 0;
	if(!(*lptr)) { back = 1; }
      }
    }
  }
  return back;
}


int
dk3str_c32_array_abbr(dk3_c32_t const * const *arr, dk3_c32_t const *str, dk3_c32_t sp, int cs)
{
  int back = -1;
  dk3_c32_t const * const *ptr = NULL;	/* Pointer into array. */
  int i = 0;				/* Current index. */

  if((arr) && (str)) {
    i = 0; ptr = arr;
    while((*ptr) && (back == -1)) {
      if(dk3str_c32_is_abbr(str, *ptr, sp, cs)) {
        back = i;
      }
      if(back == -1) {
        ptr++; i++;
      }
    }
  }
  return back;
}



int
dk3str_c32_to_c8_simple_app(char *d, size_t sz, dk3_c32_t const *s, dk3_app_t *app)
{
  int back = 0;
  dk3_c32_t const *ptr = NULL;	/* Pointer into source string. */
  dk3_c32_t c = 0UL;		/* Source character. */
  unsigned char uc = 0x00;	/* Destination character. */
  char *dptr = NULL;		/* Destination pointer. */

  if((d) && (sz) && (s)) {
    if(dk3str_c32_len(s) < sz) {
      back = 1; ptr = s; dptr = d;
      while((c = *ptr)) {
        if(c < (dk3_c32_t)0x00000100UL) {
	  uc = (unsigned char)c;
	  *(dptr++) = (char)uc;
	} else {
	  if((back == 1) && (app)) {
	    /* ERROR: Illegal character(s) in source string! */
	    dk3app_log_i1(app, DK3_LL_ERROR, 112);
	  }
	  back = 0;
	}
	ptr++;
      }
      *dptr = '\0';
    } else {
      d[0] = '\0';
      if(app) {
        /* ERROR: Source string too long! */
	dk3app_log_i1(app, DK3_LL_ERROR, 108);
      }
    }
  }
  return back;
}



int
dk3str_c32_is_bool(dk3_c32_t const *str)
{
  int back = 0;
  char mytest[256];	/* 8-bit text copy of str. */
  if(str) {
    if(dk3str_c32_to_c8_simple(mytest, sizeof(mytest), str)) {
      back = dk3str_c8_is_bool(mytest);
    }
  }
  return back;
}



int
dk3str_c32_is_on(dk3_c32_t const *str)
{
  int back = 0;
  char mytest[256];	/* 8-bit copy of str text. */
  if(str) {
    if(dk3str_c32_to_c8_simple(mytest, sizeof(mytest), str)) {
      back = dk3str_c8_is_on(mytest);
    }
  }
  return back;
}



size_t
dk3str_c32_explode(dk3_c32_t **array, size_t sz, dk3_c32_t *str, dk3_c32_t const *whsp)
{
  size_t		back = 0;
  dk3_c32_t const	*wh = NULL;	/* Whitespace set. */
  dk3_c32_t		*current = NULL;	/* Current word. */
  dk3_c32_t		*next = NULL;	/* Next word. */
  dk3_c32_t		**ptr = NULL;	/* Pointer into destination array. */
  size_t		i = 0;		/* Current index. */
  if((array) && (sz > 1) && (str)) {
    wh = (whsp ? whsp : c32_def_whsp);
    ptr = array; i = sz;
    while(i--) { *(ptr++) = NULL; }
    ptr = array; i = 0;
    current = dk3str_c32_start(str, wh);
    while((current) && (i < (sz - 1))) {
      next = dk3str_c32_next(current, wh);
      *(ptr++) = current; i++; back++;
      current = next;
    }
  }
  return back;
}


void
dk3str_c32_normalize(dk3_c32_t *l, dk3_c32_t const *w, char s)
{
  dk3_c32_t	*parts[256];	/* Words. */
  dk3_c32_t	*dp = NULL;	/* Destination pointer. */
  dk3_c32_t	*sp = NULL;	/* Source pointer. */
  size_t	np = 0;	/* Number of words. */
  size_t	i = 0;		/* Index of current word. */
  if(l) {
    np = dk3str_c32_explode(parts, 255, l, w);
    if(np > 0) {
      dp = l;
      for(i = 0; i < np; i++) {
        sp = parts[i];
	if(i) { *(dp++) = s; }
	while(*sp) { *(dp++) = *(sp++); }
      }
      *dp = 0UL;
    }
  }
}


void
dk3str_c32_correct_filename(dk3_c32_t *n)
{
  register dk3_c32_t *p;	/* Pointer into text. */
  p = n;
  while(*p) { if(*p == NO_FNS_C32) { *p = FNS_C32; } p++;}
} 




int
dk3str_c32_is_abs_path(dk3_c32_t const *n)
{
  int back = 0;
  

#line 5134 "dk3str.ctr"
  if(n) {
    if(*n == FNS_C32) {
      back = 1;
    } else {
#if DK3_ON_WINDOWS
      if(((*n >= 0x00000061UL) && (*n <= 0x0000007AUL))
        || ((*n >= 0x00000041UL) && (*n <= 0x0000005AUL)))
      {
        if(n[1] == 0x0000003AUL) {
	  if(n[2] == FNS_C32) {
	    back = 1;
	  }
	}
      }
#endif
    }
  } 

#line 5151 "dk3str.ctr"
  return back;
}



int
dk3str_c32_append_path_app(dk3_c32_t *d, size_t sz, dk3_c32_t const *n, dk3_app_t *app)
{
  int back = 0;
  dk3_c32_t	myn[DK3_MAX_PATH];	/* My editable copy of n. */
  dk3_c32_t	*p1 = NULL;		/* Current name part. */
  dk3_c32_t	*p2 = NULL;		/* Remaining text. */
  dk3_c32_t	*p3 = NULL;		/* Used to delete one part from path. */

  

#line 5166 "dk3str.ctr"
  if((d) && (sz) && (n)) {
    if(dk3str_c32_is_abs_path(n)) {	

#line 5168 "dk3str.ctr"
      if(C32LEN(n) < sz) {
        C32CPY(d,n) ;
	back = 1;
      } else {
        if(app) {
	  /* ERROR: Name n too long! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 109);
	}
      }
    } else {				

#line 5178 "dk3str.ctr"
      if(C32LEN(n) < DK3_SIZEOF(myn,dk3_c32_t)) {
        back = 1;
	C32CPY(myn,n) ;
	p1 = myn;
	while((p1) && (back)) {
	  p2 = C32CHR(p1,FNS_C32);
	  if(p2) { *(p2++) = 0UL; }
	  if(C32CMP(c32_dot,p1)) {
	    if(C32CMP(c32_dot_dot,p1)) {
	      if((C32LEN(d) + C32LEN(c32_fnsep) + C32LEN(p1)) < sz) {
	        C32CAT(d,c32_fnsep);
		C32CAT(d,p1);
	      } else {
	        if(app) {
		  /* ERROR: Result too long for destination buffer! */
		  dk3app_log_i1(app, DK3_LL_ERROR, 38);
		}
	      }
	    } else {
	      p3 = C32RCHR(d,FNS_C32);
	      if(p3) {
	        *p3 = 0UL;
	      } else {
	        if(app) {
		  /* ERROR: Too many ".." entries! */
		  dk3app_log_i1(app, DK3_LL_ERROR, 110);
		}
	      }
	    }
	  }
	  p1 = p2;
	}
      } else {
        if(app) {
	  /* ERROR: Name n too long! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 109);
	}
      }
    }
  }
  if(back) {	

#line 5219 "dk3str.ctr"
  } 

#line 5220 "dk3str.ctr"
  return back;
}



/**	Convert 8-bit plain text to other encodings.
	@param	d	Destination buffer (NULL to just count result elements).
	@param	s	Source string.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	enc	Destination encoding (DK3_ENCODING_xxx).
	@return	Number of destination elements created.
*/
static
size_t
dk3str_i_cnv_c8p(void *d, char const *s, dk3_app_t *app, int enc)
{
  size_t	back = 0;
  int		error = 0;	/* Flag: Error occured. */
  char const	*sptr = NULL;	/* Source pointer. */
  char 		*dp8 = NULL;	/* Pointer to 8-bit destination. */
  dk3_c16_t	*dp16 = NULL;	/* Pointer to 16-bit destination. */
  dk3_c32_t	*dp32 = NULL;	/* Pointer to 32-bit destination. */
  char		c = 0x00;	/* Current source character to process. */
  unsigned char	uc = 0x00;	/* Destination byte. */
  dk3_c32_t	ul = 0UL;	/* Conversion result. */
  unsigned char	myuc[16];	/* Conversion result buffer. */
  dk3_c16_t	myc16[16];	/* Conversion result buffer. */
  size_t	u8u = 0;	/* UTF-8 bytes used for encoding. */
  size_t	u16u = 0;	/* UTF-16 characters used for encoding. */
  size_t	sl = 0;		/* Number of remaining characters in source. */
  size_t	i = 0;		/* Copy converted characters to destination. */
  if(s) {
    sptr = s; sl = dk3str_c8_len(s);
    if(d) {
      switch(enc) {
        case DK3_ENCODING_UTF8: { dp8 = (char *)d; } break;
	case DK3_ENCODING_UTF16: { dp16 = (dk3_c16_t *)d; } break;
	case DK3_ENCODING_UNICODE: { dp32 = (dk3_c32_t *)d; } break;
	default: {
	  if(app) {
	    /* ERROR: Illegal destination encoding! */
	    dk3app_log_i1(app, DK3_LL_ERROR, 114);
	  }
	} break;
      }
    }
    while((sl) && (0 == error)) {
      c = *(sptr++); sl--;
      uc = (unsigned char)c;
      ul = (dk3_c32_t)uc;
      ul &= 0x000000FFUL;
      switch(enc) {
        case DK3_ENCODING_UTF8: {
	  u8u = dk3enc_uc2utf8(ul, myuc, 16);
	  if(u8u) {
	    back = dk3ma_sz_add_ok(back, u8u, &error);
	    if(d) {
	      for(i = 0; i < u8u; i++) { *(dp8++) = myuc[i]; }
	    }
	  } else {
	    if(0 == error) {
	      if(app) {
	        /* ERROR: Conversion to UTF-8 failed! */
		dk3app_log_i1(app, DK3_LL_ERROR, 115);
	      }
	    } error = 1;
	  }
	} break;
	case DK3_ENCODING_UTF16: {
	  u16u = dk3enc_uc2utf16(ul, myc16, 16);
	  if(u16u) {
	    back = dk3ma_sz_add_ok(back, u16u, &error);
	    if(d) {
	      for(i = 0; i < u16u; i++) { *(dp16++) = myc16[i]; }
	    }
	  } else {
	    if(0 == error) {
	      if(app) {
	        /* ERROR: Conversion to UTF-16 failed! */
		dk3app_log_i1(app, DK3_LL_ERROR, 116);
	      }
	    } error = 1;
	  }
	} break;
	case DK3_ENCODING_UNICODE: {
	  back = dk3ma_sz_add_ok(back, 1, &error);
	  if(d) { *(dp32++) = ul; }
	} break;
      }
    }
    if(d) {
      switch(enc) {
        case DK3_ENCODING_UTF8: { *dp8 = '\0'; } break;
	case DK3_ENCODING_UTF16: { *dp16 = 0U; } break;
	case DK3_ENCODING_UNICODE: { *dp32 = 0UL; } break;
      }
    }
    back = dk3ma_sz_add_ok(back, 1, &error);
    if(error) {
      back = 0;
      if(error == DK3_ERROR_MATH_OVERFLOW) {
        if(app) {
	  /* ERROR: Input string too long for conversion! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 108);
	}
      }
    }
  }
  return back;
}




size_t
dk3str_cnvsz_c8p_to_c8u_app(char const *s, dk3_app_t *app)
{
  size_t back = 0;
  if(s) {
    back = dk3str_i_cnv_c8p(NULL, s, app, DK3_ENCODING_UTF8);
  }
  return back;
}


int
dk3str_cnv_c8p_to_c8u_app(char *d, size_t ds, char const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Number of chars produced. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c8p(NULL, s, app, DK3_ENCODING_UTF8);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c8p((void *)d, s, app, DK3_ENCODING_UTF8)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Destination buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}



char *
dk3str_cnvnew_c8p_to_c8u_app(char const *s, dk3_app_t *app)
{
  char		*back = NULL;
  size_t	sz;		/* Number of characters produced. */
  if(s) {
    sz = dk3str_i_cnv_c8p(NULL, s, app, DK3_ENCODING_UTF8);
    if(sz) {
      back = dk3_new_app(char,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c8p((void *)back, s, app, DK3_ENCODING_UTF8)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}



size_t
dk3str_cnvsz_c8p_to_c16_app(char const *s, dk3_app_t *app)
{
  size_t back = 0;
  if(s) {
    back = dk3str_i_cnv_c8p(NULL, s, app, DK3_ENCODING_UTF16);
  }
  return back;
}



int
dk3str_cnv_c8p_to_c16_app(dk3_c16_t *d, size_t ds, char const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Destination buffer length needed. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c8p(NULL, s, app, DK3_ENCODING_UTF16);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c8p((void *)d, s, app, DK3_ENCODING_UTF16)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Destination buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}



dk3_c16_t *
dk3str_cnvnew_c8p_to_c16_app(char const *s, dk3_app_t *app)
{
  dk3_c16_t	*back = NULL;
  size_t	sz;		/* Destination buffer length needed. */
  if(s) {
    sz = dk3str_i_cnv_c8p(NULL, s, app, DK3_ENCODING_UTF16);
    if(sz) {
      back = dk3_new_app(dk3_c16_t,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c8p((void *)back, s, app, DK3_ENCODING_UTF16)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}



size_t
dk3str_cnvsz_c8p_to_c32_app(char const *s, dk3_app_t *app)
{
  size_t back = 0;
  if(s) {
    back = dk3str_i_cnv_c8p(NULL, s, app, DK3_ENCODING_UNICODE);
  }
  return back;
}



int
dk3str_cnv_c8p_to_c32_app(dk3_c32_t *d, size_t ds, char const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Destination buffer length needed. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c8p(NULL, s, app, DK3_ENCODING_UNICODE);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c8p((void *)d, s, app, DK3_ENCODING_UNICODE)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Destination buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}



dk3_c32_t *
dk3str_cnvnew_c8p_to_c32_app(char const *s, dk3_app_t *app)
{
  dk3_c32_t	*back = NULL;
  size_t	sz;		/* Destination buffer length needed. */
  if(s) {
    sz = dk3str_i_cnv_c8p(NULL, s, app, DK3_ENCODING_UNICODE);
    if(sz) {
      back = dk3_new_app(dk3_c32_t,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c8p((void *)back, s, app, DK3_ENCODING_UNICODE)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}



/**	Convert UTF-8 string to other encodings.
	@param	d	Destination pointer, may be NULL.
	@param	s	Source string.
	@param	app	Application structure for diagnostics, may be NULL.
	@param	enc	Destination encoding.
	@return	Buffer length used (d!=NULL) or needed (d==NULL).
*/
static
size_t
dk3str_i_cnv_c8u(void *d, char const *s, dk3_app_t *app, int enc)
{
  size_t		back = 0;
  int			error = 0;	/* Flag: Error occued. */
  char			*dp8 = NULL;	/* Pointer to 8-bit destination. */
  dk3_c16_t		*dp16 = NULL;	/* Pointer to 16-bit destination. */
  dk3_c32_t		*dp32 = NULL;	/* Pointer to 32-bit destination. */
  dk3_c16_t		myc16[16];	/* Conversion result buffer. */
  dk3_c32_t		c32 = 0UL;	/* Conversion result. */
  unsigned char		uc = 0x00;	/* Result character. */
  char			c = 0x00;	/* Current character to process. */
  unsigned char const	*sptr = NULL;	/* Source ponter. */
  size_t		u8u = 0;	/* Number of UTF-8 bytes used. */
  size_t		u16u = 0;	/* Number of UTF-16 chars produced. */
  size_t		i = 0;		/* Copy buffer to destination. */
  size_t		sl = 0;		/* Remaining source string length. */
  

#line 5533 "dk3str.ctr"
  if(s) {
    /* Initialize variables */
    sptr = (unsigned char const *)s; sl = dk3str_c8_len(s);
    if(d) {
      switch(enc) {
        case DK3_ENCODING_PLAIN: { dp8 = (char *)d; } break;
	case DK3_ENCODING_UTF16: { dp16 = (dk3_c16_t *)d; } break;
	case DK3_ENCODING_UNICODE: { dp32 = (dk3_c32_t *)d; } break;
	default: {
	  if(0 == error) {
	    if(app) {
	      /* ERROR: Illegal output encoding! */
	      dk3app_log_i1(app, DK3_LL_ERROR, 114);
	    }
	  } error = 1;
	} break;
      }
    }
    /* Process input */
    while((sl) && (0 == error)) {
      u8u = 0;
      if(dk3enc_utf82uc(&c32, sptr, sl, &u8u)) {
        if(u8u) {
	  switch(enc) {
            case DK3_ENCODING_PLAIN: {
	      if(c32 < (dk3_c32_t)0x00000100UL) {
		back = dk3ma_sz_add_ok(back, 1, &error);
		if(d) {
	          uc = (unsigned char)c32;
		  c = (char)uc;
		  *(dp8++) = c;
		}
	      } else {
	        if(0 == error) {
		  if(app) {
		    /* ERROR: Result character out of range! */
		    dk3app_log_i1(app, DK3_LL_ERROR, 117);
		  }
		} error = 1;
	      }
	    } break;
	    case DK3_ENCODING_UTF16: {
	      u16u = dk3enc_uc2utf16(c32, myc16, 16);
	      if(u16u) {
		back = dk3ma_sz_add_ok(back, u16u, &error);
		if(d) {
		  for(i = 0; i < u16u; i++) { *(dp16++) = myc16[i]; }
		}
	      } else {
	        if(0 == error) {
		  if(app) {
		    /* ERROR: Conversion to UTF-16 failed! */
		    dk3app_log_i1(app, DK3_LL_ERROR, 116);
		  }
		} error = 1;
	      }
	    } break;
	    case DK3_ENCODING_UNICODE: {
	      back = dk3ma_sz_add_ok(back, 1, &error);
	      if(d) { *(dp32++) = c32; }
	    } break;
	  }
	  if(sl >= u8u) {
	    sl = sl - u8u;
	    sptr = &(sptr[u8u]);
	  } else {
	    sl = 0;
	  }
	} else {
	  if(0 == error) {
	    if(app) {
	      /* ERROR: UTF-8 decode operation failed! */
	      dk3app_log_i1(app, DK3_LL_ERROR, 118);
	    }
	  } error = 1;
	}
      } else {
        if(0 == error) {
	  if(app) {
	    /* ERROR: UTF-8 decode operation failed! */
	    dk3app_log_i1(app, DK3_LL_ERROR, 118);
	  }
	} error = 1;
      }
    }
    /* Finalize output */
    back = dk3ma_sz_add_ok(back, 1, &error);
    if(d) {
      switch(enc) {
        case DK3_ENCODING_PLAIN: { *dp8 = '\0'; } break;
	case DK3_ENCODING_UTF16: { *dp16 = 0U; } break;
	case DK3_ENCODING_UNICODE: { *dp32 = 0UL; } break;
      }
    }
    if(error) {
      back = 0;
      if(error == DK3_ERROR_MATH_OVERFLOW) {
        if(app) {
	  /* ERROR: Input string too long for conversion! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 108);
	}
      }
    }
  } 

#line 5637 "dk3str.ctr"
  return back;
}



size_t
dk3str_cnvsz_c8u_to_c8p_app(char const *s, dk3_app_t *app)
{
  size_t back = 0;
  if(s) {
    back = dk3str_i_cnv_c8u(NULL, s, app, DK3_ENCODING_PLAIN);
  }
  return back;
}



int
dk3str_cnv_c8u_to_c8p_app(char *d, size_t ds, char const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Destination buffer length needed. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c8u(NULL, s, app, DK3_ENCODING_PLAIN);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c8u((void *)d, s, app, DK3_ENCODING_PLAIN)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Destination buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}


char *
dk3str_cnvnew_c8u_to_c8p_app(char const *s, dk3_app_t *app)
{
  char		*back = NULL;
  size_t	sz;		/* Destination buffer length needed. */
  if(s) {
    sz = dk3str_i_cnv_c8u(NULL, s, app, DK3_ENCODING_PLAIN);
    if(sz) {
      back = dk3_new_app(char,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c8u((void *)back, s, app, DK3_ENCODING_PLAIN)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}




size_t
dk3str_cnvsz_c8u_to_c16_app(char const *s, dk3_app_t *app)
{
  size_t back = 0;
  if(s) {
    back = dk3str_i_cnv_c8u(NULL, s, app, DK3_ENCODING_UTF16);
  }
  return back;
}



int
dk3str_cnv_c8u_to_c16_app(dk3_c16_t *d, size_t ds, char const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Destination buffer length needed. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c8u(NULL, s, app, DK3_ENCODING_UTF16);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c8u((void *)d, s, app, DK3_ENCODING_UTF16)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Destination buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}



dk3_c16_t *
dk3str_cnvnew_c8u_to_c16_app(char const *s, dk3_app_t *app)
{
  dk3_c16_t	*back = NULL;
  size_t	sz;		/* Destination buffer length needed. */
  if(s) {
    sz = dk3str_i_cnv_c8u(NULL, s, app, DK3_ENCODING_UTF16);
    if(sz) {
      back = dk3_new_app(dk3_c16_t,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c8u((void *)back, s, app, DK3_ENCODING_UTF16)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}



size_t
dk3str_cnvsz_c8u_to_c32_app(char const *s, dk3_app_t *app)
{
  size_t back = 0;
  

#line 5763 "dk3str.ctr"
  if(s) {
    back = dk3str_i_cnv_c8u(NULL, s, app, DK3_ENCODING_UNICODE);
  } 

#line 5766 "dk3str.ctr"
  return back;
}



int
dk3str_cnv_c8u_to_c32_app(dk3_c32_t *d, size_t ds, char const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Destination buffer length needed. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c8u(NULL, s, app, DK3_ENCODING_UNICODE);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c8u((void *)d, s, app, DK3_ENCODING_UNICODE)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Destination buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}



dk3_c32_t *
dk3str_cnvnew_c8u_to_c32_app(char const *s, dk3_app_t *app)
{
  dk3_c32_t	*back = NULL;
  size_t	sz;		/* Destination buffer length needed. */
  if(s) {
    sz = dk3str_i_cnv_c8u(NULL, s, app, DK3_ENCODING_UNICODE);
    if(sz) {
      back = dk3_new_app(dk3_c32_t,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c8u((void *)back, s, app, DK3_ENCODING_UNICODE)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}



/**	Convert 16-bit character string to other encodings.
	@param	d	Destination pointer (NULL for size check).
	@param	s	Source string.
	@param	app	Application structure for diagnostics.
	@param	enc	Destination encoding.
	@return	Number of destination characters needed/produced.
*/
static
size_t
dk3str_i_cnv_c16(void *d, dk3_c16_t const *s, dk3_app_t *app, int enc)
{
  size_t		back = 0;
  int			error = 0;	/* Flag: Error occured. */
  char			*dp8 = NULL;	/* Pointer to 8-bit destination. */
  dk3_c32_t		*dp32 = NULL;	/* Pointer to 32-bit destination. */
  dk3_c16_t const	*sptr = NULL;	/* Source pointer. */
  dk3_c32_t		c32 = 0UL;	/* Conversion result. */
  unsigned char		uc = 0x00;	/* Current output character. */
  char			c = 0x00;	/* Current output character. */
  unsigned char		myuc[16];	/* Conversion result buffer. */
  size_t		sl = 0;		/* Remaining string length. */
  size_t		u16u = 0;	/* Number of U16 characters used. */
  size_t		u8u = 0;	/* Number of 8-bit chars produced. */
  size_t		i = 0;		/* Copy buffer to destination. */
  if(s) {
    /* Initialize variables */
    sptr = s; sl = dk3str_c16_len(s);
    if(d) {
      switch(enc) {
        case DK3_ENCODING_PLAIN: { dp8 = (char *)d; } break;
	case DK3_ENCODING_UTF8:	{ dp8 = (char *)d; } break;
	case DK3_ENCODING_UNICODE: { dp32 = (dk3_c32_t *)d; } break;
	default: {
	  if(0 == error) {
	    if(app) {
	      /* ERROR: Illegal output encoding! */
	      dk3app_log_i1(app, DK3_LL_ERROR, 114);
	    }
	  } error = 1;
	} break;
      }
    }
    /* Process input */
    while((sl) && (0 == error)) {
      u16u = 0;
      if(dk3enc_utf162uc(&c32, sptr, sl, &u16u)) {
        if(u16u) {
	  if(sl >= u16u) {
	    switch(enc) {
              case DK3_ENCODING_PLAIN: {
	        if(c32 < (dk3_c32_t)0x00000100UL) {
		  back = dk3ma_sz_add_ok(back, 1, &error);
		  if(d) {
		    uc = (unsigned char)c32; c = (char)uc;
		    *(dp8++) = c;
		  }
		} else {
		  if(0 == error) {
		    if(app) {
		      /* ERROR: Result character out of range! */
		      dk3app_log_i1(app, DK3_LL_ERROR, 117);
		    }
		  } error = 1;
		}
	      } break;
	      case DK3_ENCODING_UTF8:	{
	        u8u = dk3enc_uc2utf8(c32, myuc, 16);
		if(u8u) {
		  back = dk3ma_sz_add_ok(back, u8u, &error);
		  if(d) {
		    for(i = 0; i < u8u; i++) { *(dp8++) = myuc[i]; }
		  }
		} else {
		  if(0 == error) {
		    if(app) {
		      /* ERROR: Conversion to UTF-8 failed! */
		      dk3app_log_i1(app, DK3_LL_ERROR, 115);
		    }
		  } error = 1;
		}
	      } break;
	      case DK3_ENCODING_UNICODE: {
		back = dk3ma_sz_add_ok(back, 1, &error);
		if(d) { *(dp32++) = c32; }
	      } break;
	    }
	    sl = sl - u16u;
	    sptr = &(sptr[u16u]);
	  } else {
	    sl = 0;
	  }
	} else {
	  if(0 == error) {
	    if(app) {
	      /* ERROR: UTF-16 decode operation failed! */
	      dk3app_log_i1(app, DK3_LL_ERROR, 119);
	    }
	  } error = 1;
	}
      } else {
        if(0 == error) {
	  if(app) {
	    /* ERROR: UTF-16 decode operation failed! */
	    dk3app_log_i1(app, DK3_LL_ERROR, 119);
	  }
	} error = 1;
      }
    }
    /* Finalize output */
    back = dk3ma_sz_add_ok(back, 1, &error);
    if(d) {
      switch(enc) {
        case DK3_ENCODING_PLAIN: { *dp8 = '\0'; } break;
	case DK3_ENCODING_UTF8:	{ *dp8 = '\0'; } break;
	case DK3_ENCODING_UNICODE: { *dp32 = 0UL; } break;
      }
    }
    if(error) {
      back = 0;
      if(error == DK3_ERROR_MATH_OVERFLOW) {
        if(app) {
	  /* ERROR: Input string too long for conversion! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 108);
	}
      }
    }
  }
  return back;
}



size_t
dk3str_cnvsz_c16_to_c8p_app(dk3_c16_t const *s, dk3_app_t *app)
{
  size_t back = 0;
  if(s) {
    back = dk3str_i_cnv_c16(NULL, s, app, DK3_ENCODING_PLAIN);
  }
  return back;
}



int
dk3str_cnv_c16_to_c8p_app(char *d, size_t ds, dk3_c16_t const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Destination buffer size needed. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c16(NULL, s, app, DK3_ENCODING_PLAIN);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c16((void *)d, s, app, DK3_ENCODING_PLAIN)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Result buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}



char *
dk3str_cnvnew_c16_to_c8p_app(dk3_c16_t const *s, dk3_app_t *app)
{
  char		*back = NULL;
  size_t	sz;		/* Destination buffer size needed. */
  if(s) {
    sz = dk3str_i_cnv_c16(NULL, s, app, DK3_ENCODING_PLAIN);
    if(sz) {
      back = dk3_new_app(char,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c16((void *)back, s, app, DK3_ENCODING_PLAIN)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}



size_t
dk3str_cnvsz_c16_to_c8u_app(dk3_c16_t const *s, dk3_app_t *app)
{
  size_t back = 0;
  if(s) {
    back = dk3str_i_cnv_c16(NULL, s, app, DK3_ENCODING_UTF8);
  }
  return back;
}



int
dk3str_cnv_c16_to_c8u_app(char *d, size_t ds, dk3_c16_t const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Destination buffer size needed. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c16(NULL, s, app, DK3_ENCODING_UTF8);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c16((void *)d, s, app, DK3_ENCODING_UTF8)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Result buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}


char *
dk3str_cnvnew_c16_to_c8u_app(dk3_c16_t const *s, dk3_app_t *app)
{
  char		*back = NULL;
  size_t	sz;		/* Destination buffer size needed. */
  if(s) {
    sz = dk3str_i_cnv_c16(NULL, s, app, DK3_ENCODING_UTF8);
    if(sz) {
      back = dk3_new_app(char,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c16((void *)back, s, app, DK3_ENCODING_UTF8)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}



size_t
dk3str_cnvsz_c16_to_c32_app(dk3_c16_t const *s, dk3_app_t *app)
{
  size_t back = 0;
  if(s) {
    back = dk3str_i_cnv_c16(NULL, s, app, DK3_ENCODING_UNICODE);
  }
  return back;
}



int
dk3str_cnv_c16_to_c32_app(dk3_c32_t *d, size_t ds, dk3_c16_t const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Destination buffer size needed. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c16(NULL, s, app, DK3_ENCODING_UNICODE);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c16((void *)d, s, app, DK3_ENCODING_UNICODE)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Result buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}



dk3_c32_t *
dk3str_cnvnew_c16_to_c32_app(dk3_c16_t const *s, dk3_app_t *app)
{
  dk3_c32_t	*back = NULL;
  size_t	sz;		/* Destination buffer size needed. */
  if(s) {
    sz = dk3str_i_cnv_c16(NULL, s, app, DK3_ENCODING_UNICODE);
    if(sz) {
      back = dk3_new_app(dk3_c32_t,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c16((void *)back, s, app, DK3_ENCODING_UNICODE)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}



/**	Convert 32-bit character string to other encodings.
	@param	d	Destination buffer pointer (may be NULL for size check).
	@param	s	Source string.
	@param	app	Application structure for diagnostics.
	@param	enc	Output encoding.
	@return	Number of destination characters produced/needed.
*/
static
size_t
dk3str_i_cnv_c32(void *d, dk3_c32_t const *s, dk3_app_t *app, int enc)
{
  size_t		back = 0;
  int			error = 0;	/* Flag: Error occured. */
  char			*dp8 = NULL;	/* Pointer to 8-bit destination. */
  dk3_c16_t		*dp16 = NULL;	/* Pointer to 16-bit destination. */
  dk3_c32_t const	*sptr = NULL;	/* Source pointer. */
  dk3_c32_t		c32 = 0UL;	/* Current character to process. */
  dk3_c16_t		myc16[16];	/* Conversion result buffer. */
  unsigned char		myuc[16];	/* Conversion result buffer. */
  unsigned char		uc = 0x00;	/* Output character. */
  char			c = 0x00;	/* Output character. */
  size_t		sl = 0;		/* Remaining string length. */
  size_t		u8u = 0;	/* Number of UTF-8 chars produced. */
  size_t		u16u = 0;	/* Numer of UTF-16 chars produced. */
  size_t		i = 0;		/* Copy buffer to destination. */
  if(s) {
    /* Initialize variables */
    sptr = s; sl = dk3str_c32_len(s);
    if(d) {
      switch(enc) {
        case DK3_ENCODING_PLAIN: { dp8 = (char *)d; } break;
	case DK3_ENCODING_UTF8: { dp8 = (char *)d; } break;
	case DK3_ENCODING_UTF16: { dp16 = (dk3_c16_t *)d; } break;
	default: {
	  if(0 == error) {
	    if(app) {
	      /* ERROR: Illegal output encoding! */
	      dk3app_log_i1(app, DK3_LL_ERROR, 114);
	    }
	  } error = 1;
	} break;
      }
    }
    /* Process input */
    while((sl) && (0 == error)) {
      c32 = *(sptr++); sl--;
      switch(enc) {
        case DK3_ENCODING_PLAIN: {
	  if(c32 < (dk3_c32_t)0x00000100UL) {
	    back = dk3ma_sz_add_ok(back, 1, &error);
	    if(d) {
	      uc = (unsigned char)c32; c = (char)uc;
	      *(dp8++) = c;
	    }
	  } else {
	    if(0 == error) {
	      if(app) {
	        /* ERROR: Output character out of range! */
		dk3app_log_i1(app, DK3_LL_ERROR, 117);
	      }
	    } error = 1;
	  }
	} break;
	case DK3_ENCODING_UTF8: {
	  u8u = dk3enc_uc2utf8(c32, myuc, 16);
	  if(u8u) {
	    back = dk3ma_sz_add_ok(back, u8u, &error);
	    if(d) {
	      for(i = 0; i < u8u; i++) { *(dp8++) = myuc[i]; }
	    }
	  } else {
	    if(0 == error) {
	      if(app) {
	        /* ERROR: UTF-8 encoding failed! */
		dk3app_log_i1(app, DK3_LL_ERROR, 115);
	      }
	    } error = 1;
	  }
	} break;
	case DK3_ENCODING_UTF16: {
	  u16u = dk3enc_uc2utf16(c32, myc16, 16);
	  if(u16u) {
	    back = dk3ma_sz_add_ok(back, u16u, &error);
	    if(d) {
	      for(i = 0; i < u16u; i++) { *(dp16++) = myc16[i]; }
	    }
	  } else {
	    if(0 == error) {
	      if(app) {
	        /* ERROR: Conversion to UTF-16 failed! */
		dk3app_log_i1(app, DK3_LL_ERROR, 116);
	      }
	    } error = 1;
	  }
	} break;
      }
    }
    /* Finalize output */
    back = dk3ma_sz_add_ok(back, 1, &error);
    if(d) {
      switch(enc) {
        case DK3_ENCODING_PLAIN: { *dp8 = '\0'; } break;
	case DK3_ENCODING_UTF8: { *dp8 = '\0'; } break;
	case DK3_ENCODING_UTF16: { *dp16 = 0U; } break;
      }
    }
    if(error) {
      back = 0;
      if(error == DK3_ERROR_MATH_OVERFLOW) {
        if(app) {
	  /* ERROR: Input string too long for conversion! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 108);
	}
      }
    }
  }
  return back;
}



size_t
dk3str_cnvsz_c32_to_c8p_app(dk3_c32_t const *s, dk3_app_t *app)
{
  size_t back = 0;
  if(s) {
    back = dk3str_i_cnv_c32(NULL, s, app, DK3_ENCODING_PLAIN);
  }
  return back;
}



int
dk3str_cnv_c32_to_c8p_app(char *d, size_t ds, dk3_c32_t const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Destination buffer size needed. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c32(NULL, s, app, DK3_ENCODING_PLAIN);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c32((void *)d, s, app, DK3_ENCODING_PLAIN)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Destination buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}



char *
dk3str_cnvnew_c32_to_c8p_app(dk3_c32_t const *s, dk3_app_t *app)
{
  char		*back = NULL;
  size_t	sz;		/* Destination buffer size needed. */
  if(s) {
    sz = dk3str_i_cnv_c32(NULL, s, app, DK3_ENCODING_PLAIN);
    if(sz) {
      back = dk3_new_app(char,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c32((void *)back, s, app, DK3_ENCODING_PLAIN)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}



size_t
dk3str_cnvsz_c32_to_c8u_app(dk3_c32_t const *s, dk3_app_t *app)
{
  size_t back = 0;
  if(s) {
    back = dk3str_i_cnv_c32(NULL, s, app, DK3_ENCODING_UTF8);
  }
  return back;
}


int
dk3str_cnv_c32_to_c8u_app(char *d, size_t ds, dk3_c32_t const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Destination buffer size needed. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c32(NULL, s, app, DK3_ENCODING_UTF8);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c32((void *)d, s, app, DK3_ENCODING_UTF8)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Destination buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}



char *
dk3str_cnvnew_c32_to_c8u_app(dk3_c32_t const *s, dk3_app_t *app)
{
  char		*back = NULL;
  size_t	sz;		/* Destination buffer size needed. */
  if(s) {
    sz = dk3str_i_cnv_c32(NULL, s, app, DK3_ENCODING_UTF8);
    if(sz) {
      back = dk3_new_app(char,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c32((void *)back, s, app, DK3_ENCODING_UTF8)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}



size_t
dk3str_cnvsz_c32_to_c16_app(dk3_c32_t const *s, dk3_app_t *app)
{
  size_t back = 0;
  if(s) {
    back = dk3str_i_cnv_c32(NULL, s, app, DK3_ENCODING_UTF16);
  }
  return back;
}



int
dk3str_cnv_c32_to_c16_app(dk3_c16_t *d, size_t ds, dk3_c32_t const *s, dk3_app_t *app)
{
  int		back = 0;
  size_t	sz;		/* Destination buffer size needed. */
  if((d) && (ds) && (s)) {
    sz = dk3str_i_cnv_c32(NULL, s, app, DK3_ENCODING_UTF16);
    if(sz) {
      if(ds >= sz) {
        if(dk3str_i_cnv_c32((void *)d, s, app, DK3_ENCODING_UTF16)) {
	  back = 1;
	}
      } else {
        if(app) {
	  /* ERROR: Destination buffer too small! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
	}
      }
    }
  }
  return back;
}



dk3_c16_t *
dk3str_cnvnew_c32_to_c16_app(dk3_c32_t const *s, dk3_app_t *app)
{
  dk3_c16_t	*back = NULL;
  size_t	sz;		/* Destination buffer size needed. */
  if(s) {
    sz = dk3str_i_cnv_c32(NULL, s, app, DK3_ENCODING_UTF16);
    if(sz) {
      back = dk3_new_app(dk3_c16_t,sz,app);
      if(back) {
        if(!dk3str_i_cnv_c32((void *)back, s, app, DK3_ENCODING_UTF16)) {
	  dk3_delete(back); back = NULL;
	}
      }
    }
  }
  return back;
}



int
dk3str_cnv_c8_to_str_app(dkChar *d, size_t sz, char const *s, dk3_app_t *app)
{
  register int		back = 0;
  register size_t	l;		/* Number of destination chars used. */
  register char const	*sptr;		/* Source pointer. */
  register dkChar	*dptr;		/* Destination pointer. */
  register char		x = 0x00;	/* Current character to process. */

  if((d) && (sz) && (s)) {
    sptr = s; dptr = d; l = 0; back = 1;
    while((*sptr) && (l < (sz - 1))) {
      x = *(sptr++);
      *(dptr++) = (dkChar)x;
      l++;
    }
    *dptr = (dkChar)'\0';
    if(*sptr) {
      back = 0;
      if(app) {
        /* ERROR: Destination buffer too small! */
	dk3app_log_i1(app, DK3_LL_ERROR, 38);
      }
    }
  }
  return back;
}



int
dk3str_string_to_c8_simple_app(char *db,size_t sz,dkChar const *s,dk3_app_t *ap)
{
  int			back = 0;
  register dkChar const	*sptr;		/* Source pointer. */
  register dkChar	x;		/* Current source character. */
  register char		*dptr;		/* Destination pointer. */

  if((db) && (sz) && (s)) {
    if(dk3str_len(s) < sz) {
      back = 1;
      sptr = s; dptr = db;
      while(*sptr) {
        x = *(sptr++);
	*(dptr++) = (char)x;
#if DK3_CHAR_SIZE > 1
	if(x > (dkChar)0xFF) {
	  back = 0;
	}
#endif
      }
      *dptr = '\0';
      if(!(back)) {
        if(ap) {
	  /* ERROR: Non-ISO-LATIN-1 characters found! */
	  dk3app_log_i1(ap, DK3_LL_ERROR, 219);
	}
      }
    } else {
      if(ap) {
        /* ERROR: Destination buffer too short! */
	dk3app_log_i1(ap, DK3_LL_ERROR, 38);
      }
    }
  }
  return back;
}



void
dk3str_string_tolower(dkChar *s)
{
  dkChar *ptr;	/* Pointer into string. */
  if(s) {
    ptr = s;
    while(*ptr) {
      *ptr = dk3str_tolower(*ptr);
      ptr++;
    }
  }
}



int
dk3str_c8_to_str_simple_app(
  dkChar *dp, size_t ds, char const *sp, dk3_app_t *app
)
{
  int		 back = 0;
  char const	*sptr;		/* Pointer into source buffer. */
  dkChar	*dptr;		/* Pointer into destination buffer. */
  size_t	 sz;		/* Required destination size. */
  if((dp) && (ds) && (sp)) {
    sz = dk3str_c8_len(sp);
    if(ds > sz) {
      back = 1; sptr = sp; dptr = dp;
      while(*sptr) { *(dptr++) = (dkChar)(*(sptr++)); }
      *dptr = dkT('\0');
    } else {
      if(app) {
        /* ERROR: Destination buffer too short! */
	dk3app_log_i1(app, DK3_LL_ERROR, 38);
      }
    }
  }
  return back;
}



int
dk3str_to_c8p_app(
  char *dp, size_t sz, dkChar const *src, int ie, dk3_app_t *app
)
{
  int back = 0;
  if((dp) && (sz) && (src)) {
#if DK3_CHAR_SIZE > 1
#if DK3_CHAR_SIZE > 2
    back = dk3str_cnv_c32_to_c8p_app(dp, sz, src, app);
#else
    back = dk3str_cnv_c16_to_c8p_app(dp, sz, src, app);
#endif
#else
    if(ie == DK3_ENCODING_PLAIN) {
      if(sz > dk3str_c8_len(src)) {
        dk3str_c8_cpy(dp, src);
	back = 1;
      }
    } else {
      back = dk3str_cnv_c8u_to_c8p_app(dp, sz, src, app);
    }
#endif
  }
  return back;
}



int
dk3str_to_c8u_app(
  char *dp, size_t sz, dkChar const *src, int ie, dk3_app_t *app
)
{
  int back = 0;
  if((dp) && (sz) && (src)) {
#if DK3_CHAR_SIZE > 1
#if DK3_CHAR_SIZE > 2
    back = dk3str_cnv_c32_to_c8u_app(dp, sz, src, app);
#else
    back = dk3str_cnv_c16_to_c8u_app(dp, sz, src, app);
#endif
#else
    if(ie == DK3_ENCODING_PLAIN) {
      back = dk3str_cnv_c8p_to_c8u_app(dp, sz, src, app);
    } else {
      if(sz > dk3str_c8_len(src)) {
        dk3str_c8_cpy(dp, src);
	back = 1;
      }
    }
#endif
  }
  return back;
}



int
dk3str_str_to_c8u_app(
  char		*d,
  size_t	 dsz,
  dkChar const	*s,
  int		 se,
  dk3_app_t	*app
)
{
  int		back = 0;
#if DK3_CHAR_SIZE > 1
#if DK3_CHAR_SIZE > 2
  back = dk3str_cnv_c32_to_c8u_app(d, dsz, s, app);
#else
  back = dk3str_cnv_c16_to_c8u_app(d, dsz, s, app);
#endif
#else
  switch(se) {
    case DK3_ENCODING_UTF8: {
      if(dk3str_c8_len(s) < dsz) {
        dk3str_c8_cpy(d, s);
	back = 1;
      } else {
        if(app) {
	  /* ERROR: String too long! */
	  dk3app_log_i1(app, DK3_LL_ERROR, 108);
	}
      }
    } break;
    default: {
      back = dk3str_cnv_c8p_to_c8u_app(d, dsz, s, app);
    } break;
  }
#endif
  return back;
}



int
dk3str_c8u_to_str_app(
  dkChar 		*d,
  size_t		 dsz,
  int			 de,
  char const		*s,
  dk3_app_t		*app
)
{
  int		 back = 0;
  

#line 6636 "dk3str.ctr"
  if((d) && (dsz) && (s)) {
#if DK3_CHAR_SIZE > 1
#if DK3_CHAR_SIZE > 2
    

#line 6640 "dk3str.ctr"
    back = dk3str_cnv_c8u_to_c32_app(d, dsz, s, app);
#else
    

#line 6643 "dk3str.ctr"
    back = dk3str_cnv_c8u_to_c16_app(d, dsz, s, app);
#endif
#else
    switch(de) {
      case DK3_ENCODING_UTF8: {
        

#line 6649 "dk3str.ctr"
        if(dsz > dk3str_c8_len(s)) {
	  dk3str_c8_cpy(d, s);
	  back = 1;
	} else {
	  if(app) {
	    /* ERROR: Source string too long! */
	    dk3app_log_i1(app, DK3_LL_ERROR, 108);
	  }
	}
      } break;
      default: {
        

#line 6661 "dk3str.ctr"
        back = dk3str_cnv_c8u_to_c8p_app(d, dsz, s, app);
      } break;
    }
#endif
  } 

#line 6666 "dk3str.ctr"
  return back;
}



int
dk3str_to_c8_app(char *dp, size_t szdp, dkChar const *src, dk3_app_t *app)
{
  int		 back = 0;
  

#line 6676 "dk3str.ctr"
  if((dp) && (szdp) && (src)) {
#if DK3_CHAR_SIZE > 1
#if DK3_CHAR_SIZE > 2
    back = dk3str_cnv_c32_to_c8p_app(dp, szdp, src, app);
#else
    back = dk3str_cnv_c16_to_c8p_app(dp, szdp, src, app);
#endif
#else
    if(strlen(src) < szdp) {
      strcpy(dp, src);
      back = 1;
    } else {
      /* ERROR: Destination buffer too small! */
      dk3app_log_i1(app, DK3_LL_ERROR, 38);
    }
#endif
  } 

#line 6693 "dk3str.ctr"
  return back;
}



/* vim: set ai sw=2 : */

