🚨 Oracle not porting Rdb to x86 and EOL on Itanium 12/2027 🚨
Technical Capabilities
Having trouble finding what you need?
Get in touch with us, so we can answer your specific questions directly.
Get In Touch

VX/FMS - OpenVMS Forms Management

Overview

VX/FMS is a native reimplementation of DEC's OpenVMS Forms Management System (FMS) for Linux. It delivers the FDV$ Form Driver API, the FMS form language compiler, and the supporting form utilities as a linked C runtime, so migrated OpenVMS applications keep their existing FDV$ calls, .flg form sources, and character-cell terminal behaviour without source changes.

The runtime library links directly into the migrated program: its FDV$ calls resolve to Sector7's implementations with the same calling sequence and VMS status conventions as OpenVMS. Forms compile from .flg source to .fbn binary through the VX/FMS compiler, User Action Routines bind by name at link time, and screens render through direct VT and ANSI terminal control with no dependency on curses, termcap, or terminfo.

<!-- Webflow embed (min). Source: fms-page-technical/fms-tech-body-embed-dark.html → python3 website/embeds/minify_webflow_embed.py … --> <div class="s7-tech-embed" data-vxfmsd-body-embed="1" data-technical-mega-embed="1" lang="en"><h2 id="architecture">Architecture and components</h2><p> VX/FMS is a linked runtime library plus a small set of command-line utilities, not a long-running server. The runtime is a C library that the migrated application links against directly, so the program's existing <code>FDV$</code> calls resolve to Sector7's implementations with no server process to administer. The table maps each OpenVMS FMS component to its VX/FMS counterpart. </p><div class="table-wrapper"><table><thead><tr><th>OpenVMS FMS component</th><th>VX/FMS artifact</th><th>Role</th><th>Status</th></tr></thead><tbody><tr><td>FMS Form Driver (<code>FDV$</code> shareable image)</td><td><code>libfms.a</code> / <code>libfms.so</code></td><td>Runtime the migrated application links; exposes the full <code>FDV$</code> call surface.</td><td><span class="ac-live">live</span></td></tr><tr><td>Form Language Translator (<code>FMS$FLTR</code>)</td><td><code>fms_form</code></td><td>Compiles <code>.flg</code> ASCII form source into <code>.fbn</code> binary form files.</td><td><span class="ac-live">live</span></td></tr><tr><td>Screen-oriented form editor (<code>FMS$FORM</code>)</td><td><code>fmsedit</code></td><td>Interactive <code>.flg</code> editor for VT and ANSI terminals.</td><td><span class="ac-live">live</span></td></tr><tr><td>UAR binding (VMS image activator)</td><td><code>fms_uar</code></td><td>Generates the User Action Routine name-to-function binding table to link into the application.</td><td><span class="ac-live">live</span></td></tr><tr><td>Diagnostics and regression tooling</td><td><code>fms_display</code> / <code>fms_dump</code> / <code>fms_compare</code></td><td>Headless render of a compiled form, escape-sequence dump, and render comparison against a captured reference.</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><div class="callout"><strong>No runtime daemon.</strong> There is no forms server and no IPC substrate to configure. The compiled <code>.fbn</code> form library is opened on disk by the linked runtime at <code>FDV$LOPEN</code> time, and forms are pulled into memory individually with <code>FDV$LOAD</code>. </div><h6>Call dispatch chain</h6><p> Each public API name is a thin dispatcher. A call to <code>FDV$DISP</code> resolves through a link-time alias to an internal dispatcher, which wraps the call in the VX runtime trace/return convention and hands off to the routine implementation: </p><style>.s7-tech-embed .fms-flow {margin: 1.5rem 0;padding: 16px;border: 1px solid var(--s7t-border);border-radius: 10px;background: rgba(255, 255, 255, 0.01);}.s7-tech-embed .fms-flow-stages {display: grid;grid-template-columns: repeat(4, minmax(0, 1fr));gap: 10px;}.s7-tech-embed .fms-flow-card {min-width: 0;padding: 15px;border-top: 3px solid var(--s7t-accent);border-radius: 6px;background: var(--s7t-surface2);color: var(--s7t-text);}.s7-tech-embed .fms-flow-card strong,.s7-tech-embed .fms-flow-card span:last-child {display: block;}.s7-tech-embed .fms-flow-card strong {margin-bottom: 4px;}.s7-tech-embed .fms-flow-card span:last-child {color: var(--s7t-muted);font-size: 0.9em;line-height: 1.45;}.s7-tech-embed .fms-flow-label {display: block;margin-bottom: 10px;font-family: var(--s7t-mono);color: var(--s7t-accent);font-size: 0.76em;font-weight: 700;letter-spacing: 0.08em;text-transform: uppercase;}.s7-tech-embed .fms-flow-output {border: 1px solid var(--s7t-note-bd);border-top: 3px solid var(--s7t-accent);background: var(--s7t-note-bg);}@media (max-width: 960px) {.s7-tech-embed .fms-flow-stages {grid-template-columns: repeat(2, minmax(0, 1fr));}}@media (max-width: 600px) {.s7-tech-embed .fms-flow-stages {grid-template-columns: 1fr;}}</style><div class="fms-flow" aria-label="VX/FMS call dispatch chain"><div class="fms-flow-stages"><div class="fms-flow-card"><span class="fms-flow-label">01 - Aliases</span><strong>Portable caller symbols</strong><span><code>FDV$DISP</code>, <code>fdv$disp</code>, and <code>fdv$disp_</code> expose C upper-case, C lower-case, and Fortran trailing-underscore names for unchanged C, COBOL, and Fortran callers.</span></div><div class="fms-flow-card"><span class="fms-flow-label">02 - Public dispatcher</span><strong><code>FDV_D_DISP</code></strong><span>All three link-time aliases resolve to this single portable symbol.</span></div><div class="fms-flow-card"><span class="fms-flow-label">03 - Runtime wrapper</span><strong>Begin, call, end</strong><span>The wrappers apply tracing and the VMS return convention around the implementation call.</span></div><div class="fms-flow-card fms-flow-output"><span class="fms-flow-label">04 - Implementation</span><strong><code>FCC_DISP()</code></strong><span>The display implementation performs the routine's actual work.</span></div></div></div><p> On an OpenVMS host, the dispatcher reads the caller's argument count and nulls out omitted optional parameters, preserving FMS's "optional trailing argument" semantics. On Linux the fixed prototype is used. The real work lives in the per-routine implementation files, which are complete implementations rather than stubs. </p><h2 id="fdv-api">The FDV$ Form Driver API</h2><p> VX/FMS implements the full FMS Form Driver call surface: <strong>66 public <code>FDV$</code> routines</strong>, each exported under the VMS dollar-sign name plus C lower-case and Fortran trailing-underscore aliases so existing object references resolve at link time. A migrated application links against <code>libfms</code> and its <code>FDV$</code> calls run unchanged. </p><h6>VMS calling convention</h6><p> Every routine returns a VMS condition value <strong>by value</strong>: odd means success, even means failure. Arguments are passed by reference as VMS descriptors (32-bit, or 64-bit descriptors under an LP64 build), matching the original VMS calling convention. This is what lets unmodified VMS source relink against VX/FMS. The canonical success status is <code>FDV$_SUC</code>; callers test the low bit of the return value exactly as they did on OpenVMS. </p><h6>Routine reference</h6><p> The table below groups the most frequently called routines by role. It is a representative selection of the 66-routine <code>FDV$</code> API; every routine listed is implemented in the runtime. </p><div class="table-wrapper"><table><thead><tr><th>Group</th><th>Routines</th><th>Purpose</th><th>Status</th></tr></thead><tbody><tr><td>Terminal session</td><td><code>FDV$ATERM</code>, <code>FDV$DTERM</code>, <code>FDV$STERM</code>, <code>FDV$FIX_SCREEN</code></td><td>Attach and detach the Form Driver session, set terminal characteristics, and re-sync the physical screen.</td><td><span class="ac-live">live</span></td></tr><tr><td>Workspace</td><td><code>FDV$AWKSP</code>, <code>FDV$SWKSP</code>, <code>FDV$DWKSP</code></td><td>Allocate, select, and free a Form Driver workspace.</td><td><span class="ac-live">live</span></td></tr><tr><td>Form library</td><td><code>FDV$LOPEN</code>, <code>FDV$LOAD</code>, <code>FDV$LCLOS</code></td><td>Open a compiled form library, load a named form into memory, and close the library.</td><td><span class="ac-live">live</span></td></tr><tr><td>Display</td><td><code>FDV$DISP</code>, <code>FDV$DISPW</code>, <code>FDV$CDISP</code>, <code>FDV$CLEAR</code>, <code>FDV$RFRSH</code></td><td>Display a form on the terminal, display at a workspace offset, clear, and refresh.</td><td><span class="ac-live">live</span></td></tr><tr><td>Field input / output</td><td><code>FDV$GET</code>, <code>FDV$GETAL</code>, <code>FDV$PUT</code>, <code>FDV$PUTAL</code>, <code>FDV$PUTL</code>, <code>FDV$RET</code>, <code>FDV$RETAL</code></td><td>Read a single field or the whole form, write values into fields, and return field values with their terminators.</td><td><span class="ac-live">live</span></td></tr><tr><td>Scrolled areas</td><td><code>FDV$GETSC</code>, <code>FDV$PUTSC</code></td><td>Read from and write to a scrolled (scrolling) region within a form.</td><td><span class="ac-live">live</span></td></tr><tr><td>Named data</td><td><code>FDV$RETDN</code>, <code>FDV$RETDI</code>, <code>FDV$NDISP</code></td><td>Retrieve named-data items by name or index, attached to a compiled form.</td><td><span class="ac-live">live</span></td></tr><tr><td>Status and operator</td><td><code>FDV$STAT</code>, <code>FDV$SIGOP</code>, <code>FDV$BELL</code>, <code>FDV$RETLE</code>, <code>FDV$RETFN</code></td><td>Return Form Driver status and field metadata, signal the operator, and sound the terminal bell.</td><td><span class="ac-live">live</span></td></tr><tr><td>Keyboard</td><td><code>FDV$DFKBD</code>, <code>FDV$LEDON</code>, <code>FDV$LEDOF</code></td><td>Configure the keyboard and toggle keyboard LEDs.</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><h6>Real call path</h6><p> A migrated program links this session sequence unchanged against <code>libfms</code>. The example uses a banking demo library and tests each status with the VMS success convention: </p> <pre><span class="cmt">/* 1. Attach the terminal (open the Form Driver session) */</span> rc = fdv$aterm(&amp;_tca, &amp;val0, &amp;val1, 0, 0, 0); if (rc != FDV$_SUC) { <span class="cmt">/* report status text and exit */</span> } <span class="cmt">/* 2. Allocate and select a workspace */</span> val0 = 2000; rc = fdv$awksp(&amp;_wksp1, &amp;val0); rc = fdv$swksp(&amp;_wksp1); <span class="cmt">/* 3. Open the compiled form library and load a form */</span> rc = fdv$lopen(_DESCR1(<span class="str">"BANKING_FORMS"</span>), &amp;val0); rc = fdv$load (_DESCR1(<span class="str">"ACCOUNT_INQUIRY"</span>)); <span class="cmt">/* 4. Display the form and read all fields (trm receives the terminator) */</span> rc = fdv$dispw(0); rc = fdv$getal(&amp;_val, &amp;trm, 0, 0); <span class="cmt">/* 5. Tear down */</span> fdv$dwksp(&amp;_wksp1); fdv$dterm(&amp;_tca);</pre> <p> The equivalent portable C entry point is declared as <code>extern "C" int fdv$get(...);</code> and returns the condition value by value. The same routines are the ones the callable <a href="/technical/api-fms-forms-management-system">FMS$ Forms Management System API</a> page documents in full detail. </p><h2 id="form-language">The FMS form language</h2><p><code>.flg</code> is the ASCII form-description source the compiler reads. The VX/FMS compiler emits a binary form file with the <code>.fbn</code> extension, byte-compatible with the compiled forms FMS produced on OpenVMS. A library of compiled forms is opened at runtime with <code>FDV$LOPEN</code>, and individual forms are pulled with <code>FDV$LOAD</code>. </p><h6>Statement keywords</h6><p>The form language has ten top-level statement types:</p><div class="table-wrapper"><table><thead><tr><th>Statement</th><th>Purpose</th></tr></thead><tbody><tr><td><code>FORM</code></td><td>Opens a form definition (takes <code>NAME=</code>).</td></tr><tr><td><code>END_OF_FORM</code></td><td>Closes a form definition (takes <code>NAME=</code>).</td></tr><tr><td><code>FIELD</code></td><td>Defines an input or output field at a row and column.</td></tr><tr><td><code>TEXT</code></td><td>Places literal text at a <code>(row,col)</code> position.</td></tr><tr><td><code>ATTRIBUTE_DEFAULTS</code></td><td>Sets default field and attribute values for the form.</td></tr><tr><td><code>NAMED_DATA</code></td><td>Attaches named constant data to the form.</td></tr><tr><td><code>ORDER</code></td><td>Defines the field navigation order.</td></tr><tr><td><code>SCROLL</code></td><td>Declares a scrolled region by line range.</td></tr><tr><td><code>DRAW</code></td><td>Line-draw or ruling directive.</td></tr><tr><td><code>VIDEO</code></td><td>Video and display-attribute directive.</td></tr></tbody></table></div><h6>Statement items and attribute flags</h6><p> Statement items take a <code>=value</code>; attribute flags are bare keywords, most with a <code>NO...</code> negation. The compiler recognises the full FMS keyword set: </p><div class="kw-grid"><div>NAME=</div><div>PICTURE=</div><div>DEFAULT=</div><div>HELP=</div><div>HELP_FORM=</div><div>WIDTH=</div><div>INDEX=</div><div>CHARACTER_SET=</div><div>CLEAR_CHARACTER=</div><div>BACKGROUND=</div><div>HIGHLIGHT=</div><div>DATA=</div><div>AREA_TO_CLEAR=</div><div>BEGIN_WITH= / END_WITH=</div><div>DATE_FIELD= / TIME_FIELD=</div><div>ACTION_ROUTINE=</div><div>FUNCTION_KEY_ACTION_ROUTINE=</div><div>PRE_HELP_ACTION_ROUTINE=</div><div>POST_HELP_ACTION_ROUTINE=</div><div>AUTOTAB / NOAUTOTAB</div><div>BOLD / NOBOLD</div><div>BLINKING / NOBLINKING</div><div>REVERSE / NOREVERSE</div><div>UNDERLINE / NOUNDERLINE</div><div>DISPLAY_ONLY / ECHO / NOECHO</div><div>MUST_FILL / RESPONSE_REQUIRED</div><div>LEFT_JUSTIFIED / RIGHT_JUSTIFIED</div><div>UPPERCASE / BLANK_FILL / ZERO_FILL</div><div>SUPERVISOR_ONLY / SUPPRESS</div></div><p> Date fields support <code>MDY</code>, <code>DDMMMYY</code>, <code>MMDDYY</code>, and <code>DDMMYY</code> pictures; time fields support <code>HHMMSS</code> and <code>HHMMAMPM</code>. <code>PICTURE</code> accepts either a literal mask (<code>PICTURE='XXXXX-XXXX'</code>) or a count-prefixed form (<code>PICTURE=40'X'</code>). </p><h6>Example form source</h6><p> A field with attribute defaults, a bound User Action Routine, a navigation order, and a help string. Comments begin with <code>!</code>; a statement ends with <code>;</code>: </p> <pre><span class="kw">FORM</span> NAME=<span class="str">'ACCOUNT_INQUIRY'</span> AREA_TO_CLEAR=1:23 WIDTH=80 BACKGROUND=CURRENT HIGHLIGHT=BOLD:UNDERLINE FUNCTION_KEY_ACTION_ROUTINE=<span class="str">'FILTER_UAR'</span> ; <span class="kw">TEXT</span> (2,30) <span class="str">'ACCOUNT INQUIRY'</span> ; <span class="kw">ATTRIBUTE_DEFAULTS</span> FIELD CLEAR_CHARACTER=<span class="str">' '</span> NOAUTOTAB BLANK_FILL NOBOLD NOREVERSE ECHO LEFT_JUSTIFIED NOSUPERVISOR_ONLY NOUPPERCASE ; <span class="kw">FIELD</span> NAME=<span class="str">'POST_IT'</span> (22,64) PICTURE=<span class="str">'X'</span> HELP=<span class="str">'Enter "Y" to post this transaction, "N" to abort'</span> UPPERCASE ACTION_ROUTINE=<span class="str">'POST_IT_UAR'</span> RESPONSE_REQUIRED ; <span class="kw">ORDER</span> BEGIN_WITH = 1 NAME=<span class="str">'ACCOUNT_NUMBER'</span> NAME=<span class="str">'POST_IT'</span> ; <span class="kw">END_OF_FORM</span> NAME=<span class="str">'ACCOUNT_INQUIRY'</span> ;</pre> <p> Scrolled regions are declared by line range, and a help form is linked with <code>HELP_FORM='HELPTOPIC'</code>. The <code>RULE</code> character set selects the VT line-drawing glyphs used for box borders: </p> <pre><span class="kw">SCROLL</span> BEGIN_WITH=9 END_WITH=13 ; <span class="kw">SCROLL</span> BEGIN_WITH=18 END_WITH=20 ;</pre> <h2 id="uars">User Action Routines</h2><p> A User Action Routine (UAR) is a user-supplied C or C++ function bound to a form or field <strong>by name</strong> in the <code>.flg</code> source. VX/FMS supports all UAR scenarios that OpenVMS FMS does: </p><ul><li>Field completion events, when the operator finishes entering a field.</li><li>Help requests raised by the terminal operator.</li><li>Function-key interactions, bound with <code>FUNCTION_KEY_ACTION_ROUTINE=</code>.</li><li>Pre-help and post-help hooks, bound with <code>PRE_HELP_ACTION_ROUTINE=</code> and <code>POST_HELP_ACTION_ROUTINE=</code>.</li><li>Screen refresh operations.</li></ul><h6>Binding and dispatch</h6><p> A form binds a UAR by string name, for example <code>ACTION_ROUTINE='POST_IT_UAR'</code> or <code>FUNCTION_KEY_ACTION_ROUTINE='FILTER_UAR'</code>. At run time the Form Driver dispatches by name through a generated lookup table that pairs each UAR name with its function pointer: </p> <pre><span class="cmt">/* generated binding table, linked into the application */</span> extern char *FMS_name_field[]; <span class="cmt">/* UAR names */</span> extern int (*FMS_ptr_field[])(void); <span class="cmt">/* parallel function pointers */</span> int FMS_find_call_uar(char *name) { <span class="cmt">/* locate name in FMS_name_field[], then call the paired pointer */</span> for (i = 0; strcmp(name, FMS_name_field[i]) &amp;&amp; ... ; i++) ; return (*FMS_ptr_field[i])(); <span class="cmt">/* invoke the UAR */</span> }</pre> <p> The name-to-pointer table is produced by the <code>fms_uar</code> generator, which scans the application's UAR source and emits the binding table to link in. On OpenVMS the image activator resolved UARs by name at run time; on Linux there is no image activator, so the generator materialises the equivalent table at link time. This is also how VX/FMS extends the original FMS capability by allowing <strong>dynamic linking of external C++ functions</strong> as UARs, giving migrated forms more flexibility than the OpenVMS original. </p><div class="callout"><strong>No source rewrite for UAR logic.</strong> Existing UAR functions keep their names and signatures. The only new build step is running <code>fms_uar</code> to generate the binding table, which replaces the OpenVMS run-time name resolution. </div><h2 id="terminal">Terminal handling</h2><p> VX/FMS drives the terminal directly and emits raw VT and ANSI escape sequences. It does <strong>not</strong> depend on curses, termcap, or terminfo. This is a deliberate design choice: rendering the screen the same way OpenVMS FMS did preserves exact character-cell behaviour, cursor addressing, and video attributes, rather than approximating them through a Unix TUI layer. </p><h6>Supported terminals</h6><ul><li>VT100, VT220, and all compatible VT-series terminals.</li><li>DECterm under DECwindows.</li><li>ANSI-compatible terminal emulators on Linux.</li></ul><h6>Display features preserved</h6><div class="table-wrapper"><table><thead><tr><th>Feature</th><th>Behaviour</th></tr></thead><tbody><tr><td>132-character mode</td><td>Wide-screen (132-column) display, switched at runtime through the screen-width routine.</td></tr><tr><td>Double-size and double-width</td><td>The <code>DBLSIZ</code> and <code>DBLWID</code> form attributes render as on VT terminals.</td></tr><tr><td>Line drawing</td><td>The <code>RULE</code> character set drives VT line-drawing glyphs for box borders and rules.</td></tr><tr><td>Video attributes</td><td><code>BOLD</code>, <code>REVERSE</code>, <code>UNDERLINE</code>, and <code>BLINKING</code> map to their SGR equivalents.</td></tr><tr><td>Scrolled regions</td><td>Scrolling areas declared by line range in the form scroll and refresh correctly.</td></tr></tbody></table></div><p> Because the runtime owns terminal I/O end to end, the diagnostic tools can capture and replay the exact escape stream: <code>fms_dump</code> writes a form render to an escape-sequence file, and <code>fms_compare</code> parses those escapes back to compare a Linux render against a captured reference render for regression testing. </p><h2 id="build-pipeline">Build and compile pipeline</h2><p> The build produces the runtime library and the form utilities. Applications then compile their forms and generate the UAR binding table before linking against the library. </p><div class="table-wrapper"><table><thead><tr><th>Step</th><th>Command</th><th>Input</th><th>Output</th></tr></thead><tbody><tr><td>Build the runtime library</td><td><code>make</code></td><td>runtime C sources</td><td><code>libfms.a</code> / <code>libfms.so</code></td></tr><tr><td>Build the utilities</td><td><code>make</code> (utilities target)</td><td>utility C sources</td><td><code>fms_form</code>, <code>fms_uar</code>, <code>fms_display</code>, <code>fms_compare</code></td></tr><tr><td>Standalone variant</td><td><code>make standalone</code></td><td>same sources</td><td>self-contained library and tools, independent of the wider VX/RT runtime</td></tr><tr><td>Compile a form</td><td><code>fms_form &lt;name&gt;</code></td><td><code>name.flg</code></td><td><code>name.fbn</code></td></tr><tr><td>Edit a form</td><td><code>fmsedit name.flg</code></td><td><code>.flg</code></td><td><code>.flg</code></td></tr><tr><td>Generate the UAR table</td><td><code>fms_uar</code></td><td>application UAR sources</td><td>name-to-pointer binding table to link in</td></tr></tbody></table></div><div class="callout"><strong>Standalone or integrated.</strong> VX/FMS builds either as a self-contained library and toolset, or against the wider Sector7 runtime so it interoperates with <a href="/technical/vx-rt-apis">VX/RT</a> and other Sector7 migration components in the same estate. </div><p> The form compiler is a hand-written recursive-descent parser: it reads the <code>.flg</code> statement stream, keys on the statement keywords against the token table, and serialises the compiled form to the <code>.fbn</code> binary. Because the output format matches the OpenVMS compiled form, existing tooling that consumes <code>.fbn</code> libraries continues to work. </p><h2 id="compatibility">Feature and platform compatibility</h2><p> VX/FMS retains the core capabilities of OpenVMS FMS so migrated applications keep their form behaviour, layout, and interactions. The matrix below lists each capability and its status in the runtime. </p><div class="table-wrapper"><table><thead><tr><th>Capability</th><th>Status</th></tr></thead><tbody><tr><td>FDV$ Form Driver API (66 routines)</td><td><span class="ac-live">live</span></td></tr><tr><td><code>.flg</code> to <code>.fbn</code> form compiler</td><td><span class="ac-live">live</span></td></tr><tr><td>User Action Routine name-to-pointer dispatch and generator</td><td><span class="ac-live">live</span></td></tr><tr><td>Scrolled areas, named data, and overlapping forms</td><td><span class="ac-live">live</span></td></tr><tr><td>132-column, double-size, and double-width display</td><td><span class="ac-live">live</span></td></tr><tr><td>HELP forms with pre-help and post-help action routines</td><td><span class="ac-live">live</span></td></tr><tr><td>Direct VT and ANSI terminal I/O (no curses, termcap, or terminfo)</td><td><span class="ac-live">live</span></td></tr><tr><td><code>fmsedit</code> interactive form editor</td><td><span class="ac-live">live</span></td></tr><tr><td>Diagnostic and regression tooling (dump, display, compare)</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><h6>Platforms</h6><p> The VX/FMS runtime is native on Linux, and the same sources build for other Unix platforms (macOS, HP-UX, and SCO) through build-time configuration. The library links directly into the migrated application, so the target platform is whatever the recompiled application targets. </p><div class="callout"><strong>100 percent FDV$ API compatibility.</strong> Every FDV$ routine an existing forms application calls is implemented with the same arguments and status conventions, so migration is a relink rather than a rewrite. This makes VX/FMS a drop-in path for OpenVMS FMS forms applications moving to Linux. </div><h2 id="quickref">Quick reference</h2><h6>Session skeleton</h6><p>The canonical Form Driver session lifecycle:</p><div class="fms-flow" aria-label="VX/FMS Form Driver session lifecycle"><div class="fms-flow-stages"><div class="fms-flow-card"><span class="fms-flow-label">01</span><strong>Attach terminal</strong><span><code>FDV$ATERM</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">02</span><strong>Attach or select workspace</strong><span><code>FDV$AWKSP</code> or <code>FDV$SWKSP</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">03</span><strong>Open library</strong><span><code>FDV$LOPEN</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">04</span><strong>Load form</strong><span><code>FDV$LOAD</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">05</span><strong>Display</strong><span><code>FDV$DISP</code> or <code>FDV$DISPW</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">06</span><strong>Read fields</strong><span><code>FDV$GET</code> or <code>FDV$GETAL</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">07</span><strong>Detach workspace</strong><span><code>FDV$DWKSP</code></span></div><div class="fms-flow-card fms-flow-output"><span class="fms-flow-label">08</span><strong>Detach terminal</strong><span><code>FDV$DTERM</code></span></div></div></div><h6>At a glance</h6><div class="table-wrapper"><table><thead><tr><th>Item</th><th>Value</th></tr></thead><tbody><tr><td>Runtime library</td><td><code>libfms.a</code> / <code>libfms.so</code>, linked into the migrated application.</td></tr><tr><td>Public API</td><td>66 <code>FDV$</code> routines, dispatched to per-routine implementations.</td></tr><tr><td>Form language</td><td>Source <code>.flg</code> compiled to <code>.fbn</code> by <code>fms_form</code>.</td></tr><tr><td>Return convention</td><td>VMS condition value by value; odd is success, <code>FDV$_SUC</code> is success.</td></tr><tr><td>UARs</td><td>Bound by name in the <code>.flg</code>; dispatched through a table generated by <code>fms_uar</code>.</td></tr><tr><td>Terminals</td><td>VT100, VT220, DECterm, and ANSI emulators, driven by direct VT and ANSI escapes.</td></tr><tr><td>Utilities</td><td><code>fms_form</code>, <code>fmsedit</code>, <code>fms_uar</code>, <code>fms_display</code>, <code>fms_dump</code>, <code>fms_compare</code>.</td></tr></tbody></table></div><h6>Status codes</h6><p> Form Driver routines return VMS-format 32-bit condition values, where odd values indicate success. Field-level input conditions (for example full field, no previous field, numeric required, or help available) are reported through the same status interface, and a workspace-item form of the status is available through <code>FDV$STAT</code> for programs that inspect completion detail. </p><h6>Related Sector7 tools</h6><ul><li><a href="/technical/api-fms-forms-management-system">FMS$ - Forms Management System</a>: the callable FDV$ API companion, documented routine by routine.</li><li><a href="/technical/vx-rt-apis">VX/RT APIs</a>: the OpenVMS runtime environment VX/FMS integrates with on Linux.</li><li><a href="/technical/vx-rms-sys-routines-for-rms">VX/RMS</a>: RMS file access for the same migrated applications.</li><li><a href="/technical/vx-tdms-terminal-data-management-system">VX/TDMS</a> and <a href="/technical/vx-decforms---decforms-ifdl-compiler-and-forms">VX/DECFORMS</a>: sibling forms and screen-management tools in the same family.</li></ul></div>

