GX Program Structure
Part 1: Set the header information
Every GXC begins with a NAME, VERSION and DESCRIPTION. In addition to being useful for source control, these parameters are reported by the VIEWGX program. Note that multi-line text is supported (see the DESCRIPTION statement.). Parameters residing in the Project Parameter Block are explained as they are used and/or modified. As in normal C, “//” indicates the start of a comment, which is ignored during compilation.
//==================================================================== NAME = "Copy one channel to another" VERSION = "v1.01.00 Copyright Geosoft Inc. 1999" DESCRIPTION = " Copies one channel to another. If the new channel does not exist, it will be created with the same definition as the original channel. The channel data can be decimated during the copy. Parameters: COPY.FROM - Original channel .TO - Destination channel .DECIMATE - Decimation factor, default 1 .FIDSTART - New fiducial start, default is current start. .FIDINCR - New fiducial increment, default is current increment. "
Part 2: Include the GX resources
If your GX interacts with the user with a dialog defined in a resource file you will need to compile the resource file (copy.grc
in this example, see below). Compiling a resource file will create a Geosoft Resource “GR” file, and a set of resource identifiers a Geosoft Resource Header “GRH” file. Add these next:
//==================================================================== // RESOURCES //==================================================================== RESOURCE = "copy.gr" #include "copy.grh"
For reference, the Resource file copy.grc
is:
// // COPY.GRC //----------------------------------------------------------------------------- RESOURCE,FORM,COPYForm,"Copy a channel",-1 LEDIT,,,16,"Copy FROM",R,FORCE,,CHAN LEDIT,,,16,"TO",R,,,CHAN EDIT,,,16,"Decimation factor",,INT,1 EDIT,,,16,"New fiducial start",,REAL EDIT,,,16,"New fiducial increment",,REAL EBUT,&OK,0 EBUT,&Cancel,1,CANCEL HBUT,&Help,help RESOURCE,LIST,CHAN RESOURCE,HELP,help,nogx.hlp
Part 3: Include GX Function Header files
The GX API is described as function prototypes in GXH files. The “catch-all” header all.gxh includes all the regular, non-mapping Geosoft function prototypes. Constants defined by the #define
pragma are also included. Refer to the .../gx/include
folder which contains all function sets organized by name.
//==================================================================== // INCLUDE //==================================================================== #include <all.gxh> // system
Part 4: Declare variables
As a C language, all variables must be declared by type before they are used. This include all object handles, as well as the int, real and string types. Though not required, it is common practice to declare variables in the following order: handles, integers, reals, strings.
//==================================================================== // VARIABLES //==================================================================== EDB EData; // Database handle DB Data; // Database handle DB_SYMB InCh; // Channel Handle DB_SYMB OutCh; // Channel Handle DB_SYMB Line; // Line Handle DGW Diag; // Dialogue handle LST List; // List handle int i; // Utility int iN; // Decimation factor int iLines; // Number of Lines Processed int iTotLines; // Total Number of Lines to Process real rFidStart; // Fid start real rFidIncr; // Fid increment real rNewStart; // New fid start real rNewIncr; // New fid increment string(50) sInCh; // Channel Names string(50) sOutCh; // Channel Names string(32) sTemp; // Temp string string(60) sLabel; // Label for progress bar
Part 5: Open the main code block
This includes the remainder of the source file. The code is enclosed in a pair of curly brackets.
//==================================================================== // CODE //==================================================================== {
Part 6: Initial setup
This usually involves getting the current database or map, and setting up information required later for user dialogs. Some GXs may also recover parameters from a control or initialization file here, and set various default values.
// --- Get database --- EData = Current_EDB(); Data = Lock_EDB(EData);
Part 7: Perform interactive processes
Most GX's support scripting and need to check if they are running interactively or in a script. If running interactively a dialog can be opened to get user input and handle any interactive logic. This generally involves creating, initializing, displaying, then interrogating a dialog object for information modifiable by a user.
To support scripting, variables can be initialized from and loaded back into the Project Parameter Block, using the SetInfoSYS_DGW and GetInfoSYS_DGW functions.
// --- Are we running interactively ? --- if (iInteractive_SYS()) { // --- Create the Dialogue --- Diag = Create_DGW("COPYForm"); // name matches the dialog name in copy.grc // --- Set up lists --- List = GetList_DGW(Diag,_COPYFORM_0); SymbLST_DB(Data,List,DB_SYMB_CHAN); Sort_LST(List,0,0); List = GetList_DGW(Diag,_COPYFORM_1); SymbLST_DB(Data,List,DB_SYMB_CHAN); Sort_LST(List,0,0); // --- Initialize to last settings from the Project Parameters --- SetInfoSYS_DGW(Diag,_COPYFORM_0,DGW_TEXT,"COPY","FROM"); SetInfoSYS_DGW(Diag,_COPYFORM_1,DGW_TEXT,"COPY","TO"); SetInfoSYS_DGW(Diag,_COPYFORM_2,DGW_TEXT,"COPY","DECIMATE"); SetInfoSYS_DGW(Diag,_COPYFORM_3,DGW_TEXT,"COPY","FIDSTART"); SetInfoSYS_DGW(Diag,_COPYFORM_4,DGW_TEXT,"COPY","FIDINCR"); // --- Display the Dialogue --- i = iRunDialogue_DGW(Diag); if (i != 0) Cancel_SYS(); // The user cancelled // --- Put user input back into Project Parameters --- GetInfoSYS_DGW(Diag,_COPYFORM_0,DGW_TEXT,"COPY","FROM"); GetInfoSYS_DGW(Diag,_COPYFORM_1,DGW_TEXT,"COPY","TO"); GetInfoSYS_DGW(Diag,_COPYFORM_2,DGW_TEXT,"COPY","DECIMATE"); GetInfoSYS_DGW(Diag,_COPYFORM_3,DGW_TEXT,"COPY","FIDSTART"); GetInfoSYS_DGW(Diag,_COPYFORM_4,DGW_TEXT,"COPY","FIDINCR"); // --- Destroy the Dialogue --- Destroy_DGW(Diag); }
Part 8: Retrieve and verify parameters
Parameters are retrieved from the Project Parameter Block and verified. Verification ensures that the data exists, and that it falls within acceptable limits for the process that must be performed.
// --- Get Parameters from Project Parameter Block --- GetString_SYS("COPY","FROM",sInCh); GetString_SYS("COPY","TO",sOutCh); iN = GetInt_SYS("COPY","DECIMATE"); rNewStart = GetReal_SYS("COPY","FIDSTART"); rNewIncr = GetReal_SYS("COPY","FIDINCR"); // --- Verify parameters --- if (iN==iDUMMY) iN = 1; if (iN<= 0) Abort_SYS("Decimation factor must be > 0."); if ((rNewIncr!=rDUMMY)&&(rNewIncr<=0.0)) Abort_SYS("Fid increment must be > 0.");
Part 9: Prepare to process data
Here we create handles to channels we will be using in the processing loop. We also initialize counter variables for reporting progress.
// --- Does the Input Channel Exist ? --- if (!iExistChan_DB(Data,sInCh)) Abort_SYS(_("channel does not exist.")); InCh = FindChan_DB(Data,sInCh); // --- Does the Output Channel Exist ? --- if (!iExistChan_DB(Data,sOutCh)) { OutCh = DupSymb_DB(Data,InCh,sOutCh); // Create it UnLockSymb_DB(Data,OutCh); } else OutCh = FindChan_DB(Data,sOutCh); // --- Lock the channel symbols --- if (InCh != OutCh) LockSymb_DB(Data,InCh,DB_LOCK_READONLY,DB_WAIT_INFINITY); LockSymb_DB(Data,OutCh,DB_LOCK_READWRITE,DB_WAIT_INFINITY); // --- Prepare to do the work --- iLines = 0; iTotLines = iCountSelLines_DB(Data); Progress_SYS(1);
Part 10: Process the data
Databases are normally processed line-by-line starting with the first selected line.
// --- Go through all selected Lines --- ProgName_SYS("",1); Line = FirstSelLine_DB(Data); while (iIsLineValid_DB(Data,Line)) { // --- Update the Progress Bar --- LockSymb_DB(Data,Line,DB_LOCK_READONLY,DB_WAIT_INFINITY); GetSymbName_DB(Data,Line,sLine); UnLockSymb_DB(Data,Line); Printf_STR(sProg1, sizeof(sProg1), _("Copying %s to %s: Line %s"), sInCh, sOutCh, sLine); ProgName_SYS(sProg1,0); ProgUpdateL_SYS(iLines,iTotLines); // --- Copy/Decimate --- Decimate_DU(Data,Line,InCh,OutCh,iN); // --- Correct the Fiducial Start --- if ((rNewIncr!=rDUMMY)||(rNewStart!=rDUMMY)) { if (rNewStart==rDUMMY) rFidStart = rGetFidStart_DB(Data,Line,InCh); else rFidStart = rNewStart; if (rNewIncr==rDUMMY) rFidIncr = rGetFidIncr_DB(Data,Line,InCh); else rFidIncr = rNewIncr; SetFid_DB(Data,Line,OutCh,rFidStart,rFidIncr); } // --- Advance to Next Line --- Line = NextSelLine_DB(Data, Line ); iLines++; }
Part 11: Clean up.
A "Maker" is a record of the GX that made a channel so that a user can remake a channel later, or see the details of how a channel was made.
We then destroy any created objects which should not exist once the GX terminates. Terminating a GX will automatically destroy all objects, but it is considered good practice to explicitly clean-up resources.
// --- Add maker --- EasyMakerSymb_DB(Data,OutCh, _("Copy channel"),"COPY;"); // --- Unlock the Channel Symbol --- if (InCh != OutCh) UnLockSymb_DB(Data,InCh); UnLockSymb_DB(Data,OutCh); // --- done --- Progress_SYS(0); UnLock_EDB(EData); // --- Release the database --- // --- display the new channel --- LoadChan_EDB( EData, sOutCh ); }