Category Archives: Clarion 12

Clarion Unicode preview — refreshed beta build (14258)

Clarion · Unicode Preview · Beta Refresh

Refresh build 14258 — the designers keep your Unicode, the fixes from four beta threads, and the wide path family

A shorter drop, built from the beta forum. The Window and Report Designers accept every U'' spelling and no longer rewrite it into a raw glyph; the Window Previewer can keep the generated program; DROP lists and COMBOs take a wide FROM at runtime; INSTRING() searches backwards from past the end; FILEDIALOG() opens on a Unicode folder; and the porting notes for SIZE() are in the help. Threads 47, 54, 57 and 60, closed. Already testing? Everything below is new since build 14234.

IDE U” hex literals in the designers · ANSI files keep U” · Save Preview Program Runtime DROP/COMBO wide FROM · INSTRING · FILEDIALOG Help SIZE() porting notes · INSTRING start rule

Highlights of this drop — then the full tester guide, whose “What’s new” section and dated “beta refresh” markers flag exactly what changed since you last read it.

Designers: every U” spelling works, and your Unicode stays Unicode

The Window and Report Designer parse U'<26DDh>', U'<1F600h>' and {n} repeats exactly like the compiler — build 14234 refused a window with a hex literal. And a designer opened from an ANSI .clw now writes wide text back as a U'' literal (decimal units) instead of a raw glyph that forced the save-as-UTF-8 prompt; UTF-8 sources keep the glyph as before.

DROP lists and COMBOs: a runtime wide FROM

?List{PROP:From} = U'…' on a LIST,DROP() or a COMBO keeps its characters — in 14234 that one property took the narrow path, so a declared FROM(U'…') worked and the runtime write showed ?. Reminder for continued FROM strings: put U on every piece.

ƒ

INSTRING backwards from past the end, and two porting notes

INSTRING(sub, s, -1, SIZE(s)) now finds the last match on a CSTRING or USTRING (those push only their used length, so a start past the end returned 0). Porting notes in the help: SIZE() of a USTRING is bytes, so a Windows API’s character count is SIZE(v)/SIZE(v[1]) — right for every string type — never SIZE(v).

Window Previewer: Save Preview Program

A second checkable item in the Window menu, under Unicode Preview: latched on, the generated preview program, its project and exe move into .WinPreview\ in the project folder with the injection include beside them, so File ▸ Open builds and runs it as-is; a preview that fails to compile still keeps its source. Both latches are menu items only — the toolbar keeps just the Preview button.

FILEDIALOG positioned; the “Internal error 01” dialog is gone

FILEDIALOG() with FILE:Directory and a USTRING start folder opens with the selection on that folder even when its name is outside the Windows codepage. The “Output corrupted stack, wsldebug.cpp line 412” dialog was the release diagnostic logger misfiring; it now logs to C120LOG.TXT and carries on, so what you see next is the real fault.

\

PATH, SETPATH, LONGPATH and SHORTPATH are wide

A USTRING folder or file name is resolved in its exact characters and the result comes back wide, so a folder whose name lies outside the Windows codepage can be entered with SETPATH and read back with PATH() (the earlier drop best-fit it to ? and SETPATH failed with error 3). The no-argument forms return the current directory exactly; a STRING argument or receiver gets the same bytes as always. With EXISTS, COPY/RENAME/REMOVE, DIRECTORY and FILEDIALOG already wide, only RUN remains in the file-name family.

?

F1 help, current for this drop

The IDE help (ClarionHelp.chm) carries the INSTRING start rule with a SIZE(cstring) example, the USTRING porting note, the previewer’s second latch, and a USTRING note on each of the PATH, SETPATH, LONGPATH and SHORTPATH topics.

Full tester guide — mental model, conversion rules, DCT import table, screen controls, reports, blobs, SQL / SQLite / text drivers / TopSpeedW / Memory / IP, recipes, and what to focus on when testing. The guide’s “What’s new” section lists everything in this drop; changes are also flagged inline with dated “beta refresh” notes.

Open the full Unicode Tester Guide

Report tool authors — the wide generator surface has shipped (IReportGeneratorW — six methods, opt-in, zero break for existing implementors). Format detection, the EMF record set, transition paths per integration style:

EMF Page Files — Transition Note

Standalone pages (best full-width). Everything described there is implemented unless marked as a known limitation — different behavior is exactly what we want to hear about.

Clarion Unicode preview — refreshed beta build (14234)

Clarion · Unicode Preview · Beta Refresh

Refresh build 14234 — Unicode file names end to end, Unicode PDF, and a previewer for wide windows

Everything in this refresh traces back to a beta thread. The whole file-name family went wide — EXISTS, COPY/RENAME/REMOVE, FILE,NAME(ustring), DIRECTORY() with 64-bit sizes and FILEDIALOG(); both PDF targets export real Unicode text; the Window Previewer previews a window as a wide program; keystrokes, clipboard and tooltips carry Unicode; the dictionary lives as text. Already testing? Everything below is new since build 14204.

Files EXISTS · COPY/RENAME/REMOVE · FILE,NAME · DIRECTORY · FILEDIALOG Reports PDF Unicode (both targets) · encryption fix IDE Unicode Preview · dictionary as text · Reload Solution

Highlights of this drop — then the full tester guide, whose “What’s new” section and dated “beta refresh” markers flag exactly what changed since you last read it.

