Ask Reuben

Overloading FGLLDPATH

How can I overwrite some basic Genero functionality?

I have mentioned this technique in a few articles and I felt it deserved an article of its own.  I call it “Overloading FGLLDPATH” but the name is a bit of misnomer as it does not involve changing FGLLDPATH.

First of all, note the following in the definition of FGLLDPATH.

The directories are searched in the following order:

  1. The current working directory.
  2. The directory where the program file resides (the .42m module containing MAIN or the .42r program file).
  3. A path defined in the FGLLDPATH environment variable.
  4. The $FGLDIR/lib directory.

The last place the Genero runtime searches for program modules (.42m files) is $FGLDIR/lib.  This is where standard Genero functionality resides.  If in FGLLDPATH there is a .42m file with the same file name as one that is in $FGLDIR/lib, it will be found and used instead of the one in $FGLDIR/lib.

The same principal applies for the files that are found using  FGLRESOURCEPATH as well …

When the specified resource file is not an absolute path, the runtime system searches in directories in the following order:

  1. The current working directory.
  2. A path defined in the FGLRESOURCEPATH (or DBPATH) environment variable.
  3. The $FGLDIR/lib directory.
  4. The directory where the program file resides (the .42m module containing MAIN or the .42r program file).

if in FGLRESOURCEPATH there is a resource file (.42f, .iem, .4ad, .4st, .4rm, .4tb, .4tm, 42s) that has the same name as one that is in $FGLDIR/lib, it will be found and used instead of the one in $FGLDIR/lib.

Where a file in $FGLDIR/lib requires a source file (.42m, .42f), you will find the relevant source file in $FGLDIR/src.

You can potentially utilise these look up rules to override some of the files shipped in $FGLDIR/lib.  For modules and form files, take a copy of the source file, place it in your source control, modify it, and place the compiled file alongside the rest of your compiled objects in a directory referenced by FGLLDPATH, FGLRESOURCEPATH as appropriate for the type of file.  Then when the runtime looks for FGLDIR/lib/filename, it will find the same filename earlier somewhere in FGLLDPATH/FGLRESOURCEPATH.

Once you go down this path, the responsibility is on you …

  • with every upgrade to review what you have done and if necessary patch any changes made in the files shipped in $FGLDIR/src to your equivalent file(s) and recompile.
  • when submitting support cases, be aware of this customisation and to check issues using the standard files.

My recommendation is to keep this sort of activity to a minimum but I can certainly understand you wanting to make sure that your application is consistent with its user interface and terminology.

A good example is the built-in find window.  At present the source file for FGLDIR/src/fglfind.per is the following …


# Property of Four Js*
# (c) Copyright Four Js 1995, 2023. All Rights Reserved.
# * Trademark of Four Js Development Tools Europe Ltd
#   in the United States and elsewhere

LAYOUT(SPACING=NORMAL, STYLE="dialog4", TEXT=%"fgl.findDialog.title")
GRID
{
[l1  |s                                                  ]
 [l2 |c                    ]
     [i             ]
     [w             ]
}
END
ATTRIBUTES
LABEL l1: TEXT=%"fgl.findDialog.lbFind", JUSTIFY=RIGHT;
EDIT s = FORMONLY.pattern;
LABEL l2: TEXT=%"fgl.findDialog.lbIn", JUSTIFY=RIGHT;
COMBOBOX c = FORMONLY.fieldId, NOT NULL;
CHECKBOX i = FORMONLY.ignoreCase, TEXT = %"fgl.findDialog.cbIgnoreCase", NOT NULL;
CHECKBOX w = FORMONLY.wrapAround, TEXT = %"fgl.findDialog.cbWrapAround", NOT NULL;

… this file might have a few things that might not be consistent with your user interface.  Copy FGLDIR/src/fglfind.per to your working area and make some modifications so that it is consistent with the rest of your user interface. In this example I have …

  • left aligned the Title LABELs and removed the use of colon as a delimiter.
  • added use of PLACEHOLDER and SCROLL to the pattern field
  • use title LABELs for the CHECKBOX widgets rather than the TEXT attribute so that the title appears same place as other widgets
  • used a different STYLE attribute value so that the OK/Cancel button appeared on right (your dialog style might differ from mine)
  • changed text by not using Localised Strings (in reality I would keep the Localised String token and amend the Localised String value in the .str)

… so that the code is now …


# Property of Four Js*
# (c) Copyright Four Js 1995, 2023. All Rights Reserved.
# * Trademark of Four Js Development Tools Europe Ltd
#   in the United States and elsewhere

LAYOUT(SPACING=NORMAL, STYLE="dialog", TEXT="Find in Array")
GRID
{
[l1  |s                    ]
[l2  |c                    ]
[l3  |i                    ]
[l4  |w                    ]
}
END
ATTRIBUTES
LABEL l1: TEXT="Find", JUSTIFY=LEFT;
LABEL l2: TEXT="In Column", JUSTIFY=LEFT;
LABEL l3: TEXT="Ignore Case", JUSTIFY=LEFT;
LABEL l4: TEXT="Wrap Around", JUSTIFY=LEFT;

EDIT     s = FORMONLY.pattern, SCROLL, PLACEHOLDER="Enter expression to find";
COMBOBOX c = FORMONLY.fieldId, NOT NULL;
CHECKBOX i = FORMONLY.ignoreCase, TEXT = " ", NOT NULL;
CHECKBOX w = FORMONLY.wrapAround, TEXT = " ", NOT NULL;

… compile it and place the resultant fglfind.42f in with the rest of your form files.

The before and after of the fglfind window is as per these screenshots …

How is this working? when the built-in fglfind looks for fglfind.42f, it is finding your fglfind.42f higher up the FGLRESOURCEPATH search hierarchy than our one in $FGLDIR/lib.

Wether the new appearance is better or worse, the beauty is in the eye of the beholder.  What is important though is that this window can match the rest of the windows in your application and your end-user has a consistent User Experience.

Note that some things can’t be changed, for instance in this example I have to keep the field names as referenced by the INPUT statement in fglfind() the same.

To get an understanding of what supplied functionality can be changed like this, some things you can do

  • note the files in FGLDIR/lib and where applicable note the source that is in FGLDIR/src.
  • add FGLDIR/src to the FGLSOURCEPATH variable and when using the debugger, break in a form/dialog that you did not write and note the source file loaded.
  • note the files in $FGLDIR/webcomponents.  You can create your own webcomponents using these as a starting point.  Note the search path for web components implicitly looks in $FGLDIR/webcomponents first  so you would need to rename your webcomponent to go down this path.
  • note the files in $FGLDIR/web_utilities/services.  You can use these as starting points for your own equivalents
  • modify predefined localization strings
  • modify runtime system messages.

As I commented above, and I’ll finish by reemphasising.  Do these sorts of activities in a controlled and disciplined manner.