Tag Archives: Templates

Clarion Unicode preview — beta refresh build 14373

Clarion · Unicode Preview · Beta Refresh

Refresh build 14373 — lost SQL connections re-establish themselves, SQL browses fetch faster, and the help gains a “How do I” chapter

A SQL drop. Lost server connections now automatically re-establish the connection to the server and the application continues gracefully: a VPN reconnect, a firewall that closed the session, a laptop that woke up — the files and views stay open, the next operation reconnects, a browse that was paging simply keeps paging. Two new browse prompts fetch a SQL page in one round trip instead of one row per trip, with a BLOB in the page up to 10x faster on SQL Server. A SQL connection configures itself from the OWNER string alone, no DSN on the user’s machine. The IDE’s “select a folder” is the modern Windows folder dialog everywhere. And the F1 help has a “How do I …” chapter with a task topic for every section of the tester guide, every topic in the Index. Plus the fixes and additions from beta testers’ reports in the forums: Known Folders, the wide CLIB twins, a two-picture DateTime format, a friendlier previewer. Already testing? Everything below is new since build 14313.

SQL automatic reconnect · ‘Page fetch size (SQL)’ · ‘BLOB fetch (SQL)’ · PROP:BlobFetch · DSN-less connect IDE the modern select-folder dialog on every “…” Help “How do I …” chapter · every topic indexed · Customizing a SQL Connection Compiler USTRING link names sz / z — rebuild multi-DLL solutions together From the forums Known Folders · CLIB wide twins + RmDirW · Pict(dt, pic1, sep, pic2) · previewer Jump / sidebar · varchar(max) as BLOB · BLOB hot fields · VALUE() / PROP:Value / SPIN FROM wide · PROP:FromQueue · Designer paints <13,10>

Highlights of this drop — then the full tester guide, whose “What’s new” section lists everything that changed since you last read it.

↻

Lost server connections re-establish themselves, the application continues

ODBC, MSSQL, Pervasive SQL and SQL Anywhere drivers. When the link to the server drops under a running program, every file and view of that connection stays open, the failed operation reports error 90 with the driver’s own message (FILEERRORCODE() = 08S01), and the next operation reconnects by itself — including a table the program opens for the first time after the drop, so the first save after an outage goes through. In a generated application (ABC and Clarion chains) the user sees one error box and the usual retry prompt, and Yes saves the record. A browse that was paging when the link went keeps paging: the generated browse re-runs its page fill once, on a fresh connection, and the user sees nothing at all. Hand code simply retries the failed statement; a VIEW continues after a RESET to its last position.

≫

SQL browses fetch a page per round trip — two new prompts

BrowseBox › Actions › Default Behavior, both chains. ‘Page fetch size (SQL)’: a value n fetches n rows per server round trip (ABC sets BRWn.PageSize, the Clarion chain emits BUFFER(view, n, 2, 0, 60)); a Clarion-chain SQL browse moves from one row per trip to n. ‘BLOB fetch (SQL)’ with the new PROP:BlobFetch: a browse that shows a BLOB keeps its page fetch — the driver positions on your row and reads the page in one trip, a 20-row page fill on SQL Server measured 110 us/row down to 11.5. Blank prompts generate exactly what they did, so an existing app changes nothing until you set them. A BLOB projected into a VIEW is the current row’s from the very first read, so a TEXT or IMAGE bound to a browse hot-field BLOB follows the highlight bar.

◫

AppGen: a BLOB can be a browse hot field

Pick a BLOB as a hot field on a BrowseBox and a TEXT or IMAGE bound to it follows the highlight bar: the picture, the note, the document of the selected row. The templates put the BLOB into the browse’s VIEW as a PROJECT and never into the queue (a queue cannot LIKE() a BLOB), and the highlighted row is re-fetched on every selection change, so the control always shows the current row’s blob. Both template chains, no hand code.

⚙

A SQL connection configured from the OWNER string alone