Unicode file names, end to end

A file name or folder outside the Windows codepage — a Unicode user profile, a currency sign, CJK — now works through the whole family: EXISTS(), COPY()/RENAME()/REMOVE(), and FILE,NAME(ustring) on TopSpeedW and the DOS/ASCII/BASIC drivers (every driver takes a USTRING name whose text fits the codepage; the classic drivers report error 45 instead of a silent 90).

DIRECTORY() with Unicode names and 64-bit sizes; FILEDIALOG goes wide

A new queue type FILE:QueueWName USTRING, Size REAL (exact past 2 GB), Attrib32 — lists every name with its real characters; the old queues are untouched. FILEDIALOG() with a USTRING variable opens on a non-codepage path and returns it exactly, and a USTRING title shows as typed.

PDF export is Unicode — both targets

The stock Report to PDF target embeds a glyph-preserving subset of each font so a REPORT,UNICODE‘s text renders, searches and copies in any reader; Image2PDF does the same through libharu, color emoji included as pictures. Password-protected PDF export — is fixed.

Window Previewer: a latched “Unicode Preview” button

Next to the Preview button (and in the Window menu): latched on, the next preview is generated as a wide program — every substituted USE variable a USTRING — so the preview runs the real wide ENTRY/TEXT/LIST classes. Latched off, the generated program is byte-identical to today’s.

Unicode keystrokes reach USTRING controls exactly

The runtime pump is wide: Win+. emoji, IME composition and any injected Unicode keystroke land in a USTRING ENTRY/TEXT as typed; ANSI windows keep their ANSI keystrokes by construction. CLIPBOARD()/SETCLIPBOARD() carry Unicode, and tooltips are wide on every lane.

The dictionary as text

A .dctx twin beside the .dct is the source of truth: honest UTF-8 (a £ in a picture, a Ω in a prompt survive the round trip), Dictionary-menu export/import, and an audit of who changed what. Reload/Close Solution no longer revert an external .sln/.cwproj edit.

ƒ

UVAL(), PROP:ClipEntry, compiler messages restored

UVAL(string [,pos]) is the inverse of UCHR() — the code point at a unit position, merging a surrogate pair. SYSTEM{PROP:ClipEntry} (opt-in) clips typed trailing spaces from @S entries into CSTRING/USTRING.

LIST and TEXT: the last residuals closed

Declared FORMAT() headers and column pictures keep their Unicode, the string FROM() lane is wide both ways, {PROP:Text} into a TEXT stores exact units, and TopScan previews a UNICODE blob as text. The LIST family is fully wide on declared and runtime lanes.

Oracle driver goes wide

NCHAR/NVARCHAR2 import as USTRING sized in units, NCLOB as a Unicode blob, DDL emits VARCHAR2(n CHAR)/NVARCHAR2(n-1) — and three long-shipped defects went with it. Set NLS_LANG to a Unicode-capable character set on Instant Client.

?

F1 help, current for this drop

The IDE help (ClarionHelp.chm) updated with the new RTL features: DIRECTORY/FILEDIALOG with FILE:QueueW, the previewer’s Unicode Preview, the PDF targets’ Unicode notes, UVAL, PROP:ClipEntry and the updated compiler messages.

Full tester guide — mental model, conversion rules, DCT import table, screen controls, reports, blobs, SQL / SQLite / text drivers / TopSpeedW / Memory / IP, recipes, and what to focus on when testing. The guide’s “What’s new” section lists everything in this drop; changes are also flagged inline with dated “beta refresh” notes.

Open the full Unicode Tester Guide

Report tool authors — the wide generator surface has shipped (IReportGeneratorW — six methods, opt-in, zero break for existing implementors). Format detection, the EMF record set, transition paths per integration style:

EMF Page Files — Transition Note

Standalone pages (best full-width). Everything described there is implemented unless marked as a known limitation — different behavior is exactly what we want to hear about.

Clarion Unicode preview — refreshed beta build (14204)

Clarion · Unicode Preview · Beta Refresh

Refresh build 14204 — a drop built from your reports

Nearly every item in this refresh traces back to a beta field report — exactly what the beta is for. CHOOSE() and POPUP() go wide, control pictures carry Unicode, TXA round-trips in UTF-8, INI files and the registry go wide, a full sweep of the string built-ins closed out the remaining port regressions — and there’s a Windows 11 fix every desktop app should retest. Already testing? Everything below is new since build 14175.

Language CHOOSE · POPUP · pictures · built-ins sweep IDE TXA in UTF-8 · %CWVersion 12026 Runtime INI · registry · Win11 hit-test fix

Highlights of this drop — then the full tester guide, whose “What’s new” section and dated “beta refresh” markers flag exactly what changed since you last read it.

?:

CHOOSE() takes USTRING values

A USTRING among CHOOSE’s values used to make the whole result numeric — even a plain-string alternative came back as '0'. Now string values give a string result that keeps every unit, and string-mixed-with- numeric stays numeric, exactly the STRING rules. From Carl B.’s report.

POPUP() is wide

Menu text draws its real glyphs — currency signs, CJK, emoji — and the item structure (|, {}, ~, …) is decided on the wide text itself, so a full-width in an item no longer splits the menu. All-ANSI POPUPs take exactly the old code path. Also from Carl B.’s reports.

