aboutsummaryrefslogtreecommitdiffhomepage
path: root/translate.c
blob: 23de015a08a4a37a2fdad94066c622d31d7cb014 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/** \file translate.c

Translation library, internally uses catgets

*/

#include "config.h"


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wchar.h>

#if HAVE_LIBINTL_H
#include <libintl.h>
#endif

#include "common.h"
#include "fallback.h"
#include "util.h"

#include "halloc_util.h"

#if HAVE_GETTEXT

/**
   Number of string_buffer_t in the ring of buffers
*/
#define BUFF_COUNT 64

/**
   The ring of string_buffer_t
*/
static string_buffer_t buff[BUFF_COUNT];
/**
   Current position in the ring
*/
static int curr_buff=0;

/**
   Buffer used by translate_wcs2str
*/
static char *wcs2str_buff=0;
/**
   Size of buffer used by translate_wcs2str
*/
static size_t wcs2str_buff_count=0;

static int is_init = 0;

static void internal_destroy()
{
	int i;

	if( !is_init )
		return;
	
	is_init = 0;
	
	for(i=0; i<BUFF_COUNT; i++ )
		sb_destroy( &buff[i] );

	free( wcs2str_buff );
}

static void internal_init()
{
	int i;

	is_init = 1;
	
	for(i=0; i<BUFF_COUNT; i++ )
	{
		sb_init( &buff[i] );
	}
	halloc_register_function_void( global_context, &internal_destroy );
	
	bindtextdomain( PACKAGE_NAME, LOCALEDIR );
	textdomain( PACKAGE_NAME );
}


/**
   Wide to narrow character conversion. Internal implementation that
   avoids exessive calls to malloc
*/
static char *translate_wcs2str( const wchar_t *in )
{
	size_t len = MAX_UTF8_BYTES*wcslen(in)+1;
	if( len > wcs2str_buff_count )
	{
		wcs2str_buff = realloc( wcs2str_buff, len );
		if( wcs2str_buff == 0 )
		{
			die_mem();
		}
	}
	
	wcstombs( wcs2str_buff, 
			  in,
			  MAX_UTF8_BYTES*wcslen(in)+1 );
	
	return wcs2str_buff;
}

const wchar_t *wgettext( const wchar_t *in )
{
	if( !in )
		return in;

	if( !is_init )
		internal_init();
		
	char *mbs_in = translate_wcs2str( in );	
	char *out = gettext( mbs_in );
	wchar_t *wres=0;

	sb_clear( &buff[curr_buff] );
	
	sb_printf( &buff[curr_buff], L"%s", out );
	wres = (wchar_t *)buff[curr_buff].buff;
	curr_buff = (curr_buff+1)%BUFF_COUNT;

	return wres;
}

#else

const wchar_t *wgettext( const wchar_t *in )
{
	return in;
}

#endif