Frequently Asked Questions

Curious about how Sector7 can facilitate your application migration? Explore our FAQs for expert insights.

How does VX/FMS support existing FMS applications?
VX/FMS translates FMS mask description language into binary runtime files, allowing applications to retain their original behavior, formatting, and user interactions on modern Linux platforms.
What are the key features of VX/FMS?
Key features of VX/FMS include:
  • 100% compatible FDV$ API implementation
  • Support for VT terminals and DECterm
  • User Action Routines (UARs) for interactive events
  • Full form compilation to binary runtime
How does VX/FMS integrate with other Sector7 tools?
VX/FMS works seamlessly with VX/RT APIs and other Sector7 migration tools to provide comprehensive OpenVMS compatibility on Linux platforms.
What terminal types does VX/FMS support?
VX/FMS supports VT100, VT220, DECterm, and ANSI-compatible terminal emulators for Linux, ensuring identical user interaction across platforms without relying on curses or termcap.
How does VX/FMS handle User Action Routines?
VX/FMS fully supports all UAR scenarios including field completion events, help requests, function key interactions, and screen refresh operations, maintaining original VMS FMS behavior.
What migration benefits does VX/FMS provide?
VX/FMS enables organizations to modernize their form-based applications while preserving existing user interfaces and workflows. This approach eliminates the need for costly UI rewrites and maintains user productivity during migration.
How can I get started with VX/FMS migration?
To learn more about VX/FMS and how it can streamline your OpenVMS forms migration to Linux, contact us for a detailed assessment and migration roadmap.
Which platforms does VX/FMS run on?