@

Control pictures carry Unicode

A picture with symbols outside the codepage — say @n~₿~-15.2 — set on a LIST column (PROPLIST:Picture) or a pictured display STRING now formats with the real symbol and reads back intact. A wide LIST heading also survives a later reformat. (The pictured-ENTRY editor is a separate queued step.)

Runtime caption rewrites go wide

{PROP:Text} = <wide value> on the caption families — PROMPT, STRING, BUTTON, CHECK, RADIO, TAB, GROUP/OPTION/SHEET — now keeps exact units. This was on the known-limitations list; it’s off it now.

ƒ

String built-ins, swept against gold

Every string built-in was measured two-era against Clarion 12 gold, and the remaining beta regressions fixed: DEFORMAT(x) with the picture omitted, ERROR() returning unclipped padding, NUMERIC() rejecting trailing spaces, ALL('',n), wide RIGHT()/CENTER() padding — and wide-to-wide compares now clip trailing spaces like narrow always did.

TXA export/import in UTF-8

Export application text as Application text, UTF-8 — a filetype choice in every export dialog, ClarionCL /u8 /ax on the command line, or the AutoExport-on-save option. Import auto-detects UTF-8 (with or without BOM) and rejects loudly, naming the line, instead of silently mangling. Defaults stay ANSI, byte-identical. From Petar’s request.

§

INI files and the registry go wide

GETINI/PUTINI accept and return USTRING exactly — and a wide write to a missing .ini creates it UTF-16 LE with BOM. The GETREG family matches the registry’s native UTF-16 end to end: RegEdit shows your real characters, and reads them back exactly.

#

Templates can gate the Unicode era

%CWVersion is now 12026#IF(%CWVersion >= 12026) is the idiom for template and third-party code that must also generate for older builds (equality tests against 12000 break; use >=). And multi-DLL exports of procedures taking USTRING arrays now link.

A Windows 11 fix worth retesting

Menus and mouse clicks going dead when another app’s always-on-top window (Windows 11 shell “island” windows are the usual trigger) overlapped a Clarion window — fixed, from a tester’s precise analysis (thanks, Alexey). If you’ve seen a Clarion app stop responding to the mouse on Win11, retest on this build.

?

F1 help, rebuilt and current

The IDE help (ClarionHelp.chm) is rebuilt: the Unicode-era language surface — USTRING and friends, the new and changed built-ins, the INI/registry notes — is now in the F1 help itself, not only in the tester documents.

Full tester guide — mental model, conversion rules, DCT import table, screen controls, reports, blobs, SQL / SQLite / text drivers / TopSpeedW / Memory / IP, recipes, and what to focus on when testing. The guide’s “What’s new” section lists everything in this drop; changes are also flagged inline with dated “beta refresh” notes.

Open the full Unicode Tester Guide

Report tool authors — the wide generator surface has shipped (IReportGeneratorW — six methods, opt-in, zero break for existing implementors). Format detection, the EMF record set, transition paths per integration style:

EMF Page Files — Transition Note

Standalone pages (best full-width). Everything described there is implemented unless marked as a known limitation — different behavior is exactly what we want to hear about.

USTRING — Unicode that feels like Clarion

Clarion · Unicode Preview

USTRING — Unicode that feels like Clarion

Wide text end to end: declare it, type it, store it, browse it. No new programming model. No special “Unicode mode.” If you already know CSTRING, you already know USTRING — and your existing ANSI apps stay byte-identical.

SQL MSSQL · ODBC · PostgreSQL · SQLite ISAM TopSpeedW · ASCII · BASIC · DOS UI ENTRY · TEXT · COMBO · captions · blobs

A few highlights for Clarion developers evaluating this build — then the full tester guide (declaration rules, import maps, backends, recipes, what to poke at).

Hands-off by design

Pick USTRING in the DCT, USE it on a control, PUT it to SQL. No conversion buffers, no “wide mode” flag, no per-screen ceremony. It just works the way Clarion always did.

Σ

All SQL backends speak Unicode

MSSQL, ODBC, PostgreSQL, and SQLite: USTRING(n) ↔ NVARCHAR(n-1) (logical length round-trips). Keys, GET, SET/NEXT, and bound WHERE values stay wide — never narrowed literals.

TopSpeed goes wide

Classic TPS is untouched. New driver: DRIVER('TopSpeedW'), .tpsw files, USTRING fields + UNICODE blobs, keys that work, and clean version rejects instead of silent mojibake.

A blob is a field

On SQL there is no MEMO(n) — long text is the blob. TEXT,USE(blob) displays and edits; IMAGE,USE(blob) displays. Window binding ships today; Report is the same mental model (next surface).

Type your language — everywhere

Source (UTF-8 / UTF-16), Window/Report designers, DCT messages/tips, IME, emoji panel, clipboard. Captions and free-form ENTRY/TEXT/COMBO carry exact UTF-16 on any system codepage.

ANSI apps stay byte-identical

No USTRING? No wide designer text? Rebuild and ship — same binary behavior as before. Opt-in tokens (e.g. PostgreSQL UNICODECONNECT=1) never change default connects.

Import maps that tell the truth

Import Tables: nvarchar → USTRING, ntext / nvarchar(max) → UNICODE memo/blob, binary max → BINARY blob — attributes already ticked. Data Browser edits wide without narrowing.

