text: /* $XConsortium: lcFile.c,v 1.1 94/01/20 17:56:55 rws Exp $ */
  /*
   *
   * Copyright IBM Corporation 1993
   *
   * All Rights Reserved
   *
   * License to use, copy, modify, and distribute this software and its
   * documentation for any purpose and without fee is hereby granted,
   * provided that the above copyright notice appear in all copies and that
   * both that copyright notice and this permission notice appear in
   * supporting documentation, and that the name of IBM not be
   * used in advertising or publicity pertaining to distribution of the
   * software without specific, written prior permission.
   *
   * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
   * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND 
   * NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL
   * IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
   * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
   * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
   * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   * SOFTWARE.
   *
  */
  #include <stdio.h>
  #include <ctype.h>
  #include "Xlibint.h"
  #include "XlcPubI.h"
  #include <X11/Xos.h>
  #ifdef X_NOT_STDC_ENV
  extern char *getenv();
  #endif
  
  /************************************************************************/
  
  #define	iscomment(ch)	((ch) == '#' || (ch) == '\0')
  #define isreadable(f)	((access((f), R_OK) != -1) ? 1 : 0)
  /*
  #define	isspace(ch)	((ch) == ' ' || (ch) == '\t' || (ch) == '\n')
  */
  
  static int
  parse_line(line, argv, argsize)
      char *line;
      char **argv;
      int argsize;
  {
      int argc = 0;
      char *p = line;
  
      while(argc < argsize){
  	while(isspace(*p)){
  	    ++p;
  	}
  	if(*p == '\0'){
  	    break;
  	}
  	argv[argc++] = p;
  	while(! isspace(*p) && *p != '\0'){
  	    ++p;
  	}
  	if(*p == '\0'){
  	    break;
  	}
  	*p++ = '\0';
      }
  
      return argc;
  }
  
  #ifndef XLOCALEDIR
  #define XLOCALEDIR "/usr/lib/X11/locale"
  #endif
  
  static void
  xlocaledir(path)
      char *path;
  {
      char *dir, *p = path;
      int len;
  
      dir = getenv("XLOCALEDIR");
      if(dir != NULL){
  	len = strlen(dir);
  	strcpy(p, dir);
  	p[len++] = ':';
  	p += len;
      }
      strcpy(p, XLOCALEDIR);
  }
  
  static int
  parse_path(path, argv, argsize)
      char *path;
      char **argv;
      int argsize;
  {
      char *p = path;
      int i, n;
  
      while((p = strchr(p, ':')) != NULL){
  	*p = ' ';	/* place space on delimter */
      }
      n = parse_line(path, argv, argsize);
      if(n == 0){
  	return 0;
      }
      for(i = 0; i < n; ++i){
  	int len;
  	p = argv[i];
  	len = strlen(p);
  	if(p[len - 1] == '/'){
  	    /* eliminate slash */
  	    p[len - 1] = '\0';
  	}
      }
      return n;
  }
  
  enum { LtoR, RtoL };
  
  static char *
  _XlcResolveName(lc_name, file_name, direction)
      char *lc_name;
      char *file_name;
      int direction;	/* mapping direction */
  {
      FILE *fp;
      char buf[BUFSIZE], *name = NULL;
  
      fp = fopen(file_name, "r");
      if(fp == (FILE *)NULL){
  	return NULL;
      }
  
      while(fgets(buf, BUFSIZE, fp) != NULL){
  	char *p = buf;
  	int n;
  	char *args[2], *from, *to;
  	while(isspace(*p)){
  	    ++p;
  	}
  	if(iscomment(*p)){
  	    continue;
  	}
  	n = parse_line(p, args, 2);		/* get first 2 fields */
  	if(n != 2){
  	    continue;
  	}
  	if(direction == LtoR){
  	    from = args[0], to = args[1];	/* left to right */
  	}else{
  	    from = args[1], to = args[0];	/* right to left */
  	}
  	if(! strcmp(from, lc_name)){
  	    name = Xmalloc(strlen(to) + 1);
  	    if(name != NULL){
  		strcpy(name, to);
  	    }
  	    break;
  	}
      }
      if(fp != (FILE *)NULL){
  	fclose(fp);
      }
      return name;
  }
  
  /*
  #define	isupper(ch)	('A' <= (ch) && (ch) <= 'Z')
  #define	tolower(ch)	((ch) - 'A' + 'a')
  */
  static char *
  lowercase(dst, src)
      char *dst;
      char *src;
  {
      char *s, *t;
  
      for(s = src, t = dst; *s; ++s, ++t){
  	*t = isupper(*s) ? tolower(*s) : *s;
      }
      *t = '\0';
      return dst;
  }
  
  /************************************************************************/
  char *
  _XlcFileName(lcd, category)
      XLCd lcd;
      char *category;
  {
      char lc_name[BUFSIZE];
      char cat[BUFSIZE], dir[BUFSIZE];
      int i, n;
      char *args[256];
      char *file_name = NULL;
  
      if(lcd == (XLCd)NULL){
  	return NULL;
      }
  
      if(! _XlcResolveLocaleName(XLC_PUBLIC(lcd, siname), lc_name,
  			       NULL, NULL, NULL)){
  	return NULL;
      }
  
      lowercase(cat, category);
      xlocaledir(dir);
      n = parse_path(dir, args, 256);
      for(i = 0; i < n; ++i){
  	char buf[BUFSIZE], *name;
  	sprintf(buf, "%s/%s.dir", args[i], cat);
  	name = _XlcResolveName(lc_name, buf, RtoL);
  	if(name == NULL){
  	    continue;
  	}
  	if(*name == '/'){
  	    /* supposed to be absolute path name */
  	    file_name = name;
  	}else{
  	    sprintf(buf, "%s/%s", args[i], name);
  	    Xfree(name);
  	    file_name = Xmalloc(strlen(buf) + 1);
  	    if(file_name == NULL){
  		break;
  	    }
  	    strcpy(file_name, buf);
  	}
  	if(isreadable(file_name)){
  	    break;
  	}
  	Xfree(file_name);
  	file_name = NULL;
  	/* Then, try with next dir */
      }
      return file_name;
  }
  
  /************************************************************************/
  #ifndef LOCALE_ALIAS
  #define LOCALE_ALIAS    "locale.alias"
  #endif
  
  int
  _XlcResolveLocaleName(lc_name, full_name, language, territory, codeset)
      char *lc_name;
      char *full_name;
      char *language;
      char *territory;
      char *codeset;
  {
      char dir[BUFSIZE], buf[BUFSIZE], *name = NULL;
      int i, n;
      char *args[256];
  
      xlocaledir(dir);
      n = parse_path(dir, args, 256);
      for(i = 0; i < n; ++i){
  	sprintf(buf, "%s/%s", args[i], LOCALE_ALIAS);
  	name = _XlcResolveName(lc_name, buf, LtoR);
  	if(name != NULL){
  	    break;
  	}
      }
  
      if(name != NULL){
  	strcpy(buf, name);
  	Xfree(name);
      }else{
  	strcpy(buf, lc_name);
      }
      if(full_name != NULL){
  	strcpy(full_name, buf);
      }
  
      if(language || territory || codeset){
  	char *ptr, *name_p;
  	/*
  	 * Decompose locale name
  	 */
  	if(language) *language = '\0';
  	if(territory) *territory = '\0';
  	if(codeset) *codeset = '\0';
  
  	name_p = buf;
  	ptr = language;
  	while (1) {
  	    if (*name_p == '_') {
  		if (ptr)
  		    *ptr = '\0';
  		ptr = territory;
  	    } else if (*name_p == '.') {
  		if (ptr)
  		    *ptr = '\0';
  		ptr = codeset;
  	    } else {
  		if (ptr)
  		    *ptr++ = *name_p;
  		if (*name_p == '\0')
  		    break;
  	    }
  	    name_p++;
  	}
      }
  
      return (buf[0] != '\0') ? 1 : 0;
  }
  
  /************************************************************************/
  #ifndef	LOCALE_DIR
  #define	LOCALE_DIR	"locale.dir"
  #endif
  
  int
  _XlcResolveDBName(lc_name, file_name)
      char *lc_name;
      char *file_name;
  {
      char dir[BUFSIZE], buf[BUFSIZE], *name = NULL;
      int i, n;
      char *args[256];
  
      xlocaledir(dir);
      n = parse_path(dir, args, 256);
      for(i = 0; i < n; ++i){
  	sprintf(buf, "%s/%s", args[i], LOCALE_DIR);
  	name = _XlcResolveName(lc_name, buf, RtoL);
  	if(name != NULL){
  	    break;
  	}
      }
      if(name == NULL){
  	return 0;
      }
      strcpy(buf, name);
      Xfree(name);
      if(file_name != NULL){
  	strcpy(file_name, buf);
      }
      return 1;
  }
  
  /************************************************************************/
  int
  _XlcResolveI18NPath(path_name)
      char *path_name;
  {
      if(path_name != NULL){
  	xlocaledir(path_name);
      }
      return 1;
  }
  