
                      _____  _             _
                     |  __ \| |           (_)
                     | |__) | |_   _  __ _ _ _ __  ___
                     |  ___/| | | | |/ _` | | '_ \/ __|
                     | |    | | |_| | (_| | | | | \__ \
                     |_|    |_|\__,_|\__, |_|_| |_|___/
                                      __/ |
                                     |___/


                            por Shawn Hargreaves




Introduccin
------------

   Es muy sencillo extender el grabber y otras utilidades de ficheros de
   datos escribiendo nuevos mdulos plugin. Estos pueden aadir soporte para
   tipos de objetos totalmente nuevos, o pueden aadir algunas rutinas
   funcionales importar/exportar para hacer que un tipo existente pueda
   trabajar con un rango ms amplio de formatos de fichero. Los plugins
   tambin son capaces de enganchar el sistema de men de grabber, aadiendo
   nuevas funciones a un men existente o creado todo un nuevo men de
   opciones propias.

   La mayora de las funciones estndar estn implementadas de hecho como
   mdulos plugin. Pruebe renombrar todos los ficheros .inc del directorio
   tools/plugins a otra extensin, y recompile grabber: descubrir que
   faltan algunas opciones de los mens, y ya no podr reconocer otra cosa
   que no sean los objetos bsicos de fichero y datos binarios!

   Este fichero no es un manual completo sobre la arquitectura plugin. Asume
   que ya tiene una buena idea sobre cmo funcionan los ficheros de datos y
   el sistema GUI, y que no tiene miedo de leer el cdigo fuente y aprender
   qu es lo que hace. Su mejor apuesta es mirar el fichero datedit.h para
   ver qu funciones estn disponibles, y usar alguno de los plugins
   existentes como base del suyo. Usando este fichero junto con el cdigo
   fuente debera ponerle en buen camino, pero como siempre, puede pedir
   ayuda si se queda atascado...



Lo Bsico
---------

   Un plugin es implementado como un conjunto de ficheros que son copiados
   en el directorio tools/plugins, y sern enlazados automticamente con las
   utilidades grabber, dat y otras. Para instalar un plugin, slo debe
   copiarlo al directorio de plugins y reconstruir Allegro.

   Como mnimo, debe crear un fichero .c de cdigo fuente y un fichero .inc
   de configuracin. El fichero .inc ser incluido directamente en
   datedit.c, y ser ejecutado una vez cuando el sistema se inicialice.
   Desde ese momento puede llamar cualquier rutina que necesite para activar
   su plugin, que normalmente incluir como mnimo una de las funciones
   datedit_register_*().

   Si un plugin hace uso de bibliotecas externas, puede proveer un fichero
   de comando .scr, que contenga las opciones adicionales de enlace que
   requiera su plugin.

   No hay restricciones sobre qu nombres puede dar a estos ficheros aparte
   de la extensin, pero para minimizar el peligro de conflictos de nombre,
   le recomiendo que use mi convenio en llamarlos dat{tipo}.*, donde {tipo}
   es la identificacin ID del tipo de objeto implementado por el plugin.

   Hay tres tipos de interfaz de plugin, que pueden ser usados en conjunto o
   aisladamente. Los plugins de objeto aaden nuevos tipos de objeto a los
   ficheros de datos, y proveen todas las funciones necesarias para
   manipular y visualizar los datos. Los plugins Importar/Exportar le dan la
   posibilidad de leer y escribir datos de tipos de ficheros externos, y
   pueden ser usados para importar y exportar funciones para tanto objetos
   predefinidos como propios. Finalmente, los plugins de men responden a
   acciones del usuario con la interfaz del grabber, y pueden aadirse al
   sistema de men existente o aadir opciones propias completamente nuevas.



Plugins Objeto
--------------

   Un plugin objeto es instalado llamando la funcin:

      void datedit_register_object(DATEDIT_OBJECT_INFO *info);

   Estos plugins estn definidos por una estructura que es:

      typedef struct DATEDIT_OBJECT_INFO
      {
         int type;
         char *desc;
         void (*get_desc)(DATAFILE *dat, char *s);
         void *(*makenew)(long *size);
         void (*save)(DATAFILE *dat, ..., PACKFILE *f);
         void (*plot)(DATAFILE *dat, int x, int y);
         int (*dclick)(DATAFILE *dat);
         void (*dat2s)(DATAFILE *dat, char *name, FILE *file, FILE *header);
      } DATEDIT_OBJECT_INFO;

   Los plugins objeto aaden soporte para nuevos tipos de objeto, y no tiene
   sentido instalar ms de uno de estos para la misma identificacin ID (si
   lo hace, el segundo plugin simplemente ser ignorado).

   Los campos de la estructura son:

   'type'
      El tipo ID de objeto, tal y como lo produce la macro DAT_ID().

   'desc'
      Descripcin ASCII de este tipo de objeto.

   get_desc()
      Opcional, Rellene 's' con una descripcin del objeto. Implementar esta
      funcin permite ver una descripcin ms detallada (ejemplo: "bitmap de
      32x32x8"). Si lo deja a NULL, el campo 'desc' ser visualizado,

   makenew()
      Crea y devuelve un puntero al nuevo objeto de este tipo, y si el
      objeto lo va a usar, pone en 'size' el tamao del objeto en bytes.

   save()
      Salva el objeto en un fichero de datos de Allegro. Esto requiere
      bastantes parmetros, pero puede ignorarlos excepto los valores 'dat'
      y 'f': los otros slo son necesarios para ficheros de datos anidados.

   plot()
      Opcional. Dibuja el objeto en la pantalla del grabber en la posicin
      especificada. Debe asegurarse de que esta rutina funcionar en todas
      las resoluciones y profundidades de color posibles!

   dclick()
      Opcional. Llamado cuando el usuario hace doble click en el objeto
      dentro del grabber.

   dat2s()
      Opcional. Usado por la utilidad dat2s para convertir el objeto en
      cdigo ensamblador. Si no implementa esto, su tipo de objeto no ser
      soportado por dat2s.

   Se habr dado cuenta que esta interfaz no provee ningn soporte para
   cargar estos objetos desde ficheros de datos, o para leer/escribir
   formatos de ficheros externos. Esto es porque la carga de ficheros de
   datos es controlada internamente por el ncleo de la biblioteca Allegro
   (debera usar register_datafile_object() para instalar su cargador), y el
   importar/exportar es controlado por un tipo diferente de plugin (lea ms
   abajo).

   La interfaz 'datsample_info' de datsamp.c es un buen ejemplo bsico de un
   plugin objeto.



Plugins Importar/Exportar
-------------------------

   Un plugin importar/exportar es instalado llamando la funcin:

      void datedit_register_grabber(DATEDIT_GRABBER_INFO *info);

   Estos plugins estn definidos por una estructura que es:

      typedef struct DATEDIT_GRABBER_INFO
         {
            int type;
            char *grab_ext;
            char *export_ext;
            void *(*grab)(char *filename, long *size, ...);
            int (*export)(DATAFILE *dat, char *filename);
         } DATEDIT_GRABBER_INFO;

   Los plugins importar/exportar aaden soporte de fichero a tipos de
   objetos existentes. Normalmente necesitar uno de estos por cada plugin
   objeto que instale, pero puede usarlos para extender tipos de objetos
   predefinidos. No hay lmite sobre cuntos plugins importar/exportar
   pueden funcionar con un solo tipo de objeto, o cuntos formatos de
   fichero pueden ser soportados por un solo plugin.

   Los campos de la estructura son:

   'type'
      El tipo ID de objeto, tal y como lo produce la macro DAT_ID().

   'grab_ext'
      Lista de extensiones de fichero que son soportadas al leer datos,
      separadas por punto y coma. Puede dejarse vaco si este plugin slo
      soporta funciones para exportar.

   'export_ext'
      Lista de extensiones de fichero que son soportadas al salvar datos,
      separadas por punto y coma. Puede dejarse vaco si este plugin slo
      soporta funciones para importar.

   grab()
      Lee un nuevo objeto del fichero mencionado, devolviendo un puntero a
      l. Si este tipo de objeto lo requiere, pone en 'size' el tamao del
      objeto en bytes.

   export()
      Salva un objeto en el fichero mencionado.

   La interfaz 'datfont_grabber' de datfont.c es un buen ejemplo de un
   plugin importar/exportar que soporta diferentes tipos de formato.



Plugins de Men
---------------

   Un plugin de men es instalado llamando a la funcin:

      void datedit_register_menu(DATEDIT_MENU_INFO *info);

   Estos plugins estn definidos por una estructura que es:

      typedef struct DATEDIT_MENU_INFO
      {
         MENU *menu;
         int (*query)(int popup);
         int flags;
         int key;
      } DATEDIT_MENU_INFO;

   Los plugins de men estn basados en la estructura de mens GUI de
   Allegro. Si instala un plugin para una opcin de men que ya existe,
   enganchar el men existente, pero tambin puede aadir nuevas opciones
   especificando una nueva cadena de texto para el men.

   Los campos de la estructura son:

   'men'
      Apunta a una estructura de men de Allegro para esta opcin. Tenga en
      cuenta que esto slo es un tem de men, no todo el array de entradas.
      Los campos flags y dp de la estructura sern sobreescritos por el
      grabber, pero debe rellenar el texto de men con, y al menos el
      puntero a funcin proc con su rutina de accin (para comandos simples
      del men como la funcin "grab"), o el campo hijo con un puntero a un
      men anidado (para estructuras jerrquicas como el men "new").

   query()
      Opcional. Si no es NULL, esta rutina ser llamada para comprobar que
      la opcin de men del plugin es utilizable en la situacin actual. Para
      mens desplegables de persiana normales, el parmetro 'popup' ser
      FALSE, y tendr la ocasin de devolver TRUE, en cuyo caso su comando
      ser usado, o FALSE, en cuyo caso el procedimiento por defecto ser
      llevado a cabo (esto le permite al plugin tomar control sobre comandos
      estndar como "grab", pero ignorarlos cuando cualquier otra cosa que
      no sea su tipo de objeto sea seleccionada, para que el comando grab
      normal siga funcionando con otros tipos de objeto. Para mens
      emergentes (botn derecho del ratn), esta rutina ser llamada
      inmediatamente antes de que el men sea visualizado, con el parmetro
      'popup' puesto a TRUE. Si devuelve FALSE a esta llamada, su comando no
      ser incluido en el men emergente (as es como cosas como 'autocrop'
      son capaces de aparecer slo al pinchar con el botn derecho en
      objetos tipo bitmap).

   'flags'
      Indica dnde en el sistema de men quiere que su comando sea aadido.
      Esto es un campo de bits que contiene cualquier combinacin de los
      siguientes valores:

         DATEDIT_MENU_FILE    - se aade al men File
         DATEDIT_MENU_OBJECT  - se aade al men Object
         DATEDIT_MENU_HELP    - se aade al men Help
         DATEDIT_MENU_POPUP   - se incluye en los mens emergentes
         DATEDIT_MENU_TOP     - nueva entrada en la barra de men

   'key'
      Si no es cero, ser el cdigo ASCII del atajo de teclado para usar el
      comando. Por favor, tenga cuidado al usar esto, porque si varios
      plugins quieren enganchar el mismo atajo, obviamente slo un de ellos
      lo conseguir :-)

   La interfaz 'datworms_menu' de datworms.c es un buen ejemplo de cmo
   aadir un nuevo comando de men, y 'datpal_grabber_menu' de datpal.c
   ensea cmo enganchar un comando existente (aade una funcin propia para
   que las paletas puedan ser recogidas de un bitmap ledo previamente, en
   vez de leerlas directamente desde un fichero de disco).



Miscelnea
----------

   Tenga en cuenta que estos plugins son usados por las utilidades dat,
   dat2s, pat2dat y grabber, por lo que no puede asumir nada sobre la
   configuracin del sistema mientras su cdigo es ejecutado. Los mens de
   comando y las funciones ver/doble-click sern usadas slo en modo grfico
   (pero en cualquier resolucin y profundidad de color), y las otras
   funciones tambin pueden ser llamadas desde un entorno grfico o en modo
   texto.

   Para ensear mensajes, errores, pedir un dato al usuario, etc, use las
   funciones datedit_msg(), datedit_error(), y datedit_ask(). Estas son
   implementadas en modo texto como llamadas a printf(), y son cajas de
   alerta en el grabber, por lo que funcionarn en cualquier situacin.

   Hay montones de funciones de ayuda tiles en datedit.h. Quizs lo ms
   importante es que cuando implemente comandos de men,
   grabber_single_selection() devuelve un puntero al objeto seleccionado
   actualmente (NULL si es una seleccin mltiple), y
   grabber_foreach_selection() itera sobre cada objeto seleccionado, usando
   una funcin callback para permitirle procesar objetos mltiples con el
   mnimo esfuerzo.



Y Finalmente
------------

   Buena suerte!
