DELTA 7519 34 4
SVN   á}á}€á}/********************************************************************** 
 Freeciv - Copyright (C) 2003-2004 - The Freeciv Project
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
***********************************************************************/

#ifdef HAVE_CONFIG_H
#include <fc_config.h>
#endif

#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

#ifdef HAVE_ICONV
#include <iconv.h>
#endif

#ifdef HAVE_LANGINFO_CODESET
#include <langinfo.h>
#endif

#ifdef HAVE_LIBCHARSET
#include <libcharset.h>
#endif

/* utility */
#include "fciconv.h"
#include "fcintl.h"
#include "log.h"
#include "mem.h"
#include "support.h"

static bool is_init = FALSE;
static char convert_buffer[4096];
static const char *transliteration_string;

#ifdef HAVE_ICONV
static const char *local_encoding, *data_encoding, *internal_encoding;
#else  /* HAVE_ICONV */
/* Hack to confuse the compiler into working. */
#  define local_encoding get_local_encoding()
#  define data_encoding get_local_encoding()
#  define internal_encoding get_local_encoding()
#endif /* HAVE_ICONV */

/***************************************************************************
  Must be called during the initialization phase of server and client to
  initialize the character encodings to be used.

  Pass an internal encoding of NULL to use the local encoding internally.
***************************************************************************/
void init_character_encodings(const char *my_internal_encoding,
			      bool my_use_transliteration)
{
  transliteration_string = "";
#ifdef HAVE_ICONV
  if (my_use_transliteration) {
    transliteration_string = "//TRANSLIT";
  }

  /* Set the data encoding - first check $FREECIV_DATA_ENCODING,
   * then fall back to the default. */
  data_encoding = getenv("FREECIV_DATA_ENCODING");
  if (!data_encoding) {
    data_encoding = FC_DEFAULT_DATA_ENCODING;
  }

  /* Set the local encoding - first check $FREECIV_LOCAL_ENCODING,
   * then ask the system. */
  local_encoding = getenv("FREECIV_LOCAL_ENCODING");
  if (!local_encoding) {
#ifdef HAVE_LIBCHARSET
    local_encoding = locale_charset();
#else  /* HAVE_LIBCHARSET */
#ifdef HAVE_LANGINFO_CODESET
    local_encoding = nl_langinfo(CODESET);
#else  /* HAVE_LANGINFO_CODESET */
    local_encoding = "";
#endif /* HAVE_LANGINFO_CODESET */
#endif /* HAVE_LIBCHARSET */
    if (fc_strcasecmp(local_encoding, "ANSI_X3.4-1968") == 0
        || fc_strcasecmp(local_encoding, "ASCII") == 0
        || fc_strcasecmp(local_encoding, "US-ASCII") == 0) {
      /* HACK: use latin1 instead of ascii in typical cases when the
       * encoding is unconfigured. */
      local_encoding = "ISO-8859-1";
    }

    if (fc_strcasecmp(local_encoding, "646") == 0) {
      /* HACK: On Solaris the encoding always comes up as "646" (ascii),
       * which iconv doesn't understand.  Work around it by using UTF-8
       * instead. */
      local_encoding = "UTF-8";
    }
  }

  /* Set the internal encoding - first check $FREECIV_INTERNAL_ENCODING,
   * then check the passed-in default value, then fall back to the local
   * encoding. */
  internal_encoding = getenv("FREECIV_INTERNAL_ENCODING");
  if (!internal_encoding) {
    internal_encoding = my_internal_encoding;

    if (!internal_encoding) {
      internal_encoding = local_encoding;
    }
  }

#ifdef ENABLE_NLS
  bind_textdomain_codeset(PACKAGE, internal_encoding);
#endif

#ifdef DEBUG
  fprintf(stderr, "Encodings: Data=%s, Local=%s, Internal=%s\n",
          data_encoding, local_encoding, internal_encoding);
#endif /* DEBUG */

#else  /* HAVE_ICONV */
   /* log_* may not work at this point. */
  fprintf(stderr,
          _("You are running Freeciv without using iconv. Unless\n"
            "you are using the UTF-8 character set, some characters\n"
            "may not be displayed properly. You can download iconv\n"
            "at http://gnu.org/.\n"));
#endif /* HAVE_ICONV */

  is_init = TRUE;
}

