genius r718 - in trunk: . help/C src ve



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]