The UNICODECONNECT form works without a DSN on the PostgreSQL Unicode driver and on SQL Server: name the driver DLL and its settings as keywords in the OWNER and nothing is configured on the user’s machine. The new help topic “Customizing a SQL Connection” lays out the three layers — the OWNER string, the driver string switches, the ODBC driver’s own settings — with a copy-ready example for each. Over a slow link to SQL Server, /MULTIPLEACTIVERESULTSETS=TRUE streams the rows instead of a server cursor round trip per fetch block; the guide’s SQL section says when to use it.

▣

The IDE picks folders with the modern dialog

Every “…” in the IDE that asks for a folder — New Project’s Location, the default project location in Options, Find in Files’ Look in, the project option folders — opens the Windows common item dialog in folder mode: the navigation bar, search, the places on the left, a “New folder” button, resizable. The small “Browse For Folder” tree is gone from the IDE. The most reported request of the beta, inside and outside.

⌂

Known Folders: Downloads, Documents, AppData and every other one, by name

SpecialFolder.GetKnownDir(KF:Downloads) returns the user’s Downloads folder, the one the CSIDL list never had. KNOWNFOLDER.EQU declares the common KNOWNFOLDERIDs as KF: equates — Downloads, Documents, Desktop, Pictures, Music, Videos, LocalAppData, RoamingAppData, ProgramData, Profile, Fonts, ProgramFiles, ProgramFilesX86, Startup, the Public ones — and any other folder from KnownFolders.h is one more equate written the same way. GetKnownDir(KF:Documents, 'MyApp') appends your sub-directory, the path comes back as a USTRING so a folder outside the ANSI code page is exact, and GetKnownError() holds the HRESULT of the last call. The CSIDL methods you already use are unchanged.

✚

Wide CLIB twins, a two-picture DateTime, a friendlier Report previewer

CLIB.CLW declares the wide twins FnSplitW, FnMergeW, MkDirW, AccessW and the new RmDirW, so a program that includes CLIB.CLW calls them by name. DateTimeUtil.Pict(dt, '@D10-', 'T', '@T04') joins two pictures with a separator — an ISO stamp, a file-name stamp — in one call. The report previewer’s Jump to a Page shows “of N pages”, clamps a typed number, and has First / Last buttons; the thumbnail sidebar’s scroll buttons sit side by side at the top. And the driver trace now shows a USTRING value in full, in the record dump and on the SQL bind lines, so a trace tells the truth about Unicode data. A browse sorted by a USTRING key on SQL Server positions cleanly from every sort tab, and saving a BLOB with bind tracing on no longer ends in an access-violation box. A wide VALUE() on a CHECK or RADIO lands in the USE variable with its exact units, {PROP:Value} on any captioned control and a SPIN’s wide FROM() deliver exact units too, and CONTENTS(?Combo) answers for a COMBO without a USE variable. And the Window and Report Designers paint <13,10>, every decimal metachar and {n} repeats exactly like the compiled window.

?

F1 help: a “How do I …” chapter, every topic in the Index

Right after Welcome to Clarion in Contents: 22 task topics, one per section of the tester guide (Unicode strings, screens, reports, SQL, TopSpeedW, the lost connection, the faster SQL browse …), each linking to the reference topics it needs. The Index finds them by title and by the words you would type — “lost connection”, “reconnect”, “faster SQL browse”. Every topic in the help now carries its title and chapter as index keywords, the 2026 reference topics carry a “See also” line, and the new browse prompts are documented where F1 on the prompt lands.

✎

From beta testers’ reports: dictionary, AppGen, DATETIME, previewer

varchar(max) imports as a BLOB, so the whole column travels (it joins text, ntext, nvarchar(max) and varbinary(max) under one rule). DateTimeUtil builds from LibSrc alone and gains Pict(dt, picture) — the date part through @D4, the time part through @T4, the whole value through @DT. The Window Previewer’s generated program reads better and compiles every time, with @DT controls primed with a real date-time sample.

ƒ

USTRING link names of their own — rebuild multi-DLL solutions together

USTRING parameters now mangle as sz (every non-RAW form) and z (RAW), a link name no other type can produce, so a *USTRING and a *SHORT,ANY prototype never share one. What to do on this build: regenerate and rebuild every module of a multi-DLL solution together (template-generated .exp files regenerate on their own); a hand-written .exp with zu/su lines changes them to sz; Pro2Exp / Exp2Map users update the letter table.

