Introduction to Seal development

Seal applications and libraries are in the DLX format (Dynamic Link eXchange format), which allows them to exchange data just as applications and ".dll"-files do in Windows 95 etc. This means that the COFF files (Common Object File Format) has to be translated into the DLX format by a converter, "dlxgen.exe". Imagine that we have a file, "hello.c", containing our sourcecode. The code in this file must have a certain structure depending on if it's supposed to be an application (*.exe) or a library (*.dlx). In this introduction we will explain the two structures and show how to use them.



Creating a Seal application

This is a very basic listing of the Seal application structure:

     #include "allegro.h"  
     #include "seal.h"


     app_begin ( void ) {

     } app_end;


"Allegro.h" includes all the graphic functions from Allegro and "seal.h" is the main header of Seal. Both of these files has to be included into EVERY Seal application or library and they are found in the "include" directory of DJGPP. The "app_begin" function is the main function of a Seal application. It replaces the "main()" function in an ordinary C or C++ program. Seal's applications and libraries gets some varaibles from "seal.h". These variables are ap_id, ap_process and ap_args:

     Name:         ap_id

     Description:  Identification of the application. Every running application
                   has it's own ap_id, which is a long pointer to memory, where
                   internal info about application is stored. Use this variable
                   for unloading applications or files with "DLXUnload(ap_id);".
                   "DLXLoad("app.exe");" returns same id that will be set in the
                   "app.exe" application as ap_id.

                   OBS: ONLY ap_id IS GLOBAL FOR ALL APPLICATIONS/LIBRARIES,  
                   OTHER ONES ARE LOCAL FOR ap_begin/lib_begin FUNCTION!



     Name:         ap_process

     Description:  Defines the process of an application. When an application or
                   a library is loaded into memory, the function app_begin (for 
                   applications) is called and ap_process is first set to 
                   AP_ALLOC. Then it's set to AP_INIT and all the following 
                   calls it's set only to AP_INIT if AP_ISOVERLOAD is set to 
                   non-zero (see above). If not this process is repeated for 
                   all application calls. When application is released then 
                   ap_process is set to AP_DONE and at last release is set to 
                   AP_FREE. In each AP_INIT is AP_CALL increased by 1 and in 
                   AP_DONE decreased by 1. In AP_ALLOC this value is ZERO, in 
                   AP_FREE also ZERO.



     Name:         ap_args

     Description:  Defines the arguments of a file. These arguments are placed in 
                   one string devided by space char " " (0x20, 32 in ASCII code).
                   You can get a list of all of these arguments by calling the 
                   function "get_args(ap_args)". See also the sections about the
                   EXE and DLX functions and the LIST object.




Once we have the main function we can create a window for our application:

     t_rect   r = rect_assign(100, 100, 300, 200);
     p_appwin w = appwin_init(malloc(sizeof(t_appwin)), 
                              r,
                              "Hello world",
                              0,
                              ap_id, 
                              NULL);

     OBJECT(desktop)->insert(OBJECT(destop), OBJECT(w));


The rect_assign() function takes the corners of our appwin object (the application window) local to the desktop and assigns them to a rectangle structure, "r". Then appwin_init() initializes the new appwin object, "w", into this new rectangle. It also sets the property name to "Hello world", flags to 0, application id to ap_id and event control function of application to NULL. Now that we have created the window, we insert it into the desktop. "OBJECT(o)" is defined in the "seal.h" file in the section "object.h". When the window is closed, the application is terminated.

Now all together in our hello.c file:

     #include "allegro.h"
     #include "seal.h"
     #include "app.h"    /* We need to include this for using appwin_init(). */


     void my_init_window ( void ) {

           t_rect   r = rect_assign(100, 100, 300, 200);
           p_appwin w = appwin_init(malloc(sizeof(t_appwin)), 
                                    r,
                                    "Hello world", 
                                    0,
                                    ap_id,
                                    NULL);

           OBJECT(desktop)->insert(OBJECT(destop), OBJECT(w));
     };



     app_begin ( void ) {


           if ( ap_process == AP_ALLOC ) {
           } 
           else 

           if ( ap_process == AP_INIT ) {

               AP_SETNUMOFCALLS(1);
		
               my_init_window();      /* Let's show our window! */

           }
           else 

           if ( ap_process == AP_DONE ) {
           }
           else

           if ( ap_process == AP_FREE ) {
           };

     } app_end;




Compiling

So, now that we have a "hello.c" file with our sourcecode we can compile it with DJGPP by typing:
     gcc -c hello.c

This gives us two files; "hello.c" and "hello.o". Now we want to create a Seal executable from this "hello.o" file. This is done by typing:
     dlxgen hello.exe hello.o

Now we finally have a "hello.exe" file. Run it in Seal and you will se our window with the caption "Hello world".




Creating a Seal library

The difference between a Seal application and a library is the structure of the main function. A Seal library creates a table with the functions that will be exported from it and used by other applications. This table is exported by the AP_EXPORTLIB() function in the AP_ALLOC process (only this process is only called once for sure and at the begining of execution). When a library is released, no other application can use their functions or variables. A library can export all type of DJGPP exportable tags.

If you add text to your library or application please use this style of text:
     #ifndef  TXT_HELLOWORLD 
     #define  TXT_HELLOWORLD  INI_TEXT("Hello world")
     #endif

For lower case you should use "strlwr(TXT_HELLOWORLD)". This keeps your application or library language indenpendant in future versions. "INI_TEXT()" will find the phrase "Hello world" that will contains your lenguage name as "Halo welt" in German f.e. It may be in structure "Hello world" = "Halo welt" in file german.lng, but this all in next version. But please, keep compatibility and your applications will be translated automatically.

The structure of a Seal library:

     /* hellolib.c */

     #include "allegro.h"
     #include "seal.h"

     /* We need to include the same files as in an application. */


     void hello_function ( void ) {
     };


     lib_exportlib;


     lib_begin ( void ) {

           if ( ap_process == AP_INIT ) {

                 AP_EXPORTLIB();
           };

     } lib_end;


All the variables as those in an application are supported. "lib_exportlib" is a definition that you can find in "seal.h" (section "DLX.H") and default set functions/ variables to be exported from library to nothing. So no functions or variables are exported from the library. Compile the file in DJGPP:
     gcc -c hellolib.c

You will now get the file "hellolib.o". Now we need to get the functions and variables to export. We do this by typing:
     dlxmake.exe -x hellolib.exp hellolib.o

This gives us a new file called "hellolib.exp" that contains a table of all exportable variables and functions from the library. In this case, it will only contain our "hello_function()" function. If you don't want to export a function or a variable, just preceed its declaration with the static keyword like this:
static void hello_function ( void ) {
};

Now, when we have a "hellolib.exp" file, we must return to our sourcecode file and remove the lib_exportable; definiton and include our "hellolib.exp" file. The final version of our library should look something like this:

     /* hellolib.c */

     #include "allegro.h"
     #include "seal.h"

     /* We need to include the same files as in an application. */


     void hello_function ( void ) {
     };


     /*lib_exportlib;*/
     #include"hellolib.exp"



     lib_begin ( void ) {

          if ( ap_process == AP_INIT ) {

                AP_EXPORTLIB();
          };

     } lib_end;


Compile the library again with DJGPP as above to get a new "hellolib.o" file. Then we create our library out of this one by typing:
     dlxgen.exe hellolib.dlx hellolib.o 

That's it! Add the name of the library to the file "app.set", and it will be loaded automatically every time that Seal is started. Once it is loaded, any other application may use the new "hello_function()" function.