Surrogate-safe editing

Emoji and non-BMP text edit as atomic characters on wide ENTRY/COMBO. Color emoji via DirectWrite where available; ordinary edits never leave half a pair behind.

Full tester guide — mental model, conversion rules, DCT import table, screen controls, blobs, SQL / SQLite / text drivers / TopSpeedW, recipes, and what to focus on when testing.

Open the full Unicode Tester Guide

Standalone page (best full-width). Everything described there is implemented unless marked as a known limitation — different behavior is exactly what we want to hear about.

Maintenance Release + USTRING Beta (Compiler/RTL Changes)

We have two updates scheduled for release this week:

  • Maintenance Release (shipping first)
  • USTRING Beta Release (follows)

USTRING Beta: Compiler + RTL Changes

The USTRING implementation requires coordinated changes to both the Compiler and RTL (Runtime Library).

We initially explored making the RTL interchangeable at runtime, allowing the IDE to switch between:

  • Shipping (production) RTL
  • USTRING-enabled (beta) RTL

However, this approach introduced unnecessary complexity and risk of cross-contamination between environments.

Decision:
We are shipping the USTRING beta as a separate IDE build, each with its own aligned Compiler + RTL.

Result:

  • Eliminates risk of mixing beta RTL into production builds
  • Keeps production and experimental toolchains fully isolated
  • Simplifies support and debugging

Fix: “Check for Updates” Failure

The Check for Updates feature failed shortly after the C12 release.

Root Cause:

  • A server-side WAF (Web Application Firewall) policy change
  • Requests were rejected with HTTP 403 (Forbidden) during TLS negotiation/connection handling

Status:

  • ✅ Client-side handling updated
  • ✅ Server compatibility restored

The update mechanism is now functioning normally.

Email Notification Rollout

Because the update mechanism is unavailable, we are notifying all subscribers via email.

  • Rollout begins this week
  • Email platform has been changed to improve delivery reliability

If you encounter any issues with updates or the new builds, please report them so we can address them quickly.

Understanding USTRING: A Deep Dive into Clarion 12’s UTF-16 Implementation

This post focuses on practical details and what they mean for your day-to-day development, with an eye toward where we’re headed next.

In our previous article, we announced the USTRING data type was coming back, and its intended role in Clarion 12’s Unicode support. Now, let’s explore the implementation details that will help you work more effectively with the USTRING.

USTRING is UTF-16: What This Means for You

At its core, the USTRING data type uses UTF-16 encoding, allocating two bytes per character. This architectural decision provides several key advantages:

  • Native Windows support: Windows internally uses UTF-16 for all Unicode operations, making USTRING integration seamless
  • Fixed-width benefits: Most common characters (including all Latin, Cyrillic, Greek, and CJK characters in the Basic Multilingual Plane) use exactly 2 bytes, simplifying string indexing
  • Complete Unicode coverage: Through surrogate pairs, UTF-16 can represent every Unicode character
  • Predictable memory usage: Easy calculation of memory requirements
