2006-09-07 German Poo-Caaman~o <gpoo@ubiobio.cl>
author"German Poo-Caaman~o <gpoo@ubiobio.cl>"
Thu, 07 Sep 2006 16:46:51 -0400
changeset 0 7e52f5046fb6
child 1 52d161ada41e
2006-09-07 German Poo-Caaman~o <gpoo@ubiobio.cl> * Makefile: * programming-guidelines.xml: * stylesheets/README * stylesheets/devhelp.xsl * stylesheets/home.png * stylesheets/left.png * stylesheets/librognome-html.xsl * stylesheets/programming-guidelines.css: * stylesheets/right.png: * stylesheets/up.png: * ChangeLog: Initial version.
Makefile
programming-guidelines.xml
stylesheets/README
stylesheets/devhelp.xsl
stylesheets/home.png
stylesheets/left.png
stylesheets/librognome-html.xsl
stylesheets/programming-guidelines.css
stylesheets/right.png
stylesheets/up.png
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Thu Sep 07 16:46:51 2006 -0400
@@ -0,0 +1,19 @@
+PACKAGE = programming-guidelines
+STYLESHEET = stylesheets/librognome-html.xsl
+
+SGML_FILES = \
+	programming-guidelines.xml
+
+all: articulo
+
+articulo: $(SGML_FILES)
+	 xsltproc --stringparam gtkdoc.bookname $(PACKAGE) \
+	          --stringparam html.stylesheet $(PACKAGE).css \
+	          --output html/index.html \
+	          $(STYLESHEET) \
+	          programming-guidelines.xml
+	cp -a stylesheets/*.png html
+	cp -a stylesheets/$(PACKAGE).css html
+
+clean: 
+	rm -rf html/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programming-guidelines.xml	Thu Sep 07 16:46:51 2006 -0400
@@ -0,0 +1,2120 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
+    "/usr/share/sgml/docbook/dtd/xml/4.1.2/docbookx.dtd" [
+<!ENTITY Emacs "<application>Emacs</application>">
+<!ENTITY Vim "<application>Vim</application>">
+<!ENTITY ChangeLog "<filename>ChangeLog</filename>">
+]>
+
+
+<article class="techreport" id="index" lang="es">
+
+  <articleinfo>
+    <title>Guía de programación de GNOME</title>
+
+    <authorgroup>
+      <author>
+	<firstname>Federico</firstname>
+	<surname>Mena Quintero</surname>
+	<affiliation>
+	  <address>
+	    <email>federico@gnu.org</email>
+	  </address>
+	</affiliation>
+      </author>
+      <author>
+	<firstname>Miguel</firstname>
+	<surname>de Icaza</surname>
+	<affiliation>
+	  <address>
+	    <email>miguel@kernel.org</email>
+	  </address>
+	</affiliation>
+      </author>
+      <author>
+	<firstname>Morten</firstname>
+	<surname>Welinder</surname>
+	<affiliation>
+	  <address>
+	    <email>terra@diku.dk</email>
+	  </address>
+	</affiliation>
+      </author>
+      <othercredit>
+	<firstname>Germ&aacute;n</firstname>
+	<surname>Po&oacute; Caama&ntilde;o</surname>
+	<contrib>Traducción al español</contrib>
+	<affiliation>
+	  <address>
+	    <email>gpoo@ubiobio.cl</email>
+	  </address>
+	</affiliation>
+      </othercredit>
+    </authorgroup>
+    <copyright>
+      <year>2000</year>
+      <holder>The Free Software Foundation</holder>
+    </copyright>
+    <copyright>
+      <year>2004</year>
+      <holder>GNOME Foundation, respecto de la versión en español.</holder>
+    </copyright>
+
+    <abstract>
+      <para>
+	Este artículo contiene varías guías y sugerencias para los
+	programadores de GNOME, así como ciertas políticas que
+	deberían seguirse cuando se escriben programas para GNOME.
+	Es un intento para que los programadores puedan aprender
+	acerca del proceso de desarrollo de GNOME y su filosofía.
+	GNOME es un esfuerzo de equipo, así que será útil para 
+	que los programadores sepan «la forma de hacer la
+	cosas».
+      </para>
+    </abstract>
+  </articleinfo>
+
+  <!-- Introduction -->
+
+  <sect1 id="intro">
+    <title>Introducción</title>
+
+    <para>
+	  GTK+, la biblioteca de interfaz de usuario básica de GNOME, nos
+	  ha enseñado algunas lecciones importantes en el diseño de software.
+	  El código de GTK+ es limpio, consistente, mantenible y tiene
+	  sentido.  Tal código no sólo provoca placer al trabajar con el,
+	  sino que además es un incentivo para las buenas prácticas de 
+	  programación para aquellos que quieran extenderlo y modificarlo.
+    </para>
+
+    <para>
+	  En este artículo intentamos presentar algunas sugerencias y 
+	  guías que debería tener en cuenta cuando escriba código para
+	  el proyecto GNOME.  Presentamos algunas de las políticas
+	  que deben seguirse cuando se modifica el código de otras
+	  personas, usando el repositorio CVS y asegurándose de que su
+	  código se ajusta para ser incluído en GNOME. También 
+	  presentamos información que será útil para los mantenedores
+	  de paquetes.
+    </para>
+
+    <para>
+	  Además de este documento, asegúrese de leer los Estándares de 
+	  Programación de GNU.  Estos se encuentran disponibles en el
+	  nodo indo <filename>(Standards)</filename> en la documentación
+	  estándar de GNU.
+    </para>
+  </sect1>
+
+  <!-- The Importance of Writing Good Code -->
+
+  <sect1 id="good-code">
+    <title>La importancia de escribir buen código</title>
+
+    <para>
+	  GNOME es un proyecto de software libre muy ambicioso y, como tal,
+	  está compuesto por muchos paquetes de software que son más o menos
+	  independientes el uno del otro.  Mucho del trabajo en GNOME lo 
+	  realizan voluntarios; programadores que vienen y se van
+	  en cualquier momento y que serán capaces de dedicar
+	  diferentes cantidades de tiempo al proyecto GNOME.
+	  Muchas personas trabajan en software libre en su tiempo libre o
+	  como un pasatiempo, así, si sus responsabilidades del «mundo
+	  real» cambian, se verá reflejado en la cantidad de trabajo que
+	  dedicarán a proyectos de software libre.
+    </para>
+
+    <para>
+	  Se tarda mucho tiempo en escribir software y supone una
+	   gran cantidad de trabajo. Es por esto que muchos
+	  de los voluntarios de tiempo parcial no pueden comenzar 
+	  grandes proyectos por sí mismos; es mucho más fácil y
+	  gratificante contribuir a proyectos existentes, puesto que
+	  los resultados son inmediatamente visibles y usables.
+    </para>
+
+    <para>
+	  Teniendo esto en cuenta y el hecho que los programadores de
+	  software libre tiene recursos escasos, concluimos que
+	  para los proyectos existentes es muy importante facilitar,
+	  tanto como sea posible, que otras personas puedan contribuir.
+	  Una forma de hacerlo es asegurándose de que los programas
+	  sean fáciles de leer, entender y modificar.
+    </para>
+
+    <para>
+	  El código desordenado es difícil de leer y las personas pueden
+	  perder interés si no son capaces de descifrar lo que el código
+	  intenta hacer.  Además, es importante que los programadores sean
+	  capaces de entender el código rápidamente, y así poder comenzar
+	  a contribuir reparando fallos y extendiéndolo en un período breve
+	  de tiempo.  El código fuente es una forma de comunicación, y así
+	  como a alguien podría no querer leer una novela con errores
+	  ortográficos y mala puntuación, los programadores deben intentar
+	  escribir buen código de tal forma que sea fácil de entender y
+	  modificar por otros.
+    </para>
+
+    <para>
+	  Existen algunas cualidades que son importantes en un buen 
+	  código y por qué son importantes para los desarrolladores
+	  de software libre:
+
+      <variablelist>
+	<varlistentry>
+	  <term>Limpieza</term>
+	  <listitem>
+	    <para>
+		  Un código limpio es fácil de leer; permite a las
+		  personas leerlo con un mínimo esfuerzo y así pueden
+		  entenderlo más fácilmente.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term>Consistencia</term>
+	  <listitem>
+	    <para>
+		  El código consistente permite más fácilmente que las
+		  personas entiendan como funciona el programa; cuando se
+		  lee código consistente, subconcientemente uno se forma
+		  una número de supuestos y expectativas acerca del 
+		  funcionamiento del código, de esta forma es más fácil
+		  y seguro realizarle modificaciones.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term>Extensibilidad</term>
+	  <listitem>
+	    <para>
+		  El código de propósito general es más fácil de reutilizar
+		  y modificar que el código demasiado específico con muchos
+		  supuestos escritos directamente en el código (hardcoded).
+		  Cuando alguien desea agregar una nueva características
+		  a un programa, obviamente será más fácil hacerlo si el
+		  código fue diseñado para ser extensible desde el inicio.
+		  El código que no fue escrito de esta forma hará que las
+		  personas deban implementar hacks muy feos para poder
+		  añadir características.
+	    </para>
+	  </listitem>
+	</varlistentry>
+	<varlistentry>
+	  <term>Corrección</term>
+	  <listitem>
+	    <para>
+		  Finalmente, el código diseñado debe ser correcto para
+		  que las personas pierdan menos tiempo preocupándose de
+		  los errores y se ocupen  en extender las
+		  características de un programa.  Los usuarios también
+		  apreciarán un código correcto, ya que a nadie le gusta
+		  que un programa se caiga.
+	    </para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+    </para>
+
+    <para>
+	  En resumen, los programadores a menudo contribuyen en
+	  su tiempo libre a proyectos de software libre, y aún quienes
+	  contribuyen de forma regular pueden detenerse en cualquier
+	  instante del tiempo, así que es muy importante que el código
+	  sea bueno y les permita modificarlo facilmente.  El resultado
+	  final será un mejor software al que los programadores 
+	  querrán extender.
+    </para>
+  </sect1>
+
+  <!-- Coding Style -->
+
+  <sect1 id="code-style">
+    <title>Estilo de programación</title>
+
+    <para>
+      «El estilo de programación» se refiere a la forma en 
+	  que se da formato al código fuente.  Para C, esto involucra
+	  la forma en que se ubican las llaves, se indenta el código y
+	  se utilizan los paréntesis.  GNOME tiene una mezcla de estilos
+	  de programación y no obligamos el uso de ninguno de ellos.  Lo más
+	  importante es que el código sea consistente dentro de un programa
+	  o una biblioteca --- el código con un formato desordenado
+	  no es aceptable debido a que es difícil de leer.
+    </para>
+
+    <para>
+	  Cuando se escribe un nuevo programa o biblioteca, siga un
+	  estilo consistente de ubicación de llaves y de indentación.
+	  Si no tiene ninguna preferencia personal de estilo, 
+	  recomendamos el estilo de programación del núcleo de Linux o
+	  el estilo de programación de GNU.
+    </para>
+
+    <para>
+	  Lea el nodo de info <filename>(Standards)Writing C</filename> 
+	  en la documentación de GNU. Luego, obtenga el código fuente
+	  de Linux y lea el archivo 
+	  <filename>linux/Documentation/CodingStyle</filename>, e
+	  ignore los chistes de Linus.  Estos dos documentos le darán
+	  una buena idea de nuestras recomendaciones para el código de
+	  GNOME.
+    </para>
+
+    <!-- Indentation Style -->
+
+    <sect2 id="indent">
+      <title>Estilo de indentación</title>
+
+      <para>
+		Para el código del núcleo de GNOME preferimos el estilo
+		de indentación del núcleo de Linux.  Use tabuladores
+		de 8 espacios para la indentación.
+      </para>
+
+      <para>
+		Usar tabuladores de 8 espacios para indentación proporciona
+		un número de beneficios.  Permite que el código sea más
+		fácil de leer, ya que la indentación se marca claramente.
+		También ayuda a mantener su código ordenado
+		forzando a dividir funciones en trozos más modulares y
+		bien definidos --- si la indentación va más allá del
+		margen derecho, significa que la función está mal
+		diseñada y que debiera dividirse para hacerla más modular
+		o bien, repensarla.
+      </para>
+
+      <para>
+		Los tabuladores de 8 espacios para indentación también
+		ayudan al diseño de funciones que encajen bien en la pantalla, 
+		lo cual significa que las personas puedan entender el código
+		sin tener que desplazarse atrás y adelantes para entenderlo.
+      </para>
+
+      <para>
+		Si usa &Emacs;, entonces puedes seleccionar el estilo de
+		indentación del núcleo de Linux incluyendo en el 
+		archivo <filename>.emacs</filename> lo siguiente:
+
+	<programlisting>
+(add-hook 'c-mode-common-hook
+          (lambda ()
+            (c-set-style "k&amp;r")
+            (setq c-basic-offset 8)))
+	</programlisting>
+
+	En los nuevos Emacs o con el nuevo cc-mode, puedes ser capaz
+	de hacerlo más simple con:
+
+	<programlisting>
+(add-hook 'c-mode-common-hook
+          (lambda ()
+            (c-set-style "linux")))
+	</programlisting>
+      </para>
+
+      <para>
+		El estilo de indentación de GNU es el predeterminado para
+		&Emacs;, así que no es necesario agregar nada en el 
+		archivo <filename>.emacs</filename> para habilitarlo.
+		Si desea seleccionarlo explícitamente, sustituya
+		«gnu» por «linux» en el ejemplo
+		anterior.
+      </para>
+
+      <para>
+		Si usa &Vim;, entonces puede seleccionar el estilo
+		de indentación del núcleo de Linux incluyendo el 
+		siguiente fragmento en el 
+		archivo <filename>.vimrc</filename>:
+
+	<programlisting>
+set ts=8
+if !exists("autocommands_loaded")
+  let autocommands_loaded = 1
+  augroup C
+      autocmd BufRead *.c set cindent
+  augroup END
+endif
+	</programlisting>
+      </para>
+
+      <para>
+		Como alternativa puede seleccionar el estilo de 
+		indentación de GNU en &Vim; usando lo siguiente en
+		el archivo <filename>.vimrc</filename>:
+	<footnote>
+	  <para>
+	    Gracias a Tomas Ögren por proporcionar este código.
+	  </para>
+	</footnote>:
+
+	<programlisting>
+augroup C
+   autocmd BufRead *.c set cinoptions={.5s,:.5s,+.5s,t0,g0,^-2,e-2,n-2,p2s,(0,=.5s formatoptions=croql cindent shiftwidth=4 tabstop=8
+augroup END
+	</programlisting>
+      </para>
+
+      <note>
+	<para>
+	  Si sabe personalizar el estilo de indentación en otros
+	  editores populares, por favor háganoslo saber y así podemos
+	  expandir este documento.
+	</para>
+      </note>
+    </sect2>
+
+    <!-- Naming Conventions -->
+
+    <sect2 id="naming">
+      <title>Convenciones de nombres</title>
+
+      <para>
+		Es importante seguir una buena convención de nombres para
+		los símbolos de los programas.   Es específicamente 
+		importante para las bibliotecas, ya que no debería
+		ensuciarse el espacio de nombres global --- es muy
+		molesto cuando una biblioteca tiene símbolos nombrados
+		desordenadamente que chocan con nombres que pueda
+		querer usar en sus programas.
+      </para>
+
+      <para>
+		Los nombres de las funciones deberían ser de la forma
+		<function>modulo_submodulo_operacion</function>, por ejemplo,
+		<function>gnome_canvas_set_scroll_region</function> o
+		<function>gnome_mime_get_keys</function>.  Esta convención
+		elimina las colisiones de nombres de símbolos entre módulos.
+		Es muy importante para las bibliotecas.
+      </para>
+
+      <para>
+		Los símbolos deben tener nombres descriptivos.  Como Linus
+		dice, no use <function>cntusr()</function>, sino que use
+		<function>count_active_users()</function>.  Esto permite
+		que el código sea más fácil de leer y casi se auto
+		documenta.
+      </para>
+
+      <para>
+		Intente usar las mismas convenciones de nombre que tienen
+		GTK+ y las bibliotecas de GNOME:
+
+	<itemizedlist>
+	  <listitem>
+	    <para>
+		  Los nombres de las funciones en minúsculas, con líneas
+		  de subrayado para separar palabras, tal como:
+	      <function>gnome_canvas_set_scroll_region()</function>,
+	      <function>gnome_mime_get_keys()</function>.
+	    </para>
+	  </listitem>
+
+	  <listitem>
+	    <para>
+		  Las macros y las enumeraciones en mayúsculas, con líneas
+		  de subrayado para separar palabras, tal como:
+	      <symbol>GNOMEUIINFO_SUBTREE()</symbol> para una macro y
+	      <symbol>GNOME_INTERACT_NONE</symbol> para un valor 
+		  enumerado.
+	    </para>
+	  </listitem>
+
+	  <listitem>
+	    <para>
+		  Los nombres de tipos y estructuras usan una mezcla de
+		  mayúsculas y minúsculas, tal como:
+	      <symbol>GnomeCanvasItem</symbol>,
+		  <symbol>GnomeIconList</symbol>.
+	    </para>
+	  </listitem>
+	</itemizedlist>
+
+	Al utilizar líneas de subrayado para separar palabras el
+	código estará menos apretado y facilita la edición, ya
+	que puede usar las secuencias de teclas que permiten
+	navegar entre palabras más rápidamente en cualquier editor.
+      </para>
+
+      <para>
+		Si está escribiendo una biblioteca, entonces puede necesitar
+		exportar símbolos que serán usados sólo dentro de la
+		biblioteca.   Por ejemplo, dos de los archivos objeto que
+		componen la biblioteca <filename>libfoo.so</filename> pueden
+		requerir acceder a símbolos ubicados en el otro archivo,
+		pero se tiene la intención que éstos símbolos sean 
+		utilizados desde los programas de usuario.  En este caso,
+		coloque una línea de subrayado antes del nombre de la
+		función y haga que la primera palabra siga la convención
+		estándar módulo/submódulo.  Por ejemplo, podría tener
+		una función llamada
+	<function>_foo_internal_frobnicate()</function>.
+      </para>
+
+      <!-- Consistency in Naming -->
+
+      <sect3 id="consist">
+	<title>Consistencia entre nombres</title>
+
+	<para>
+	  Es importante que las variables se nombren de manera 
+	  consistente.  Por ejemplo, un módulo que manipula una
+	  lista puede elegir nombrar las variables que mantienen
+	  un puntero a la lista como «<symbol>l</symbol>», 
+	  por elegancia y simplicidad.  Sin embargo, es importante que
+	  un módulo que manipula widgets y tamaños no use variables
+	  llamadas «<symbol>w</symbol>» tanto para
+	  widgets y anchos («width») (como en valores de ancho/alto =>
+	  width/height); esto podría hacer que el código sea inconsistente
+	  y difícil de leer.
+	</para>
+
+	<para>
+	  Por supuesto, nombre muy cortos y elegantes solamente deberían
+	  ser usados para variables locales de funciones.
+	  Nunca llame una variable global «<symbol>x</symbol>»; use 
+	  un nombre más largo que indique lo que significa.
+	</para>
+      </sect3>
+    </sect2>
+
+    <!-- Cleanliness -->
+
+    <sect2 id="clean">
+      <title>Limpieza</title>
+
+      <para>
+		El código de GNOME debe ser tan limpio como sea posible.
+		Esto implica usar un estilo de indentación consistente
+		y una buena convención para nombrar símbolos, como se
+		ha indicado anteriormente.  Esto también implica lo
+		siguiente.
+      </para>
+
+      <para>
+		Aprender el uso correcto de la palabra reservada
+		<symbol>static</symbol>.
+		<emphasis>No</emphasis> declarar todos los símbolos como
+		globales.  Esto tiene la ventaja de que puede usar nombres
+		más cortos dentro de las funciones en un sólo archivo
+		fuente, ya que no son globalmente visibles y por
+		consiguiente no necesita emplear el prefijo 
+		módulo/submódulo.
+      </para>
+
+      <para>
+		Aprenda el uso correcto de la palabra reservada
+		<symbol>const</symbol>.  Úsela consistentemente,
+		así le permitirá al compilador que atrape muchos
+		errores estúpidos.
+      </para>
+
+      <para>
+		Si tiene una función que retorna un puntero a
+		un dato interno que se supone que el usuario
+		no debe liberar, debería usar el modificador
+		const.  Este avisará al usuario si intenta 
+		hacer alguna operación incorrecta, por ejemplo:
+
+	<programlisting>
+const char *gnome_mime_get_info (const char *info);
+	</programlisting>
+
+		El compilador avisará si el usuario intenta liberar
+		la cadena retornada.  Esto puede atrapar muchos
+		errores.
+      </para>
+
+      <para>
+		Si tiene «valores mágicos» en el programa o
+		biblioteca, use macros que los definan en vez de usarlos
+		directamente en el código:
+
+	<programlisting>
+/* Amount of padding for GUI elements */
+#define GNOME_PAD          8
+#define GNOME_PAD_SMALL    4
+#define GNOME_PAD_BIG      12
+	</programlisting>
+      </para>
+
+      <para>
+		Si tiene una lista de valores posibles para una variable,
+		no use macros para ellas, use enum para darle 
+		un nombre de tipo --- esto permite disponer de nombres
+		simbólicos en un depurador.  Además, no use 
+		«int» para almacenar un valor enumerado; use
+		el tipo enum.  Esto le permite al compilador atrapar
+		los errores por usted, permitiéndole al depurador mostrar los
+		valores apropiados y hacer obvios los valores que una 
+		variable puede tomar. A continuación un
+	ejemplo:
+
+	<programlisting>
+/* Shadow types */
+typedef enum {
+	GTK_SHADOW_NONE,
+	GTK_SHADOW_IN,
+	GTK_SHADOW_OUT,
+	GTK_SHADOW_ETCHED_IN,
+	GTK_SHADOW_ETCHED_OUT
+} GtkShadowType;
+
+void gtk_frame_set_shadow_type (GtkFrame *frame, GtkShadowType type);
+	</programlisting>
+      </para>
+
+      <para>
+	Si define un conjunto de valores para un campo de bits, haga
+	lo siguiente:
+
+	<programlisting>
+<![CDATA[
+/* Update flags for items */
+enum {
+	GNOME_CANVAS_UPDATE_REQUESTED  = 1 << 0,
+	GNOME_CANVAS_UPDATE_AFFINE     = 1 << 1,
+	GNOME_CANVAS_UPDATE_CLIP       = 1 << 2,
+	GNOME_CANVAS_UPDATE_VISIBILITY = 1 << 3,
+	GNOME_CANVAS_UPDATE_IS_VISIBLE = 1 << 4
+};]]>
+	</programlisting>
+
+	Esto hace más fácil modificar la lista de valores y menos 
+	propenso a error que especificando los valores a mano.  También
+	permite usar estos valores como símbolos en un depurador.
+      </para>
+
+      <para>
+		No escriba código ofuscado, intente que sea espartano. 
+		Para clarificar una expresión, no use más paréntesis que 
+		los necesarios.  Use espacios antes de los paréntesis y
+		después de las comas y también alrededor de los operadores
+		binarios.
+      </para>
+
+      <para>
+		No coloque hacks en el código.  En vez de escribir un 
+		hack feo, reescriba el código para que quede limpio,
+		extensible y mantenible.
+      </para>
+
+      <para>
+		Asegúrese de que el código compila absolutamente sin ningún
+		aviso del compilador.  Esto le ayudará a atrapar errores
+		estúpidos.  Use los prototipos de las funciones en los
+		archivos de encabezados de forma consistente.
+      </para>
+
+      <para>
+		Dentro de GNOME puede usar la macro de Autoconf 
+        <symbol>GNOME_COMPILE_WARNINGS</symbol> en el archivo
+        <filename>configure.in</filename>.  Esto permitirá contar
+		con un buen conjunto de avisos del compilador de una manera
+		portable.
+      </para>
+
+      <para>
+		Comente el código.  Coloque comentarios antes de
+		cada función para decir que hace.  No diga cómo lo hace
+		a menos que sea absolutamente necesario; debería ser 
+		obvio al leer el código.  Si no lo fuera, entonces
+		pueda desear reescribirla hasta que sea fácil de 
+		entender.
+      </para>
+
+      <para>
+		Cuando documente las funciones de la API de una biblioteca,
+		siga las directrices indicadas en el archivo
+        <filename>gnome-libs/devel-docs/api-comment-style.txt</filename>.
+		Esto permite que el código fuente pueda proporcionar documentación
+		en línea, que posteriormente se extrae mediante el sistema
+        <application>gtk-doc</application> para crear un manual DocBook
+	  	de forma automática.
+      </para>
+
+      <!-- Portability considerations -->
+
+      <sect3 id="portability">
+	<title>Consideraciones de portabilidad</title>
+
+	<para>
+	  Se construye GNOME en muchas plataformas diferentes.
+	  Se puede asumir que serán plataformas más o menos tipo Unix;
+	  hasta el momento GNOME no ha sido portado a sistema no-Unix,
+	  así que se puede asumir que los servicios estándar de 
+	  Unix estarán disponibles.<footnote>
+	    <para>
+		  ¿Servicios estándar de Unix? Por supuesto que estamos
+		  bromeando.
+	    </para>
+	  </footnote>
+	</para>
+
+	<para>
+	  Recuerde que el mundo no es su propio equipo con GNU/Linux;
+	  las gente realmente usa otros tipos de máquinas.
+	</para>
+
+	<para>
+	  Intente no usar extensiones específicas de
+	  <application>GCC</application> debido a que éstas no 
+	  funcionarán con otros compiladores.  Si realmente debe
+	  hacer uso de tal cosa, vea la forma en que se hace
+	  en <application>Glib</application> con el conjunto de
+	  macros G_GNUC; asegúrese también de incluir código
+	  que funcione con compiladores ISO C. Si sólo tiene
+	  disponible <application>GCC</application>, aprenda a usar
+	  las opciones <option>-ansi -pedantic</option> que
+	  permiten probar código sospechoso.
+	</para>
+
+	<para>
+	  Recuerde que algunas plataformas no disponen de
+	  <application>GCC</application> o que
+	  <application>GDB</application> puede ser inusable en ellos,
+	  y se querrán usar otros compiladores y 
+	  depuradores.
+	</para>
+      </sect3>
+
+      <!-- GTK+-related Issues -->
+
+      <sect3 id="gtk">
+	<title>Tópicos relacionados con GTK+</title>
+
+	<para>
+	  GTK+ permite hacer mucha magia y ofuscación con manipuladores
+	  de señas, pasar cerraduras y conjuntos de datos.  Si se
+	  encuentra hadiendo muchos 
+	  <symbol>gtk_object_set_data()</symbol> en un mismo lugar,
+	  o pasado estados de forma extraña a través de manejadores de
+	  señales, reescriba el código.  Si necesita adjuntar muchos
+	  datos a un objeto en particular, entonces es un buen candidato
+	  para una nueva clase derivada, que no sólo hará al código
+	  más limpio, sino que también lo hará más extensible.
+	</para>
+
+	<para>
+      Mucha de la heurística en manejadores de eventos complicadas
+	  a menudo se pueden reemplazar limpiando el código a través
+	  de una máquina de estados.  Esto es útil cuando se quieren
+	  implementar cosas truculentas como selección y comportamientos
+	  de arrastrado, y hará al código más fácil de depurar y extender.
+	</para>
+      </sect3>
+    </sect2>
+  </sect1>
+
+  <!-- Correctness and Robustness -->
+
+  <sect1 id="robust">
+    <title>Corrección y robustez</title>
+
+    <para>
+	  Es extremadamente importante que el código de GNOME sea
+	  correcto y robusto.  Esto significa que el código debería hacer
+	  lo que se espera que haga, y debería manejar bien las condiciones
+	  de excepción.  Aunque esto pueda parecer obvio, esta sección
+	  dará algunas ideas para asegurar la corrección de su código
+	  de GNOME.  Esto es muy importante, ya que los usuarios esperan
+	  y merecen un software fiable que se ejecute correctamente
+	  y que no se caiga.
+    </para>
+
+    <!-- Ensuring Consistency -->
+
+    <sect2 id="ensure">
+      <title>Cómo asegurar la consistencia</title>
+
+      <para>
+	  	<!-- FIXME: Buscar un mejor termino para "assertion" -->
+		Utilice las macros de aserción de Glib para asegurarse de
+		que el estado de un programa es consistente.  Estas macros
+		ayudan a localizar errores muy rápidamente y se gastará 
+		mucho menos tiempo en el depurado si se emplean de forma
+		generosa y consistente.
+      </para>
+
+      <para>
+		Inserte verificaciones de sanidad en el código en puntos
+		importantes como es el inicio de funciones públicas, al
+		final de código que realiza una búsqueda que siempre
+		debe ser exitosa y en cualquier lugar donde
+		el rango de valores calculados es importante.
+      </para>
+    </sect2>
+
+    <!-- Assertions and Preconditions -->
+
+    <sect2 id="assert">
+      <title>Aserciones y precondiciones</title>
+
+      <para>
+		Las aserciones y precondiciones ayudan a asegurar que
+		el estado de un programa es consistente.  Glib proporciona
+		macros para colocar aserciones y precondiciones en el
+		código.  Debería usarlas libremente; a cambio podrá
+		localizar errores muy rápidamente y ocupará menos tiempo
+		rastreando errores con el depurador.
+      </para>
+
+      <para>
+		Existen macros de Glib para precondiciones, las cuales
+		emiten un mensaje cuando una condición falla y retornan
+		de la función desde donde fueron llamadas.  Debieran ser
+		usadas en el inicio de las funciones.
+
+	<variablelist>
+	  <varlistentry>
+	    <term><symbol>g_return_if_fail
+		(condición)</symbol></term>
+	    <listitem>
+	      <para>
+			Retorna desde la línea actual de la función si la
+		<symbol>condición</symbol> es falsa.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term><symbol>g_return_val_if_fail (condición,
+		valor)</symbol></term>
+	    <listitem>
+	      <para>
+			Retorna el <symbol>valor</symbol> indicado desde
+			la función actual si la <symbol>condición</symbol>
+			es falsa.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </para>
+
+      <para>
+		También existen macros para aserciones.  Estas emitirán
+		un mensaje cuando una condición falle y llamará a la
+		función <function>abort(3)</function> para terminar el
+		programa.  Debieran ser usadas para asegurarse la
+		consistencia para códigos internos.
+
+	<variablelist>
+	  <varlistentry>
+	    <term><symbol>g_assert (condición)</symbol></term>
+	    <listitem>
+	      <para>
+			Aborta el programa si la <symbol>condición</symbol>
+			es falsa.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term><symbol>g_assert_not_reached ()</symbol></term>
+	    <listitem>
+	      <para>
+			Aborta el programa si se llama a la macro.
+	      </para>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </para>
+
+      <para>
+		Estas funciones debieran emplearse para imponer 
+		precondiciones en el código y verificar su corrección
+		--- piense en ellas como verificaciones de sanidad
+		en los programas.  Debiera usarlas libremente como
+		asistencia para atrapar los errores rápidamente; una
+		vez que el programa se encuentre completamente depurado,
+		puede compilarlo con estas macros deshabilitadas y así
+		evitar añadirle sobrecarga en el momento de ejecutarlos.
+      </para>
+
+      <para>
+		Las macros <symbol>g_return_*()</symbol> debieran 
+		emplearse al inicio de las funciones públicas de las
+		bibliotecas, para asegurarse de que los argumentos que se pasan
+		a ellas sean correctos y tengan un rango válido.  Si
+		una función no retorna valor (por ejemplo, retorna
+		<symbol>void</symbol>), debiera usar 
+		<symbol>g_return_if_fail()</symbol>.  En caso contrario,
+		debiera usar <symbol>g_return_val_if_fail()</symbol> 
+		para retornar un valor «seguro».  Cuando
+		se invoca una función de biblioteca que usa estas macros 
+		con un argumento incorrecto , se producirá un
+		mensaje de error y continuará la ejecución.  El
+		programa cliente podrá tener algún sobresalto, hacer
+		nada o caerse, pero al menos sabrá 
+		<emphasis>dónde</emphasis> se le ha pasado un valor 
+		incorrecto a la función.
+      </para>
+
+      <para>
+	  	La macro <symbol>g_assert()</symbol> debiera usarse para
+		asegurar la consistencia interna de una biblioteca o
+		programa.  En vez de retornar de la función y continuar
+		la ejecución si la condición falla, 
+		<symbol>g_assert()</symbol> producirá en mensaje de error
+		e inmediatamente abortará el programa.  Esto es para
+		evitar que el programa continúe ejecutándose en un
+		estado inconsistente.  Debiera usar esta macro para
+		asegurarse de que el programa o biblioteca está usando
+		valores internos sanos.
+      </para>
+
+      <para>
+		La macro <symbol>g_assert_not_reached()</symbol> se
+		usa para marcar el lugar en el código que nunca 
+		debiera producirse.  Por ejemplo, si tiene una 
+		cláusula <symbol>switch</symbol> y piensa que maneja
+		todos los valores posibles en las etiquetas
+		<symbol>case</symbol>, entonces debiera colocar 
+		<symbol>g_assert_not_reached()</symbol> en la 
+		etiqueta <symbol>default</symbol> para asegurarse de que
+		el código nunca llegue allá (podría significar que
+		ha perdido algún valor o que el programa se encuentra
+		incorrecto).
+      </para>
+
+      <para>
+		Estas macros ayudan a encontrar errores más rápido 
+		a través de avisos que se producen tan pronto como
+		el programa alcanza un estado incosistente.  Úselos
+		frecuentemente y encontrará muchos errores más 
+		fácilmente.
+      </para>
+    </sect2>
+
+    <!-- GTK+-related Issues -->
+
+    <sect2 id="assert-gtk">
+      <title>Tópicos relacionados con GTK+</title>
+
+      <para>
+		Sea cuidadoso cuando escriba manejadores de eventos 
+		--- asegurése de que los eventos son manipuladas en
+		las situaciones apropiadas.  Es necesario asegurarse de
+		que los manejadores de señales tengan los prototipos
+		correctos.  Esto es muy importante.  Recuerde que no
+		todos los prototipos de manejadores de señal se parecen
+		a lo siguiente:
+
+	<programlisting>
+static void my_handler (GtkWidget *widget, gpointer data);
+	</programlisting>
+
+	Por ejemplo, los manejadores de eventos tienen un parámetro
+	extra de evento y retornan <symbol>gint</symbol>.  Vea los
+	archivos de encabezado de GTK+ cuando necesite verificarlo.
+      </para>
+
+      <para>
+		Asegúrese de que el programa trata de una forma apropiada
+		todas las acciones generadas por el usuario.  Recuerde
+		que el usuario puede cerrar una ventana en cualquier 
+		momento a través del administrador de ventanas; téngalo
+		presente y escriba el código necesario para manejar esta
+		situación.
+      </para>
+
+      <para>
+		Si verifica los modificadores de teclas con una máscara
+		de estado de eventos, por ejemplo,
+		<keycombo><keycap>Control</keycap><keycap>F10</keycap></keycombo>
+		haga esto:
+
+	<programlisting>
+  guint modifiers;
+
+  modifiers = gtk_accelerator_get_default_mod_mask ();
+
+  if (event-&gt;keysym == GDK_F10
+      &amp;&amp; (event-&gt;state &amp; modifiers) == GDK_CONTROL_MASK) {
+          do_something ();
+  }
+	</programlisting>
+
+	Esto es necesario; si en vez de lo anterior hace:
+
+	<programlisting>
+  if (event-&gt;keysym == GDK_F10 &amp;&amp; event-&gt;state == GDK_CONTROL_MASK)
+	</programlisting>
+
+		entonces el programa no funcionará correctamente si el
+		usuario tiene, por ejemplo, activada la tecla 
+		<keycap>NumLock</keycap> &mdash; <keycap>NumLock</keycap> 
+		también es un modificador, y si está activado, entonces
+		la máscara de estado del evento no será como se espera
+		en el segundo ejemplo.
+      </para>
+
+      <!-- Visuals and Colormaps -->
+
+      <sect3 id="visuals">
+	<title>Vistas y mapas de color</title>
+
+	<para>
+	  <!-- FIXME: Buscar un término adecuado para "Visual" en
+	       vez de "vista" -->
+	  Algunos usuarios utilizan tarjetas de vídeo avanzadas
+	  (por ejemplo, SGIs y Suns) que soportan múltiples vistas
+	  simúltaneamente.  Una vista define la representación en memoria
+	  que usa un dispositivo de hardware para almacenar los 
+	  contenidos de una imagen.  Muchas tarjetas de vídeo de
+	  PC soportan sólo una vista a la vez, pero el hardware
+	  avanzado puede tener diferentes ventanas y pixmaps en
+	  diferentes vistas simultáneamente.
+	</para>
+
+	<para>
+	  Es importante entender las vistas y mapas de colores si
+	  va a escribir código que crea ventanas y pixmaps por sus
+	  propios medios, en vez de utilizar las funciones de alto
+	  nivel como GnomeCanvas y GnomePixmap.  Para mayor información,
+	  lea el manual de programación de Xlib.
+	</para>
+
+	<para>
+	  <!-- FIXME: traducir -->
+	  In general, you just need to remember that the visual and
+	  colormap for a drawable must match the ones of another
+	  drawable if you want to copy an area from the first drawable
+	  into the second one.  If they are not the same, you will get
+	  a BadMatch error from X and you application will most likely
+	  abort.
+	</para>
+
+	<para>
+	  If you create a graphics context (GC) and share it to paint
+	  onto several drawables, make sure all of them have the same
+	  visual and colormap for which the GC was defined.  The same
+	  applies if you want to copy an area from a pixmap to a
+	  window; both must have the same visual and colormap
+	</para>
+
+	<para>
+	  Si no está seguro de que su código lo hace correctamente, pregunte
+	  educadamente en una de las listas de correo de desarrollo de
+	  GNOME si alguien puede realizar una prueba con una tarjeta
+	  de video que soporta esta característica.  Dicha personas 
+	  sabrá como arreglar el problema y le dirá al respecto.
+	</para>
+      </sect3>
+    </sect2>
+
+    <!-- Unix-related Issues -->
+
+    <sect2 id="unix">
+      <title>Temas relacionados con Unix</title>
+
+      <para>
+		Verifique los valores de retorno de <emphasis>todas</emphasis>
+		las llamas al sistema que el programa realice.  Recuerde
+		que muchas de las llamadas al sistema pueden ser 
+		interrumpidas (por ejemplo, la llamada retornar -1 y
+		errno será definido a EINTR) y deben reiniciarse.
+      </para>
+
+      <para>
+		No asuma, por ejemplo, que la función 
+		<function>write(2)</function> escribirá el buffer completo
+		de una vez; tiene que verificar el valor de retorno, el cual
+		indica el número de bytes escritos e intente nuevamente 
+		hasta que sea cero.  Si el valor de retorno es -1, recuerde
+		verificar el valor de errno y manejar el error 
+		apropiadamente.
+      </para>
+
+      <para>
+		Si la aplicación llama a la función <function>fork(2)</function>
+		sin llamar a <function>execve(2)</function>, recuerde que
+		el proceso hijo no puede hacer llamadas X.  Normalmente se
+		puede diagnosticar este problema a través de un oscuro
+		mensaje de error de Xlib.
+      </para>
+
+      <para>
+		Lea el libro «Advanced programming in the Unix 
+		environment», de Stevens, para aprender acerca de
+		todos estos temas y asegúrese de que sus programas usan
+		la API de Unix de forma correcta.  Si no desea asegurarse
+		del uso correcto de las llamadas Unix, pregunte en las
+		listas de correo.
+      </para>
+    </sect2>
+  </sect1>
+
+  <!-- Security Considerations -->
+
+  <sect1 id="security">
+    <title>Consideraciones de seguridad</title>
+
+    <para>
+	  La seguridad es un tema complejo y en esta sección no se
+	  puede explicar ni de lejos todo lo relacionado.
+	  Intentaremos indicar las situaciones más comunes donde sus
+	  programas deben interesarse por la seguridad.
+    </para>
+
+    <para>
+	  Es muy fácil crear hoyos de seguridad a través de la creación
+	  incorrecta de archivos temporales en <filename>/tmp</filename>.
+	  Debe garantizar que los archivos que usará no existen al 
+	  momento de su creación.  Usando un nombre de archivo «único»
+	  e «impredecible» no es suficiente; debe garantizar que el archivo
+	  con ese nombre no será creado por alguien más entre el tiempo
+	  que determina el nombre y el tiempo en que es efectivamente
+	  creado (básicamente los ataques involucran que un tercero
+	  cree un enlace simbólico al archivo que ellos quieren 
+	  sobreescribir).
+    </para>
+
+    <para>
+	  Afortunadamente, esto es fácil de hacer.  Use el siguiente trozo
+	  de código:
+
+      <programlisting>
+	char *filename;
+	int fd;
+
+	do {
+		filename = tempnam (NULL, "foo");
+		if (!filename) {
+			fprintf (stderr, "Could not create temporary file name\n");
+			exit (EXIT_FAILURE);
+		}
+
+		fd = open (filename, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0600);
+		free (filename);
+	} while (fd == -1);
+      </programlisting>
+
+      Recuerde liberar <symbol>filename</symbol> usando la función
+	  <function>free()</function> y llamar a las funciones 
+	  <function>close()</function> y <function>unlink()</function> 
+	  con el archivo respectivo cuando haya terminado; aquí
+	  liberamos <symbol>filename</symbol> con <function>free()</function>
+	  inmediatamente y así no causará una pérdida de memoria.
+    </para>
+
+    <para>
+	  Si desea usar las biblioteca estándar de E/S, puede usar la
+	  función <function>fdopen()</function> para transformar el
+	  descriptor de archivo en <symbol>FILE *</symbol>, o puede
+	  usar la <function>tmpfile()</function> para hacerlo en un
+	  solo paso.
+    </para>
+
+    <para>
+	  Intente no usar buffers de tamaño fijo.  Los buffers de tamaño
+	  fijo para cadenas constituyen los típicas fuentes de hoyos
+	  explotables que pueden llegar a oscuros errores.  Si definitivamente
+	  debe usar buffers de tamaño fijo para cadenas, use la función
+      <function>g_snprintf()</function> para especificar el tamaño 
+	  máximo del buffer.
+    </para>
+
+    <para>
+	  Glib proporciona la muy conveniente función 
+      <function>g_strdup_printf()</function>, la cual funciona como
+      <function>sprintf()</function> pero automáticamente 
+	  localizará un buffer con el tamaño correcto.  El valor de retorno
+	  de esta función debiera ser liberada usando
+	  <function>g_free()</function>.  A menudo es más conveniente de
+	  usar que <function>g_snprintf()</function>, ya que esta no 
+	  limita el tamaño de las cadenas que un programa puede manipular.
+    </para>
+
+    <para>
+	  Si desea concatenar un grupo de cadenas, puede usar la función
+      <function>g_strconcat()</function>, la cual recibe una lista
+	  variables de cadenas y un puntero a NULL como último argumento.
+    </para>
+
+    <para>
+      <emphasis>Bajo ninguna circunstancia</emphasis> cree un 
+	  programa GTK+ con setuid root.  Las bibliotecas de GTK+ y
+	  GNOME son grandes y complejas y no han tenido auditorías
+	  de seguridad.  En cualquier caso, no debiera querer que 
+	  una pieza tan grande código sea setuid root.  Si definitivamente
+	  requiere usar privilegios de root para algo, escriba un 
+	  programa que sea la interfaz de usuario como un proceso
+	  normal, sin privilegios y cree un programa de ayuda que
+	  tenga setuid y se encargue de realizar la operaciones
+	  «peligrosas».  Además, notifique a las listas
+	  de correo de desarrollo de GNOME indicando que requiere
+	  que alguien realice una auditoría de seguridad a su
+	  programa de ayuda.
+    </para>
+
+    <para>
+	  En general, si no está seguro si puede crear un riesgo de
+	  seguridad, pregunte en la listas de correo de desarrollo
+	  de GNOME.
+    </para>
+
+    <para>
+	  Puede leer más sobre temas de seguridad que debiera encontrar
+	  cuando programe una aplicación Unix en el documento
+      <ulink URL="http://www.fish.com/security/murphy.html">«Murphy's
+      Law and Computer Security»</ulink>, de Wietse Wenema.  
+	  Hay otros documentos de seguridad en <ulink
+      URL="http://www.fish.com/security">el sitio fish.com</ulink>
+	  que podría encontrar interesante.
+    </para>
+
+    <para>
+	  Puede encontrar muchas otras guías útiles para escribir programas
+	  seguros en <ulink
+      url="http://www.dwheeler.com/secure-programs">«Secure
+      Programming for Linux and Unix HOWTO»</ulink>.
+    </para>
+  </sect1>
+
+  <!-- Performace -->
+
+  <sect1 id="performance">
+    <title>Rendimiento</title>
+
+    <para>
+	  No lea esta sección hasta que esté seguro de que su programa está
+	  correcto, por ejemplo, cuando esté seguro de que funciona 
+	  correctamente y no tiene errores.  Es más importante que
+	  el código sea correcto a que sea rápido.  Un programa lento
+	  pero correcto es mucho mejor a uno rápido pero con errores.
+    </para>
+
+    <para>
+	  Si quiere optimizar su programa, el primer paso es determinar
+	  un perfil al programa ejecutándolo con datos de la vida real
+	  y recopilar puntos calientes que requieran optimización.
+	  Esto ayudará a determinar los lugares que necesitan optimizarse.
+	  Es importante que nunca adelante la optimización si no tiene
+	  una idea clara sobre donde está el problema.  Podría terminar 
+	  perdiendo el tiempo en agilizar una rutina que no es la causa 
+	  del cuello de boteLla y como resultado podría terminar ofuscando 
+	  dicha rutina.  Esto podría reducir la legibilidad y mantenibilidad
+	  del código sin ganancia visible en velocidad.
+    </para>
+
+    <para>
+	  Un código sencillo es bueno porque es fácil de entender y 
+	  mantener.  Si puede escribir código simple que además sea
+	  potente y rápido, tanto mejor.  Si tiene un trozo de código
+	  inteligente pero que no es fácil de seguir, entonces documéntelo
+	  para que las personas no lo estropeen accidentalmente.
+    </para>
+
+    <para>
+	  No escriba código que sea difícil de leer y mantener por el
+	  sólo hecho de hacerlo más rápido.  En cambio prefiera un algoritmo
+	  agradable y claro e impleméntelo claramente.
+    </para>
+
+    <para>
+	  Hacer un buen trabajo en el caso general es a menudo mejor que
+	  tener muchos casos especiales.  Sólo provea casos especiales
+	  cuando se han identificado puntos débiles en el programa.
+    </para>
+
+    <!-- List Management in Glib -->
+
+    <sect2 id="list">
+      <title>Administración de listas en Glib</title>
+    	<para>
+		  Evite emplear construcciones que terminen ralentizando
+		  los algoritmos.  Si usa 
+		  <function>g_list_insert_sorted()</function> o
+    	  <function>g_list_append()</function> sin ningún cuidado,
+		  fácilmente puede tener un algoritmo que se ejecuta en
+		  tiempo proporcional a O(n<superscript>2</superscript>).  
+		  Normalmente puede crear listas hacia atrás, usando
+    	  <function>g_list_prepend()</function>, e invirtiéndola
+		  cuando haya terminado usando 
+		  <function>g_list_reverse()</function>.  Esta es una
+		  operación O(n).  Y si necesita una lista ordenada, puede
+		  crearla de la misma forma (hacia atrás) y una vez terminado,
+		  usar <function>g_list_sort()</function>.
+    	</para>
+
+    	<para>
+		  Si necesita una lista ordenada en todo momento, puede ser
+		  mejor emplear un estructura de árbol o un híbrido 
+		  lista/árbol.  Si necesita construir una lista añadiendo
+		  nodos a ella, mantenga un puntero al final de la lista
+		  y vaya cambiándola según sea apropiado; esto le permitira
+		  insertar un nodo al inicio o al final en un tiempo constante.
+    	</para>
+    </sect2>
+  </sect1>
+
+  <!-- Localization -->
+
+  <sect1 id="l10n">
+    <title>Localización</title>
+
+    <para>
+	  Se pretende que GNOME pueda ejecutarse en distintas localidades
+	  y lenguajes, y los programas debieran tener esto en cuenta.  No
+	  tiene que localizar los programas, sólo debe permitir que éstos
+	  sean traducibles y localizables.
+    </para>
+
+    <para>
+	  Debe recordar que los diferentes idiomas humanos tienen diferentes
+	  gramáticas, así que no debiera suponer la forma de estructurar
+	  cada frase.  Esto es importante, por ejemplo, cuando se 
+	  construyen cadenas a partir de trozos separados.
+    </para>
+
+    <para>
+	  La concatenación normalmente no es la forma correcta de construir
+	  una cadena para que sea presentada al usuario.  Normalmente terminan
+	  en mensajes que no pueden ser traducidos correctamente en todos
+	  los idiomas.  En vez de concatenar, intente usar
+	  <function>g_strdup_printf()</function>, por ejemplo:
+
+      <programlisting>
+	/* Una forma no muy buena */
+	char *message = g_strconcat (_("Hello, "),
+				     name,
+				     _(", would you like fries with that?"),
+				     NULL);
+
+	/* Una mejor forma */
+	char *message = g_strdup_printf (_("Hello, %s, would you like fries with that?"),
+					 name);
+      </programlisting>
+
+	  Esto permitirá al traductor mover %s donde corresponda según
+	  lo requiera la gramática del idioma en el cual trabaja.
+    </para>
+
+    <para>
+	  Recuerdo que no todos los idiomas forman los plurales añadiendo
+	  una «s» a las palabras.  Además, las estructuras de
+	  frases pueden cambiar con los plurales.  Por ejemplo,
+
+      <programlisting>
+	/* Una forma no muy buena */
+	printf (_("%d happy monkey%s bouncing on the bed."),
+		num_monkeys,
+		(num_monkeys > 1) ? "s", "");
+
+	/* Una mejor forma */
+	printf ((num_monkeys > 1)
+		? _("%d happy monkeys bouncing on the bed."),
+		: _("%d happy monkey bouncing on the bed."));
+      </programlisting>
+
+	  Se requiere de esta forma ya que el plural se forma de 
+	  distintas maneras en distintos idiomas, y la estructura
+	  completa de la frase puede cambiar.
+    </para>
+
+    <para>
+	  Si el programa muestra fechas u horas, use la función
+      <function>strftime()</function> para darles formato como
+	  cadenas.  Esto se encargará de usar la representación
+	  adecuada de fecha y hora de acuerdo a la definición local
+	  del usuario.  Además, si el programa debe generar una
+	  representación visual de un calendario, recuerde que en
+	  algunos países se considera como primer día de la semana
+	  el domingo y no el lunes.  El programa debiera permitir 
+	  ambas formas de calendarios.
+    </para>
+
+    <para>
+	  Si el programa usa medidas, asegúrese de permitir tanto
+	  el sistema métrico decimal como el sistema imperial (o anglosajón).
+    </para>
+  </sect1>
+
+  <!-- Binary Compatibility -->
+
+  <sect1 id="binary">
+    <title>Compatibilidad binaria en las bibliotecas</title>
+
+    <para>
+	  Para bibliotecas estables y ya liberadas, es muy importante
+	  intentar preservar la compatibilidad binaria en las revisiones
+	  mayores del código.  Los desarrolladores de bibliotecas deben
+	  intentar no alienar a los usuarios realizando de forma frecuente
+	  cambios que sean binariamente incompatibles en bibliotecas que
+	  son de producción.  Por supuesto, en aquellas bibliotecas que se
+	  encuentran en desarrollo o están etiquetadas como no finalizadas
+	  puede realizar tantos cambios como lo necesiten.
+    </para>
+
+    <para>
+	  Una biblioteca típicamente exporta un número de interfaces.  Estas
+	  incluyen nombres de rutinas, las firmas o prototipos de estas
+	  rutinas, variables globales, estructuras, campos de estructura
+	  (tanto los tipos como su significado), el significado de los
+	  valores enumerados y la semántica de los archivos que la
+	  biblioteca crea.  Mantener compatibilidad binaria significa que
+	  estas interfaces no cambiarán.  Puede añadir nuevas interfaces
+	  sin romper la compatibilidad binaria, pero no puede cambiar
+	  las ya existentes, ya que los programas antiguos no se ejecutarán
+	  correctamente.
+    </para>
+
+    <para>
+	  Esta sección incluye un número de ideas acerca de como lograr
+	  que el código de una biblioteca sea compatible con sus
+	  versiones anteriores.
+    </para>
+
+    <para>
+	  Mantener la compatibilidad binaria significa que los programas
+	  y archivos objetos que fueron compilados con una versión 
+	  previa del código continuarán funcionando sin recompilar aún
+	  cuando la biblioteca sea reemplazada. Es posible encontrar
+	  una descripción detallada en el nodo info
+      <filename>(libtool)Interfaces</filename> de la documentación
+	  de GNU libtool.
+    </para>
+
+    <!-- Private Information in Structures -->
+
+    <sect2 id="private">
+      <title>Información privada en las estructuras</title>
+
+      <para>
+		En el sistema GNOME es una tarea muy común crear un
+		nuevo <structname>GtkObject</structname> para crear
+		una estructura cuyo primer miembro corresponde a la 
+		clase de la cual hereda este objeto y posteriormente
+		un número de variables de instancia que se añaden 
+		después del primer miembro.
+      </para>
+
+      <para>
+		Este esquema de diseño normalmente lleva a que el código
+		sea difícil de actualizar y cambiar: si se quiere
+		extender un objeto donde se necesita mantener su estado 
+		interno, los programadores necesitan recurrir a varios 
+		hacks para mantener el mismo tamaño de las estructuras.  
+		Esto hace difícil agregar nuevos campos a las estructuras 
+		públicas sin romper la compatibilidad binaria, ya que 
+		los campos de la estructura pueden cambiar y el tamaño 
+		de las estructuras pueden variar.
+      </para>
+
+      <para>
+		Por consiguiente, se sugiere una estrategia que puedan
+		adoptar los desarrolladores en el momento de crear nuevos
+		objetos.  Esta estrategia asegurará la compatibilidad
+		binaria y al mismo tiempo mejorará la legibilidad y 
+		mantenibilidad del código.
+      </para>
+
+      <para>
+		La idea es que, para un objeto dado, el programador
+		debiera crear tres archivos: el primero que contiene
+		el contrato entre la biblioteca y el usuario (esto
+		es el archivo de encabezado que se instala en el 
+		sistema); el segundo contiene la implementación del
+		objeto; y el tercer archivo contiene la definición 
+		de la estructura para los campos privados o internos
+		que no necesitan estar en la estructura pública.
+      </para>
+
+      <para>
+		La API pública de la estructura podría incluir un
+		puntero a un elemento privado, el cual podría 
+		apuntar a los datos privado de la instancia. Las
+		rutinas de implementación podría dereferenciar
+		este punto para acceder a los datos privados; por
+		supuesto, el puntero apunta a la estructura que se
+		localiza privadamente.
+      </para>
+
+      <para>
+		Por ejemplo, imagine que se crea el objeto GnomeFrob. 
+		La implementación del widget sera dividido en tres 
+		archivos:
+
+	<table>
+	  <title>Archivos que muestran el widget de ejemplo 
+	  GnomeFrob</title>
+
+	  <tgroup cols="2">
+	    <thead>
+	      <row>
+		<entry>Archivo</entry>
+		<entry>Contenido</entry>
+	      </row>
+	    </thead>
+	    <tbody>
+	      <row>
+		<entry><filename>gnome-frob.h</filename></entry>
+		<entry>API pública de GnomeFrob</entry>
+	      </row>
+	      <row>
+		<entry><filename>gnome-frob.c</filename></entry>
+		<entry>Implementación del objeto Gnomefrob</entry>
+	      </row>
+	      <row>
+		<entry><filename>gnome-frob-private.h</filename></entry>
+		<entry>Datos privados de la implementación de GnomeFrob.
+			Debiera querer usar esto si planea compartir los
+			datos privados a través de varios archivos C. Si
+			limita el uso de la información privada a sólo un
+			archivo, no necesita esto, ya que al definir la
+			estructura en el archivo de implementación logrará
+			el mismo efecto.</entry>
+	      </row>
+	    </tbody>
+	  </tgroup>
+	</table>
+      </para>
+
+      <para>
+	<example>
+	  <title>Ejemplo de la API pública de <filename>gnome-frob.h</filename>
+	  </title>
+	  <programlisting>
+typedef struct _GnomeFrob GnomeFrob;
+typedef struct _GnomeFrobPrivate GnomeFrobPrivate;
+
+struct _GnomeFrob {
+       GtkObject parent_object;
+
+       int  public_value;
+       GnomeFrobPrivate *priv;
+} GnomeFrob;
+
+GnomeFrob *gnome_frob_new (void);
+void       gnome_frob_frobate (GnomeFrob *frob);
+	  </programlisting>
+
+	</example>
+
+	<example>
+	  <title>Ejemplo de 
+	  <filename>gnome-frob-private.h</filename></title>
+	  <programlisting>
+typedef struct {
+        gboolean frobbed;
+} GnomeFrobPrivate;
+	  </programlisting>
+	</example>
+
+	<example>
+	  <title>Ejemplo de la implementación de 
+	  <filename>gnome-frob.c</filename>.</title>
+	  <programlisting>
+void gnome_frob_frobate (GnomeFrob *frob)
+{
+        g_return_if_fail (frob != NULL);
+	g_return_if_fail (GNOME_IS_FROB (frob));
+
+	frob->priv->frobbed = TRUE;
+}
+	  </programlisting>
+	</example>
+
+		Fíjese en el uso de prototipos de estructura: esto permite que
+		el compilador realice más verificaciones en tiempo de
+		compilación respecto a los tipos que estan siendo empleados.
+      </para>
+
+      <para>
+		Este esquema es útil en algunas situaciones, particularmente
+		en el caso en el cual vale la pena almacenar un puntero
+		extra para una instancia del objeto.  Si esto no fuera
+		posible, el programador necesitaría recurrir a otros
+		artilugios para evitar este problema.
+      </para>
+
+      <para>
+		El propósito de tener un archivo de encabezado privado
+		extra para las estructuras privadas es permitir que las
+		clases derivadas usen esta información.  Por supuesto,
+		una buena práctica de programación indicaría que debiera
+		proveerse de interfaces o métodos de acceso precisamente
+		para que el programador no tenga que lidiar con 
+		estructuras privadas.  Se debiera intentar alcanzar un 
+		balance entre buena práctica y pragmatismo cuando se
+		crean estructuras privadas y métodos de acceso públicos.
+      </para>
+
+      <para>
+		Podrían aparecer algunos problemas, por ejemplo, cuando
+		se ha enviado un versión del código y que está siendo
+		ampliamente usado y se desea extenderlo.  Hay dos 
+		soluciones para esto.
+      </para>
+
+      <para>
+		La primera opción es encontrar un campo puntero en la
+		estructura pública que pueda hacerse privada y 
+		reemplazar el puntero a la parte privada de la 
+		estructura.  Esto preserva el tamaño de la estructura
+		ya que, para los propósitos de GNOME, se puede
+		asumir que los punteros son todos del mismo tamaño.
+		Se puede hacer que este campo apunte a la parte privada
+		de la estructura que será ubicada por la función que
+		originalmente creaba la estructura pública.  Es
+		importante que este campo sea llamado
+		<structfield>private</structfield>, se trata de
+		una palabra reservada de C++ y creará problemas cuando
+		el archivo de encabezado sea usado desde programas
+		fuentes C++ &mdash; mejor llámelo 
+		<structfield>priv</structfield>.  Por supuesto, este
+		tipo de cambios sólo funcionará si el antiguo campo
+		puntero solamente era usado para propósitos internos;
+		si los usuarios de la biblioteca habían tenido acceso
+		a dicho campo para cualquier propósito, será necesario
+		buscar otro campo o buscar una solución diferente.
+      </para>
+
+      <para>
+		Si la estructura original fue derivada de
+	<structname>GtkObject</structname> y no hay campos punteros
+	que puedan ser reemplazados, puede usar la facilidad
+	de datos de objetos de GTK+.  Esto permite asociar punteros
+	a datos arbitrarios a objetos.  Use la función
+	<function>gtk_object_set_data()</function> para adjuntar
+	valores o estructuras a un objeto y cuando requiera usarlos
+	la función <function>gtk_object_get_data()</function> 
+	permitirá recuperar dichos valores.  Esto puede ser empleado
+	para adjuntar una estructura privada a un objeto GTK+.
+	Esto no es tan eficiente como el enfoque anterior, pero podría
+	no importar para el dominio particular de la aplicación.  Si
+	los datos serán accedidos frecuentemente, se pueden usar
+	quarks en vez de cadenas para agregar y obtenerlos a través
+	de las funciones
+	<function>gtk_object_set_data_by_id()</function> y
+	<function>gtk_object_get_data_by_id()</function>, 
+	respectivamente.
+      </para>
+
+    </sect2>
+  </sect1>
+
+  <!-- Modifying Other People's Code -->
+
+  <sect1 id="modify">
+    <title>Cómo modificar el código de otros</title>
+
+    <para>
+	  GNOME es un proyecto de equipo, así las contribuciones de
+	  código a programas de otras personas siempre son apreciadas.
+	  Siga los siguientes lineamientos cuando modifique el código
+	  de otra persona.
+    </para>
+
+    <!-- General Etiquette -->
+
+    <sect2 id="etiquette">
+      <title>Etiqueta general</title>
+
+      <para>
+		Siga el mismo estilo de indentación usado en el código 
+		original.  El código original perdurará durante más tiempo
+		que el que le pueda dedicar, mantener las 
+		contribuciones consistentes respecto a la indentación
+		es más importante que forzar su estilo de indentación
+		en el código.
+      </para>
+
+      <para>
+		Aunque sus parches pueden implementar una 
+		funcionalidad muy llamativa, es muy molesto para el 
+		autor tener que reindentar el código antes de aplicar
+		un parche al código principal.  Así, si el código
+		original luce como
+
+      <programlisting>
+int
+sum_plus_square_of_indices (int *values, int nvalues)
+{
+	int i, total;
+
+	total = 0;
+
+	for (i = 0; i &lt; nvalues; i++)
+		total += values[i] + i * i;
+
+	return total;
+}
+	</programlisting>
+
+	entonces no agregue una función que luce como
+
+	<programlisting>
+int sum_plus_cube_of_indices(int *values, int nvalues) {
+  int i,total;
+
+  total=0;
+
+  for (i=0;i&lt;nvalues;i++)
+    total+=values[i]+i*i*i;
+
+  return total;
+}
+	</programlisting>
+
+	En el segundo ejemplo, la indentanción y ubicación de las
+	llaves no coincide con el código original, no hay espacios 
+	alrededor de los operadores y el código no se parecerá
+	al original.  Siga el estilo de programación del autor
+	original del programa y los parches que envíe tendrán una mejor
+	oportunidad de ser aceptados.
+      </para>
+
+      <para>
+		No repare errores con hacks rápidos o artilugios; repárelo
+		correctamente.  Tampoco añada características como hacks o
+		con código que no sea extensible; es mejor rehacer el 
+		código original para que sea extensible y luego agregue 
+		la nueva característica, utilizando el código como 
+		estructura.
+      </para>
+
+      <para>
+		La limpieza de código siempre es bienvenida; si encuentra
+		trozos de código feos y sucios en GNOME, será muy
+		apreciado si envía parches que hagan el código más
+		agradable y fácil de mantener.
+      </para>
+
+      <para>
+		Como siempre, asegúrese de que el código que contribuye compila
+		sin ningún tipo de aviso, que tenga los prototipos correctos
+		y que siga las directrices de este documento.
+      </para>
+    </sect2>
+
+    <!-- Documenting Your Changes -->
+
+    <sect2 id="document">
+      <title>Cómo documentar los cambios</title>
+
+      <para>
+		GNOME utiliza los archivos &ChangeLog; estándar de GNU para
+		documentar los cambios al código.  Cada cambio que 
+		efectúe a un programa <emphasis>debe</emphasis> ser
+		acompañado por una registro en el &ChangeLog;.  Esto
+		permite a las personas leer la historia de cambios 
+		del programa de una manera sencilla.
+      </para>
+
+      <para>
+		Si usa &Emacs;, puede agregar las líneas al 
+		&ChangeLog; presionando «C-x 4 a».
+      </para>
+
+      <note>
+	<para>
+		Si conoce la forma de realizarlos para otros editores
+		populares, agradeceremos que nos lo haga saber para
+		expandir este documento.
+	</para>
+      </note>
+
+      <para>
+	Cada registro en el &ChangeLog; tiene un forma general:
+	<programlisting>
+1999-04-19  J. Random Hacker  &lt;jrandom@foo.org&gt;
+
+	* foo.c (some_function): Changed the way MetaThingies are
+	frobnicated.  We now use a hash table instead of a linked list to
+	look MetaThingies up.
+	(some_other_function): Support the MetaThingies hash table by
+	feeding it when necessary
+
+	* bar.c (another_function): Fixed bug where it would print "Take
+	me to your leader" instead of "Hello, World".
+
+1999-04-18  Johnny Grep  &lt;grep@foobar.com&gt;
+
+	* baz.c (ugly_function): Beautified by using a helper function.
+	</programlisting>
+      </para>
+
+      <para>
+		Si agrega una nueva función a una biblioteca, escriba
+		la referencia necesaria y la documentación de programación.
+		Puede escribir una referencia a la documentacion 
+		en línea usando el formato de comentarios descrito en
+		<filename>gnome-libs/devel-docs/api-comment-style.txt</filename>.
+		Si usa &Emacs;,
+		<filename>gnome-libs/tools/gnome-doc/gnome-doc.el</filename>
+		provee un acelerador que puede ser empleado para añadir
+		una plantilla de documentación al programa.
+      </para>
+    </sect2>
+
+    <!-- Changing Code on CVS -->
+
+    <sect2 id="change-cvs">
+      <title>Cómo actualizar en CVS</title>
+
+      <para>
+		Si tiene acceso de escritura en el repositorio CVS de GNOME,
+		debe seguir algunas políticas adicionales.  Ya que está
+		trabajando en la copia maestra de los fuentes, debe tener
+		especial cuidado.
+      </para>
+
+      <para>
+		Si está reparando algo en un programa que está en el CVS
+		o si está añadiendo una funcionalidad allí, y si no ha
+		estado trabajando en dicho programa por un período largo
+		de tiempo, pregunte al autor original antes de aplicar
+		sus parches.  Generalmente está bien formular estas
+		preguntas en la lista de correo
+		<filename>gnome-devel-list</filename>.
+      </para>
+
+      <para>
+		Una vez que el autor del programa lo indique como un
+		«contribuyente frecuente», puede comenzar 
+		aplicar los parches sin previo consentimiento. Si
+		quiere aplicar un reorganización mayor del código,
+		debiera preguntar primero.
+      </para>
+
+      <para>
+		Algunos módulos en el CVS tienen rama estable y de
+		desarrollo.  Normalmente el desarrollo debiera ir
+		en la rama HEAD en el CVS, y la rama estable debiera
+		mantenerse separadamente.  Generalmente no se añaden
+		nuevas características a las rama estable; sólo
+		se reparan errores.  Repare el error a la rama estable
+		y pregunte al autor principal sobre la política para
+		mezclar parches en la rama de desarrollo; algunos
+		autores prefieren hacerlo por lotes, mientras hay otros
+		que prefieren mezclarlos inmediatamente.
+      </para>
+
+      <para>
+		Si trabaja en una característica experimental que
+		podría estropear mucho código, cree una rama en el CVS
+		y realice los cambios allí.  No los mezcle en la rama
+		principal de desarrollo hasta que se encuentre 
+		razonablemente seguro que funcionará correctamente y que
+		se integrará bien dentro del resto del código.  El uso de
+		una rama para trabajo en características experimentales
+		le permitirá evitar interrumpir el trabajo de otros
+		desarrolladores.  Pregunte al autor principal antes de
+		mezclar su rama y traer sus cambios a la parte principal 
+		del árbol.
+      </para>
+
+      <para>
+		Como siempre, agrege un registro en el &ChangeLog; 
+		cuando realice un cambio.  Algunos autores tienen la
+		política de rechazar, correctamente, los cambios que 
+		no tienen tal registro.
+      </para>
+
+      <para>
+		Algunas veces existen diferentes políticas para los módulos,
+		verifique si el módulo contiene un archivo
+        <filename>README.CVS</filename>.  Si es así, lea ese archivo
+		antes de realizar cambios.
+      </para>
+
+      <!-- Branches and Tags -->
+
+      <sect3 id="branches">
+	<title>Ramas y marcas</title>
+
+	<para>
+	  Tenemos una convención para nombrar las ramas y marcas o
+	  puntos de una rama en el repositorio de CVS de GNOME. 
+	  Las marcas deben ser definidas después que se libera cada
+	  nueva version y deben ser de la forma
+	  «MODULE_MAJOR_MINOR_MICRO», por ejemplo,
+	  «GNOME_LIBS_1_0_53».  Los puntos de una rama
+	  deben ser de la forma «MODULE_BRANCH_ANCHOR», 
+	  como en «GNOME_LIBS_1_0_ANCHOR».  Finalmente, 
+	  una rama raíz en este punto debiera ser de la forma
+	  «module-branch», por ejemplo, 
+	  «gnome-libs-1-0».  Use esta convención cuando
+	  cree marcas, puntos de una rama y ramas.
+	</para>
+      </sect3>
+
+      <!-- Additional CVS Policies -->
+
+      <sect3 id="cvs-policies">
+	<title>Políticas adicionales del CVS</title>
+
+	<para>
+	  CVS no proporciona un manera preconstruida para renombrar archivos
+	  o moverlos a otros directorios.  Debiera planificar 
+ 	  cuidadosamente el árbol del repositorio de tal forma que evite
+	  mover o renombrar archivos.
+	</para>
+
+	<para>
+	  En el caso que deba mover o renombrar un archivo en el CVS,
+	  <emphasis>NO EJECUTE</emphasis> «cvs remove»
+	  y luego «cvs add».  Si lo hace, los archivos
+	  «nuevos» perderán la capacidad de seguir su
+	  historia de cambios, ya que desde el punto de vista de CVS
+	  serán archivos completamente nuevos en su revisión
+	  inicial.  Un objetivo del repositorio CVS de GNOME es 
+	  poder seguir la historia de los fuentes de manera 
+	  precisa desde el inicio.
+	</para>
+
+	<para>
+	  <emphasis>Por favor</emphasis>, pregunte al mantenedor
+	  del CVS, esto es, una persona conocida con acceso shell
+	  a la máquina con CVS, para realizar la cirugía necesaria
+	  para mover los archivos por usted.  Esto requiere 
+	  conocimiento de la forma en que funciona CVS y debe ser
+	  hecho muy cuidadosamente.  La recuperación de un error de
+	   «cvs add/remove» es una tarea muy desagradable;
+	  <!-- FIXME -->
+	  if you move files in this
+	  erroneous way a CVS maintainer who has to go through this
+	  job will summon a flaming bat of death from hell to bite
+	  your head off.  So please ask for someone to move the files
+	  for you.
+	</para>
+      </sect3>
+    </sect2>
+    
+  </sect1>
+
+  <!-- Maintaining a Package -->
+
+  <sect1 id="maintain">
+    <title>Cómo mantener un paquete</title>
+
+    <para>
+	  Un mantenedor de paquete es una persona que se preocupa de
+	  liberar versiones, integrar cambios de otras personas y,
+	  en general, ser responsable de un paquete.  Durante el
+	  período de vida de un paquete, este puede cambiar de 
+	  mantenedores, por ejemplo, una persona que pierde interés
+	  o que ya no puede dedicarle tiempo suficiente como mantenedor.
+    </para>
+
+    <para>
+	  En conformidad con los Estándares de programación de GNU, GNOME
+	  usa GNU Autoconf para manejar la portabilidad  y GNU Automake
+	  para crear makefiles.  Automake hace especialmente fácil
+	  construir paquetes correctos, así que si es un mantenedor
+	  de paquetes, debiera aprender como usarlo.  Autoconf y 
+	  Automake tienen muchas áreas truculentas, así que siéntase
+	  libre de pedir ayuda en las listas de desarrollo de GNOME
+	  si tiene preguntas sobre la forma correcta de makefiles
+	  para su paquete.
+    </para>
+
+    <para>
+	  Un número de personas regularmente contribuye con traducciones
+	  localizadas de los catálogos de mensajes en los paquetes de
+	  GNOME.  Para mantener las traducciones actualizadas tanto como
+	  sea posible, los mantenedores deben coordinarse con los 
+	  traductores para que estos últimos puedan actualizar las
+	  traducciones a tiempo cuando se va a liberar una nueva 
+	  versión del paquete.  Una buena forma de notificar a los
+	  traductores consiste en enviar un mensaje a
+      <email>gnome-i18n@gnome.org</email> con suficientes
+	  días de anticipación.  Esto les permitirá actualizar sus
+	  respectivas traducciones a tiempo para puedan ser incluidas
+	  en la siguiente versión liberada.
+    </para>
+  </sect1>
+
+  <!-- Memory Leaks Agenda -->
+
+  <sect1 id="memory-leak">
+    <title>¿Por qué debería preocuparse por la pérdida de memoria?.</title>
+
+    <para>
+	  Échele un vistazo a la lista de errores de Mozilla y una cosa es
+	  clara: el nuevo código que entra a Mozilla no es (o no ha sido)
+	  verificado suficientemente por pérdida de memoria y problemas
+	  de acceso.
+    </para>
+  
+    <para>
+	  Las pérdidas de memoria son malas por varias razones:
+
+      <itemizedlist>
+	<listitem>
+	  <para>
+		Se comerá el área de intercambio lentamente. A la larga su
+		programa, o hasta su máquina sucumbirán.
+          </para>
+          <para>
+		Nadie quiere que su programa o biblioteca adquiera la 
+		reputación de ser una porquería sólo porque uno ha sido
+		vago.  Déjeselo a las personas en Redmond.
+		</para>
+	</listitem>
+
+	<listitem>
+	  <para>
+		Ocultan el mal uso de la memoria.  Si olvida liberar la
+			memoria, no hay forma de atrapar las lecturas y
+			escrituras a esos trozos de memoria.  Si posteriormente
+			repara la pérdida, una parte completamente distinta
+			del programa podría fallar.
+          </para>
+	</listitem>
+
+	<listitem>
+          <para>
+			Cuando se usan verificadores automáticos de memoria,
+			nadie quiere ver 600 problemas, de los cuales 500
+			se encuentran en las bibliotecas de soporte. Lo que
+			desea ver es que las todo iba como una seda antes de
+			que empezara a toquetear y que, por lo tanto, le toca
+			arreglar los problemas.
+	  </para>
+
+	  <para>
+		Este es uno de los problemas de Mozilla actualmente: 
+		gotea sin parar así qiu ¿cómo va a saber si ha contribuido al problema?
+          </para>
+	</listitem>
+      </itemizedlist>
+    </para>
+ 
+    <sect2 id="memory-advice">
+      <title>Algunos consejos en la lucha contra la pérdida de memoria.</title>
+
+      <para>
+        <itemizedlist>
+          <listitem>
+	    <para>
+	      Use «const» donde sea posible (para punteros obviamente).
+            </para>
+	    <para>
+		  Si un argumento es «const», entonces indudablemente la
+		  	función llamada no liberará la memoria por usted.
+            </para>
+	    <para>
+		  Si el tipo de resultado de una función es «const», entonces
+		  claramente no es responsable por liberarlo. 
+		  *Probablemente* lo será para un resultado distinto de 
+		  «const» (que no sea un entero o algo similar).
+            </para>
+	    <para>
+			  Fíjese en que, desafortunadamente, esto no funciona muy bien
+			  con los objetos que cuentan referencias.  Funciona bien
+			  con cadenas.
+            </para>
+	    <para>
+			  Dado que C usa llamadas por valor, no tiene sentido
+			  aplicar «const» a tipos int, double y similares.
+            </para>
+	  </listitem>
+
+	  <listitem>
+	    <para>
+	      <emphasis>Documente las responsabilidades.</emphasis>
+            </para>
+	    
+	    <itemizedlist>
+	      <listitem>
+		<para>
+			  Si una función toma la propiedad de un objeto/referencia,
+			  	sea explícito acerca de ello.
+                </para>
+	      </listitem>
+
+	      <listitem>
+		<para>
+				  Indique siempre si el que llama a la función debiera
+				  liberar/desreferenciar los resultados.
+                </para>
+	      </listitem>
+
+	      <listitem>
+		<para>
+				  Documenta *cómo* entregar la memoria: unref, free,
+				  g_free, ...
+                </para>
+	      </listitem>
+	    </itemizedlist>
+	  </listitem>
+
+          <listitem>
+	    <para>
+	      <emphasis>Sea cuidadoso cuando use copiar-y-pegar.</emphasis>
+            </para>
+
+	    <para>
+			  El proceso de cortado y pegado no mejora el código, al 
+			  contrario de lo que creen muchos programadores.  Primero
+			  mire el código y si intenta producir muchas copias, quizás
+			  necesite una función de ayuda. <!-- FIXME: mejor 
+			  traducción de helper -->
+            </para>
+	  </listitem>
+
+          <listitem>
+	    <para>
+	      <emphasis>Libere todo antes de salir.</emphasis>
+            </para>
+            <para>
+			  Esto lleva tiempo, así que quizás debiera hacerlo sólo dentro 
+			  de una condición.
+            </para>  
+	    <para>
+			El motivo de este consejo es que los verificadores de memoria
+			toman tiempo en determinar entre una pérdida que conoce y no
+			le preocupa y las otras pérdidas.
+            </para>
+	  </listitem>
+
+	  <listitem>
+	    <para>
+	      <emphasis>No deje punteros sueltos en sus estructuras de 
+		  datos.</emphasis>
+            </para>
+
+	    <para>
+			  Asigne NULL o (void *)0xdeadbeef para los miembros liberados a
+			  menos que vaya a liberar la estructura a la que pertenecen.
+            </para>
+	    
+	    <para>
+			  Los punteros sueltos tienen la mala tendencia de ocultar pérdidas
+			  de memoria.
+	    </para>
+	  </listitem>
+
+	  <listitem>
+	    <para>
+	      <emphasis>Ejecute el nuevo código en un ciclo 1 millón de 
+		  veces.</emphasis>
+            </para>
+
+	    <para>
+			   Si pierde memoria, lo sabrá &mdash; sólo siga al proceso con
+			   top en otra ventana.  Podría querer especificar a top el PID 
+			   del proceso con la opción -p.
+            </para>
+	  </listitem>
+
+	  <listitem>
+	    <para>
+	      <emphasis>Repárelo ahora, no después.</emphasis>
+            </para>
+
+	    <para>
+			  No escriba una porquería de código; más temprano que tarde le
+			  pesará.
+            </para>
+	  </listitem>
+	</itemizedlist>
+      </para>
+    </sect2>
+  </sect1>
+</article>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stylesheets/README	Thu Sep 07 16:46:51 2006 -0400
@@ -0,0 +1,14 @@
+librognome-html.xsl: Es una hoja de estilo modificada de gtk-doc.xsl.
+    No tiene CSS inline, sino que se le indica una como parametro
+    al momento de aplicar dicha hoja.
+
+devhelp.xsl: Es la hoja de estilo que permite crear un libro
+    devhelp.  Es necesario realizar un proceso extra para generar
+    los terminos de busqueda.
+
+programming-guidelines.css: Es la hoja de estilos para HTML.  Cada clase
+    alli indicada, corresponde al nombre de algun marca empleada
+    en DocBook.
+
+*.png: Son las imagenes de navegacion usadas al utilizar la
+    hoja de estilos librognome-html.xsl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stylesheets/devhelp.xsl	Thu Sep 07 16:46:51 2006 -0400
@@ -0,0 +1,131 @@
+<?xml version='1.0'?> <!--*- mode: xml -*-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version='1.0'
+                xmlns="http://www.devhelp.net/book"
+                exclude-result-prefixes="#default">
+
+  <xsl:template name="generate.devhelp">
+    <xsl:call-template name="write.chunk">
+      <xsl:with-param name="filename">
+        <xsl:choose>
+          <xsl:when test="$gtkdoc.bookname">
+            <xsl:value-of select="$gtkdoc.bookname"/>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:text>book</xsl:text>
+          </xsl:otherwise>
+        </xsl:choose>
+        <xsl:text>.devhelp</xsl:text>
+      </xsl:with-param>
+      <xsl:with-param name="method" select="'xml'"/>
+      <xsl:with-param name="indent" select="'yes'"/>
+      <xsl:with-param name="encoding" select="'utf-8'"/>
+      <xsl:with-param name="content">
+        <xsl:call-template name="devhelp"/>
+      </xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+
+  <xsl:template name="devhelp">
+    <xsl:variable name="title">
+      <xsl:apply-templates select="." mode="generate.devhelp.toc.title.mode"/>
+    </xsl:variable>
+    <xsl:variable name="link">
+      <xsl:call-template name="href.target"/>
+    </xsl:variable>
+    <xsl:variable name="author">
+      <xsl:if test="articleinfo|bookinfo">
+        <xsl:apply-templates mode="generate.devhelp.authors"
+                             select="articleinfo|bookinfo"/>
+      </xsl:if>
+    </xsl:variable>
+    <xsl:variable name="toc.nodes" select="part|reference|preface|chapter|
+                                           appendix|article|bibliography|
+                                           glossary|index|refentry|
+                                           bridgehead|sect1"/>
+
+    <book title="{$title}" link="{$link}" author="{$author}" name="{$gtkdoc.bookname}">
+      <xsl:if test="$toc.nodes">
+        <chapters>
+          <xsl:apply-templates select="$toc.nodes"
+                               mode="generate.devhelp.toc.mode"/>
+        </chapters>
+      </xsl:if>
+      <functions>
+        <xsl:apply-templates select="//refsect2"
+                             mode="generate.devhelp.index.mode"/>
+      </functions>
+    </book>
+  </xsl:template>
+
+  <xsl:template match="*" mode="generate.devhelp.toc.mode">
+    <xsl:variable name="title">
+      <xsl:apply-templates select="." mode="generate.devhelp.toc.title.mode"/>
+    </xsl:variable>
+    <xsl:variable name="target">
+      <xsl:variable name="anchor" select="title/anchor"/>
+      <xsl:choose>
+        <xsl:when test="$anchor">
+          <xsl:call-template name="href.target">
+            <xsl:with-param name="object" select="$anchor"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="href.target"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+
+    <sub name="{$title}" link="{$target}">
+      <xsl:apply-templates select="section|sect1|
+                                   refentry|refsect|
+                                   bridgehead|part|chapter"
+                           mode="generate.devhelp.toc.mode"/>
+    </sub>
+  </xsl:template>
+
+  <xsl:template match="*" mode="generate.devhelp.index.mode">
+    <xsl:variable name="title" select="title"/>
+    <xsl:variable name="anchor" select="title/anchor"/>
+    <xsl:variable name="target">
+      <xsl:choose>
+        <xsl:when test="$anchor">
+          <xsl:call-template name="href.target">
+            <xsl:with-param name="object" select="$anchor"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="href.target"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <function name="{$title}" link="{$target}"/>
+  </xsl:template>
+
+  <!-- get title -->
+  <xsl:template match="article" mode="generate.devhelp.toc.title.mode">
+    <xsl:value-of select="articleinfo/title"/>
+  </xsl:template>
+  <xsl:template match="book" mode="generate.devhelp.toc.title.mode">
+    <xsl:value-of select="bookinfo/title"/>
+  </xsl:template>
+  <xsl:template match="refentry" mode="generate.devhelp.toc.title.mode">
+    <xsl:value-of select="refmeta/refentrytitle"/>
+  </xsl:template>
+  <xsl:template match="*" mode="generate.devhelp.toc.title.mode">
+    <xsl:value-of select="title"/>
+  </xsl:template>
+
+  <!-- generate list of authors ... -->
+  <xsl:template match="articleinfo|bookinfo" mode="generate.devhelp.authors">
+    <xsl:for-each select="authorgroup/author">
+      <xsl:value-of select="firstname"/>
+      <xsl:text> </xsl:text>
+      <xsl:value-of select="surname"/>
+      <xsl:if test="not(last())">
+        <xsl:text>, </xsl:text>
+      </xsl:if>
+    </xsl:for-each>
+  </xsl:template>
+
+</xsl:stylesheet>
Binary file stylesheets/home.png has changed
Binary file stylesheets/left.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stylesheets/librognome-html.xsl	Thu Sep 07 16:46:51 2006 -0400
@@ -0,0 +1,277 @@
+<?xml version='1.0'?> <!--*- mode: xml -*-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="1.0">
+
+  <!-- import the chunked XSL stylesheet -->
+  <xsl:import href="/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/chunk.xsl"/>
+  <xsl:include href="devhelp.xsl"/>
+
+  <!-- change some parameters -->
+  <xsl:param name="toc.section.depth">1</xsl:param>
+
+  <xsl:param name="default.encoding" select="'ISO-8859-1'"/>
+  <xsl:param name="chapter.autolabel" select="0"/>
+  <xsl:param name="use.id.as.filename" select="'1'"/>
+  <xsl:param name="html.ext" select="'.html'"/>
+  <xsl:param name="refentry.generate.name" select="0"/>
+  <xsl:param name="refentry.generate.title" select="1"/>
+
+  <!-- display variablelists as tables -->
+  <xsl:param name="variablelist.as.table" select="1"/>
+
+  <!-- this gets set on the command line ... -->
+  <xsl:param name="gtkdoc.version" select="''"/>
+  <xsl:param name="gtkdoc.bookname" select="''"/>
+
+  <!-- ========================================================= -->
+  <!-- template to create the index.sgml anchor index -->
+
+  <xsl:template match="book|article">
+    <xsl:apply-imports/>
+
+    <!-- generate the index.sgml href index -->
+    <xsl:call-template name="generate.index"/>
+    <xsl:call-template name="generate.devhelp"/>
+  </xsl:template>
+
+  <xsl:template name="generate.index">
+    <xsl:call-template name="write.text.chunk">
+      <xsl:with-param name="filename" select="'index.sgml'"/>
+      <xsl:with-param name="content">
+        <!-- check all anchor and refentry elements -->
+        <xsl:apply-templates select="//anchor|//refentry"
+                             mode="generate.index.mode"/>
+      </xsl:with-param>
+      <xsl:with-param name="encoding" select="'utf-8'"/>
+    </xsl:call-template>
+  </xsl:template>
+
+  <xsl:template match="*" mode="generate.index.mode">
+    <xsl:if test="not(@href)">
+      <xsl:text>&lt;ANCHOR id=&quot;</xsl:text>
+      <xsl:value-of select="@id"/>
+      <xsl:text>&quot; href=&quot;</xsl:text>
+      <xsl:if test="$gtkdoc.bookname">
+        <xsl:value-of select="$gtkdoc.bookname"/>
+        <xsl:text>/</xsl:text>
+      </xsl:if>
+      <xsl:call-template name="href.target"/>
+      <xsl:text>&quot;&gt;
+</xsl:text>
+    </xsl:if>
+  </xsl:template>
+
+  <!-- ========================================================= -->
+  <!-- template to output gtkdoclink elements for the unknown targets -->
+
+  <xsl:template match="link">
+    <xsl:choose>
+      <xsl:when test="id(@linkend)">
+        <xsl:apply-imports/>
+      </xsl:when>
+      <xsl:otherwise>
+        <GTKDOCLINK HREF="{@linkend}">
+          <xsl:apply-templates/>
+        </GTKDOCLINK>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!-- ========================================================= -->
+  <!-- Below are the visual portions of the stylesheet.  They provide
+       the normal gtk-doc output style. -->
+
+  <xsl:param name="shade.verbatim" select="0"/>
+  <xsl:param name="refentry.separator" select="0"/>
+
+  <xsl:template match="refsect2">
+    <xsl:if test="preceding-sibling::refsect2">
+      <hr/>
+    </xsl:if>
+    <xsl:apply-imports/>
+  </xsl:template>
+
+  <xsl:template name="user.head.content">
+    <xsl:if test="$gtkdoc.version">
+      <meta name="generator"
+            content="GTK-Doc V{$gtkdoc.version} (XML mode)"/>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="title" mode="book.titlepage.recto.mode">
+    <table class="navigation" width="100%"
+           cellpadding="2" cellspacing="0">
+      <tr>
+        <th valign="middle">
+          <p class="{name(.)}">
+            <xsl:value-of select="."/>
+          </p>
+        </th>
+      </tr>
+    </table>
+  </xsl:template>
+
+  <xsl:template name="header.navigation">
+    <xsl:param name="prev" select="/foo"/>
+    <xsl:param name="next" select="/foo"/>
+    <xsl:variable name="home" select="/*[1]"/>
+    <xsl:variable name="up" select="parent::*"/>
+
+    <xsl:if test="$suppress.navigation = '0' and $home != .">
+      <table class="navigation" width="100%"
+             summary = "Navigation header" cellpadding="2" cellspacing="2">
+        <tr valign="middle">
+          <xsl:if test="count($prev) > 0">
+            <td>
+              <a accesskey="p">
+                <xsl:attribute name="href">
+                  <xsl:call-template name="href.target">
+                    <xsl:with-param name="object" select="$prev"/>
+                  </xsl:call-template>
+                </xsl:attribute>
+                <img src="left.png" width="24" height="24" border="0">
+                  <xsl:attribute name="alt">
+                    <xsl:call-template name="gentext">
+                      <xsl:with-param name="key">nav-prev</xsl:with-param>
+                    </xsl:call-template>
+                  </xsl:attribute>
+                </img>
+              </a>
+            </td>
+          </xsl:if>
+          <xsl:if test="count($up) > 0 and $up != $home">
+            <td>
+              <a accesskey="u">
+                <xsl:attribute name="href">
+                  <xsl:call-template name="href.target">
+                    <xsl:with-param name="object" select="$up"/>
+                  </xsl:call-template>
+                </xsl:attribute>
+                <img src="up.png" width="24" height="24" border="0">
+                  <xsl:attribute name="alt">
+                    <xsl:call-template name="gentext">
+                      <xsl:with-param name="key">nav-up</xsl:with-param>
+                    </xsl:call-template>
+                  </xsl:attribute>
+                </img>
+              </a>
+            </td>
+          </xsl:if>
+          <xsl:if test="$home != .">
+            <td>
+              <a accesskey="h">
+                <xsl:attribute name="href">
+                  <xsl:call-template name="href.target">
+                    <xsl:with-param name="object" select="$home"/>
+                  </xsl:call-template>
+                </xsl:attribute>
+                <img src="home.png" width="24" height="24" border="0">
+                  <xsl:attribute name="alt">
+                    <xsl:call-template name="gentext">
+                      <xsl:with-param name="key">nav-home</xsl:with-param>
+                    </xsl:call-template>
+                  </xsl:attribute>
+                </img>
+              </a>
+            </td>
+          </xsl:if>
+          <th width="100%" align="center">
+            <xsl:apply-templates select="$home"
+                                 mode="object.title.markup"/>
+          </th>
+          <xsl:if test="count($next) > 0">
+            <td>
+              <a accesskey="n">
+                <xsl:attribute name="href">
+                  <xsl:call-template name="href.target">
+                    <xsl:with-param name="object" select="$next"/>
+                  </xsl:call-template>
+                </xsl:attribute>
+                <img src="right.png" width="24" height="24" border="0">
+                  <xsl:attribute name="alt">
+                    <xsl:call-template name="gentext">
+                      <xsl:with-param name="key">nav-next</xsl:with-param>
+                    </xsl:call-template>
+                  </xsl:attribute>
+                </img>
+              </a>
+            </td>
+          </xsl:if>
+        </tr>
+      </table>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template name="footer.navigation">
+    <xsl:param name="prev" select="/foo"/>
+    <xsl:param name="next" select="/foo"/>
+
+    <xsl:if test="$suppress.navigation = '0'">
+      <table class="navigation" width="100%"
+             summary="Navigation footer" cellpadding="2" cellspacing="0">
+        <tr valign="middle">
+          <td align="left">
+            <xsl:if test="count($prev) > 0">
+              <a accesskey="p">
+                <xsl:attribute name="href">
+                  <xsl:call-template name="href.target">
+                    <xsl:with-param name="object" select="$prev"/>
+                  </xsl:call-template>
+                </xsl:attribute>
+                <b>
+                  <xsl:text>&lt;&lt;&#160;</xsl:text>
+                  <xsl:apply-templates select="$prev"
+                                       mode="object.title.markup"/>
+                </b>
+              </a>
+            </xsl:if>
+          </td>
+          <td align="right">
+            <xsl:if test="count($next) > 0">
+              <a accesskey="n">
+                <xsl:attribute name="href">
+                  <xsl:call-template name="href.target">
+                    <xsl:with-param name="object" select="$next"/>
+                  </xsl:call-template>
+                </xsl:attribute>
+                <b>
+                  <xsl:apply-templates select="$next"
+                                       mode="object.title.markup"/>
+                  <xsl:text>&#160;&gt;&gt;</xsl:text>
+                </b>
+              </a>
+            </xsl:if>
+          </td>
+        </tr>
+      </table>
+    </xsl:if>
+  </xsl:template>
+
+<xsl:template match="author" mode="titlepage.mode">
+  <div class="{name(.)}">
+    <xsl:call-template name="person.name"/>
+    <xsl:apply-templates mode="titlepage.mode" select="./contrib"/>
+    <xsl:apply-templates mode="titlepage.mode" select="./affiliation"/>
+    <xsl:apply-templates mode="titlepage.mode" select="./email"/>
+  </div>
+</xsl:template>
+
+<xsl:template match="email" mode="titlepage.mode">
+  <span class="{name(.)}">
+    &lt;<a href="mailto:{.}"><xsl:value-of select="."/></a>&gt;
+  </span>
+</xsl:template>
+
+<xsl:template match="address" mode="titlepage.mode">
+  <span class="{name(.)}">
+	<xsl:apply-templates mode="titlepage.mode"/>
+  </span>
+</xsl:template>
+
+<xsl:template match="affiliation" mode="titlepage.mode">
+  <span class="{name(.)}">
+	<xsl:apply-templates mode="titlepage.mode"/>
+  </span>
+</xsl:template>
+
+</xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stylesheets/programming-guidelines.css	Thu Sep 07 16:46:51 2006 -0400
@@ -0,0 +1,83 @@
+body {
+	font-family: sans, verdana, arial, geneva;
+}
+
+.funcsynopsis {
+	background: #eeeeff;
+	border: solid 0px #aaaaff;
+	padding: 0.5em;
+}
+
+.screen {
+	font-family: monospace, courier;
+	background: #eeeeff;
+	border: solid 1px #aaaaff;
+	padding: 0.5em;
+}
+
+.figure {
+	text-align: center;
+}
+
+.affiliation {
+	font-size: small;
+}
+
+.firstname, .surname {
+	font-weight: bold;
+}
+
+.author {
+	padding: 0em;
+}
+
+/* Definidos por gtk-doc */
+.synopsis, .classsynopsis {
+	background: #eeeeee;
+	border: solid 1px #aaaaaa;
+	padding: 0.5em;
+}
+
+.programlisting {
+	background: #eeeeff;
+	border: solid 1px #aaaaff;
+	padding: 0.5em;
+}
+
+.variablelist {
+	padding: 4px;
+	margin-left: 3em;
+}
+
+.navigation {
+	background: #ffeeee;
+	border: solid 1px #ffaaaa;
+	margin-top: 0.5em;
+	margin-bottom: 0.5em;
+}
+
+.navigation a {
+	color: #770000;
+}
+
+.navigation a:visited {
+	color: #550000;
+}
+
+.navigation .title {
+	font-size: 200%;
+}
+
+.revhistory {
+	padding: 0.5em;
+}
+
+div.revhistory > table {
+	border: solid 1px #ccc;
+	background-color: #eee;
+	color: #444;
+	border-collapse: collapse;
+	font-size: x-small;
+	/* border-style: hidden; */
+}
+
Binary file stylesheets/right.png has changed
Binary file stylesheets/up.png has changed