/***************************************************************************
  Return the data encoding (usually UTF-8).
***************************************************************************/
const char *get_data_encoding(void)
{
  fc_assert_ret_val(is_init, NULL);
  return data_encoding;
}

/***************************************************************************
  Return the local encoding (dependent on the system).
***************************************************************************/
const char *get_local_encoding(void)
{
#ifdef HAVE_ICONV
  fc_assert_ret_val(is_init, NULL);
  return local_encoding;
#else  /* HAVE_ICONV */
#  ifdef HAVE_LIBCHARSET
  return locale_charset();
#  else  /* HAVE_LIBCHARSET */
#    ifdef HAVE_LANGINFO_CODESET
  return nl_langinfo(CODESET);
#    else  /* HAVE_LANGINFO_CODESET */
  return "";
#    endif /* HAVE_LANGINFO_CODESET */
#  endif /* HAVE_LIBCHARSET */
#endif /* HAVE_ICONV */
}

/***************************************************************************
  Return the internal encoding.  This depends on the server or GUI being
  used.
***************************************************************************/
const char *get_internal_encoding(void)
{
  fc_assert_ret_val(is_init, NULL);
  return internal_encoding;
}

/***************************************************************************
  Convert the text.  Both 'from' and 'to' must be 8-bit charsets.  The
  result will be put into the buf buffer unless it is NULL, in which case it
  will be allocated on demand.

  Don't use this function if you can avoid it.  Use one of the
  xxx_to_yyy_string functions.
***************************************************************************/
char *convert_string(const char *text,
		     const char *from,
		     const char *to,
		     char *buf, size_t bufsz)
{
#ifdef HAVE_ICONV
  iconv_t cd = iconv_open(to, from);
  size_t from_len = strlen(text) + 1, to_len;
  bool alloc = (buf == NULL);

  fc_assert_ret_val(is_init && NULL != from && NULL != to, NULL);
  fc_assert_ret_val(NULL != text, NULL);

  if (cd == (iconv_t) (-1)) {
    /* Do not do potentially recursive call to freeciv logging here,
     * but use fprintf(stderr) */
    /* Use the real OS-provided strerror and errno rather than Freeciv's
     * abstraction, as that wouldn't do the correct thing with third-party
     * iconv on Windows */

    /* TRANS: "Could not convert text from <encoding a> to <encoding b>:" 
     *        <externally translated error string>."*/
    fprintf(stderr, _("Could not convert text from %s to %s: %s.\n"),
            from, to, strerror(errno));
    /* The best we can do? */
    if (alloc) {
      return fc_strdup(text);
    } else {
      fc_snprintf(buf, bufsz, "%s", text);
      return buf;
    }
  }

  if (alloc) {
    to_len = from_len;
  } else {
    to_len = bufsz;
  }

  do {
    size_t flen = from_len, tlen = to_len, res;
    const char *mytext = text;
    char *myresult;

    if (alloc) {
      buf = fc_malloc(to_len);
    }

    myresult = buf;

    /* Since we may do multiple translations, we may need to reset iconv
     * in between. */
    iconv(cd, NULL, NULL, NULL, NULL);

    res = iconv(cd, (ICONV_CONST char **)&mytext, &flen, &myresult, &tlen);
    if (res == (size_t) (-1)) {
      if (errno != E2BIG) {
        /* Invalid input. */

        fprintf(stderr, "Invalid string conversion from %s to %s: %s.\n",
                from, to, strerror(errno));
        iconv_close(cd);
        if (alloc) {
          free(buf);
          return fc_strdup(text); /* The best we can do? */
        } else {
          fc_snprintf(buf, bufsz, "%s", text);
          return buf;
        }
      }
    } else {
      /* Success. */
      iconv_close(cd);

      /* There may be wasted space here, but there's nothing we can do
       * about it. */
      return buf;
    }

    if (alloc) {
      /* Not enough space; try again. */
      buf[to_len - 1] = 0;

      free(buf);
      to_len *= 2;
    }
  } while (alloc);

  return buf;
#else /* HAVE_ICONV */
  if (buf) {
    strncpy(buf, text, bufsz);
    buf[bufsz - 1] = '\0';
    return buf;
  } else {
    return fc_strdup(text);
  }
#endif /* HAVE_ICONV */
}

