summary refs log tree commit diff stats
path: root/plugins/perl/perl.c
AgeCommit message (Collapse)Author
2012-11-12Update Perl error message according to recent changesBerke Viktor
2012-11-11RebrandingBerke Viktor
2012-11-04Use configdir instead of *xchatdir*Berke Viktor
2012-10-30Some final rebrandingBerke Viktor
2012-10-30Rebrand get_info(xchatdir) but remain compatible for Perl and PythonBerke Viktor
2012-10-30Some remaining fixesBerke Viktor
2012-10-30Rebranding for the rest of plugin*Berke Viktor
2012-10-30Rebranding for XCHAT_EAT_*Berke Viktor
2012-10-30Rebranding for XCHAT_FD_*Berke Viktor
2012-10-30Rebranding for XCHAT_PRI_*Berke Viktor
2012-10-27Ignore generated config.h properly on UnixBerke Viktor
2012-10-24A lot more rebrandingBerke Viktor
2012-07-26Auto-load user plugins and scripts from <config>/addonsBerke Viktor
On Unix leave $(libdir)/hexchat/plugins for plugin packagers, on Windows prevent users from modifying Program Files by ignoring everything except bundled plugins
2012-07-21Use <configdir>/scripts to (auto)load Lua/Perl/Python/Tcl scriptsBerke Viktor
2012-07-20Some more rebrandingBerke Viktor
2012-07-19more branding changesxhmikosr
2012-07-13Dirent is no longer required for PerlBerke Viktor
2012-07-13Update XChat to r1514Berke Viktor
2012-07-13Update XChat to r1511Berke Viktor
2012-06-10More solution fixes and add language interfacesBerke Viktor
2011-12-11some more multiplatform supportBerke Viktor
2011-12-11initial patches for linux compatibilityBerke Viktor
2011-11-23Merge branch 'master' into wdkBerke Viktor
2011-11-23update xchat to r1498Berke Viktor
2011-07-28instruct users to download strawberry perl instead of activeperlberkeviktor@aol.com
2011-02-28add wdk changes to named branchberkeviktor@aol.com
2011-02-24add xchat r1489berkeviktor@aol.com
/a> 119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307



















                                                                               
                                                                                          

   


                               
                         
      


























































































                                                                                               
            
                                                                                 


                                                                                






















































































































































































                                                                                              
/*
 *  Copyright (C) 2005 Nathan Fredrickson
 *  Borrowed from Galeon, renamed, and simplified to only use iso-codes with no
 *  fallback method.
 *
 *  Copyright (C) 2004 Christian Persch
 *  Copyright (C) 2004 Crispin Flowerday
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#ifdef WIN32
#include "../../config-win32.h"
#else
#include "../../config.h"
#endif

#include "sexy-iso-codes.h"

#include <glib/gi18n.h>

#include <string.h>

#include <libxml/xmlreader.h>

static GHashTable *iso_639_table = NULL;
static GHashTable *iso_3166_table = NULL;

#define ISO_639_DOMAIN	"iso_639"
#define ISO_3166_DOMAIN	"iso_3166"

#ifdef HAVE_ISO_CODES

#define ISOCODESLOCALEDIR "/share/locale"

static void
read_iso_639_entry (xmlTextReaderPtr reader,
		    GHashTable *table)
{
	xmlChar *code, *name;

	code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_1_code");
	name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");

	/* Get iso-639-2 code */
	if (code == NULL || code[0] == '\0')
	{
		xmlFree (code);
		/* FIXME: use the 2T or 2B code? */
		code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_2T_code");
	}

	if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0')
	{
		g_hash_table_insert (table, code, name);
	}
	else
	{
		xmlFree (code);
		xmlFree (name);
	}
}

static void
read_iso_3166_entry (xmlTextReaderPtr reader,
		     GHashTable *table)
{
	xmlChar *code, *name;

	code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "alpha_2_code");
	name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");

	if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0')
	{
		char *lcode;

		lcode = g_ascii_strdown ((char *) code, -1);
		xmlFree (code);

		g_hash_table_insert (table, lcode, name);
	}
	else
	{
		xmlFree (code);
		xmlFree (name);
	}

}

typedef enum
{
	STATE_START,
	STATE_STOP,
	STATE_ENTRIES,
} ParserState;

