Ejemplo de uso del Widgetserver desde Octave.

Las comunicaciones con el Widgetserver se realizarán usando el comando de octave popen2. El problema es que la implementación de este comando falla. La implementación correcta de este comando sería:
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

Se puede incluir dentro de los programas de Octave, pues Octave permite redefinir las funciones.

Para comunicarse con Octave se seguirán los siguientes pasos:
1. Se abrirán las comunicaciones con el Widgetserver usando popen2.
2. Se le mandarán las instrucciones necesarias para construir la ventana.
3. Se escucharán los eventos con fgets.

Ejemplo comentado.

El siguiente ejemplo abre una ventana que pide el argumento de la función sombrero:
[out,in,pid]=popen2("widgetserver");
if(pid<0)
	printf("Error widgetserver couldn't be executed\n");
	exit(1);
end
Lo que se ha hecho es abrir las comunicaciones con el Widgetserver. En el caso de que el programa widgetserver no se encuentre, se muestra un mensaje de error. En el caso de que no funcione correctamente, se puede usar la implementación de popen2 mostrada anteriormente.
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);

Se envía la ventana que se tiene que mostrar. El fflush(out) es importante para poder enviar los datos..Es mucho más cómodo escribir la ventana en un fichero y enviarla después leyendo el fichero.

%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 botón de Ok.
	
	% Se lee la línea 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

Este era el bucle de eventos, se van leyendo, línea a línea los datos que envía el Widgetserver y se procesan.
Las funciones strcmp, substr y length se usan para comparar las cadenas. La función 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.

fclose(in);
fclose(out);

% Fin del programa

En el fichero ej_sombrero.m se puede encontrar el ejemplo anterior.