genius r718 - in trunk: . help/C src ve
- From: jirka svn gnome org
- To: svn-commits-list gnome org
- Subject: genius r718 - in trunk: . help/C src ve
- Date: Mon, 16 Feb 2009 00:52:56 +0000 (UTC)
Author: jirka
Date: Mon Feb 16 00:52:56 2009
New Revision: 718
URL: http://svn.gnome.org/viewvc/genius?rev=718&view=rev
Log:
Sun Feb 15 18:51:42 2009 Jiri (George) Lebl <jirka 5z com>
* src/graphing.c: Add solver dialog to vectorfields. Also add
VectorfieldDrawSolution and VectorfieldClearSolutions. Also draw
arrows with proper arrows not triangles. Change default to not
normalize arrow length, that's better default I think.
* help/C/genius.xml, help/C/gel-function-list.xml: update
* ve/ve-nongnome.c: remove some unused functions
Modified:
trunk/ChangeLog
trunk/NEWS
trunk/help/C/gel-function-list.xml
trunk/help/C/genius.txt
trunk/help/C/genius.xml
trunk/src/graphing.c
trunk/ve/ve-nongnome.c
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Mon Feb 16 00:52:56 2009
@@ -1,3 +1,9 @@
+Changes to 1.0.6
+
+* Remove dependence on libgnome/ui
+* Draw solutions for vector fields
+* Add VectorfieldDrawSolution and VectorfieldClearSolutions
+
Changes to 1.0.5
* Fix buffer overrun in print (Simon Munton)
Modified: trunk/help/C/gel-function-list.xml
==============================================================================
--- trunk/help/C/gel-function-list.xml (original)
+++ trunk/help/C/gel-function-list.xml Mon Feb 16 00:52:56 2009
@@ -4966,6 +4966,36 @@
</listitem>
</varlistentry>
+ <varlistentry id="gel-function-VectorfieldClearSolutions">
+ <term>VectorfieldClearSolutions</term>
+ <listitem>
+ <synopsis>VectorfieldClearSolutions ()</synopsis>
+ <para>
+ Clears the solutions drawn by the
+ <link linkend="gel-function-VectorfieldDrawSolution"><function>VectorfieldDrawSolution</function></link>
+ function.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry id="gel-function-VectorfieldDrawSolution">
+ <term>VectorfieldDrawSolution</term>
+ <listitem>
+ <synopsis>VectorfieldDrawSolution (x, y, dt, tlen)</synopsis>
+ <para>
+ When a vector field plot is active, draw a solution with
+ the specified initial condition. The standard
+ Runge-Kutta method is used with increment <varname>dt</varname>
+ for an interval of length <varname>tlen</varname>.
+ Solutions stay on the graph until a different plot is shown or until
+ you call
+ <link linkend="gel-function-VectorfieldClearSolutions"><function>VectorfieldClearSolutions</function></link>.
+ You can also use the graphical interface to draw solutions and specify
+ initial conditions with the mouse.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="gel-function-VectorfieldPlot">
<term>VectorfieldPlot</term>
<listitem>
Modified: trunk/help/C/genius.txt
==============================================================================
--- trunk/help/C/genius.txt (original)
+++ trunk/help/C/genius.txt Mon Feb 16 00:52:56 2009
@@ -550,8 +550,23 @@
plotting using the command line see the documentation of the
VectorfieldPlot function.
- By default only the direction of the vector field is shown. To show the
- magnitude, uncheck the appropriate checkbox.
+ By default the direction and magnitude of the vector field is shown. To
+ only show direction and not the magnitude, check the appropriate checkbox
+ to normalize the arrow lengths.
+
+ When a vector field is active, there is an extra Solver menu available,
+ through which you can bring up the solver dialog. Here you can have Genius
+ plot specific solutions for the given initial conditions. You can either
+ specify initial conditions in the dialog, or you can click on the plot
+ directly to specify the initial point. While the solver dialog is active,
+ the zooming by clicking and dragging does not work. You have to close the
+ dialog first if you want to zoom using the mouse.
+
+ The solver uses the standard Runge-Kutta method. The plots will stay on
+ the screen until cleared. Zooming does not change the limits or parameters
+ of the solutions, you will have to clear and redraw them with appropriate
+ parameters. You can also use the VectorfieldDrawSolution function to draw
+ solutions from the command line or programs.
----------------------------------------------------------------------
@@ -5556,6 +5571,25 @@
genius> SurfacePlot(`(x,y)=x^2+y,-1,1,-1,1,-2,2)
genius> SurfacePlot(`(z)=|z|^2,-1,1,-1,1,0,2)
+ VectorfieldClearSolutions
+
+ VectorfieldClearSolutions ()
+
+ Clears the solutions drawn by the VectorfieldDrawSolution
+ function.
+
+ VectorfieldDrawSolution
+
+ VectorfieldDrawSolution (x, y, dt, tlen)
+
+ When a vector field plot is active, draw a solution with the
+ specified initial condition. The standard Runge-Kutta method is
+ used with increment dt for an interval of length tlen. Solutions
+ stay on the graph until a different plot is shown or until you
+ call VectorfieldClearSolutions. You can also use the graphical
+ interface to draw solutions and specify initial conditions with
+ the mouse.
+
VectorfieldPlot
VectorfieldPlot (funcx, funcy)
Modified: trunk/help/C/genius.xml
==============================================================================
--- trunk/help/C/genius.xml (original)
+++ trunk/help/C/genius.xml Mon Feb 16 00:52:56 2009
@@ -3,7 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY app "<application>Genius Mathematics Tool</application>">
<!ENTITY appname "Genius">
- <!ENTITY appversion "1.0.5">
+ <!ENTITY appversion "1.0.6">
<!ENTITY manrevision "0.2.3">
<!ENTITY date "February 2009">
@@ -603,8 +603,28 @@
</para>
<para>
- By default only the direction of the vector field is shown. To show the magnitude, uncheck the
- appropriate checkbox.
+ By default the direction and magnitude of the vector field is shown.
+ To only show direction and not the magnitude, check the appropriate
+ checkbox to normalize the arrow lengths.
+ </para>
+
+ <para>
+ When a vector field is active, there is an extra <guilabel>Solver</guilabel> menu available,
+ through which you can bring up the solver dialog. Here you can have &appname; plot specific
+ solutions for the given initial conditions. You can either specify initial conditions in the dialog,
+ or you can click on the plot directly to specify the initial point. While the solver dialog
+ is active, the zooming by clicking and dragging does not work. You have to close the dialog first
+ if you want to zoom using the mouse.
+ </para>
+
+ <para>
+ The solver uses the standard Runge-Kutta method.
+ The plots will stay on the screen until cleared.
+ Zooming does not change the limits or parameters of the solutions,
+ you will have to clear and redraw them with appropriate parameters.
+ You can also use the
+ <link linkend="gel-function-VectorfieldDrawSolution"><function>VectorfieldDrawSolution</function></link>
+ function to draw solutions from the command line or programs.
</para>
</sect1>
Modified: trunk/src/graphing.c
==============================================================================
--- trunk/src/graphing.c (original)
+++ trunk/src/graphing.c Mon Feb 16 00:52:56 2009
@@ -57,6 +57,7 @@
static GtkWidget *function_notebook = NULL;
static GtkWidget *solver_dialog = NULL;
+gboolean solver_dialog_slopefield = TRUE;
static GtkWidget *plot_zoomout_item = NULL;
static GtkWidget *plot_zoomin_item = NULL;
@@ -106,8 +107,8 @@
static GtkWidget *slopefield_entry = NULL;
static GtkWidget *slopefield_status = NULL;
-static GtkWidget *slopefield_sol_x_sb = NULL;
-static GtkWidget *slopefield_sol_y_sb = NULL;
+static GtkWidget *solver_x_sb = NULL;
+static GtkWidget *solver_y_sb = NULL;
static GtkWidget *vectorfield_entry_x = NULL;
static GtkWidget *vectorfield_status_x = NULL;
@@ -141,9 +142,9 @@
static gboolean lineplot_draw_legends = TRUE;
static gboolean lineplot_draw_legends_cb = TRUE;
static gboolean lineplot_draw_legends_parameter = TRUE;
-static gboolean vectorfield_normalize_arrow_length = TRUE;
-static gboolean vectorfield_normalize_arrow_length_cb = TRUE;
-static gboolean vectorfield_normalize_arrow_length_parameter = TRUE;
+static gboolean vectorfield_normalize_arrow_length = FALSE;
+static gboolean vectorfield_normalize_arrow_length_cb = FALSE;
+static gboolean vectorfield_normalize_arrow_length_parameter = FALSE;
/* Replotting info */
static GelEFunc *plot_func[MAXFUNC] = { NULL };
@@ -183,6 +184,8 @@
static int plot_points_num = 0;
static double solver_xinc = 0.1;
+static double solver_tinc = 0.1;
+static double solver_tlen = 0.1;
static double solver_x = 0.0;
static double solver_y = 0.0;
@@ -254,6 +257,7 @@
static void replot_fields (void);
static void slopefield_draw_solution (double x, double y, double dx);
+static void vectorfield_draw_solution (double x, double y, double dt, double tlen);
static GtkWidget *
create_range_spinboxes (const char *title, double *val1, GtkWidget **w1,
@@ -324,6 +328,16 @@
}
if (plot_mode == MODE_LINEPLOT_SLOPEFIELD) {
+ if ( ! solver_dialog_slopefield &&
+ solver_dialog != NULL) {
+ gtk_widget_destroy (solver_dialog);
+ }
+ gtk_widget_show (solver_menu_item);
+ } else if (plot_mode == MODE_LINEPLOT_VECTORFIELD) {
+ if (solver_dialog_slopefield &&
+ solver_dialog != NULL) {
+ gtk_widget_destroy (solver_dialog);
+ }
gtk_widget_show (solver_menu_item);
} else {
if (solver_dialog != NULL) {
@@ -1247,7 +1261,8 @@
if (plot_in_progress == 0 &&
line_plot != NULL &&
- plot_mode == MODE_LINEPLOT_SLOPEFIELD &&
+ (plot_mode == MODE_LINEPLOT_SLOPEFIELD ||
+ plot_mode == MODE_LINEPLOT_VECTORFIELD) &&
solver_dialog != NULL) {
double x, y;
len = plotx2 - plotx1;
@@ -1255,14 +1270,18 @@
len = ploty2 - ploty1;
y = ploty1 + len * ymin;
- if (slopefield_sol_x_sb != NULL)
+ if (solver_x_sb != NULL)
gtk_spin_button_set_value
- (GTK_SPIN_BUTTON (slopefield_sol_x_sb), x);
- if (slopefield_sol_y_sb != NULL)
+ (GTK_SPIN_BUTTON (solver_x_sb), x);
+ if (solver_y_sb != NULL)
gtk_spin_button_set_value
- (GTK_SPIN_BUTTON (slopefield_sol_y_sb), y);
+ (GTK_SPIN_BUTTON (solver_y_sb), y);
- slopefield_draw_solution (x, y, solver_xinc);
+ if (plot_mode == MODE_LINEPLOT_SLOPEFIELD)
+ slopefield_draw_solution (x, y, solver_xinc);
+ else if (plot_mode == MODE_LINEPLOT_VECTORFIELD)
+ vectorfield_draw_solution (x, y, solver_tinc,
+ solver_tlen);
return;
}
@@ -1460,7 +1479,10 @@
solver_dialog_response (GtkWidget *w, int response, gpointer data)
{
if (response == RESPONSE_PLOT) {
- slopefield_draw_solution (solver_x, solver_y, solver_xinc);
+ if (plot_mode == MODE_LINEPLOT_SLOPEFIELD)
+ slopefield_draw_solution (solver_x, solver_y, solver_xinc);
+ else
+ vectorfield_draw_solution (solver_x, solver_y, solver_tinc, solver_tlen);
} else if (response == RESPONSE_CLEAR) {
clear_solutions ();
} else {
@@ -1483,7 +1505,8 @@
double inc;
if (line_plot == NULL ||
- plot_mode != MODE_LINEPLOT_SLOPEFIELD)
+ (plot_mode != MODE_LINEPLOT_SLOPEFIELD &&
+ plot_mode != MODE_LINEPLOT_VECTORFIELD))
return;
if (solver_dialog != NULL) {
@@ -1528,23 +1551,48 @@
gtk_label_set_line_wrap (GTK_LABEL (w), TRUE);
gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0);
- solver_xinc = (plotx2-plotx1) / 100;
+ if (plot_mode == MODE_LINEPLOT_SLOPEFIELD) {
+ solver_dialog_slopefield = TRUE;
- if (solver_xinc <= 0.005)
- inc = 0.001;
- else if (solver_xinc <= 0.05)
- inc = 0.01;
- else if (solver_xinc <= 0.5)
- inc = 0.1;
- else
- inc = 1;
+ solver_xinc = (plotx2-plotx1) / 100;
- w = create_range_spinboxes (_("X increment:"), &solver_xinc, NULL,
- 0, G_MAXDOUBLE, inc,
- NULL, NULL, NULL, 0, 0, 0,
- NULL, NULL, NULL, 0, 0, 0,
- solver_entry_activate);
- gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0);
+ if (solver_xinc <= 0.005)
+ inc = 0.001;
+ else if (solver_xinc <= 0.05)
+ inc = 0.01;
+ else if (solver_xinc <= 0.5)
+ inc = 0.1;
+ else
+ inc = 1;
+
+ w = create_range_spinboxes (_("X increment:"), &solver_xinc, NULL,
+ 0, G_MAXDOUBLE, inc,
+ NULL, NULL, NULL, 0, 0, 0,
+ NULL, NULL, NULL, 0, 0, 0,
+ solver_entry_activate);
+ gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0);
+ } else {
+ solver_dialog_slopefield = FALSE;
+
+ solver_tinc = (plotx2-plotx1) / 100;
+
+ if (solver_tinc <= 0.005)
+ inc = 0.001;
+ else if (solver_tinc <= 0.05)
+ inc = 0.01;
+ else if (solver_tinc <= 0.5)
+ inc = 0.1;
+ else
+ inc = 1;
+
+ w = create_range_spinboxes (_("T increment:"), &solver_tinc, NULL,
+ 0, G_MAXDOUBLE, inc,
+ _("T interval length:"), &solver_tlen, NULL,
+ 0, G_MAXDOUBLE, 1,
+ NULL, NULL, NULL, 0, 0, 0,
+ solver_entry_activate);
+ gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0);
+ }
if (solver_x < plotx1 || solver_x > plotx2)
solver_x = plotx1 + (plotx2-plotx1)/2;
@@ -1552,10 +1600,10 @@
solver_y = ploty1 + (ploty2-ploty1)/2;
w = create_range_spinboxes (_("Point x:"), &solver_x,
- &slopefield_sol_x_sb,
+ &solver_x_sb,
-G_MAXDOUBLE, G_MAXDOUBLE, 1,
_("y:"), &solver_y,
- &slopefield_sol_y_sb,
+ &solver_y_sb,
-G_MAXDOUBLE, G_MAXDOUBLE, 1,
NULL, NULL, NULL, 0, 0, 0,
solver_entry_activate);
@@ -3039,6 +3087,91 @@
}
static void
+vectorfield_draw_solution (double x, double y, double dt, double tlen)
+{
+ double *xx, *yy;
+ double cx, cy, t;
+ int len;
+ int i;
+ GdkColor color;
+ GtkPlotData *data;
+
+ if (vectorfield_func_x == NULL ||
+ vectorfield_func_y == NULL ||
+ dt <= 0.0 ||
+ tlen <= 0.0)
+ return;
+
+ gdk_color_parse ("red", &color);
+
+ len = (int)(tlen / dt) + 2;
+ xx = g_new0 (double, len);
+ yy = g_new0 (double, len);
+
+ i = 1;
+ xx[0] = x;
+ yy[0] = y;
+ cx = x;
+ cy = y;
+ t = 0.0;
+ while (t < tlen && i < len) {
+ gboolean ex = FALSE;
+ double xk1, xk2, xk3, xk4, xsl;
+ double yk1, yk2, yk3, yk4, ysl;
+
+ /* standard Runge-Kutta */
+ xk1 = call_xy_or_z_function (vectorfield_func_x,
+ cx, cy, &ex);
+ if G_UNLIKELY (ex) break;
+ yk1 = call_xy_or_z_function (vectorfield_func_y,
+ cx, cy, &ex);
+ if G_UNLIKELY (ex) break;
+
+ xk2 = call_xy_or_z_function (vectorfield_func_x,
+ cx+(dt/2)*xk1, cy+(dt/2)*yk1, &ex);
+ if G_UNLIKELY (ex) break;
+ yk2 = call_xy_or_z_function (vectorfield_func_y,
+ cx+(dt/2)*xk1, cy+(dt/2)*yk1, &ex);
+ if G_UNLIKELY (ex) break;
+
+ xk3 = call_xy_or_z_function (vectorfield_func_x,
+ cx+(dt/2)*xk2, cy+(dt/2)*yk2, &ex);
+ if G_UNLIKELY (ex) break;
+ yk3 = call_xy_or_z_function (vectorfield_func_y,
+ cx+(dt/2)*xk2, cy+(dt/2)*yk2, &ex);
+ if G_UNLIKELY (ex) break;
+
+ xk4 = call_xy_or_z_function (vectorfield_func_x,
+ cx+dt*xk3, cy+dt*yk3, &ex);
+ if G_UNLIKELY (ex) break;
+ yk4 = call_xy_or_z_function (vectorfield_func_y,
+ cx+dt*xk3, cy+dt*yk3, &ex);
+ if G_UNLIKELY (ex) break;
+
+ xsl = (xk1+2*xk2+2*xk3+xk4)/6.0;
+ ysl = (yk1+2*yk2+2*yk3+yk4)/6.0;
+
+ cx += xsl * dt;
+ cy += ysl * dt;
+
+ xx[i] = cx;
+ yy[i] = cy;
+
+ i ++;
+ t += dt;
+ }
+
+ len = i;
+
+ data = draw_line (xx, yy, len, 2 /* thickness */, &color);
+ solutions_list = g_slist_prepend (solutions_list,
+ data);
+ g_signal_connect (G_OBJECT (data), "destroy",
+ G_CALLBACK (solution_destroyed), NULL);
+}
+
+
+static void
replot_fields (void)
{
if (slopefield_func != NULL) {
@@ -3119,7 +3252,7 @@
gtk_plot_flux_set_arrow (GTK_PLOT_FLUX (vectorfield_data),
- 6, 6, GTK_PLOT_SYMBOL_OPAQUE);
+ 6, 6, GTK_PLOT_SYMBOL_EMPTY);
gtk_plot_flux_show_scale (GTK_PLOT_FLUX (vectorfield_data), FALSE);
@@ -4955,8 +5088,7 @@
static GelETree *
SlopefieldClearSolutions_op (GelCtx *ctx, GelETree * * a, int *exception)
{
- if (plot_mode != MODE_LINEPLOT_SLOPEFIELD ||
- slopefield_func == NULL) {
+ if (plot_mode != MODE_LINEPLOT_SLOPEFIELD) {
gel_errorout (_("%s: Slope field not active"),
"SlopefieldClearSolutions");
return NULL;
@@ -4968,6 +5100,56 @@
}
static GelETree *
+VectorfieldDrawSolution_op (GelCtx *ctx, GelETree * * a, int *exception)
+{
+ double x, y, dt, tlen;
+
+ GET_DOUBLE (x, 0, "VectorfieldDrawSolution");
+ GET_DOUBLE (y, 1, "VectorfieldDrawSolution");
+ GET_DOUBLE (dt, 2, "VectorfieldDrawSolution");
+ GET_DOUBLE (tlen, 3, "VectorfieldDrawSolution");
+
+ if (dt <= 0.0) {
+ gel_errorout (_("%s: dt must be positive"),
+ "VectorfieldDrawSolution");
+ return NULL;
+ }
+
+ if (tlen <= 0.0) {
+ gel_errorout (_("%s: tlen must be positive"),
+ "VectorfieldDrawSolution");
+ return NULL;
+ }
+
+ if (plot_mode != MODE_LINEPLOT_VECTORFIELD ||
+ vectorfield_func_x == NULL ||
+ vectorfield_func_y == NULL) {
+ gel_errorout (_("%s: Vector field not active"),
+ "VectorfieldDrawSolution");
+ return NULL;
+ }
+
+ vectorfield_draw_solution (x, y, dt, tlen);
+
+ return gel_makenum_null ();
+}
+
+
+static GelETree *
+VectorfieldClearSolutions_op (GelCtx *ctx, GelETree * * a, int *exception)
+{
+ if (plot_mode != MODE_LINEPLOT_VECTORFIELD) {
+ gel_errorout (_("%s: Vector field not active"),
+ "VectorfieldClearSolutions");
+ return NULL;
+ }
+
+ clear_solutions ();
+
+ return gel_makenum_null ();
+}
+
+static GelETree *
SlopefieldPlot_op (GelCtx *ctx, GelETree * * a, int *exception)
{
double x1, x2, y1, y2;
@@ -5877,6 +6059,9 @@
FUNC (SlopefieldDrawSolution, 3, "x,y,dx", "plotting", N_("Draw a solution for a slope field starting at x,y and using dx as increment"));
FUNC (SlopefieldClearSolutions, 0, "", "plotting", N_("Clear all the slopefield solutions"));
+ FUNC (VectorfieldDrawSolution, 4, "x,y,dt,tlen", "plotting", N_("Draw a solution for a vector field starting at x,y, using dt as increment for tlen units"));
+ FUNC (VectorfieldClearSolutions, 0, "", "plotting", N_("Clear all the vectorfield solutions"));
+
VFUNC (SurfacePlot, 2, "func,args", "plotting", N_("Plot a surface function which takes either two arguments or a complex number. First comes the function then optionally limits as x1,x2,y1,y2,z1,z2"));
Modified: trunk/ve/ve-nongnome.c
==============================================================================
--- trunk/ve/ve-nongnome.c (original)
+++ trunk/ve/ve-nongnome.c Mon Feb 16 00:52:56 2009
@@ -73,224 +73,3 @@
return NULL;
}
-
-/* Following stolen from libgnome / gnome-i18n.c */
-
-static GHashTable *alias_table = NULL;
-
-/*read an alias file for the locales*/
-static void
-read_aliases (char *file)
-{
- FILE *fp;
- char buf[256];
- if (!alias_table)
- alias_table = g_hash_table_new (g_str_hash, g_str_equal);
- VE_IGNORE_EINTR (fp = fopen (file,"r"));
- if (!fp)
- return;
- for (;;)
- {
- char *p;
- VE_IGNORE_EINTR (p = fgets (buf, sizeof (buf), fp));
- if (p == NULL)
- break;
- g_strstrip(buf);
- if (buf[0]=='#' || buf[0]=='\0')
- continue;
- p = strtok (buf,"\t ");
- if (!p)
- continue;
- p = strtok (NULL,"\t ");
- if(!p)
- continue;
- if (!g_hash_table_lookup (alias_table, buf))
- g_hash_table_insert (alias_table, g_strdup(buf), g_strdup(p));
- }
- VE_IGNORE_EINTR (fclose (fp));
-}
-
-/*return the un-aliased language as a newly allocated string*/
-static char *
-unalias_lang (char *lang)
-{
- char *p;
- int i;
- if (!alias_table)
- {
- read_aliases ("/usr/share/locale/locale.alias");
- read_aliases ("/usr/local/share/locale/locale.alias");
- read_aliases ("/usr/lib/X11/locale/locale.alias");
- read_aliases ("/usr/openwin/lib/locale/locale.alias");
- }
- i = 0;
- while ((p=g_hash_table_lookup(alias_table,lang)) && strcmp(p, lang))
- {
- lang = p;
- if (i++ == 30)
- {
- static gboolean said_before = FALSE;
- if (!said_before)
- g_warning (_("Too many alias levels for a locale; "
- "may indicate a loop"));
- said_before = TRUE;
- return lang;
- }
- }
- return lang;
-}
-
-/* Mask for components of locale spec. The ordering here is from
- * least significant to most significant
- */
-enum
-{
- COMPONENT_CODESET = 1 << 0,
- COMPONENT_TERRITORY = 1 << 1,
- COMPONENT_MODIFIER = 1 << 2
-};
-
-/* Break an X/Open style locale specification into components
- */
-static guint
-explode_locale (const gchar *locale,
- gchar **language,
- gchar **territory,
- gchar **codeset,
- gchar **modifier)
-{
- const gchar *uscore_pos;
- const gchar *at_pos;
- const gchar *dot_pos;
-
- guint mask = 0;
-
- uscore_pos = strchr (locale, '_');
- dot_pos = strchr (uscore_pos ? uscore_pos : locale, '.');
- at_pos = strchr (dot_pos ? dot_pos : (uscore_pos ? uscore_pos : locale), '@');
-
- if (at_pos)
- {
- mask |= COMPONENT_MODIFIER;
- *modifier = g_strdup (at_pos);
- }
- else
- at_pos = locale + strlen (locale);
-
- if (dot_pos)
- {
- mask |= COMPONENT_CODESET;
- *codeset = g_new (gchar, 1 + at_pos - dot_pos);
- strncpy (*codeset, dot_pos, at_pos - dot_pos);
- (*codeset)[at_pos - dot_pos] = '\0';
- }
- else
- dot_pos = at_pos;
-
- if (uscore_pos)
- {
- mask |= COMPONENT_TERRITORY;
- *territory = g_new (gchar, 1 + dot_pos - uscore_pos);
- strncpy (*territory, uscore_pos, dot_pos - uscore_pos);
- (*territory)[dot_pos - uscore_pos] = '\0';
- }
- else
- uscore_pos = dot_pos;
-
- *language = g_new (gchar, 1 + uscore_pos - locale);
- strncpy (*language, locale, uscore_pos - locale);
- (*language)[uscore_pos - locale] = '\0';
-
- return mask;
-}
-
-/*
- * Compute all interesting variants for a given locale name -
- * by stripping off different components of the value.
- *
- * For simplicity, we assume that the locale is in
- * X/Open format: language[_territory][ codeset][ modifier]
- *
- * TODO: Extend this to handle the CEN format (see the GNUlibc docs)
- * as well. We could just copy the code from glibc wholesale
- * but it is big, ugly, and complicated, so I'm reluctant
- * to do so when this should handle 99% of the time...
- */
-static GList *
-compute_locale_variants (const gchar *locale)
-{
- GList *retval = NULL;
-
- gchar *language;
- gchar *territory;
- gchar *codeset;
- gchar *modifier;
-
- guint mask;
- guint i;
-
- g_return_val_if_fail (locale != NULL, NULL);
-
- mask = explode_locale (locale, &language, &territory, &codeset, &modifier);
-
- /* Iterate through all possible combinations, from least attractive
- * to most attractive.
- */
- for (i=0; i<=mask; i++)
- if ((i & ~mask) == 0)
- {
- gchar *val = g_strconcat(language,
- (i & COMPONENT_TERRITORY) ? territory : "",
- (i & COMPONENT_CODESET) ? codeset : "",
- (i & COMPONENT_MODIFIER) ? modifier : "",
- NULL);
- retval = g_list_prepend (retval, val);
- }
-
- g_free (language);
- if (mask & COMPONENT_CODESET)
- g_free (codeset);
- if (mask & COMPONENT_TERRITORY)
- g_free (territory);
- if (mask & COMPONENT_MODIFIER)
- g_free (modifier);
-
- return retval;
-}
-
-/* The following is (partly) taken from the gettext package.
- Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. */
-
-static const gchar *
-guess_category_value (const gchar *categoryname)
-{
- const gchar *retval;
-
- /* The highest priority value is the `LANGUAGE' environment
- variable. This is a GNU extension. */
- retval = g_getenv ("LANGUAGE");
- if (retval != NULL && retval[0] != '\0')
- return retval;
-
- /* `LANGUAGE' is not set. So we have to proceed with the POSIX
- methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some
- systems this can be done by the `setlocale' function itself. */
-
- /* Setting of LC_ALL overwrites all other. */
- retval = g_getenv ("LC_ALL");
- if (retval != NULL && retval[0] != '\0')
- return retval;
-
- /* Next comes the name of the desired category. */
- retval = g_getenv (categoryname);
- if (retval != NULL && retval[0] != '\0')
- return retval;
-
- /* Last possibility is the LANG environment variable. */
- retval = g_getenv ("LANG");
- if (retval != NULL && retval[0] != '\0')
- return retval;
-
- return NULL;
-}
-
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]