static gboolean
load_iso_entries (int iso,
		  GFunc read_entry_func,
		  gpointer user_data)
{
	xmlTextReaderPtr reader;
	ParserState state = STATE_START;
	xmlChar iso_entries[32], iso_entry[32];
	char *filename;
	int ret = -1;

#ifdef WIN32
	filename = g_strdup_printf (".\\share\\xml\\iso-codes\\iso_%d.xml", iso);
#else
	filename = g_strdup_printf ("/usr/share/xml/iso-codes/iso_%d.xml", iso);
#endif
	reader = xmlNewTextReaderFilename (filename);
	if (reader == NULL) goto out;

	xmlStrPrintf (iso_entries, sizeof (iso_entries),
				  (xmlChar *)"iso_%d_entries", iso);
	xmlStrPrintf (iso_entry, sizeof (iso_entry),
				  (xmlChar *)"iso_%d_entry", iso);

	ret = xmlTextReaderRead (reader);

	while (ret == 1)
	{
		const xmlChar *tag;
		xmlReaderTypes type;

		tag = xmlTextReaderConstName (reader);
		type = xmlTextReaderNodeType (reader);

		if (state == STATE_ENTRIES &&
		    type == XML_READER_TYPE_ELEMENT &&
		    xmlStrEqual (tag, iso_entry))
		{
			read_entry_func (reader, user_data);
		}
		else if (state == STATE_START &&
			 type == XML_READER_TYPE_ELEMENT &&
			 xmlStrEqual (tag, iso_entries))
		{
			state = STATE_ENTRIES;
		}
		else if (state == STATE_ENTRIES &&
			 type == XML_READER_TYPE_END_ELEMENT &&
			 xmlStrEqual (tag, iso_entries))
		{
			state = STATE_STOP;
		}
		else if (type == XML_READER_TYPE_SIGNIFICANT_WHITESPACE ||
			 type == XML_READER_TYPE_WHITESPACE ||
			 type == XML_READER_TYPE_TEXT ||
			 type == XML_READER_TYPE_COMMENT)
		{
			/* eat it */
		}
		else
		{
			/* ignore it */
		}

		ret = xmlTextReaderRead (reader);
	}

	xmlFreeTextReader (reader);

out:
	if (ret < 0 || state != STATE_STOP)
	{
		/* This is not critical, we will fallback to our own code */
		g_free (filename);
		return FALSE;
	}

	g_free (filename);

	return TRUE;
}

#endif /* HAVE_ISO_CODES */


static void
ensure_iso_codes_initialised (void)
{
	static gboolean initialised = FALSE;

	if (initialised == TRUE)
	{
		return;
	}
	initialised = TRUE;

#if defined (ENABLE_NLS) && defined (HAVE_ISO_CODES)
	bindtextdomain (ISO_639_DOMAIN, ISOCODESLOCALEDIR);
	bind_textdomain_codeset (ISO_639_DOMAIN, "UTF-8");

	bindtextdomain(ISO_3166_DOMAIN, ISOCODESLOCALEDIR);
	bind_textdomain_codeset (ISO_3166_DOMAIN, "UTF-8");
#endif

	iso_639_table = g_hash_table_new_full (g_str_hash, g_str_equal,
					       (GDestroyNotify) xmlFree,
					       (GDestroyNotify) xmlFree);

	iso_3166_table = g_hash_table_new_full (g_str_hash, g_str_equal,
						(GDestroyNotify) g_free,
						(GDestroyNotify) xmlFree);
	
#ifdef HAVE_ISO_CODES
	load_iso_entries (639, (GFunc) read_iso_639_entry, iso_639_table);
	load_iso_entries (3166, (GFunc) read_iso_3166_entry, iso_3166_table);
#endif
}


static char *
get_iso_name_for_lang_code (const char *code)
{
	char **str;
	char *name = NULL;
	const char *langname, *localename;
	int len;

	str = g_strsplit (code, "_", -1);

	/* count the entries */
	for (len = 0; str[len]; len++ ) /* empty */;

	g_return_val_if_fail (len != 0, NULL);

	langname = (const char *) g_hash_table_lookup (iso_639_table, str[0]);

	if (len == 1 && langname != NULL)
	{
		name = g_strdup (dgettext (ISO_639_DOMAIN, langname));
	}
	else if (len == 2 && langname != NULL)
	{
		localename = (const char *) g_hash_table_lookup (iso_3166_table, str[1]);

		if (localename != NULL)
		{
			/* translators: the first %s is the language name, and the
			 * second %s is the locale name. Example:
			 * "French (France)
			 *
			 * Also: The text before the "|" is context to help you decide on
                         * the correct translation. You MUST OMIT it in the translated string.
			 */
			name = g_strdup_printf (Q_("language|%s (%s)"),
						dgettext (ISO_639_DOMAIN, langname),
						dgettext (ISO_3166_DOMAIN, localename));
		}
		else
		{
			name = g_strdup_printf (Q_("language|%s (%s)"),
						dgettext (ISO_639_DOMAIN, langname), str[1]);
		}
	}

	g_strfreev (str);

	return name;
}

/**
 * gtkspell_iso_codes_lookup_name_for_code:
 * @code: A language code, e.g. en_CA
 *
 * Looks up a name to display to the user for a language code,
 * this might use the iso-codes package if support was compiled
 * in, and it is available
 *
 * Returns: the UTF-8 string to display to the user, or NULL if 
 * a name for the code could not be found
 */
char *
gtkspell_iso_codes_lookup_name_for_code (const char *code)
{
	char * lcode;
	char * ret;

	g_return_val_if_fail (code != NULL, NULL);

	ensure_iso_codes_initialised ();

	lcode = g_ascii_strdown (code, -1);

	ret = get_iso_name_for_lang_code (lcode);

	g_free (lcode);

	return ret;
}