<html>
<body>
<h1>Ejemplo de uso del Widgetserver desde Octave.</h1>
Las comunicaciones con el Widgetserver se realizarn usando el comando de octave <b>popen2</b>. El problema es que la implementacin de este comando falla. La implementacin correcta de este comando sera:
<pre>
function [in, out, pid] = popen2 (command, args)

  in = -1;
  out = -1;
  pid = -1;

  if (nargin == 1 || nargin == 2)

    if (nargin == 1)
      args = "";
    endif

    if (ischar (command))

      [stdin_pipe, stdin_status] = pipe ();
      [stdout_pipe, stdout_status] = pipe ();

      if (stdin_status == 0 && stdout_status == 0)

        pid = fork ();

        if (pid == 0)

	  ## In the child.

          fclose (nth (stdin_pipe, 2));
          fclose (nth (stdout_pipe, 1));

          dup2 (nth (stdin_pipe, 1), stdin);
          fclose (nth (stdin_pipe, 1));

          dup2 (nth (stdout_pipe, 2), stdout);
          fclose (nth (stdout_pipe, 2));

          if (exec (command, args) < 0)
            error ("popen2: unable to start process `%s'", command);
            exit (0);
          endif

        elseif (pid)

	  ## In the parent.

          fclose (nth (stdin_pipe, 1));
          fclose (nth (stdout_pipe, 2));

          %if (fcntl (nth (stdout_pipe, 1), F_SETFL, O_NONBLOCK) < 0)
          %  error ("popen2: error setting file mode");
          %else
            in = nth (stdin_pipe, 2);
            out = nth (stdout_pipe, 1);
          %endif

        elseif (pid < 0)
          error ("popen2: fork failed -- unable to create child process");
        endif
      else
        error ("popen2: pipe creation failed");
      endif
    else
      error ("popen2: file name must be a string");
    endif
  else
    usage ("[in, out, pid] = popen2 (command, args)");
  endif

endfunction
</pre>
<p>Se puede incluir dentro de los programas de Octave, pues Octave permite redefinir las funciones.</p>
Para comunicarse con Octave se seguirn los siguientes pasos:<br>
1. Se abrirn las comunicaciones con el Widgetserver usando popen2.<br>
2. Se le mandarn las instrucciones necesarias para construir la ventana.<br>
3. Se escucharn los eventos con fgets.<br>
<br>
<h1>Ejemplo comentado.</h1>
El siguiente ejemplo abre una ventana que pide el argumento de la funcin sombrero:
<pre>
[out,in,pid]=popen2("widgetserver");
if(pid<0)
	printf("Error widgetserver couldn't be executed\n");
	exit(1);
end
</pre>
Lo que se ha hecho es abrir las comunicaciones con el Widgetserver. En el caso de que el programa <i>widgetserver</i> no se encuentre, se muestra un mensaje de error. En el caso de que no funcione correctamente, se puede usar la implementacin de popen2 mostrada anteriormente.
<pre>
fprintf(out, "<window:frame>\n");
fprintf(out, "	<title:Sombrero/>\n");
fprintf(out, "	<p>\n");
fprintf(out, "	<label:l1>\n");
fprintf(out, "	 	Number of grids\n");
fprintf(out, "	</label>\n");
fprintf(out, "	<lineedit:w0>\n");
fprintf(out, "		<text: 20/>\n");
fprintf(out, "	</lineedit>\n");
fprintf(out, "	</p>\n");
fprintf(out, "	<html:ht1>\n");
fprintf(out, "		Draws sombrero function\n");
fprintf(out, "	</html>\n");
fprintf(out, "	<p>\n");
fprintf(out, "	<button:ok>\n");
fprintf(out, "		<listen: clicked/>\n");
fprintf(out, "		<text>\n");
fprintf(out, "	 		Ok\n");
fprintf(out, "		</text>\n");
fprintf(out, "	</button>\n");
fprintf(out, "	<button:cancel>\n");
fprintf(out, "		<listen: clicked/>\n");
fprintf(out, "		<text>\n");
fprintf(out, "	 		Cancel\n");
fprintf(out, "		</text>\n");
fprintf(out, "	</button>\n");
fprintf(out, "	</p>\n");
fprintf(out, "</window>\n");

fflush(out);

</pre>
Se enva la ventana que se tiene que mostrar. <i>El fflush(out) es importante para poder enviar los datos.</i>.Es mucho ms cmodo escribir la ventana en un fichero y enviarla despus leyendo el fichero.
<pre>

%Event loop
while( isstr ( line=fgets(in) ) )
	% Se procesan los eventos para cerrar la ventana
	if(
		( length(line)>=15 && strcmp(substr(line,1,16),'*clicked: cancel') )
		||
		( length(line)>=13 && strcmp(substr(line,1,13),'*close: frame') )
	  )
		fprintf(out, "<quit/>\n");
		fflush(out);
		break;
	end;
	
	% Se debe haber hecho click sobre el botn de Ok.
	
	% Se lee la lnea de texto.
	fprintf(out, "<lineedit:w0>\n");
	fprintf(out, "	<getText/>\n");
	fprintf(out, "</lineedit>\n");
	fflush(out);
	
	line=fgets(in);
	w0=fgets(in);

	%Se dibuja el sombrero
	sombrero(eval(w0));

end

</pre>
Este era el bucle de eventos, se van leyendo, lnea a lnea los datos que enva el Widgetserver y se procesan.<br>
Las funciones strcmp, substr y length se usan para comparar las cadenas. La funcin strcmp compara dos cadenas e indica si son iguales. length sirve para indicar la longitud de un array (una cadena). substr sirve para extraer una parte de una cadena.
<pre>

fclose(in);
fclose(out);

% Fin del programa

</pre>

En el fichero <a href="ej_sombrero.m">ej_sombrero.m</a> se puede encontrar el ejemplo anterior.

</body>
</html>