#define CONV_FUNC_MALLOC(src, dst)                                          \
char *src ## _to_ ## dst ## _string_malloc(const char *text)                \
{                                                                           \
  const char *encoding1 = (dst ## _encoding);				    \
  char encoding[strlen(encoding1) + strlen(transliteration_string) + 1];    \
									    \
  fc_snprintf(encoding, sizeof(encoding),				    \
	      "%s%s", encoding1, transliteration_string);		    \
  return convert_string(text, (src ## _encoding),			    \
			(encoding), NULL, 0);				    \
}

#define CONV_FUNC_BUFFER(src, dst)                                          \
char *src ## _to_ ## dst ## _string_buffer(const char *text,                \
					   char *buf, size_t bufsz)         \
{                                                                           \
  const char *encoding1 = (dst ## _encoding);				    \
  char encoding[strlen(encoding1) + strlen(transliteration_string) + 1];    \
									    \
  fc_snprintf(encoding, sizeof(encoding),				    \
	      "%s%s", encoding1, transliteration_string);		    \
  return convert_string(text, (src ## _encoding),			    \
                        encoding, buf, bufsz);				    \
}

#define CONV_FUNC_STATIC(src, dst)                                          \
char *src ## _to_ ## dst ## _string_static(const char *text)                \
{                                                                           \
  (src ## _to_ ## dst ## _string_buffer)(text,                              \
					convert_buffer,                     \
					sizeof(convert_buffer));            \
  return convert_buffer;                                                    \
}

CONV_FUNC_MALLOC(data, internal)
CONV_FUNC_MALLOC(internal, data)
CONV_FUNC_MALLOC(internal, local)
CONV_FUNC_MALLOC(local, internal)

CONV_FUNC_BUFFER(local, internal)
CONV_FUNC_BUFFER(internal, local)

static CONV_FUNC_STATIC(internal, local)

/***************************************************************************
  Do a fprintf from the internal charset into the local charset.
***************************************************************************/
void fc_fprintf(FILE *stream, const char *format, ...)
{
  va_list ap;
  char string[4096];
  const char *output;
  static bool recursion = FALSE;

  /* The recursion variable is used to prevent a recursive loop.  If
   * an iconv conversion fails, then log_* will be called and an
   * fc_fprintf will be done.  But below we do another iconv conversion
   * on the error messages, which is of course likely to fail also. */
  if (recursion) {
    return;
  }

  va_start(ap, format);
  fc_vsnprintf(string, sizeof(string), format, ap);
  va_end(ap);

  recursion = TRUE;
  if (is_init) {
    output = internal_to_local_string_static(string);
  } else {
    output = string;
  }
  recursion = FALSE;

  fputs(output, stream);
  fflush(stream);
}

/****************************************************************************
  Return the length, in *characters*, of the string.  This can be used in
  place of strlen in some places because it returns the number of characters
  not the number of bytes (with multi-byte characters in UTF-8, the two
  may not be the same).

  Use of this function outside of GUI layout code is probably a hack.  For
  instance the demographics code uses it, but this should instead pass the
  data directly to the GUI library for formatting.
****************************************************************************/
size_t get_internal_string_length(const char *text)
{
  int text2[(strlen(text) + 1)]; /* UCS-4 text */
  int i;
  int len = 0;

  convert_string(text, internal_encoding, "UCS-4",
                 (char *)text2, sizeof(text2));
  for (i = 0; ; i++) {
    if (text2[i] == 0) {
      return len;
    }
    if (text2[i] != 0x0000FEFF && text2[i] != 0xFFFE0000) {
      /* Not BOM */
      len++;
    }
  }
}
ENDREP
id: 2g7.5kv.r34843/12578
type: file
pred: 2g7.5kv.r26807/3206
count: 32
text: 34843 0 12555 12541 4fdd8d1b75809d92c1f85f0499e56587
props: 10128 14152 111 0 28e613ef70fc8e4efe7ed7b15f74e6e7
cpath: /branches/S2_5/utility/fciconv.c
copyroot: 22812 /branches/S2_5

PLAIN
K 11
Makefile.am
V 25
file 2gg.5kv.r26189/11447
K 9
astring.c
V 23
file h5.5ck.r22395/1264
K 9
astring.h
V 23
file h6.5ck.r20479/1668
K 11
bitvector.c
V 25
file 4un.5kv.r26906/38163
K 11
bitvector.h
V 25
file 4uo.5kv.r26906/39090
K 12
capability.c
V 21
file 7p.5ck.r20361/90
K 12
capability.h
V 24
file 7q.5ck.r18858/85852
K 12
distribute.c
V 26
file 2lp.5ck.r19259/362511
K 12
distribute.h
V 25
file 2lq.5ck.r18858/87951
K 9
fc_utf8.c
V 23
file 4ku.5kv.r26945/198
K 9
fc_utf8.h
V 25
file 4kv.5kv.r26906/38782
K 13
fcbacktrace.c
V 22
file 731.5kv.r26960/60
K 13
fcbacktrace.h
V 23
file 732.5kv.r31560/207
K 9
fciconv.c
V 25
file 2g7.5kv.r34843/12578
K 9
fciconv.h
V 25
file 2g8.5ck.r18858/89144
K 8
fcintl.c
V 21
file k3.5kv.r32931/54
K 8
fcintl.h
V 24
file fw.5kv.r24145/31999
K 10
fcthread.c
V 25
file 6hv.5kv.r26906/32941
K 10
fcthread.h
V 25
file 6hw.5kv.r31586/25755
K 20
generate_specenum.py
V 24
file 4ia.5kv.r23283/1974
K 9
genhash.c
V 24
file 57v.5kv.r27502/8440
K 9
genhash.h
V 25
file 57w.5kv.r27498/46583
K 9
genlist.c
V 23
file 51.5kv.r32068/1061
K 9
genlist.h
V 23
file 52.5kv.r32068/1314
K 11
inputfile.c
V 21
file h9.5kv.r29814/49
K 11
inputfile.h
V 24
file ha.5ck.r18858/84203
K 5
ioz.c
V 22
file uh.5kv.r34727/148
K 5
ioz.h
V 23
file ui.5kv.r24201/7308
K 10
iterator.c
V 25
file 4h5.5kv.r26906/34168
K 10
iterator.h
V 25
file 4f3.5kv.r26906/35098
K 5
log.c
V 21
file 53.5kv.r32049/46
K 5
log.h
V 24
file 54.5kv.r30376/30380
K 5
md5.c
V 22
file 33q.5kv.r25083/54
K 5
md5.h
V 25
file 33r.5ck.r19849/16287
K 5
mem.c
V 25
file d9.5ck.r19259/362758
K 5
mem.h
V 24
file da.5ck.r20315/22211
K 9
netfile.c
V 23
file 6m8.5kv.r32525/254
K 9
netfile.h
V 25
file 6m9.5kv.r26906/34478
K 9
netintf.c
V 23
file t6.5kv.r33595/3097
K 9
netintf.h
V 22
file t7.5kv.r33588/197
K 6
rand.c
V 25
file m5.5ck.r19259/363664
K 6
rand.h
V 24
file m6.5ck.r20315/22687
K 10
registry.c
V 25
file agw.5kv.r26906/35712
K 10
registry.h
V 25
file 7po.5kv.r26906/36324
K 14
registry_ini.c
V 21
file dh.5nm.r34733/78
K 14
registry_ini.h
V 24
file di.5or.r26115/21372
K 14
section_file.c
V 25
file bw9.5kv.r31547/57073
K 14
section_file.h
V 25
file axo.5kv.r26906/39392
K 8
shared.c
V 21
file 55.5kv.r32187/64
K 8
shared.h
V 23
file 1d.5kv.r33383/5311
K 10
spechash.h
V 25
file 57x.5kv.r27498/46844
K 10
speclist.h
V 21
file gb.5kv.r23840/61
K 8
specpq.h
V 26
file 1brz.5kv.r26906/37857
K 9
specvec.h
V 22
file z9.5kv.r34147/115
K 15
string_vector.c
V 25
file 4hy.5kv.r26906/33851
K 15
string_vector.h
V 25
file 4hz.5kv.r26906/34784
K 9
support.c
V 24
file m9.5kv.r33480/21626
K 9
support.h
V 22
file ma.5kv.r28237/161
K 8
timing.c
V 23
file el.5kv.r24201/8068
K 8
timing.h
V 24
file em.5ck.r22382/27015
END
ENDREP
id: 1c.5kv.r34843/15541
type: dir
pred: 1c.5kv.r34733/3054
count: 912
text: 34843 12839 2689 0 8463702c37dd70c2092451ec465f1528
props: 17175 331 84 0 5447a85ba28edec0d4a8f6120070e2b2
cpath: /branches/S2_5/utility
copyroot: 22812 /branches/S2_5

PLAIN
K 9
ABOUT-NLS
V 24
file fu.5kv.r23463/86338
K 7
AUTHORS
V 24
file 5u.5ck.r22143/14016
K 7
COPYING
V 22
file 1h.5kv.r29456/845
K 9
ChangeLog
V 26
file 6l.5kv.r34570/2817316
K 7
INSTALL
V 21
file 6.5kv.r29707/213
K 11
Makefile.am
V 22
file 59.5kv.r31921/510
K 4
NEWS
V 22
file 6m.5kv.r28524/894
K 8
NEWS-2.5
V 25
file 1h59.5kv.r34568/7019
K 6
README
V 20
file 7.0.r4421/96382
K 2
ai
V 21
dir 8.5kv.r33925/2728
K 10
autogen.sh
V 22
file 12o.5kv.r32731/46
K 9
bootstrap
V 24
dir 2p5.5kv.r32828/24335
K 6
client
V 21
dir d.5kv.r34623/7844
K 6
common
V 21
dir p.5kv.r34527/4758
K 12
configure.ac
V 23
file 149.5kv.r34520/111
K 4
data
V 21
dir w.5kv.r34443/4715
K 6
debian
V 22
dir 5w.5kv.r23304/4091
K 12
dependencies
V 23
dir 2yu.5kv.r33073/6577
K 11
diff_ignore
V 24
file qq.5ck.r21039/26581
K 3
doc
V 22
dir k7.5kv.r34376/3266
K 10
fc_version
V 22
file 2lo.5kw.r34569/46
K 3
lua
V 24
dir 2c60.5kv.r31921/4513
K 2
m4
V 23
dir 12p.5kv.r33131/2724
K 7
scripts
V 23
dir 2yo.5kv.r28718/5390
K 6
server
V 21
dir z.5kv.r34804/4034
K 5
tests
V 22
dir 2g9.5kv.r32363/652
K 5
tools
V 24
dir 4pj.5lo.r33179/24964
K 12
translations
V 26
dir t0n.5kv.r34747/2830422
K 7
utility
V 23
dir 1c.5kv.r34843/15541
K 3
vms
V 25
dir u9.5ck.r21528/1396085
K 5
win32
V 23
dir 2eu.5kv.r33615/2070
END
ENDREP
id: 3.5kv.r34843/17071
type: dir
pred: 3.5kv.r34804/5560
count: 18762
text: 34843 15786 1272 0 6fad8c1e54ee7b48d3f5c904eabda5fd
props: 20140 3888 282 0 e4bb46e81629a60eef613b169b23a9ea
cpath: /branches/S2_5
copyroot: 22812 /branches/S2_5

PLAIN
K 5
S1_14
V 21
dir 3.21.r18109/18803
K 4
S2_0
V 21
dir 3.10x.r21862/4178
K 4
S2_1
V 22
dir 3.59e.r20026/11014
K 4
S2_2
V 21
dir 3.5cy.r21861/5036
K 4
S2_3
V 21
dir 3.5f2.r29458/5135
K 4
S2_4
V 23
dir 3.5ii.r32693/294508
K 4
S2_5
V 22
dir 3.5kv.r34843/17071
K 6
S2_5_3
V 23
dir 3.5ut.r31805/553797
K 4
S2_6
V 22
dir 3.5qi.r34840/17399
K 4
S3_0
V 21
dir 3.5xw.r34841/4996
K 11
freeciv-web
V 22
dir 3.5bl.r13594/14918
END
ENDREP
id: 1.0.r34843/17742
type: dir
pred: 1.0.r34841/5666
count: 12210
text: 34843 17310 419 0 140a1a1edd9867cf3959591cea135e42
cpath: /branches
copyroot: 0 /

PLAIN
K 8
branches
V 20
dir 1.0.r34843/17742
K 4
tags
V 19
dir 2.0.r34572/6701
K 5
trunk
V 21
dir 3.5ck.r34842/4971
K 7
website
V 20
dir 3ge.0.r34597/802
END
ENDREP
id: 0.0.r34843/18062
type: dir
pred: 0.0.r34842/5358
count: 34843
text: 34843 17897 152 0 8fc481d2109282121a4ca02d819e22f5
cpath: /
copyroot: 0 /

2g7.5kv.t34842-1 modify true false /branches/S2_5/utility/fciconv.c


18062 18209
