Archive for the ‘Clarion 7’ Category

Automated Import and Export of Applications and Dictionaries

Saturday, February 27th, 2010

Clarion 7.1 added the ability to automatically import and export .App and .Dct files to/from their text representations.  This was primarily added for use with version control systems like Subversion, but developers may also find it useful for automated backup purposes.

With this system any time a dictionary or application is saved it is automatically exported to text.  If you load a dictionary or application and the text file has a newer time-stamp then the binary file, then the text file will be loaded into the binary file.  With this system you can then check in and check out the text representation of your files into your version control system, and the IDE will automate updating the binary files.   Further, if you are using Subversion as your version control system you can see the history of your file via the History tab (shown in the image below) appears at the bottom of the DCT Explorer or Application View.

The History tab displays the version history pulled from your SVN repository.

dcthistory

ClarionCl.exe is also auto import/export enabled.  So if you use another new feature of Clarion 7.1 (Enterprise Edition) to generate an application, the .App and .Dct files will be updated if the timestamp of the text file is newer then the binary file.  This allows you to use automated build tools like CruiseControl.NET to build your Clarion applications.

To enable automated import/export of files go to Tools/Options/General/Binary File auto-export/import.  You will then have a screen similar to the image below.

importexportconfig

The import/export automation does its work on a background thread, so you should not see any impact on your normal work flow.

Update for 7.1

Friday, February 26th, 2010

A new update for 7.1 is now available.  One often requested feature was added; FEATURE:  You can now set (via Tools/Options/General/Projects and Solutions dialog) if new projects should default to release or debug mode.  Several good bug fixes, including a fix for a regression that popped up in build 6813. You can check the complete change log here.

And look for a new Clarion.Net release on this coming Monday!

Template Writing Tips

Friday, February 26th, 2010

This is one of many posts to come with advice and tips about things you should do, and things to avoid, when writing Templates. It is intended to help developers who write templates to validate their templates, and to implement some best practices to ensure the templates they deliver work as expected.

The template language is very strict in its syntax, and blank spaces/lines can have a big impact. Spaces where they are not expected are evil. A blank line in the templates will generate a blank line in the generated code, but where that blank line lands in the generated code depends upon where that blank line is within the template code.

Some areas of a template are not meant to generate code, for example #PROMPTs representing the UI. Some templates, like an Extension template, are not supposed to contain any generated code except within #ATs where the code is inserted into an #EMBED.

If a blank line is found in a template, but in a place that is not correct, like between #PROMPTs, or outside a #AT in an Extension template, the code generator will push that line into the generated code, but because the blank line was in an incorrect location there is no explicit place to insert that blank line, and it will add it at the beginning of the block of generated code. To summarize, blank lines in a template are good, except when they are somewhere they are not supposed to be.

Blank lines intended to make the template code easier to read should be always be replaced with #! in column 1 (or just removed). There isn’t a blank line “statement” in the template language, and the reason for that is so that you don’t not mix template language code, with generated output text. Using something like #!———- is much better than a blank line, better in that it is safer and it is more visual.

Some places where a blank line should not be placed:

In any template between a #PROMPT or any other UI code (#SHEET,#TAB,etc.).
In #EXTENSION templates any blank line outside an #AT/#ENDAT block is incorrect.
In a #UTILITY template any blank line outside the scope of an #OPEN or #CREATE is incorrect.
In any template, any blank line used as a separator between #DECLARE statements or as a separator between any other statement is incorrect.

As a golden rule, if the blank line is not intended to be output to the generated code, then the blank line should be replaced by a #! in column 1, or just removed.

LastChanceHook

Tuesday, February 9th, 2010

Geoff Thomson from Capesoft asked me about an example on how to override the RTL’s internal exception handler.   I think this is a topic that is likely of interest to many Clarion developers and warrants an example, so here we go.

Overview