Full tester guide — mental model, conversion rules, DCT import table, screen controls, reports, blobs, SQL / SQLite / text drivers / TopSpeedW / Memory / IP, recipes, the new-language-surface quick reference, and what to focus on when testing. The guide’s “What’s new” section lists everything in this drop, and every section has its task topic in the F1 help’s “How do I …” chapter.

Open the full Unicode Tester Guide

Report tool authors — the wide generator surface (IReportGeneratorW), format detection, the EMF record set, transition paths per integration style, and the PageTextIndexClass text index the previewer searches with:

EMF Page Files — Transition Note

Standalone pages (best full-width). Everything described there is implemented unless marked as a known limitation — if you see something different, the beta forum is the place.

Template Tips #3 – #ATEND vs #AT(%AfterGeneratedApplication)

It looks like the embed %AfterGeneratedApplication is a very popular embed these days.
We already talked about it in the Template Tips #2 post where we compare it with the #AT(%ProgramEnd). Now we’ll compare #AT(%AfterGeneratedApplication) with #ATEND, and we’ll explain which of these is appropriate for a given task.

Why do we compare #ATEND with #AT(%AfterGeneratedApplication) ?
Because both of these are executed at the end of the code generation process (when we click on the Generate button).
Some 3rd Party Templates have the need to execute code that requires the App to be have been generated, and you’ll find they make use of #ATEND or #AT(%AfterGeneratedApplication).

All of the templates support #ATEND, but we’ll focus on the #APPLICATION #ATEND embed.
The #ATEND is comparable to a Destructor of a class, it is executed at the end of a templates code generation cycle, and the purpose is typically to execute some clean up code. When I mention clean up code I’m not talking about generating backups, creating extra files, or doing some extra  processing, etc. I’m talking about cleaning up template symbol values. Any other processing should not be executed in the #ATEND.

One of the reasons additional processing should not be executed in the #ATEND is that the #ATEND is similar to a Class Destructor, and that means the scope of the template is already ending, so just like in any other Class Destructor. you should not be creating new instances of anything at that point.

Another reason, that is more related to the templates is the Embeditor. What does the Embeditor have to do with the #APPLICATION #ATEND?
Well if you inspect the #APPLICATION code closely you will see that there is one magic part that make the Embeditor work.

I’m talking about this code:

#IF (%EditProcedure)            #! Special for editing embedded source in context
  #CREATE(%EditFilename)
  #FIND(%ModuleProcedure,%EditProcedure)
  #FIX(%Procedure,%ModuleProcedure)           #! Fix current procedure
  #MESSAGE('Generating Module:    ' & %Module,1) #! Post generation message
  #MESSAGE('Generating Procedure: ' & %Procedure,2) #! Post generation message
  #GENERATE(%Procedure)                       #! Generate procedure code
  #COMMENT(60)                                #!Set comment alignment to column 60
  #CLOSE
  #ABORT                                      #!Stop execution of any other code
#ENDIF

Yes, the Embeditor code is just the #GENERATION of the procedure with a little bit of magic.

Because this code is executed in the #APPLICATION section of the template we are expecting the #APPLICATION #ATEND to be executed.
Actually everything would be executed if it was not for the #ABORT at the end of the above code.
So if you are using the #ATEND, you are not only adding code to the equivalence of a Class Destructor, but you are also adding code that will always be executed unless you check for the value of the %EditFilename symbol. If the value of %EditFilename is null then you can be sure that you are in regular code generation, and not in the Embeditor generation. This is a very important point.

Where does the #AT(%AfterGeneratedApplication) fit into all this code generation?
Well the #EMBED(%AfterGeneratedApplication) is located at the end of the #APPLICATION template, it’s the last code to be generated before the #ATEND, but the big difference is that it only executes when we are generating the #APPLICATION during regular code generation. The execution of that embed will not happen on the Embeditor generation because of the #ABORT that we already mentioned.

The conclusion, if you need to execute code at the end of the Application generation process, I always recommend the use of the #AT(%AfterGeneratedApplication) instead of the #ATEND. And always try to use a PRIORITY, that will make other templates play nice with yours.

Template Writing Tips

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.