VX/FMS is a native reimplementation of DEC's OpenVMS Forms Management System for Linux. It reproduces the original FMS behaviour, formatting, and user interactions so migrated applications run without functional changes, and the same sources also build for other Unix platforms through build-time configuration.

Does my application code have to change to use VX/FMS?

No. VX/FMS implements the FDV$ APIs with the same arguments and status conventions as OpenVMS FMS, so existing applications that call the FDV$ interface keep their calling sequence unchanged. Migration is a relink rather than a rewrite.

What does the VX/FMS compiler do?

It translates the FMS mask description language (.flg source) into binary runtime form files (.fbn), the same compiled form output FMS produced on OpenVMS, so form logic, attributes, and layout are preserved and execute identically after migration.

Which terminals and emulators does VX/FMS support?

VX/FMS supports VT100, VT220, and all compatible VT-series terminals, DECterm under DECwindows, and ANSI-compatible terminal emulators on Linux, giving identical character-cell user interaction across platforms.

Does VX/FMS depend on curses, termcap, or terminfo?

No. The Form Driver renders FMS screens directly with VT and ANSI escape sequences and does not rely on curses, termcap, or terminfo. That is how it keeps exact compatibility with original VMS FMS display behaviour rather than approximating it through a Unix TUI layer.

What FMS features are preserved during migration?

Scrolled areas, named data, overlapping forms, 132-character wide-screen mode, VMS HELP forms, and User Action Routines are all supported, so the migrated environment retains the core capabilities of OpenVMS FMS.

What are User Action Routines (UARs) and how are they supported?

UARs are user-defined callback procedures triggered by form events. A form binds a UAR by name in the .flg source, and the Form Driver dispatches it at run time. VX/FMS supports all UAR scenarios, including field completion, operator help requests, function-key interactions, and screen refresh, and it also allows dynamic linking of external C++ functions for extra flexibility.

How does VX/FMS fit with the rest of the Sector7 toolset?

VX/FMS can run as a standalone product or integrate with VX/RT, Sector7's OpenVMS runtime environment on Linux, and it works alongside VX/RMS and other Sector7 migration tools so an entire OpenVMS forms application can move together.

Transform Your Legacy Software Today!

Get In Touch
Unlock the potential of your legacy software with our expert migration services.