Name     USTRING(21)              ! 21-character Unicode string
Company  USTRING('SoftVelocity')  ! Initialized with a value
Phone    USTRING(@P(###)###-####P) ! Formatted with picture token
MyStr    USTRING(20)              ! 20 characters available

When you declare USTRING(20), you’re reserving space for 20 characters plus a null terminator. Internally, this allocates 42 bytes (21 characters × 2 bytes each).

Memory Layout: USTRING(20)

Declaration:  USTRING(20)
Allocation:   [    40 bytes for 20 characters    ][2 bytes null]
              |<────────── 20 chars × 2 bytes ─────>|
Total Size:   42 bytes

Example with "Hello":
Position:     1    2    3    4    5    6-20  21
Character:    H    e    l    l    o    (empty) \0
Bytes:       [H ][e ][l ][l ][o ][  ...  ][\0]
              2   2   2   2   2      30      2
                                          WCHAR(0)
              <─── 40 bytes for data ────> <2>

Total: 42 bytes allocated (40 for characters + 2 for null terminator)

Important: The null terminator WCHAR(0) occupies 2 bytes because it’s a wide character, just like every other character in the string. This is how functions like lstrlenW know where the string ends—they scan for this 2-byte null value.

Dual Character Set Support: The Best of Both Worlds

One of USTRING’s practical strengths is transparent handling of both Unicode and ANSI content. You can freely mix Unicode literals and ANSI strings in your code:

MYUSTR  USTRING(50)

CODE
  MYUSTR = u'Α Ω'            ! Greek Unicode characters
  MYUSTR = 'Regular Text'    ! ANSI text works too
  MYUSTR = u'Mix: ' & 'Α Ω' ! Concatenate both types

The runtime handles conversions automatically, respecting the current code page settings. When working with international applications, you can set the code page and locale to ensure proper character handling:

SYSTEM {PROP:Codepage} = 1253   ! Greece
SYSTEM {PROP:Locale} = 1032     ! Greece

LEN() vs SIZE(): A Critical Distinction

This is where developers first encounter USTRING’s two-byte nature. The distinction between LEN() and SIZE() directly reflects the UTF-16 implementation:

MYUSTR  USTRING(20)
L       LONG
S       LONG

CODE
  MYUSTR = u'Α Ω'            ! 3 Unicode characters
  L = LEN(MYUSTR)            ! L = 3 (character count)
  S = SIZE(MYUSTR)           ! S = 40 (20 characters × 2 bytes)

LEN() returns the logical length—the number of characters actually stored in the string. This is what you typically care about when processing text.

SIZE() returns the allocated byte capacity. For a USTRING(20), SIZE() always returns 40, regardless of how many characters you’ve stored. This represents the maximum storage available.

Understanding this distinction matters when:

  • Allocating buffers for string operations
  • Interfacing with external APIs that expect byte counts
  • Optimizing memory usage in data structures
  • Working with file I/O operations

How SIZE() Actually Works

For fixed-size declarations like USTRING(20), SIZE() is calculated by the Clarion compiler at compile-time. The compiler knows the capacity is 20 characters and generates code that returns 20 × 2 = 40 directly—no runtime function call needed.

This is why SIZE() is so fast: it’s just a constant value, not a calculation that happens when your code runs.

When LEN() and SIZE() Differ: A Practical Example

UserInput  USTRING(100)      ! Allocated capacity: 100 chars
Bytes      LONG
Chars      LONG

CODE
  UserInput = ''             ! Empty string
  Chars = LEN(UserInput)     ! Chars = 0 (no content)
  Bytes = SIZE(UserInput)    ! Bytes = 200 (capacity still allocated)

  UserInput = u'Hi'          ! Short string
  Chars = LEN(UserInput)     ! Chars = 2 (actual content)
  Bytes = SIZE(UserInput)    ! Bytes = 200 (capacity unchanged)

  ! Key insight: SIZE() never changes after declaration
  ! LEN() reflects actual content

Memory Allocation: Understanding the 2:1 Ratio

When you declare a USTRING, the actual memory allocated is double the character count you specify:

Small   USTRING(10)              ! Allocates 20 bytes (10 × 2)
Medium  USTRING(100)             ! Allocates 200 bytes (100 × 2)
Large   USTRING(1000)            ! Allocates 2000 bytes (1000 × 2)

Right-Sizing Your Strings

Choose appropriate sizes to avoid wasting memory. Here’s what oversizing costs:

! Good - sized appropriately
FirstName  USTRING(50)            ! 100 bytes allocated

! Wasteful - unnecessarily large
UserName   USTRING(500)           ! 1000 bytes allocated
                                  ! If only ~50 chars used: 100 used, 900 wasted

Comment    USTRING(5000)          ! 10,000 bytes allocated
                                  ! If only ~100 chars used: 200 used, 9,800 wasted

When Memory Size Actually Matters

Understanding when to worry about USTRING memory overhead:

! Scenario 1: Single string - overhead is negligible
CustomerName  USTRING(100)     ! 200 bytes total
! Impact: Minimal - 100 extra bytes compared to ANSI

! Scenario 2: Large collections - overhead multiplies
CustomerQueue QUEUE
Name            USTRING(100)   ! 200 bytes
Address         USTRING(200)   ! 400 bytes
City            USTRING(50)    ! 100 bytes
              END

! Impact with 100,000 records in queue:
! USTRING: 70,000,000 bytes (70 MB)
! STRING:  35,000,000 bytes (35 MB)
! Difference: 35 MB - this is where sizing matters!

! Or with an array:
CustomerArray USTRING(100), DIM(100000)  ! 20,000,000 bytes (20 MB)
! vs STRING(100), DIM(100000)            ! 10,000,000 bytes (10 MB)

Rule of thumb: For individual strings, use generous sizes. For large queues, arrays, or tables, size more carefully.

Design-Time vs Runtime Allocation

! Design-time: Fixed size declared in source
MyStr  USTRING(100)          ! 200 bytes allocated at compile time

! Runtime: Dynamic allocation with NEW
MyStr &USTRING               ! Reference to dynamically allocated string
CODE
  MyStr &= NEW USTRING(100)  ! 200 bytes allocated at runtime

Design-time declarations have a maximum size of 4MB, while runtime allocations can be sized dynamically based on your application’s needs.

Working with Unicode Literals

When initializing or assigning to a USTRING, use the U or u prefix for Unicode literals:

MyStr USTRING(50)
CODE
  MyStr = U'Ω α β'     ! Correct - U prefix for Unicode
  MyStr = u'Ω α β'     ! Also correct - lowercase works too
  MyStr = 'Ω α β'      ! Works but may not preserve Unicode properly

Practical Implications for Your Code

Character Access is Read-Only on Assignment

You can read individual characters using slice syntax, but cannot assign to them:

C = MyStr[5]        ! Read character at position 5 - ALLOWED
MyStr[1] = 'A'      ! ERROR - Not allowed, creates invalid string

This restriction maintains string integrity in the UTF-16 implementation.

Use LEN() for Logic, SIZE() for Memory

! Correct usage
IF LEN(UserInput) > 0            ! Check if string has content
  ! Process input
END

! Memory allocation calculation
BytesNeeded = SIZE(MyStr)        ! Get total allocated bytes

Current Limitations

The current implementation doesn’t support Unicode strings in these specific contexts:

  • EVALUATE statement
  • MATCH built-in function
  • STRPOS built-in function

These are implementation-specific constraints that may be addressed in future releases.

Working Example: Practical USTRING Usage

MAP
  MODULE('API')
    GetSystemInfo(*LONG, *LONG), PROC, RAW, PASCAL, NAME('GetSystemInfo')
  END
END

MyName    USTRING(50)
MyCompany USTRING(100)
FullInfo  USTRING(200)
CharCount LONG
ByteCount LONG

CODE
  ! Assign Unicode content
  MyName = u'Αλέξανδρος'       ! Greek name
  MyCompany = u'SoftVelocity'   ! Company name
  
  ! Concatenate strings
  FullInfo = MyName & u' - ' & MyCompany
  
  ! Get character count and byte size
  CharCount = LEN(FullInfo)     ! Actual characters in string
  ByteCount = SIZE(FullInfo)    ! Total bytes allocated
  
  ! Display results
  MESSAGE('Name: ' & MyName & |
          '|Characters: ' & CharCount & |
          '|Bytes Allocated: ' & ByteCount)

Behind the Scenes: What Happens When You Concatenate

When you write a string expression like this:

Result = FirstName & ' ' & LastName

The Clarion runtime evaluates it using a string stack—a temporary workspace for building the final result. Here’s the step-by-step process:

String Expression Evaluation

Step 1: Push FirstName onto stack       → Stack: [FirstName]
Step 2: Push ' ' onto stack             → Stack: [FirstName][' ']
Step 3: Concatenate top 2 items         → Stack: [FirstName ]
Step 4: Push LastName onto stack        → Stack: [FirstName ][LastName]
Step 5: Concatenate top 2 items         → Stack: [FirstName LastName]
Step 6: Pop result into Result variable → Result gets final string

This stack-based approach doesn’t create temporary variables that need cleanup. The runtime handles all intermediate strings automatically, and they vanish when the expression completes.

Why this matters for you:

  • Write complex expressions freely – No performance penalty for chaining operations
  • No memory leaks – Intermediate results are cleaned up automatically
  • Thread-safe by design – Each thread has its own string stack, no locking needed
  • Efficient memory use – Stack allocation is faster than heap allocation for temporaries

Performance Implication

The string stack is why expressions like Name = FirstName & ' ' & MiddleName & ' ' & LastName don’t create memory leaks or slow down your application. Each intermediate result (FirstName & ' ', etc.) exists only temporarily on the stack and is automatically cleaned up.

Best practice: Write natural, readable string expressions. The runtime is optimized for this pattern.

Common Pitfalls and How to Avoid Them

Pitfall 1: Using SIZE() When You Mean LEN()

! WRONG - This won't work as expected
Name  USTRING(50)
CODE
  Name = u'John'
  IF SIZE(Name) > 10         ! Always TRUE (SIZE is 100, not 8)
    ! This always executes
  END

! CORRECT - Use LEN() for content checks
  IF LEN(Name) > 10          ! FALSE (LEN is 4)
    ! This executes only when needed
  END

Pitfall 2: Buffer Size Confusion

! WRONG - Allocating based on character count for bytes
Name     USTRING(50)
Buffer   STRING(LEN(Name))    ! Too small! Only 50 bytes, need 100

! CORRECT - Use SIZE() for byte allocations
Buffer   STRING(SIZE(Name))   ! Correct: 100 bytes

Pitfall 3: Forgetting the U Prefix

Greek  USTRING(20)
CODE
  ! INEFFICIENT - ANSI string converted to Unicode at runtime
  Greek = 'Αθήνα'

  ! EFFICIENT - Direct Unicode assignment, no conversion
  Greek = u'Αθήνα'

Migration from STRING to USTRING: Real Examples

Example 1: Buffer Sizing

! Before (ANSI STRING)
Name    STRING(50)           ! 50 bytes
Buffer  STRING(SIZE(Name))   ! 50 bytes

! After (USTRING)
Name    USTRING(50)          ! 100 bytes (50 × 2)
Buffer  STRING(SIZE(Name))   ! 100 bytes - SIZE() handles it correctly

Example 2: Loop Iterations

! Before (ANSI STRING)
Text  STRING(100)
I     LONG
CODE
  LOOP I = 1 TO LEN(Text)    ! Good - use LEN() not SIZE()
    ! Process Text[I]
  END

! After (USTRING)
Text  USTRING(100)
I     LONG
CODE
  LOOP I = 1 TO LEN(Text)    ! Same - LEN() still correct
    ! Process Text[I]
  END
  ! KEY: LEN() works the same way for both types!

Example 3: API Calls

! Before (ANSI STRING)
Buffer  STRING(1000)
Size    LONG
CODE
  Size = SIZE(Buffer)        ! 1000 bytes
  ! Pass Size to Windows API expecting byte count

! After (USTRING)
Buffer  USTRING(1000)
Size    LONG
CODE
  Size = SIZE(Buffer)        ! 2000 bytes (1000 × 2)
  ! SIZE() correctly returns byte count for Unicode APIs

Migration Considerations

When moving existing ANSI string code to USTRING:

  • Use LEN() for character-based logic, not SIZE()
  • Add U prefix to string literals containing Unicode characters
  • Test with international character sets if your application supports them
  • Be aware of the EVALUATE, MATCH, and STRPOS limitations
  • Review buffer size calculations—you may need double the byte count you used with ANSI

Looking Forward

The USTRING implementation provides a solid foundation for Unicode support while maintaining the Clarion language’s characteristic simplicity. The UTF-16 encoding, dual character set support, and clear LEN/SIZE distinction give you the tools needed for modern, international applications.

Key takeaways:

  • USTRING uses UTF-16 encoding (2 bytes per character)
  • Automatic conversion between ANSI and Unicode character sets
  • LEN() returns character count; SIZE() returns byte count
  • USTRING(n) allocates n × 2 bytes of memory
  • Code page awareness ensures proper locale handling
  • Runtime uses string stack for efficient expression evaluation

Thanks for being part of the Clarion community. If you try this out, let us know what you think — and stay tuned, there’s more to come.


Related: Clarion 12 Beta: USTRING Returns ANSI & Unicode

Clarion 12 Beta: USTRING Returns (ANSI + Unicode)

What’s shipping in the mid-January beta

In mid-January we’ll be releasing a Clarion 12 beta that brings back USTRING.

TL;DR

  • Clarion 12 beta (mid-January) reintroduces USTRING.
  • USTRING is updated to handle both ANSI and Unicode strings.
  • A Clarion 12 maintenance update for the current shipping release will be published at the same time.
  • The beta is intended for side-by-side installation in a separate folder.
  • This beta focuses on predictable behavior and clearer intent in string handling.
  • You can evaluate the change incrementally before the next full release.

Also shipping: Clarion 12 maintenance update

At the same time as the beta, we’ll also be releasing an updated maintenance build for the current shipping version of Clarion 12.

Install notes (side-by-side)

The Clarion 12 beta is intended to be installed into a separate folder so you can keep your production Clarion 12 install intact and evaluate the beta side-by-side.

Why USTRING is back

Clarion developers care about two things when it comes to string handling: correctness and stability. In Clarion 12 we explored making Unicode capability available through the existing STRING type with a strong emphasis on minimizing impact to existing code. Since then, we’ve continued testing and listening to practical, real-world feedback about how developers want to work with strings.

The mid-January beta takes a more explicit approach: USTRING returns, and has been updated to handle both Unicode strings and regular ANSI strings.

What this means for day-to-day development

  • Clearer intent: USTRING makes it obvious (at the declaration level) that a value may be Unicode-aware.
  • Practical compatibility: USTRING is designed to work with both ANSI and Unicode content, so you can adopt it where it makes sense.
  • Incremental evaluation: You can test this beta in focused areas first (utilities, import/export, API edges, UI text, etc.).

Impact and rollout

This is a beta release, so the goal is to give you something you can run against real applications and real data. If you have areas of your app that are particularly string-heavy (parsing, formatting, concatenation, report output, external integrations), those are the best candidates for early testing.

Your feedback is what helps us validate the edge cases and ensure this lands in a way that improves the day-to-day experience for Clarion developers.

What’s next

We’ll follow up with more concrete notes as the beta is delivered (including any implementation details and feedback from early testers). The direction is straightforward: keep Clarion development productive today while continuing to modernize the foundations for what comes next.

We’re excited to start the new year with both the beta release and a maintenance update release for the shipping version of C12. If you try this beta, let us know what you think — and stay tuned, there’s more to come.

Merry Christmas from SoftVelocity!

And Thank you for all the support this year!

Clarion 12 is released



Clarion 12 Release

Clarion 12 is Here: Smarter, Faster, and Built for the Future

We’re excited to announce the official release of Clarion 12!

After a marathon development journey, this release delivers 100% backward compatibility and introduces powerful new features to enhance your development experience. Clarion 12 ensures your existing projects compile seamlessly — even those pushing the limits of the C11 compiler and runtime library (RTL) — while laying the groundwork for 64-bit binaries in the next release (C12 currently produces 32-bit binaries).


✨ What’s New in Clarion 12?


  • Just about every important IDE component, and close to 65% of the Runtime Library has been refactored, optimized and adjusted in preparation for the move away from the Topspeed compiler technologies and into a modern compiler architecture – it was both necessary and meticulous work required to get to the end goal of 64-bit. We’ve posted about version 12 many times, but here is a recap of some of the more recent and significant changes.

  • Improved Unicode Support with a Refactored STRING Type

    We’ve eliminated the complications of managing two string data types (STRING/USTRING). The improved STRING type simplifies working with Unicode, making your apps more compatible with global languages — and, perhaps most importantly, ensures 64-bit readiness for future updates.

  • Compiler Performance Improvements

    You’ll notice faster compilation times and improved code generation, making the dev cycle smoother and more efficient.

  • Foundation for 64-Bit Compatibility

    We’ve made significant improvements to the runtime library, laying the foundation for full 64-bit compilation in an upcoming release. This ensures Clarion remains future-proof for all of your projects.

  • “Check for Updates”

    On the IDE “Start Page” you’ll find a new Check for Updates button option that allows you to keep you up to date incrementally and effortlessly. When run, it displays details on any available updates, your subscription coverage, and links to your purchased products. Enhancements and Bug fixes to the IDE, RTL, drivers, and templates will reach you faster. When an update is available you can download and install the new version right from the IDE.

Let us know what you think, and thanks for being a part of the Clarion community!


Clarion 12 news

The Clarion 12 release was delayed past our initial January 1st target as we maintained our traditional end-of-year break, I had planned for us to work straight through but decided we needed the break to recharge. Here’s something else that is new in this release.

Microsoft SQL Server Driver Updates

We’ve rebuilt the Microsoft SQL Server driver with some new capabilities:

Security

  • TLS 1.2/1.3 support with related configuration options
  • Column-level encryption
  • Support for Server Certificate validation (including self-issued certificates)
  • Improved error handling for security operations

Note: these features require the Microsoft ODBC Driver 17+

Version Support

  • SQL Server 2005 through 2022
  • SQL Server on Linux
  • Azure SQL Database
  • Existing connection strings and configurations remain valid unchanged

Azure SQL Database Support

  • Azure Active Directory and Managed Identity authentication
  • Failover group support
  • Region-aware connectivity
  • Elastic pool connections

Backward Compatibility

As with all our releases, Clarion 12 maintains 100% backward compatibility. Existing applications will work without modification, and all new features are opt-in.

General ODBC Driver Improvements

The SQL Server driver improvements extend into our entire ODBC stack:

  • Refactored connection handling
  • Enhanced custom connection string support
  • More detailed error handling
  • Full compatibility with existing applications

PostgreSQL Support

Our ODBC driver layer provides enhanced support for the official PostgreSQL ODBC driver:

  • Improved connection string handling
  • Enhanced error reporting
  • Full compatibility with PostgreSQL’s native ODBC capabilities

SQLite Updates

And we’re working on new SQLite features:

  • In-memory database support
  • Improved transaction handling
  • Better concurrent connection management

Next

We’ll soon provide a web application where developers can sign up to test upcoming AI features in the IDE. The database improvements in this release are complete and are in final testing. We need a few more days of testing before we announce C12 GA. Thanks for you support and patience!

Clarion 12 – Upcoming release

Embracing the Future

We’re excited to announce the upcoming release of Clarion 12. While the release timeline has extended beyond our initial projections, we’ve used this additional development time to implement improvements that will benefit our entire developer community.

A significant improvement emerging from this extended development period involves our string handling architecture. While we had previously announced the introduction of a USTRING type to handle Unicode alongside the traditional STRING type for ANSI strings, we’ve arrived at a more elegant solution. Clarion 12 will feature a unified, enhanced string type that provides superior Unicode support while maintaining complete backwards compatibility. This streamlined approach not only simplifies development but also paves the way for an easier transition to 64-bit compilation in the future.

Beyond this architectural refinement, much of Clarion 12’s development has focused on building a solid foundation for future capabilities. We’ve made important internal improvements that, while not immediately visible, strengthen the platform’s core and prepare it for upcoming features.

Introducing AI-Powered Development

Clarion 12 marks our entry into AI-assisted development with a flexible, pragmatic approach. While our initial focus was on local LLM integration, we’ve built the system to accommodate any external LLM as we progress. During testing, we recognized that even machines well-suited for traditional software development might not handle local LLM processing efficiently. We’ve conducted extensive experiments with the LLaMA 3 series and various smaller models as local options, keeping the default choice flexible to accommodate different development environments.

This isn’t just another code completion tool – it’s a comprehensive coding assistant that truly understands (with your help) your application’s context and needs. For developers who prefer or require cloud-based solutions, we’ll also offer commercial AI integration options. This dual approach ensures everyone can access these powerful features, regardless of their local hardware capabilities.

Business AI: Today and Tomorrow

Clarion 12 introduces AI capabilities starting with practical IDE enhancements that streamline your development process. This is just the beginning of our AI journey. Just as websites became essential for business success in the 1990s, AI integration in business applications is becoming crucial for maintaining competitive advantage today. We’re laying the groundwork for you to capitalize on this opportunity.

Current IDE Intelligence

In this release, Clarion 12 includes AI tools to analyze your existing applications and suggest potential enhancements:

  • Comprehensive application scanning and analysis
  • Intelligent feature recommendations based on your specific business domain
  • Vector database creation for deep application understanding
  • AI-powered development assistance and code insights

Future Application AI

In upcoming releases, you’ll be able to integrate AI directly into your business applications:

  • Ready-to-use semantic search capabilities
  • Vector database integration with standard SQL databases
  • AI features that don’t require machine learning expertise
  • Templates and frameworks for easy AI integration into your applications

This phased approach ensures you can start benefiting from AI immediately in your development process while preparing for the next wave of AI-enhanced business applications.

System Requirements

For local AI features:

  • Minimum 16GB RAM
  • Modern CPU (12th gen Intel or AMD Ryzen 7000 series or newer recommended)
  • Windows 11 recommended (Windows 10 compatible but not officially supported for all AI features)

Standard Clarion development requirements remain unchanged for non-AI features

Looking Ahead

The release of Clarion 12 represents more than just an update – it’s a strategic step toward empowering our development community with next-generation capabilities. By focusing on practical AI implementation and maintaining our commitment to efficient business application development, we’re ensuring that Clarion developers are well-positioned to meet evolving market demands.

The release will be available before year-end, with updated documentation. We are also pushing hard to complete additional training resources, including videos and detailed blog posts, to help you make the most of these new capabilities. We’re exploring the possibility of featuring Clarion 12 on the ClarionLive channel. Stay tuned for specific release date announcements and early access opportunities.

Get Ready

We encourage all developers to begin planning their upgrade to Clarion 12. The improvements in this release, combined with the foundational work for future enhancements, make this a crucial upgrade for staying competitive in today’s rapidly evolving software development landscape.