Jugando a la ajedrez en el mundo xBase...
El ajedrez es un juego formado por 64 casillas, las cual estan formadas
por distintas piezas, donde hay 6 piezas distantas, y cada pieza tiene
un movimiento distinto.
¿ Y que tiene que ver el ajedrez con el mundo xBase ?
Ufff!! Mucho mas que lo que pensais..., bajo mi punto de vista.
Atentos a la comparacion:
Tablero = xBase
*Piezas = GUI-C3 FIVEWIN XAILER xIde MINI-Gui HwGUI FIVELINUX
*Hay más, pero simplificamos
Pero ahora, en esta variante del juego, tenemos a parte, los compiladores
de C a elegir y los compiladores de xBase.
Ahora, en esta guerra de guerrillas, si señores, esto ya empieza a dar que
hablar, las ostias virtuales.
En una situacion 'irreal', fruto de mi imaginacion, describiremos una
partida del Ajedrez 'a la' xBase
Salen blancas.....
1.b5! Bién es cierto que ganar la casilla RAD cuesta ceder la de POO,
pero la diferencia está en que xailer se instala en el campo enemigo.
1...a6 [ 1...Ce5 2.De2 amenazaría 22.f4 y 22.Cxe6]
2.Cc6 Af8 [ 2...Ac5 era un mal menor, banneado en la siguiente...]
3.a4 axb5
4.axb5 Txa1 [ 4..axc6 podria ser ya que xIde esta esperando el momento... ]
5.Txa1 Ta8 [ummm...Enrocandose Fivewin....]
6.Td1! en opinión de los masters, esta jugada puede decidir la partida.
Realmente la torre negra no tiene nada que hacer en la columna a.
6...Ce8 [ uummm... interesante, Compilador+IDE en uno, C3...., jugada
que merece una especial atención..]
7.Cc4 Cc5
8.e5! Tc8 [ 8...Cc7 9.Td7+-, aqui , el intento de crackear a salido por
la cerros de úbeda, eso da lugar a Xailer a contraatacar en la siguiente...]
9.Ta1! Tc7 [ 9...Ta8 10.Txa8 Dxa8 11.Ce7++-, jugadas posibles... ]
10.Ta7 Dxa7 [ 10...Dc8 11.Cxb6+-, puede liarse la 'gorda' al final, los
jugadores saltan al terreno de juego y empiezan a tirarse los trastos...,
habiendo algunos heridos entre los asistentes.
Como anecdota , el reloj del tiempo la da a uno en 'tol ojo' ]
11.Cxa7 [ 1-0 ] ...y gana, and the winner is... ???
Parece mentira lo que se llega a aprender de una partida de ajedrez. :-)
Y tu, ¿ ya te has posicionado en el tablero ?
Saludos.
Jose F. Gimenez , Ignacio Ortiz y el resto de compomentes, nos presentan una nueva GUI para xHarbour, un autentico RAD para xBase
Xailer, es un nuevo entorno de programacion teniendo por debajo al compilador
Free Software [x]Harbour, a la 'delphi'.
Si, a la 'delphi', pues el RAD es practicamente como Delphi.
La primera beta que llego a mis manos, gracias a Jose F. que me dejo jugar,
me quede 'agilipollao'.
Realmente, no podia creer lo que estaba viendo, asi que pense que habia metido
mucho 'C' en el IDE.
Pues no, mi sorpresa llega cuando Jose informa que el IDE esta echo con el mismo Xailer!!!
Ahi es na! Crean su propio IDE con su propia GUI, claro, que mejor manera de empezar
a probar las posibilidades que realizar el propio IDE en su nueva GUI ;-)
Por lo que se esta viendo, Xailer esta causando verdadera admiracion/celos entre
la comunidad xBase.
Realmente, SIEMPRE nos hemos quejado que cada vez somos MENOS desarrollando en
los distintos dialectos de Dbase, y empezar a usarlo en ambientes graficos,
era muy complicado para todos los 'potenciales' primeros programadores.
Con Xailer, eso desaparece. Ahora, no hay excusa, puesto que programar en xBase
es tan o mas sencillo que usar Delphi o/y VB.
Creo sinceramente, que Xailer es la 1ª opcion para empezar a todo aquel que se
quiera introducirse en la programacion xBase.
Ahora bien, una de cal y otra de arena. ;-)
Los 'carrozas' nos sentimos 'extraños'. Muchos años siguiendo una pautas, hace
que se nos atragante el usar un IDE.
No estamos acostumbrados a que ninguna herramienta haga las cosas por nosotros,
y nos resistimos a cambiar, es la naturaleza humana, que le vamos hacer.
Si, y en eso le doy la razon a Jose F., cuando me comentó , que esto no
quita que tu tengas TODO el control de tu codigo, y si, esta en lo cierto,
lo necesario es hacer un cambio de mentalidad, pero no es tan sencillo.
Lo que si es seguro, es que programar bajo Xailer es muy sencillo, todo
esta a la palma de la mano, y se termino toda esa complicacion a la hora
de crearte un maldito ejecutable.
Creo, que una vez este disponible la ayuda completa, asi como MUCHISISMOS
ejemplos de usos, eso realmente es el mejor maestro, sera una herramienta
MUY A TENER EN CUENTA.
Ahora he visto que han dejado una beta para todo del mundo, para
que la gente se haga una idea de como es Xailer, y creo que ha sido
todo un acierto.
Mas información en:
http://www.xailer.com
Y el punto de encuentro , en las news, para hablar sobre xailer :
news://news.xailer.com/local.xailer.beta
Espero que les guste Xailer, al menos, mi primera aplicación no tuve
que escribir ni una línea de código.
Solamente desearles todos mis mejores deseos a todos los componentes de Xailer Team ;-)
Saludos.
Motivos por los que he decidido dejar de publicar sobre T-Gtk...
Mis motivos a no revelar 'codigo' mas alla del lenguaje xBase,
se fundamenta principalmente en varios motivos.
El primero y fundamental es atacarme y criticarme como persona, en vez de mi código,
que puede ser malo, feo y asquerosamente mal echo, eso estaria dispuesto
hasta acertarlo, pero no acepto que se entre en el terreno personal.
Me he he dado cuenta de una cosa,
¿ que interes puede haber mas alla del codigo xBase ?
Particularmente, creo que los programadores de xBase, les da igual, no van a meterse a programar en C para enseñar un dialogo.
En cambio, la frontera entre la conexion harbour/api grafica, no esta tan clara, y
mas en los tiempos en que estamos viviendo.
Hay muchos intereses comerciales por medio, en uno u otro sentido, y yo me
abstengo en inclinarme para un lado o para el otro, lo que si se, es que me gusta
que se vea ese movimiento, donde las distintas opciones se van posicionando
en el mercado y todos tengamos donde poder elegir.
Yo, seguire mi propio 'curso de autoformacion' sobre HARBOUR/C/GTK, y quizas
algun dia sea capaz de tener un completo entorno de desarrollo para mi,
para jugar y perder mis horas en mi propio beneficio, no en beneficio de
terceras partes, gracias a dios no vivo de ello.
Eso si, seguire ayudando en la medida de lo posible en mejorar/crear/arreglar
codigo xbase que tenemos en el CVS, que Jose Alfonso nos brinda,
principalmente en la programacion sobre Fivewin, que es hoy por hoy la
herramienta dominante y de las que venimos casi todos.
Quizas, el dia que desde el grupo Olivares 2000 organice una nueva reunion,
nos veamos ahi y con gusto les explicare todo , con pelos y señales hasta
donde he podido averiguar sobre la creacion de un GUI grafico para Harbour,
siempre y cuando pueda asistir, que esa es otra ;-), y sepa expresarlo, que
escribiendo trasmito mejor mis conocimientos que hablando, no soy un buen
orador.
Si que este mundo del xBase me he dado cuenta que estan todos paranoicos!!
Solamente decirles , feliz programacion.
Saludos.
T-Gtk sigue su curso de experimentacion....
A unos amigos les he enviado la imagen para que vieran como se T-Gtk es posible dibujar primitivas graficas.
Ya descubri el tema de como coger valores devueltos por una funcion de harbour a C, y ya esta funcionando como deberia salirse de Gtk+.
La cuestion es que T-Gtk, usa el mismo mecanismo de salida que en C, por lo tanto todo lo que veas de documentacion de C es aplicable a harbour, por ejemplo:
window = widget a conectar la señar.
"delete_event"= señal que se dispara cuando cerramos aplicacion.
"Continuar"= Funcion que procesa dicha señal desde harbour.
gtk_signal_connect( window, "delete_event", "Continuar" )
// Tal y como hace GTK+
Function Continuar()
// Si queremos continuar, devolvemos .T.
// En caso contrario, devolvermos .F.
Return .F.
Espero que la imagen os brinde la unica posibilidad de ver como con linux tambien es posible hacer cosas interesantes con Harbour.
Lamentablemente he de comunicar que esto es lo unico que veras, pues he decidido a no publicar nada con respecto a T-Gtk ni liberar ningun tipo de codigo al respecto y ni comunicare/explicare como se hace.
En un proxima post, explicare la decision que me ha hecho cambiar de rumbo.
Saludos.
GUI T-GTK Y ya van.....
Una nueva GUI bajo Gtk+ / Harbour experimental realizada integramente por mi.
Buenas, ya puedo respirar mas tranquilo, todas mis frustaciones se han acabado, de momento ;-)
Por fin logré, lo que tanto estuve en su dia buscando:
Crearme mi propia GUI para jugar
Yo no pretendo, ni creo que lo lograria, ni hacerle competencia desleal, como un amigo cree que hago realizando esto, ni mucho menos, a Fivetech.
Por mucho que le intente convencerle de que yo no me muevo por puros motivos economicos, si no mas bien por el tema de saber como , o mas bien, si sere capaz de hacer algun dia un GUI como la de Fivewin.
Por favor, no intenteis creeros que esto es una alternativa a FiveLinux, ni mucho menos, me encanta FiveLinux, es más Antonio sabe que le he ayudado en lo humanamente en lo que sabia y le he pasado mejoras de sus propias clases, ahi estoy, en los creditos, creo que el primero ;-), para mi eso es
suficiente, y SI , no he cobrado NI UN DURO, es que la gente no lo entiende, como tampoco cobre NI UN DURO por traducirles al catalan a Xailer, lo hago simplemente por que me gusta ayudar a mis amigos, independientemente de que ellos se ganen la vida de esa manera, se, que cuando tengo un problema, ahi los tengo, y eso vale su peso en oro, cuando Murphy hace de las suyas y eso amigo mio, no se paga con dinero.
Este juguete lo he bautizado como T-Gtk+.
Es muy simple, solamente esta realizado el punto de entrada a las librerias GTK,
crear una simple ventana y un boton, y la conexion de los eventos para saltar a nuestro codigo de Harbour realizado desde el mismo Harbour.
Todo ello similar tal y como lo hace GTK+, con el mismo nombre de funcion.
Todavia estoy pensando 'como realizar' una mejor gestion de los eventos, a nivel de C, no soy muy lucho en C, pero bueno, vamos haciendo.
No se cuando ni como lo liberare, todavia estoy pensando en ello, y estoy seriamente pensando en la posibilidad de escribir un libro sobre la creacion de GUIs para Harbour incluyendo la criatura, vete tu a saber, que ni lo se yo ;-)
Y lo volvere a repetir, esto NO SUSTITUYE A FIVELINUX, no sirve para crear aplicaciones, si no como experimento sobre creacion de GUIs, o para algun curioso.
Espero que con estas imagenes podais admirar a mi juguete
Si coges la imagen y la visualizas a tamaño normal, lo veras mejor
Saludos.
He aqui 'el como' funciona el tema del 'punto de entrada' desde harbour a una GUI grafica.
Siempre dicen que segundas partes nunca fueron buenas, pero....
¿ Tu que crees ?
En un mensaje en las news de Fivetech, news://news.fivetechsoft.comAntonio Linares, genio y creador de las librerias Fivewin, posteo, a un mensaje expuesta desde esta bitacora :
Normalmente cuando nos referimos al punto de entrada, nos podemos referir al
inicio de la aplicación. En una aplicación C estandard, sería main(), y en
una aplicación Windows sería WinMain().
Cuando hablamos de una aplicación xbase, se trata de cuando desde el nivel
de C se salta al nivel de PRG.
¿ En que circunstancias ocurre eso ?
En Windows, las ventanas solicitan un puntero a una función en C, que se
suele denominar "callback", que significa que es una función que será
llamada desde Windows, para notificarle de los distintos eventos que van
ocurriendo. Ahora bien, si Windows llama a ese punto de entrada en C, desde
ahí hemos de saltar a nivel PRG. En Harbour no hay problema en hacer eso ya
que todo su API es código abierto y se han publicado ejemplos al respecto.
En Linux ocurre exactamente igual. Por ejemplo la librería GTK+ tambien pide
determinados "callback"s a los que llamará, y desde esas funciones en C,
tambien tendremos que saltar a nivel PRG.
//---End...//
En mi contrareplica, mi argumentación fue más precisa , más que nada para saber si estaba o no equivocado, y de paso, que Antonio me corrigiera:
Gracias Antonio por tus respuesta, pero... ya estamos.. los ejemplos
de toda la teoria se echa en falta, y ya se que estas muy ocupado en
explicarnos, a los que posiblemente nunca llegaremos a tu nivel de
conocimientos,
aprovechare para que nos ilustres a todos.
> En una aplicación C estandard, sería main(), y en una aplicación Windows
sería WinMain().
Ok. Por lo que deduzco del codigo de harbour, veo que todo ocurre en ,
dependiendo
sobre que sistema a emplear, ocurre desde /harbour/source/main.c
Dicho fichero, simplemente seleccionara el punto de entrada en el cual
queramos
operar, y en este caso, para Windows, se haria uso de
/harbour/source/mainwin.c
en el cual , vemos como los parametros pasados a una aplicacion de harbour,
seran pasados a harbour a traves de hb_cmdargInit()
hb_cmdargInit( argc, argv );
acontinuacion, teoricamente, se pone en marcha la 'maquina virtual',
hb_vmInit( TRUE );
digamos que es ahi cuando salta a 'nuestra' Function Main() de Harbour,
( obviamente , teoricamente saltara al INIT Procedure, etc..., pero a
grandes rasgos )
Y por ultimo, la salida de la aplicacion , provoca la siguiente instruccion:
hb_vmQuit();
Si me equivoco , rectificame.
Ahora bien, siguiendo ese esquema, obtenemos, como bien dices:
Eso seria por cada sistema a implementar. Es decir, para GTK,
podemos inicializar como:
int main( ...)
if( gtk_init_check( ..) ) // Lo mismo que gtk_init() , pero devuelve si se
inicializo o no
hb_cmdargInit( argc, argv );
hb_vmInit( TRUE ); // Entramos ya en 'Harbour' Function Main()
hb_vmQuit();
else
{ fgprintf("Error de inicializacion") }
Esto, es lo que he estado buscando durante tanto tiempo, sin exito, hasta
hace 2 dias.
Pero... siempre esta el puto pero... a ser un sistema de eventos tipo
Win32/GTK+,
nos falta el decir como y donde tiene que saltar , una vez mas , desde C a
Harbour.
Claro esta, que todo esto en Fivewin/FiveLinux esta implementado, pero yo no
se como,
logico cada cual protege su inversion/producto como mas le apetezca, y ahi
es donde
estoy mosqueado, en el 'como'.
Lógicamente, hablare sobre Win32 pues es lo que mas conozco, por que
ciertamente
en GTK+ la cosa es distinta, pero ya se como implementarlo o al menos creo
saberlo. ;-)
Para poder entendernos y que nos entiendan, voy a tratar de 'averiguar' como
realiza Fivewin la magia,
en parte pues no tengo el codigo.
Bien, si os habeis fijado, en Fivewin todo control debe de ser registado, es
logico porque asi lo
requiere el api Win32.
Ahora bien, que pasa realmente cuando registramos un control, y es asi
cuando se lleva a cabo
el control de los eventos del sistema.
>En Windows, las ventanas solicitan un puntero a una función en C, que se
>suele denominar "callback", que significa que es una función que será
>llamada desde Windows, para notificarle de los distintos eventos que van
>ocurriendo
En el siguiente paso, nos vamos de la mano al C, donde se rellena una
estructura llamada WNDCLASS.
Dicha estructura se llena con los valores necesarios, MAS una cosa muy
importante en uno de sus miembros :
wndclass.lpfnWndProc = WndProc;
Lo que hace eso es decirle que funcion será la encargada de procesar los
mensajes para todas los controles
en base a esa clase de ventana.
Como bien has dicho antes, el puntero de la llamada a la funcion 'WndProc'
sera:
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM
lParam)
La cual nos informa la 'ventana' que a producido el evento, hWnd, que evento
se a producido , message, y
dos parametros mas.
Hasta aqui, creo que todo es correcto, pero aqui si que puede diferir en la
forma en que devolver dichos
parametros a Harbour, el famoso method HandleEvent() de Fivewin.
( Si me equivoco en algun punto, por favor, rectificarme... )
Lógicamente, de alguna manera debemos de informar a Harbour de lo que esta
ocurriendo, sino,
no serviria de mucho, porque si tenemos que gestionar los eventos desde C,
para que quiero el Harbour ? ;-)
Dentro de Wndproc, y he aqui lo que puede diferenciar a los diferentes GUI
es como tratar esto :
( Esto me lo enseño Jose Gimenez e Ignacio Ortiz , sobre una pregunta al
respecto )
PHB_DYNS pDynSym;
pDynSym = hb_dynsymFind( "HandleEvent" ); // Busca una funcion llamada
HandleEvent
hb_vmPushSymbol( pDynSym->pSymbol ); // Mete en la pila el simbolo a la
que me voy a ir
hb_vmPushNil();
hb_vmPushLong( ( LONG ) hWnd ); // mete el hWnd
hb_vmPushLong( message ); // el message
hb_vmPushLong( wParam ); //
hb_vmPushLong( lParam ); //
hb_vmDo( 4 ); // Llama a la funcion
HandeEvent en Harbour y le pasas los cuatros parametros
// No estoy seguro, pero creo que esta linea se ejecutara, cuando la func
HandleEvent retorne.
return DefWindowProc( ( HWND ) hWnd, message, wParam, lParam ); //
procesa todos los mensajes que no se tienen en cuenta
Básicamente, consiste en algo parecido.
Claro esta, que en harbour habria que crear un mecanismo de control para
determinar a traves del objeto:hWnd que sea igual
a hWnd, y saltar a su method HandleEvent. Vamos, vamos a ver nuestra
function HandleEvent de harbour:
// Imaginamos que todos los controles estan contenidos en una array llamado
aControls
Function HandleEvent( hWnd, nMsg, nParam1, nParam2 ) // Aqui vienen a parar
los mensajes de Windows
local nPos := AScan( aControls, { | oControl | oControl:hWnd == hWnd } )
local nReturn := 0
if nPos != 0 // Hey!! Se encontro
nReturn := aControl[ nPos ]:HandleEvent( nMsg, nParam1, nParam2 )
endif
Return nReturn
Veamos, veamos, si matamos la aplicacion, al final de todo llegara este
method, del objeto en cuestion,
con el mensaje VM_DESTROY
METHOD HandleEvent( nMsg, nParam1, nParam2 ) CLASS MICLASSE
do case
case nMsg == WM_DESTROY
? "Que nos morimos"
PostQuitMessage( 0 ) // Introduce en la cola de mensajes
"terminar", WM_QUIT, y termina ejecucion del programa.
return 0
endcase
return nil
Esto, que es una estupidez, si no te lo explican, creo que muy pocos de
aqui, son capaces por si mismo de haber
llegado a esta conclusion, o al menos entender 'el como se hace'.
Creo que no me equivocado mucho, si no, puedes corregirme en algo.
>En Harbour no hay problema en hacer eso ya que todo su API es código
abierto
>y se han publicado ejemplos al respecto.
Creo, que si estoy en lo cierto, mi explicacion es mejor para entender el
mecanismo, que cualquier
codigo fuente que halla, eso hablando de personas que no tenemos 'mucho'
nivel de conomientos.
Y si, estoy de acuerdo contigo, en que con el codigo fuente de ejemplos, hay
gente que a realizado sus GUIs,
gracias en parte a tu trabajo sobre harbour, pero dime.. ¿ Cuantos...? se
cuenta con los dedos de la mano,
y yo creo que eso solamente se debe a la ignorancia de la gente, aparte de
otros aspectos, claro esta. ;-)
// ---- End ------
A su vez , Antonio, me hizo una pequeña correción:
Totalmente correcta tu explicación. Tan sólo una observación: Solo se
llamará a DefWindowProc() cuando tu no proceses el evento desde PRG.
Asi que espero con estos explicaciones tengais ahora una mejor vision de lo que
ocurre dentro de todo tu codigo, aunque quizas no os sirva de nada a la practica, el simple hecho de tener el conocimiento de como suceden las cosas,
os haga un pelin mas y mejor informados.
Saludos.
¿ No sientes curiosidad de como es posible que usando una libreria
sea posible transformar Harbour en una GUI usando distintas API graficas,
como Win32 , GTK+, etc... como Fivewin, Xailer, etc...?
Yo no me considero ningún experto, faltaria más, pero si soy una persona
al menos saber como funciona el invento.
Si os fijais, nadie dice nada, no hay documentos a nivel compresible
a los 'profanos' que nos pemita 'saber el como', y siempre se suele
decir : Mira el código fuente!
Eso no es suficiente!!.
Por mucho código fuente que tengas, hay cosas, que si no son explicadas,
nunca nos enteraremos de nada.
Bien, estoy ahora en ese etapa en que no estoy satisfecho con lo que se,
necesito más, como la droga jejeje, y quiero saber realmente como funciona
y el porque.
Acabo de comprender una de las cosas que me tenian con la mosca detrás de la
oreja, y es saber el punto de entrada que permite usar el WinApi
de Win32 a Harbour.
Jajaja, ahora me falta comprender como entrar en el bucle de eventos...
umm, el cuento de nunca acabar...
Ahora solamente me queda reproducirlo en ejemplos de codigo, pero como
estoy teorizando, de momento no voy a escribir nada hasta que por lo menos
sepa un poco más del tema, ya que mi idea no es hacerlo bajo el api Win32,
sino bajo GTK+ o mas concretamente, haciendo uso de Gnome.
Si alguien le interesa el saber porque sobre Gnome, ya posteare otra entrada
explicando porque.
Además, hay múltiples maneras de hacerlo, tantas como GUI existan y por cada GUI, distintas implementaciones, según a gusto del programador.
Espero que con esta reflexion, alguien le de tambien por pensar en ello.
¿ Y tú, sabes ya como se produce 'el punto de entrada' ?
Saludos.
Para todos aquellos que no lo sepan, Jose Alfonso y yo mismo, hemos habilitado un
CVS con Free Software para todos aquellos que quieran estar a la ultima en cuestion de codigo para xBase.
Hace tiempo que la comunidad xBase cada dia se esta dividiendo, y cada dia más rapido de lo que nos gustaria.
Siempre hemos podido acceder/actualizar parte de nuestro codigo con nuevas revisiones de clases y/o funciones que los distintos autores nos han brindado a usar y compartir entre todos.
Pero, tiempo atras , estamos viendo como sitios tan útiles como :
Fivewin.info o Dbwide estan cada vez mas desfasados al mantenimiento de dichas Webs.
Y... eso es un problema para nosotros, pues estamos condenados a fracasar en intentar poseer las múltiples mejoras que podrían tener las clases o funciones tan útiles que poseemos.
Entre las múltiples causas de porque ocurre esto, creo que la principal es la falta de tiempo, tiempo que los webmasters, por eso del amor al arte, recordad que es un servicio gratuito, no disponen en ofrecernos lo que la gente les envia para su colocacion en sus webs.
Reflexionando sobre el tema, la unica solución fue montar un sistema en que todos podamos contribuir con nuestros tiempo/esfuerzo en colaborar y disponer de un sistema donde podamos tener lo ultimo conocido.
Es asi, como Jose Alfonso Suerez, http:www.chochurro.com y yo mismo decidimos crear un CVS público para programadores de xBase.
A pesar de hallar cierta resistencia por diversos motivos, nuestro proyecto en común comenzo a rodar, siendo más grande los beneficios que las penas..
( Puede hallar mas informacion sobre dichos temas en :
Servidor de News en los foros de spanish, buscar por remitente Thefull )
Para poder usar el CVS, aqui teneis los parámetros para tu 'cliente CVS' :
Protocol: pserver
Server: 80.59.9.216
Repositorio: /xbase
Module: xbase
User Name: cvsuser
password:paquito ( Si te lo preguntase al hacer el checkout, le sueltas este )
Si lo tuyo es una completa ignorancia en el uso del CVS,
sigue las instrucciones que te dictan ahi para el cliente CVS, esta bien explicado.
http://www.cbati.com/harbour/harboursp/tools_sp.html
Saludos.
En una nueva era...
Hace tiempo quise meterme en montar un weblog, haber ahora si lo consigo...