PROP:LastChanceHook is a write-only SYSTEM property, which allows you to specify your own function that will be invoked if an exception occurs. The hook function allows you to display information about the exception and choose one of the following actions:

  • Continue execution of the thread where the exception occurred (unless the exception is fatal)
  • Stop the thread (or the entire process if the exception occurred in the main process thread) without invoking the RTL’s internal exception handler
  • Invoke the RTL’s internal exception handler

    This allows you to catch an exception, and if it is non-fatal you can allow your end users to continue executing your program even when an exception has occurred in one of its threads.


    How It Works

    Your function, which you assign to the SYSTEM{PROP:LastChanceHook} property has to have a prototype of:

    HookProc (*ICWExceptionInfo),LONG

    The ICWExceptionInfo parameter is an interface declared in CWEXCPT.INT which you’ll find in your .\Libsrc folder.

    The result returned by the hooked function is evaluated as follows:

    • If the result is equal to Zero, the RTL executes its own internal exception handler dialog to show information about the exception and subsequently perform the action chosen by the end user.
    • If a Positive number is returned, the RTL stops the thread (or the entire process if the exception occurred in the main process thread) without invoking the RTL exception handler.
    • If a Negative number is returned, the program will try to continue from the point of the exception. Note, if the exception is non-continuable, this result is ignored and treated as equal to Zero.

    So in our example we start with this code:


    PROGRAM

    INCLUDE(’CWEXCPT.INT’),ONCE

    MAP
    Test (LONG,LONG)
    Hook (*ICWExceptionInfo),LONG
    HEX (LONG),STRING,PRIVATE
    MODULE(”)
    MessageBox (UNSIGNED, CONST *CSTRING, CONST *CSTRING, UNSIGNED),SIGNED,PROC,PASCAL,NAME(’MessageBoxA’)
    END

    END

    MB_ICONHAND EQUATE(00000010h)

    CODE
    SYSTEM{PROP:LastChanceHook} = ADDRESS (Hook)
    Test (10, 0)  ! causes an exception
    RETURN

    In this example the Procedure named “Hook” is assigned as our exception handler. That’s the only Procedure we are concerned with, the others are just there to help make the example work by 1) causing an exception and 2) informing the user about the exception. Next we have:


    ! ------------------------------------------------------------------------------

    Hook PROCEDURE (*ICWExceptionInfo info)

    S CSTRING(1024)
    Caption CSTRING(256)

    CODE
    IF info &= NULL
    RETURN 0
    END

    Caption = ‘Exception ‘ & HEX (info.ExceptionCode()) & ‘ at ‘ & HEX (info.ExceptionAddress())
    S = ‘Registers’ & |
    ‘<13,10>EAX=’ & HEX (info.Register (i386_Register:Reg32_EAX)) & |
    ‘ EBX=’ & HEX (info.Register (i386_Register:Reg32_EBX)) & |
    ‘ ECX=’ & HEX (info.Register (i386_Register:Reg32_ECX)) & |
    ‘ EDX=’ & HEX (info.Register (i386_Register:Reg32_EDX)) & |
    ‘<13,10>ESI=’ & HEX (info.Register (i386_Register:Reg32_ESI)) & |
    ‘ EDI=’ & HEX (info.Register (i386_Register:Reg32_EDI)) & |
    ‘ ESP=’ & HEX (info.Register (i386_Register:Reg32_ESP)) & |
    ‘ EBP=’ & HEX (info.Register (i386_Register:Reg32_EBP)) & |
    ‘<13,10,13,10>Current thread is being terminated’

    MessageBox (0, S, Caption, MB_ICONHAND)
    RETURN 1      ! a positive value signals the RTL to kill the thread

    ! ——————————————————————————

    Test PROCEDURE (LONG a, LONG b)

    CODE
    a %= b

    ! ——————————————————————————

    HEX PROCEDURE (LONG A)

    i UNSIGNED,AUTO
    S STRING(8),AUTO
    DIGITS STRING(’0123456789ABCDEF’),STATIC

    CODE
    i = SIZE(S)

    LOOP WHILE i <> 0
    S [i] = DIGITS [BAND (A, 0Fh) + 1]
    A = BSHIFT (A, -4)
    i -= 1
    END

    RETURN S

    ! ——————————————————————————



    These first two lines of code assign our exception handler function and then call the Test procedure that raises an exception:

    SYSTEM{PROP:LastChanceHook} = ADDRESS (Hook)
    Test (10, 0)  ! causes an exception

    The exception is trapped and we show the result in a MessageBox which looks like this:

    customexception

    our Hook PROCEDURE (*ICWExceptionInfo info) uses the methods in the interface to show the exception code, its address, and the values of the registers at the time of the exception. And remember we said that:

    “If a Positive number is returned, the RTL stops the thread (or the entire process if the exception occurred in the main process thread) without invoking the RTL exception handler.”

    in our example our Hook PROCEDURE does a “RETURN 1” and since we are running on the main thread then immediately after the MessageBox is displayed and the user presses the OK button the program itself is terminated.

    In a future article we’ll show you how to easily display the callstack so that your end-user can tell you exactly which procedure caused the exception. And we’ll be adding an option to the templates so that you can do the same with a couple of mouse clicks. You can download the source code for this example from this link

    Code Completion in the Embed Editor

    Wednesday, January 27th, 2010

    There was much gnashing of teeth over the fact that the plain Embed Editor didn’t implement Code Completion - well now the next 7.1.x update implements Code Completion in the Embed Editor. We are also looking at adding the support for Code Folding, which as of today isn’t supported in the Embed Editor, and Clarion devs have asked that we also provide code folding for Control Statements such as IF, CASE, LOOP, etc. and we’re looking into this too.

    In case you haven’t found this yet, you can define your own “folding regions” anywhere you like with this syntax:

    !region SomeDescriptiveText
    …….source code
    !endregion

    Check the Help file index for this topic: “Regions - Source Code” or just give it a try with the above syntax.